0ef4e8ed4f
The QML design of styling is that one extends the "Template" version of a component. With the Basic, the Fusion etc already provided. But after upgrading to Qt6.9 that styling for Popup changed and broke the look of Flowee Pay. So, we no longer use the Basic styled class, but the bare one which should never change. This additionally simplifies a lot of the workarounds surrounding insets and other stuff that existed in the Basic.Popup, and we just don't set in our own "style" of Popup. Beautiful result, lots of complexity removed from AccountDetails, TransactionListItem and very much from PopupOverlay
151 lines
5.1 KiB
QML
151 lines
5.1 KiB
QML
/*
|
|
* This file is part of the Flowee project
|
|
* Copyright (C) 2022-2025 Tom Zander <tom@flowee.org>
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
import QtQuick
|
|
import QtQuick.Controls.Basic as QQC2
|
|
import "../Flowee" as Flowee
|
|
|
|
FocusScope {
|
|
id: root
|
|
anchors.fill: parent
|
|
enabled: thePopup.visible
|
|
|
|
property bool isOpen: false;
|
|
|
|
/**
|
|
* @param sourceComponent is a Component we set on the loader.
|
|
* @param target is the visual item we position next to (vertically).
|
|
* @param overlayComponent is a component that we place on top of the
|
|
* \a 'target' item, but inside of the popup to avoid dimming.
|
|
* @returns the item instance of the sourceComponent template
|
|
*
|
|
* Note, make sure that the sourceComponent sets an implicitHeight,
|
|
* which is used in the popup.
|
|
*/
|
|
function open(sourceComponent, target, overlayComponent) {
|
|
thePopup.palette = mainWindow.palette
|
|
thePopup.width = root.width - 18
|
|
thePopup.x = (width - thePopup.width) / 2
|
|
if (target === null) {
|
|
thePopup.sourceRect = Qt.rect(0, 0, 0, 0);
|
|
} else {
|
|
thePopup.sourceRect = root.mapFromItem(target, 0, 0, target.width, target.height);
|
|
}
|
|
overlayLoader.sourceComponent = overlayComponent;
|
|
loader.sourceComponent = sourceComponent; // last, as it starts the loading
|
|
return loader.item;
|
|
}
|
|
function close() {
|
|
thePopup.visible = false;
|
|
}
|
|
|
|
Connections {
|
|
target: Pay
|
|
function onAppProtectionChanged() {
|
|
// when the app is locked, make sure we remove all popups
|
|
root.close();
|
|
}
|
|
}
|
|
|
|
Flowee.Popup {
|
|
id: thePopup
|
|
width: parent.width
|
|
height: 100
|
|
modal: true
|
|
closePolicy: QQC2.Popup.CloseOnEscape + QQC2.Popup.CloseOnReleaseOutside
|
|
property rect sourceRect: Qt.rect(0, 0, 0, 0)
|
|
onVisibleChanged: {
|
|
if (!visible) { // closing
|
|
loader.sourceComponent = undefined;
|
|
overlayLoader.sourceComponent = undefined;
|
|
}
|
|
root.isOpen = visible; // ensure listeners of that property get notified after we acted on visibility changes.
|
|
}
|
|
background: Item { }
|
|
|
|
Loader {
|
|
id: overlayLoader
|
|
width: parent.width - 2
|
|
x: 1
|
|
}
|
|
Rectangle {
|
|
color: palette.base
|
|
border.color: palette.midlight
|
|
border.width: 1
|
|
radius: 5
|
|
anchors.fill: loader
|
|
// the popup imposes a border on us, we take it back
|
|
anchors.margins: -10
|
|
}
|
|
|
|
Loader {
|
|
id: loader
|
|
width: parent.width - 20
|
|
x: 10
|
|
onLoaded: {
|
|
thePopup.visible = true;
|
|
root.forceActiveFocus();
|
|
}
|
|
|
|
onHeightChanged: {
|
|
if (item == null)
|
|
return;
|
|
var h = loader.item.implicitHeight
|
|
thePopup.height = h
|
|
var rect = thePopup.sourceRect;
|
|
if (overlayLoader.item) { // the overlay is supposed to be at the same position as the sourceRect
|
|
var h2 = overlayLoader.height
|
|
thePopup.height += h2;
|
|
|
|
if (root.height - rect.bottom >= h) { // fits below
|
|
thePopup.y = rect.bottom - h2;
|
|
overlayLoader.y = 0
|
|
loader.y = h2;
|
|
}
|
|
else if (h < rect.y) { // fits above
|
|
thePopup.y = rect.y - h
|
|
overlayLoader.y = h
|
|
loader.y = 0;
|
|
}
|
|
else {
|
|
thePopup.y = root.height - h; // make it bottom aligned, even if it overlaps
|
|
overlayLoader.y = 0 // item above
|
|
loader.y = h2;
|
|
}
|
|
|
|
return;
|
|
}
|
|
loader.y = 0;
|
|
|
|
if (root.height - rect.bottom >= h) // fits below
|
|
thePopup.y = rect.bottom;
|
|
else if (h < rect.y) // fits above
|
|
thePopup.y = rect.y - h;
|
|
else
|
|
thePopup.y = root.height - h; // make it bottom aligned, even if it overlaps
|
|
}
|
|
}
|
|
}
|
|
|
|
Keys.onPressed: (event)=> {
|
|
if (event.key === Qt.Key_Back || event.key === Qt.Key_Escape) {
|
|
event.accepted = true;
|
|
root.close();
|
|
}
|
|
}
|
|
}
|