import QtQuick 2.13 import QtQuick.Controls 2.3 import QtQuick.Layouts 1.13 import utils 1.0 import shared.popups 1.0 import StatusQ.Core 0.1 import StatusQ.Controls 0.1 import StatusQ.Core.Theme 0.1 FocusScope { id: root property string sectionTitle property int contentWidth readonly property int contentHeight: root.height - titleRow.height - Style.current.padding property alias titleRowLeftComponentLoader: leftLoader property alias titleRowComponentLoader: loader property list headerComponents property alias bottomHeaderComponents: secondHeaderRow.contentItem default property alias content: contentWrapper.children property alias titleLayout: titleLayout property bool stickTitleRowComponentLoader: false property bool dirty: false // Used to configure the dirty behaviour of the settings page as a must blocker notification when // user wants to leave the current page or just, ignore the changes done. Default: blocker property bool ignoreDirty: false property bool saveChangesButtonEnabled: false readonly property alias toast: settingsDirtyToastMessage // Used to configure the dirty toast behaviour (by default overlay on top of content) property bool autoscrollWhenDirty: false readonly property real availableHeight: scrollView.availableHeight - settingsDirtyToastMessagePlaceholder.height - Style.current.bigPadding signal baseAreaClicked() signal saveChangesClicked() signal saveForLaterClicked() signal resetChangesClicked() function notifyDirty() { settingsDirtyToastMessage.notifyDirty(); } QtObject { id: d readonly property int titleRowHeight: 56 readonly property int bottomDirtyToastMargin: 36 } MouseArea { anchors.fill: parent onClicked: { root.baseAreaClicked() } } Component.onCompleted: { if (headerComponents.length) { for (let i in headerComponents) { headerComponents[i].parent = titleRow } } } ColumnLayout { id: titleRow width: root.contentWidth spacing: 0 RowLayout { id: titleLayout Layout.fillWidth: true Layout.preferredHeight: visible ? d.titleRowHeight : 0 visible: (root.sectionTitle !== "") Loader { id: leftLoader } StatusBaseText { Layout.fillWidth: !root.stickTitleRowComponentLoader text: root.sectionTitle font.weight: Font.Bold font.pixelSize: Constants.settingsSection.mainHeaderFontSize color: Theme.palette.directColor1 } Loader { id: loader Layout.leftMargin: root.stickTitleRowComponentLoader ? 8 : 0 } } Control { id: secondHeaderRow Layout.fillWidth: true visible: !!contentItem } } StatusScrollView { id: scrollView objectName: "settingsContentBaseScrollView" anchors.top: titleRow.bottom anchors.bottom: parent.bottom anchors.topMargin: titleLayout.visible ? Style.current.padding: 0 padding: 0 width: root.width contentWidth: root.contentWidth contentHeight: contentLayout.implicitHeight + Style.current.bigPadding Column { id: contentLayout width: scrollView.availableWidth MouseArea { onClicked: root.baseAreaClicked() width: contentWrapper.implicitWidth height: contentWrapper.implicitHeight hoverEnabled: true Column { id: contentWrapper onVisibleChanged: if (visible) forceActiveFocus() } } // Used only when dirty toast visible and in case of autoscrolling configuration Item { id: settingsDirtyToastMessagePlaceholder width: settingsDirtyToastMessage.implicitWidth height: settingsDirtyToastMessage.active && root.autoscrollWhenDirty ? (settingsDirtyToastMessage.implicitHeight + d.bottomDirtyToastMargin) : 0 /*Overlay on top of content*/ Behavior on implicitHeight { enabled: root.autoscrollWhenDirty NumberAnimation { duration: 150 easing.type: Easing.InOutQuad } } } } } SettingsDirtyToastMessage { id: settingsDirtyToastMessage anchors.bottom: scrollView.bottom anchors.bottomMargin: d.bottomDirtyToastMargin // Left anchors and margin added bc of the implementation of the `SettingsContentBase` parent margin and to avoid // this toast to be wrongly centered // Constants.settingsSection.leftMargin is the margin set up to the parent when using `SettingsContentBase` inside central // panel property of `StatusSectionLayout` and needs to be taken into account to counteract it // when trying to align horizontally the save toast component anchors.left: root.left anchors.leftMargin: -Constants.settingsSection.leftMargin / 2 + (root.width / 2 - width / 2) active: root.dirty flickable: root.autoscrollWhenDirty ? scrollView.flickable : null saveChangesButtonEnabled: root.saveChangesButtonEnabled onResetChangesClicked: root.resetChangesClicked() onSaveChangesClicked: root.saveChangesClicked() onSaveForLaterClicked: root.saveForLaterClicked() } }