diff --git a/containments/homescreens/folio/README.md b/containments/homescreens/folio/README.md index ff4874f8..0cc78094 100644 --- a/containments/homescreens/folio/README.md +++ b/containments/homescreens/folio/README.md @@ -14,20 +14,15 @@ Most of the homescreen is in C++ in order to keep logic together, with QML only As such, all of the positioning and placement of delegates on the screen are top down from the model, as well as drag and drop behaviour. #### TODO -- Add folio/halcyon switcher in initial-start -- If an app gets uninstalled, the homescreen UI needs to ensure that delegates are updated +- BUG: If an app gets uninstalled, the homescreen UI needs to ensure that delegates are updated - BUG: landscape favourites bar duplication when dragging icon from it sometimes - BUG: can't insert delegates in-between very well in landscape favourites bar - BUG: drag and drop animation when rejected on a different page - IMPROVEMENT: can make the touch area only the icon? - +- FEATURE: Add folio/halcyon switcher in initial-start - FEATURE: add widget import/export - FEATURE: keyboard navigation - FEATURE: touchpad navigation - FEATURE: option to darken wallpaper - FEATURE: option to turn off row/column swap -- FEATURE: animate homescreen config opening - -- RESTORE: app drawer overshoot - - PERFORMANCE: ensure that the widget config overlays are in loaders diff --git a/containments/homescreens/folio/package/contents/ui/settings/AppletListViewer.qml b/containments/homescreens/folio/package/contents/ui/settings/AppletListViewer.qml index 85cdbc31..a34977cc 100644 --- a/containments/homescreens/folio/package/contents/ui/settings/AppletListViewer.qml +++ b/containments/homescreens/folio/package/contents/ui/settings/AppletListViewer.qml @@ -33,15 +33,30 @@ MouseArea { color: Qt.rgba(0, 0, 0, 0.7) } - PC3.Label { - id: heading - color: 'white' - text: i18n("Widgets") - font.weight: Font.Bold - font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.5 - anchors.horizontalCenter: parent.horizontalCenter + RowLayout { + id: header + spacing: Kirigami.Units.largeSpacing + anchors.left: parent.left + anchors.leftMargin: Kirigami.Units.gridUnit anchors.top: parent.top anchors.topMargin: Kirigami.Units.gridUnit * 3 + root.homeScreen.topMargin + + PC3.ToolButton { + Layout.alignment: Qt.AlignVCenter + icon.name: 'go-previous' + implicitWidth: Kirigami.Units.gridUnit * 2 + implicitHeight: Kirigami.Units.gridUnit * 2 + padding: Kirigami.Units.smallSpacing + onClicked: root.requestClose() + } + + PC3.Label { + id: heading + color: 'white' + text: i18n("Widgets") + font.weight: Font.Bold + font.pointSize: Kirigami.Theme.defaultFont.pointSize * 1.5 + } } GridView { @@ -51,7 +66,7 @@ MouseArea { opacity: 0 // we display with the opacity gradient below - anchors.top: heading.bottom + anchors.top: header.bottom anchors.topMargin: Kirigami.Units.gridUnit anchors.left: parent.left anchors.leftMargin: root.homeScreen.leftMargin @@ -87,6 +102,16 @@ MouseArea { cursorShape: Qt.PointingHandCursor hoverEnabled: true + property real zoomScale: pressed ? 0.8 : 1 + transform: Scale { + origin.x: delegate.width / 2; + origin.y: delegate.height / 2; + xScale: delegate.zoomScale + yScale: delegate.zoomScale + } + + Behavior on zoomScale { NumberAnimation { duration: 80 } } + readonly property string pluginName: model.pluginName onPressAndHold: { diff --git a/containments/homescreens/folio/package/contents/ui/settings/SettingsWindow.qml b/containments/homescreens/folio/package/contents/ui/settings/SettingsWindow.qml index 8f6dde51..eb10fce7 100644 --- a/containments/homescreens/folio/package/contents/ui/settings/SettingsWindow.qml +++ b/containments/homescreens/folio/package/contents/ui/settings/SettingsWindow.qml @@ -14,275 +14,311 @@ import org.kde.kirigamiaddons.formcard 1.0 as FormCard import '../delegate' -Kirigami.ApplicationWindow { +Window { id: root flags: Qt.FramelessWindowHint + color: 'transparent' - pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.ToolBar - pageStack.globalToolBar.showNavigationButtons: Kirigami.ApplicationHeaderStyle.NoNavigationButtons; + onVisibleChanged: { + if (visible) { + opacityAnim.to = 1; + opacityAnim.restart(); + } + } + + onClosing: (close) => { + if (applicationItem.opacity !== 0) { + close.accepted = false; + opacityAnim.to = 0; + opacityAnim.restart(); + } + } signal requestConfigureMenu() - pageStack.initialPage: Kirigami.ScrollablePage { - id: page - opacity: root.opacity + Kirigami.ApplicationItem { + id: applicationItem + anchors.fill: parent - titleDelegate: RowLayout { - QQC2.ToolButton { - Layout.leftMargin: -Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing - icon.name: "arrow-left" - onClicked: root.close() - } + opacity: 0 - Kirigami.Heading { - level: 1 - text: page.title - } - } - - title: i18n("Homescreen Settings") - - topPadding: 0 - bottomPadding: 0 - leftPadding: 0 - rightPadding: 0 - - ColumnLayout { - FormCard.FormHeader { - title: i18n("Icons") - } - - FormCard.FormCard { - Kirigami.Theme.inherit: false - Kirigami.Theme.colorSet: Kirigami.Theme.Complementary - - Item { - Layout.preferredHeight: Folio.HomeScreenState.pageCellHeight - Layout.fillWidth: true - - AbstractDelegate { - anchors.centerIn: parent - implicitHeight: Folio.HomeScreenState.pageCellHeight - implicitWidth: Folio.HomeScreenState.pageCellWidth - name: i18n('Application') - - contentItem: DelegateAppIcon { - height: Folio.FolioSettings.delegateIconSize - width: Folio.FolioSettings.delegateIconSize - source: 'applications-system' - } - } - } - } - - FormCard.FormCard { - id: iconsCard - readonly property bool isVerticalOrientation: Folio.HomeScreenState.pageOrientation === Folio.HomeScreenState.RegularPosition || - Folio.HomeScreenState.pageOrientation === Folio.HomeScreenState.RotateUpsideDown - - readonly property string numOfRowsText: i18n("Number of rows") - readonly property string numOfColumnsText: i18n("Number of columns") - - FormCard.FormSpinBoxDelegate { - id: iconSizeSpinBox - label: i18n("Size of icons on homescreen") - from: 16 - to: 128 - value: Folio.FolioSettings.delegateIconSize - onValueChanged: { - if (value !== Folio.FolioSettings.delegateIconSize) { - Folio.FolioSettings.delegateIconSize = value; - } - } - } - - FormCard.FormSpinBoxDelegate { - id: rowsSpinBox - label: iconsCard.isVerticalOrientation ? iconsCard.numOfRowsText : iconsCard.numOfColumnsText - from: 3 - to: 10 - value: Folio.FolioSettings.homeScreenRows - onValueChanged: { - if (value !== Folio.FolioSettings.homeScreenRows) { - Folio.FolioSettings.homeScreenRows = value; - } - } - } - - FormCard.FormSpinBoxDelegate { - id: columnsSpinBox - label: iconsCard.isVerticalOrientation ? iconsCard.numOfColumnsText : iconsCard.numOfRowsText - from: 3 - to: 10 - value: Folio.FolioSettings.homeScreenColumns - onValueChanged: { - if (value !== Folio.FolioSettings.homeScreenColumns) { - Folio.FolioSettings.homeScreenColumns = value; - } - } - } - } - - FormCard.FormSectionText { - text: i18n("The rows and columns will swap depending on the screen rotation.") - } - - FormCard.FormHeader { - title: i18n("Homescreen") - } - - FormCard.FormCard { - FormCard.FormSwitchDelegate { - id: showLabelsOnHomeScreen - text: i18n("Show labels on homescreen") - checked: Folio.FolioSettings.showPagesAppLabels - onCheckedChanged: { - if (checked != Folio.FolioSettings.showPagesAppLabels) { - Folio.FolioSettings.showPagesAppLabels = checked; - } - } - } - - FormCard.FormDelegateSeparator { above: showLabelsOnHomeScreen; below: showLabelsInFavourites } - - FormCard.FormSwitchDelegate { - id: showLabelsInFavourites - text: i18n("Show labels in favorites bar") - checked: Folio.FolioSettings.showFavouritesAppLabels - onCheckedChanged: { - if (checked != Folio.FolioSettings.showFavouritesAppLabels) { - Folio.FolioSettings.showFavouritesAppLabels = checked; - } - } - } - - FormCard.FormDelegateSeparator { above: showLabelsInFavourites; below: pageTransitionCombobox } - - FormCard.FormComboBoxDelegate { - id: pageTransitionCombobox - text: i18n("Page transition effect") - - currentIndex: indexOfValue(Folio.FolioSettings.pageTransitionEffect) - model: ListModel { - // we can't use i18n with ListElement - Component.onCompleted: { - append({"name": i18n("Slide"), "value": Folio.FolioSettings.SlideTransition}); - append({"name": i18n("Cube"), "value": Folio.FolioSettings.CubeTransition}); - append({"name": i18n("Fade"), "value": Folio.FolioSettings.FadeTransition}); - append({"name": i18n("Stack"), "value": Folio.FolioSettings.StackTransition}); - append({"name": i18n("Rotation"), "value": Folio.FolioSettings.RotationTransition}); - - // indexOfValue doesn't bind to model changes unfortunately, set currentIndex manually here - pageTransitionCombobox.currentIndex = pageTransitionCombobox.indexOfValue(Folio.FolioSettings.pageTransitionEffect) - } - } - - textRole: "name" - valueRole: "value" - - onCurrentValueChanged: Folio.FolioSettings.pageTransitionEffect = currentValue - } - } - - FormCard.FormHeader { - title: i18n("Favorites Bar") - } - - FormCard.FormCard { - FormCard.FormSwitchDelegate { - text: i18n('Show background') - icon.name: 'draw-rectangle' - checked: Folio.FolioSettings.showFavouritesBarBackground - onCheckedChanged: { - if (checked !== Folio.FolioSettings.showFavouritesBarBackground) { - Folio.FolioSettings.showFavouritesBarBackground = checked; - } - } - } - } - - FormCard.FormHeader { - title: i18n("General") - } - - FormCard.FormCard { - Layout.bottomMargin: Kirigami.Units.gridUnit - FormCard.FormButtonDelegate { - id: containmentSettings - text: i18n('Switch Homescreen') - icon.name: 'settings-configure' - onClicked: root.requestConfigureMenu() - } - - FormCard.FormDelegateSeparator { above: containmentSettings; below: exportSettings } - - FormCard.FormButtonDelegate { - id: exportSettings - text: i18n('Export layout') - icon.name: 'document-export' - onClicked: exportFileDialog.open() - } - - FormCard.FormDelegateSeparator { above: exportSettings; below: importSettings } - - FormCard.FormButtonDelegate { - id: importSettings - text: i18n('Import layout') - icon.name: 'document-import' - onClicked: importFileDialog.open() + NumberAnimation on opacity { + id: opacityAnim + duration: 200 + easing.type: Easing.OutCubic + onFinished: { + if (applicationItem.opacity === 0) { + root.close(); } } } - FileDialog { - id: exportFileDialog - title: i18n("Export layout to") - fileMode: FileDialog.SaveFile - defaultSuffix: 'json' - nameFilters: ["JSON files (*.json)"] - onAccepted: { - console.log('saving layout to ' + selectedFile); - if (selectedFile) { - let status = Folio.FolioSettings.saveLayoutToFile(selectedFile); - if (status) { - exportedSuccessfullyPrompt.open(); - } else { - exportFailedPrompt.open(); + scale: 0.7 + 0.3 * applicationItem.opacity + + pageStack.globalToolBar.style: Kirigami.ApplicationHeaderStyle.ToolBar + pageStack.globalToolBar.showNavigationButtons: Kirigami.ApplicationHeaderStyle.NoNavigationButtons; + + pageStack.initialPage: Kirigami.ScrollablePage { + id: page + opacity: applicationItem.opacity + + titleDelegate: RowLayout { + QQC2.ToolButton { + Layout.leftMargin: -Kirigami.Units.gridUnit + Kirigami.Units.smallSpacing + icon.name: "arrow-left" + onClicked: root.close() + } + + Kirigami.Heading { + level: 1 + text: page.title + } + } + + title: i18n("Homescreen Settings") + + topPadding: 0 + bottomPadding: 0 + leftPadding: 0 + rightPadding: 0 + + ColumnLayout { + FormCard.FormHeader { + title: i18n("Icons") + } + + FormCard.FormCard { + Kirigami.Theme.inherit: false + Kirigami.Theme.colorSet: Kirigami.Theme.Complementary + + Item { + Layout.preferredHeight: Folio.HomeScreenState.pageCellHeight + Layout.fillWidth: true + + AbstractDelegate { + anchors.centerIn: parent + implicitHeight: Folio.HomeScreenState.pageCellHeight + implicitWidth: Folio.HomeScreenState.pageCellWidth + name: i18n('Application') + + contentItem: DelegateAppIcon { + height: Folio.FolioSettings.delegateIconSize + width: Folio.FolioSettings.delegateIconSize + source: 'applications-system' + } + } + } + } + + FormCard.FormCard { + id: iconsCard + readonly property bool isVerticalOrientation: Folio.HomeScreenState.pageOrientation === Folio.HomeScreenState.RegularPosition || + Folio.HomeScreenState.pageOrientation === Folio.HomeScreenState.RotateUpsideDown + + readonly property string numOfRowsText: i18n("Number of rows") + readonly property string numOfColumnsText: i18n("Number of columns") + + FormCard.FormSpinBoxDelegate { + id: iconSizeSpinBox + label: i18n("Size of icons on homescreen") + from: 16 + to: 128 + value: Folio.FolioSettings.delegateIconSize + onValueChanged: { + if (value !== Folio.FolioSettings.delegateIconSize) { + Folio.FolioSettings.delegateIconSize = value; + } + } + } + + FormCard.FormSpinBoxDelegate { + id: rowsSpinBox + label: iconsCard.isVerticalOrientation ? iconsCard.numOfRowsText : iconsCard.numOfColumnsText + from: 3 + to: 10 + value: Folio.FolioSettings.homeScreenRows + onValueChanged: { + if (value !== Folio.FolioSettings.homeScreenRows) { + Folio.FolioSettings.homeScreenRows = value; + } + } + } + + FormCard.FormSpinBoxDelegate { + id: columnsSpinBox + label: iconsCard.isVerticalOrientation ? iconsCard.numOfColumnsText : iconsCard.numOfRowsText + from: 3 + to: 10 + value: Folio.FolioSettings.homeScreenColumns + onValueChanged: { + if (value !== Folio.FolioSettings.homeScreenColumns) { + Folio.FolioSettings.homeScreenColumns = value; + } + } + } + } + + FormCard.FormSectionText { + text: i18n("The rows and columns will swap depending on the screen rotation.") + } + + FormCard.FormHeader { + title: i18n("Homescreen") + } + + FormCard.FormCard { + FormCard.FormSwitchDelegate { + id: showLabelsOnHomeScreen + text: i18n("Show labels on homescreen") + checked: Folio.FolioSettings.showPagesAppLabels + onCheckedChanged: { + if (checked != Folio.FolioSettings.showPagesAppLabels) { + Folio.FolioSettings.showPagesAppLabels = checked; + } + } + } + + FormCard.FormDelegateSeparator { above: showLabelsOnHomeScreen; below: showLabelsInFavourites } + + FormCard.FormSwitchDelegate { + id: showLabelsInFavourites + text: i18n("Show labels in favorites bar") + checked: Folio.FolioSettings.showFavouritesAppLabels + onCheckedChanged: { + if (checked != Folio.FolioSettings.showFavouritesAppLabels) { + Folio.FolioSettings.showFavouritesAppLabels = checked; + } + } + } + + FormCard.FormDelegateSeparator { above: showLabelsInFavourites; below: pageTransitionCombobox } + + FormCard.FormComboBoxDelegate { + id: pageTransitionCombobox + text: i18n("Page transition effect") + + currentIndex: indexOfValue(Folio.FolioSettings.pageTransitionEffect) + model: ListModel { + // we can't use i18n with ListElement + Component.onCompleted: { + append({"name": i18n("Slide"), "value": Folio.FolioSettings.SlideTransition}); + append({"name": i18n("Cube"), "value": Folio.FolioSettings.CubeTransition}); + append({"name": i18n("Fade"), "value": Folio.FolioSettings.FadeTransition}); + append({"name": i18n("Stack"), "value": Folio.FolioSettings.StackTransition}); + append({"name": i18n("Rotation"), "value": Folio.FolioSettings.RotationTransition}); + + // indexOfValue doesn't bind to model changes unfortunately, set currentIndex manually here + pageTransitionCombobox.currentIndex = pageTransitionCombobox.indexOfValue(Folio.FolioSettings.pageTransitionEffect) + } + } + + textRole: "name" + valueRole: "value" + + onCurrentValueChanged: Folio.FolioSettings.pageTransitionEffect = currentValue + } + } + + FormCard.FormHeader { + title: i18n("Favorites Bar") + } + + FormCard.FormCard { + FormCard.FormSwitchDelegate { + text: i18n('Show background') + icon.name: 'draw-rectangle' + checked: Folio.FolioSettings.showFavouritesBarBackground + onCheckedChanged: { + if (checked !== Folio.FolioSettings.showFavouritesBarBackground) { + Folio.FolioSettings.showFavouritesBarBackground = checked; + } + } + } + } + + FormCard.FormHeader { + title: i18n("General") + } + + FormCard.FormCard { + Layout.bottomMargin: Kirigami.Units.gridUnit + FormCard.FormButtonDelegate { + id: containmentSettings + text: i18n('Switch Homescreen') + icon.name: 'settings-configure' + onClicked: root.requestConfigureMenu() + } + + FormCard.FormDelegateSeparator { above: containmentSettings; below: exportSettings } + + FormCard.FormButtonDelegate { + id: exportSettings + text: i18n('Export layout') + icon.name: 'document-export' + onClicked: exportFileDialog.open() + } + + FormCard.FormDelegateSeparator { above: exportSettings; below: importSettings } + + FormCard.FormButtonDelegate { + id: importSettings + text: i18n('Import layout') + icon.name: 'document-import' + onClicked: importFileDialog.open() } } } - } - FileDialog { - id: importFileDialog - fileMode: FileDialog.OpenFile - nameFilters: ["JSON files (*.json)"] - onAccepted: { - console.log('about to load layout from ' + selectedFile); - confirmImportPrompt.open(); + FileDialog { + id: exportFileDialog + title: i18n("Export layout to") + fileMode: FileDialog.SaveFile + defaultSuffix: 'json' + nameFilters: ["JSON files (*.json)"] + onAccepted: { + console.log('saving layout to ' + selectedFile); + if (selectedFile) { + let status = Folio.FolioSettings.saveLayoutToFile(selectedFile); + if (status) { + exportedSuccessfullyPrompt.open(); + } else { + exportFailedPrompt.open(); + } + } + } } - } - Kirigami.PromptDialog { - id: exportFailedPrompt - title: i18n("Export Status") - subtitle: i18n("Failed to export to %1", String(exportFileDialog.selectedFile).substring('file://'.length)) - standardButtons: Kirigami.Dialog.Close - } + FileDialog { + id: importFileDialog + fileMode: FileDialog.OpenFile + nameFilters: ["JSON files (*.json)"] + onAccepted: { + console.log('about to load layout from ' + selectedFile); + confirmImportPrompt.open(); + } + } - Kirigami.PromptDialog { - id: exportedSuccessfullyPrompt - title: i18n("Export Status") - subtitle: i18n("Homescreen layout exported successfully to %1", String(exportFileDialog.selectedFile).substring('file://'.length)) - standardButtons: Kirigami.Dialog.Close - } + Kirigami.PromptDialog { + id: exportFailedPrompt + title: i18n("Export Status") + subtitle: i18n("Failed to export to %1", String(exportFileDialog.selectedFile).substring('file://'.length)) + standardButtons: Kirigami.Dialog.Close + } - Kirigami.PromptDialog { - id: confirmImportPrompt - title: i18n("Confirm Import") - subtitle: i18n("This will overwrite your existing homescreen layout!") - standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel - onAccepted: Folio.FolioSettings.loadLayoutFromFile(importFileDialog.selectedFile); + Kirigami.PromptDialog { + id: exportedSuccessfullyPrompt + title: i18n("Export Status") + subtitle: i18n("Homescreen layout exported successfully to %1", String(exportFileDialog.selectedFile).substring('file://'.length)) + standardButtons: Kirigami.Dialog.Close + } + + Kirigami.PromptDialog { + id: confirmImportPrompt + title: i18n("Confirm Import") + subtitle: i18n("This will overwrite your existing homescreen layout!") + standardButtons: Kirigami.Dialog.Ok | Kirigami.Dialog.Cancel + onAccepted: Folio.FolioSettings.loadLayoutFromFile(importFileDialog.selectedFile); + } } } }