diff --git a/initialstart/CMakeLists.txt b/initialstart/CMakeLists.txt index 9cfd6202..07cead8e 100644 --- a/initialstart/CMakeLists.txt +++ b/initialstart/CMakeLists.txt @@ -14,6 +14,8 @@ add_executable(plasma-mobile-initial-start utils.h initialstartutil.cpp initialstartutil.h + initialstartmodule.cpp + initialstartmodule.h ) qt_add_qml_module(plasma-mobile-initial-start diff --git a/initialstart/initialstartmodule.cpp b/initialstart/initialstartmodule.cpp new file mode 100644 index 00000000..dcaf8770 --- /dev/null +++ b/initialstart/initialstartmodule.cpp @@ -0,0 +1,42 @@ +// SPDX-FileCopyrightText: 2024 Devin Lin +// SPDX-License-Identifier: LGPL-2.0-or-later + +#include "initialstartmodule.h" + +InitialStartModule::InitialStartModule(QObject *parent) + : QObject{parent} +{ +} + +bool InitialStartModule::available() const +{ + return m_available; +} + +void InitialStartModule::setAvailable(bool available) +{ + if (m_available == available) { + return; + } + m_available = available; + Q_EMIT availableChanged(); +} + +QQuickItem *InitialStartModule::contentItem() +{ + return m_contentItem; +} + +void InitialStartModule::setContentItem(QQuickItem *contentItem) +{ + if (m_contentItem == contentItem) { + return; + } + m_contentItem = contentItem; + Q_EMIT contentItemChanged(); +} + +QQmlListProperty InitialStartModule::children() +{ + return QQmlListProperty(this, &m_children); +} diff --git a/initialstart/initialstartmodule.h b/initialstart/initialstartmodule.h new file mode 100644 index 00000000..276048e5 --- /dev/null +++ b/initialstart/initialstartmodule.h @@ -0,0 +1,40 @@ +// SPDX-FileCopyrightText: 2024 Devin Lin +// SPDX-License-Identifier: LGPL-2.0-or-later + +#pragma once + +#include "qqml.h" +#include +#include +#include + +class InitialStartModule : public QObject +{ + Q_OBJECT + QML_ELEMENT + + Q_PROPERTY(bool available READ available WRITE setAvailable NOTIFY availableChanged) + Q_PROPERTY(QQuickItem *contentItem READ contentItem WRITE setContentItem REQUIRED NOTIFY contentItemChanged) + Q_PROPERTY(QQmlListProperty children READ children CONSTANT) + Q_CLASSINFO("DefaultProperty", "children") + +public: + InitialStartModule(QObject *parent = nullptr); + + bool available() const; + void setAvailable(bool available); + + QQuickItem *contentItem(); + void setContentItem(QQuickItem *contentItem); + + QQmlListProperty children(); + +Q_SIGNALS: + void availableChanged(); + void contentItemChanged(); + +private: + bool m_available{true}; + QQuickItem *m_contentItem{nullptr}; + QList m_children; +}; diff --git a/initialstart/modules/cellular/package/contents/ui/main.qml b/initialstart/modules/cellular/package/contents/ui/main.qml index 67324ad3..1966bb35 100644 --- a/initialstart/modules/cellular/package/contents/ui/main.qml +++ b/initialstart/modules/cellular/package/contents/ui/main.qml @@ -9,129 +9,133 @@ import org.kde.kirigami as Kirigami import org.kde.kirigamiaddons.formcard 1 as FormCard import org.kde.plasma.mm as PlasmaMM -Item { - id: root - property string name: i18n("Cellular") +import org.kde.plasma.mobileinitialstart.initialstart - readonly property real cardWidth: Math.min(Kirigami.Units.gridUnit * 30, root.width - Kirigami.Units.gridUnit * 2) +InitialStartModule { + contentItem: Item { + id: root + property string name: i18n("Cellular") - function toggleMobileData() { - if (PlasmaMM.SignalIndicator.needsAPNAdded || !PlasmaMM.SignalIndicator.mobileDataSupported) { - // open settings if unable to toggle mobile data - MobileShell.ShellUtil.executeCommand("plasma-open-settings kcm_cellular_network"); - } else { - PlasmaMM.SignalIndicator.mobileDataEnabled = !PlasmaMM.SignalIndicator.mobileDataEnabled; - } - } + readonly property real cardWidth: Math.min(Kirigami.Units.gridUnit * 30, root.width - Kirigami.Units.gridUnit * 2) - EditProfileDialog { - id: profileDialog - profile: null - } - - ColumnLayout { - anchors { - fill: parent - topMargin: Kirigami.Units.gridUnit - bottomMargin: Kirigami.Units.largeSpacing - } - width: root.width - spacing: Kirigami.Units.gridUnit - - Label { - Layout.leftMargin: Kirigami.Units.gridUnit - Layout.rightMargin: Kirigami.Units.gridUnit - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - - wrapMode: Text.Wrap - horizontalAlignment: Text.AlignHCenter - text: { - if (!PlasmaMM.SignalIndicator.modemAvailable) { - return i18n("Your device does not have a modem available."); - } else if (PlasmaMM.SignalIndicator.needsAPNAdded) { - return i18n("Please configure your APN below for mobile data, further information will be available with your carrier."); - } else if (PlasmaMM.SignalIndicator.mobileDataSupported) { - return i18n("You are connected to the mobile network."); - } else if (PlasmaMM.SignalIndicator.simEmpty) { - return i18n("Please insert a SIM card into your device."); - } else { - return i18n("Your device does not have a modem available."); - } + function toggleMobileData() { + if (PlasmaMM.SignalIndicator.needsAPNAdded || !PlasmaMM.SignalIndicator.mobileDataSupported) { + // open settings if unable to toggle mobile data + MobileShell.ShellUtil.executeCommand("plasma-open-settings kcm_cellular_network"); + } else { + PlasmaMM.SignalIndicator.mobileDataEnabled = !PlasmaMM.SignalIndicator.mobileDataEnabled; } } - FormCard.FormCard { - visible: PlasmaMM.SignalIndicator.modemAvailable && PlasmaMM.SignalIndicator.mobileDataSupported - maximumWidth: root.cardWidth + EditProfileDialog { + id: profileDialog + profile: null + } - Layout.alignment: Qt.AlignTop | Qt.AlignHCenter + ColumnLayout { + anchors { + fill: parent + topMargin: Kirigami.Units.gridUnit + bottomMargin: Kirigami.Units.largeSpacing + } + width: root.width + spacing: Kirigami.Units.gridUnit - FormCard.FormSwitchDelegate { - text: i18n("Mobile Data") - checked: PlasmaMM.SignalIndicator.mobileDataEnabled - onCheckedChanged: { - if (checked !== PlasmaMM.SignalIndicator.mobileDataEnabled) { - root.toggleMobileData(); + Label { + Layout.leftMargin: Kirigami.Units.gridUnit + Layout.rightMargin: Kirigami.Units.gridUnit + Layout.alignment: Qt.AlignTop + Layout.fillWidth: true + + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + text: { + if (!PlasmaMM.SignalIndicator.modemAvailable) { + return i18n("Your device does not have a modem available."); + } else if (PlasmaMM.SignalIndicator.needsAPNAdded) { + return i18n("Please configure your APN below for mobile data, further information will be available with your carrier."); + } else if (PlasmaMM.SignalIndicator.mobileDataSupported) { + return i18n("You are connected to the mobile network."); + } else if (PlasmaMM.SignalIndicator.simEmpty) { + return i18n("Please insert a SIM card into your device."); + } else { + return i18n("Your device does not have a modem available."); } } } - } - FormCard.FormCard { - visible: PlasmaMM.SignalIndicator.modemAvailable && !PlasmaMM.SignalIndicator.simEmpty - maximumWidth: root.cardWidth + FormCard.FormCard { + visible: PlasmaMM.SignalIndicator.modemAvailable && PlasmaMM.SignalIndicator.mobileDataSupported + maximumWidth: root.cardWidth - Layout.fillHeight: true - Layout.alignment: Qt.AlignTop | Qt.AlignHCenter - - ListView { - id: listView - currentIndex: -1 - clip: true - - Layout.fillWidth: true - Layout.fillHeight: true - - model: PlasmaMM.SignalIndicator.profiles - - delegate: FormCard.FormRadioDelegate { - width: listView.width - text: modelData.name - description: modelData.apn - checked: modem.activeConnectionUni == modelData.connectionUni + Layout.alignment: Qt.AlignTop | Qt.AlignHCenter + FormCard.FormSwitchDelegate { + text: i18n("Mobile Data") + checked: PlasmaMM.SignalIndicator.mobileDataEnabled onCheckedChanged: { - if (checked) { - PlasmaMM.SignalIndicator.activateProfile(modelData.connectionUni); - checked = Qt.binding(() => { return modem.activeConnectionUni == modelData.connectionUni }); + if (checked !== PlasmaMM.SignalIndicator.mobileDataEnabled) { + root.toggleMobileData(); } } + } + } - trailing: RowLayout { - ToolButton { - icon.name: "entry-edit" - text: i18n("Edit") - onClicked: { - profileDialog.profile = modelData; - profileDialog.open(); + FormCard.FormCard { + visible: PlasmaMM.SignalIndicator.modemAvailable && !PlasmaMM.SignalIndicator.simEmpty + maximumWidth: root.cardWidth + + Layout.fillHeight: true + Layout.alignment: Qt.AlignTop | Qt.AlignHCenter + + ListView { + id: listView + currentIndex: -1 + clip: true + + Layout.fillWidth: true + Layout.fillHeight: true + + model: PlasmaMM.SignalIndicator.profiles + + delegate: FormCard.FormRadioDelegate { + width: listView.width + text: modelData.name + description: modelData.apn + checked: modem.activeConnectionUni == modelData.connectionUni + + onCheckedChanged: { + if (checked) { + PlasmaMM.SignalIndicator.activateProfile(modelData.connectionUni); + checked = Qt.binding(() => { return modem.activeConnectionUni == modelData.connectionUni }); } } - ToolButton { - icon.name: "delete" - text: i18n("Delete") - onClicked: PlasmaMM.SignalIndicator.removeProfile(modelData.connectionUni) + + trailing: RowLayout { + ToolButton { + icon.name: "entry-edit" + text: i18n("Edit") + onClicked: { + profileDialog.profile = modelData; + profileDialog.open(); + } + } + ToolButton { + icon.name: "delete" + text: i18n("Delete") + onClicked: PlasmaMM.SignalIndicator.removeProfile(modelData.connectionUni) + } } } } - } - FormCard.FormButtonDelegate { - icon.name: "list-add" - text: i18n("Add APN") - onClicked: { - profileDialog.profile = null; - profileDialog.open(); + FormCard.FormButtonDelegate { + icon.name: "list-add" + text: i18n("Add APN") + onClicked: { + profileDialog.profile = null; + profileDialog.open(); + } } } } diff --git a/initialstart/modules/finished/contents/ui/main.qml b/initialstart/modules/finished/contents/ui/main.qml index ff7d29bc..b46ee0fe 100644 --- a/initialstart/modules/finished/contents/ui/main.qml +++ b/initialstart/modules/finished/contents/ui/main.qml @@ -9,31 +9,32 @@ import org.kde.kirigami 2.20 as Kirigami import org.kde.plasma.mobileinitialstart.initialstart -Item { - id: root +InitialStartModule { + contentItem: Item { + id: root - property string name: i18n("Complete!") + property string name: i18n("Complete!") - ColumnLayout { - anchors.fill: parent - anchors.margins: Kirigami.Units.gridUnit + ColumnLayout { + anchors.fill: parent + anchors.margins: Kirigami.Units.gridUnit - Label { - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter | Qt.AlignTop - text: i18n("Your device is now ready.

Enjoy %1!", InitialStartUtil.distroName) - wrapMode: Text.Wrap - horizontalAlignment: Text.AlignHCenter - } + Label { + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter | Qt.AlignTop + text: i18n("Your device is now ready.

Enjoy %1!", InitialStartUtil.distroName) + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + } - Item { Layout.fillHeight: true } + Item { Layout.fillHeight: true } - Image { - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - fillMode: Image.PreserveAspectFit - source: "konqi-calling.png" + Image { + Layout.fillWidth: true + Layout.alignment: Qt.AlignHCenter + fillMode: Image.PreserveAspectFit + source: "konqi-calling.png" + } } } } - diff --git a/initialstart/modules/prepare/package/contents/ui/main.qml b/initialstart/modules/prepare/package/contents/ui/main.qml index 53a9d47f..8f466e66 100644 --- a/initialstart/modules/prepare/package/contents/ui/main.qml +++ b/initialstart/modules/prepare/package/contents/ui/main.qml @@ -10,132 +10,137 @@ import org.kde.kirigamiaddons.formcard 1.0 as FormCard import org.kde.plasma.mobileinitialstart.prepare 1.0 as Prepare import org.kde.plasma.private.mobileshell.screenbrightnessplugin as ScreenBrightness -Item { - id: root - property string name: i18n("Before we get started…") +import org.kde.plasma.mobileinitialstart.initialstart - readonly property real cardWidth: Math.min(Kirigami.Units.gridUnit * 30, root.width - Kirigami.Units.gridUnit * 2) +InitialStartModule { + id: module + contentItem: Item { + id: root + property string name: i18n("Before we get started…") - ScreenBrightness.ScreenBrightnessUtil { - id: screenBrightness - } + readonly property real cardWidth: Math.min(Kirigami.Units.gridUnit * 30, root.width - Kirigami.Units.gridUnit * 2) - ScrollView { - anchors { - fill: parent - topMargin: Kirigami.Units.gridUnit + ScreenBrightness.ScreenBrightnessUtil { + id: screenBrightness } - ScrollBar.horizontal.policy: ScrollBar.AlwaysOff - contentWidth: -1 - - ColumnLayout { - width: root.width - spacing: Kirigami.Units.gridUnit - - Label { - Layout.leftMargin: Kirigami.Units.gridUnit - Layout.rightMargin: Kirigami.Units.gridUnit - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - - visible: screenBrightness.brightnessAvailable - wrapMode: Text.Wrap - horizontalAlignment: Text.AlignHCenter - text: i18n("Adjust the screen brightness to be comfortable for the installation process.") + ScrollView { + anchors { + fill: parent + topMargin: Kirigami.Units.gridUnit } - FormCard.FormCard { - id: brightnessCard - visible: screenBrightness.brightnessAvailable - maximumWidth: root.cardWidth + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + contentWidth: -1 - Layout.alignment: Qt.AlignTop | Qt.AlignHCenter + ColumnLayout { + width: root.width + spacing: Kirigami.Units.gridUnit - FormCard.AbstractFormDelegate { - background: null + Label { + Layout.leftMargin: Kirigami.Units.gridUnit + Layout.rightMargin: Kirigami.Units.gridUnit + Layout.alignment: Qt.AlignTop + Layout.fillWidth: true - contentItem: RowLayout { - spacing: Kirigami.Units.gridUnit + visible: screenBrightness.brightnessAvailable + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + text: i18n("Adjust the screen brightness to be comfortable for the installation process.") + } - Kirigami.Icon { - implicitWidth: Kirigami.Units.iconSizes.smallMedium - implicitHeight: Kirigami.Units.iconSizes.smallMedium - source: "brightness-low" - } + FormCard.FormCard { + id: brightnessCard + visible: screenBrightness.brightnessAvailable + maximumWidth: root.cardWidth - Slider { - id: brightnessSlider - Layout.fillWidth: true - from: 1 - to: screenBrightness.maxBrightness - value: screenBrightness.brightness - onMoved: screenBrightness.brightness = value; + Layout.alignment: Qt.AlignTop | Qt.AlignHCenter - // HACK: for some reason, the slider initial value doesn't set without being done after the component completes loading - Timer { - interval: 0 - running: true - repeat: false - onTriggered: brightnessSlider.value = Qt.binding(() => screenBrightness.brightness) + FormCard.AbstractFormDelegate { + background: null + + contentItem: RowLayout { + spacing: Kirigami.Units.gridUnit + + Kirigami.Icon { + implicitWidth: Kirigami.Units.iconSizes.smallMedium + implicitHeight: Kirigami.Units.iconSizes.smallMedium + source: "brightness-low" + } + + Slider { + id: brightnessSlider + Layout.fillWidth: true + from: 1 + to: screenBrightness.maxBrightness + value: screenBrightness.brightness + onMoved: screenBrightness.brightness = value; + + // HACK: for some reason, the slider initial value doesn't set without being done after the component completes loading + Timer { + interval: 0 + running: true + repeat: false + onTriggered: brightnessSlider.value = Qt.binding(() => screenBrightness.brightness) + } + } + + Kirigami.Icon { + implicitWidth: Kirigami.Units.iconSizes.smallMedium + implicitHeight: Kirigami.Units.iconSizes.smallMedium + source: "brightness-high" } } - - Kirigami.Icon { - implicitWidth: Kirigami.Units.iconSizes.smallMedium - implicitHeight: Kirigami.Units.iconSizes.smallMedium - source: "brightness-high" - } } } - } - Label { - Layout.leftMargin: Kirigami.Units.gridUnit - Layout.rightMargin: Kirigami.Units.gridUnit - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true + Label { + Layout.leftMargin: Kirigami.Units.gridUnit + Layout.rightMargin: Kirigami.Units.gridUnit + Layout.alignment: Qt.AlignTop + Layout.fillWidth: true - wrapMode: Text.Wrap - horizontalAlignment: Text.AlignHCenter - text: i18n("Adjust the size of elements on the screen.") - } - - FormCard.FormCard { - id: scalingCard - maximumWidth: root.cardWidth - - Layout.alignment: Qt.AlignTop | Qt.AlignHCenter - - FormCard.FormComboBoxDelegate { - id: displayScaling - text: i18n("Display Scaling") - displayMode: FormCard.FormComboBoxDelegate.Dialog - currentIndex: Prepare.PrepareUtil.scalingOptions.indexOf(Prepare.PrepareUtil.scaling.toString() + "%"); - model: Prepare.PrepareUtil.scalingOptions - - // remove % suffix - onCurrentValueChanged: Prepare.PrepareUtil.scaling = parseInt(currentValue.substring(0, currentValue.length - 1)); + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + text: i18n("Adjust the size of elements on the screen.") } - } - FormCard.FormCard { - id: darkThemeCard - maximumWidth: root.cardWidth + FormCard.FormCard { + id: scalingCard + maximumWidth: root.cardWidth - Layout.alignment: Qt.AlignTop | Qt.AlignHCenter + Layout.alignment: Qt.AlignTop | Qt.AlignHCenter - FormCard.FormSwitchDelegate { - id: darkThemeSwitch - text: i18n("Dark Theme") - checked: Prepare.PrepareUtil.usingDarkTheme - onCheckedChanged: { - if (checked !== Prepare.PrepareUtil.usingDarkTheme) { - Prepare.PrepareUtil.usingDarkTheme = checked; + FormCard.FormComboBoxDelegate { + id: displayScaling + text: i18n("Display Scaling") + displayMode: FormCard.FormComboBoxDelegate.Dialog + currentIndex: Prepare.PrepareUtil.scalingOptions.indexOf(Prepare.PrepareUtil.scaling.toString() + "%"); + model: Prepare.PrepareUtil.scalingOptions + + // remove % suffix + onCurrentValueChanged: Prepare.PrepareUtil.scaling = parseInt(currentValue.substring(0, currentValue.length - 1)); + } + } + + FormCard.FormCard { + id: darkThemeCard + maximumWidth: root.cardWidth + + Layout.alignment: Qt.AlignTop | Qt.AlignHCenter + + FormCard.FormSwitchDelegate { + id: darkThemeSwitch + text: i18n("Dark Theme") + checked: Prepare.PrepareUtil.usingDarkTheme + onCheckedChanged: { + if (checked !== Prepare.PrepareUtil.usingDarkTheme) { + Prepare.PrepareUtil.usingDarkTheme = checked; + } } } } } } } -} +} \ No newline at end of file diff --git a/initialstart/modules/time/package/contents/ui/main.qml b/initialstart/modules/time/package/contents/ui/main.qml index c9deaec5..7a5eab52 100644 --- a/initialstart/modules/time/package/contents/ui/main.qml +++ b/initialstart/modules/time/package/contents/ui/main.qml @@ -9,93 +9,97 @@ import org.kde.kirigami 2.20 as Kirigami import org.kde.kirigamiaddons.formcard 1.0 as FormCard import org.kde.plasma.mobileinitialstart.time 1.0 as Time -Item { - id: root - property string name: i18n("Time and Date") +import org.kde.plasma.mobileinitialstart.initialstart - readonly property real cardWidth: Math.min(Kirigami.Units.gridUnit * 30, root.width - Kirigami.Units.gridUnit * 2) +InitialStartModule { + contentItem: Item { + id: root + property string name: i18n("Time and Date") - ColumnLayout { - anchors { - fill: parent - topMargin: Kirigami.Units.gridUnit - bottomMargin: Kirigami.Units.largeSpacing - } + readonly property real cardWidth: Math.min(Kirigami.Units.gridUnit * 30, root.width - Kirigami.Units.gridUnit * 2) - width: root.width - spacing: Kirigami.Units.gridUnit - - Label { - Layout.leftMargin: Kirigami.Units.gridUnit - Layout.rightMargin: Kirigami.Units.gridUnit - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - - wrapMode: Text.Wrap - horizontalAlignment: Text.AlignHCenter - text: i18n("Select your time zone and preferred time format.") - } - - FormCard.FormCard { - maximumWidth: root.cardWidth - - Layout.alignment: Qt.AlignTop | Qt.AlignHCenter - Layout.fillWidth: true - - FormCard.FormSwitchDelegate { - Layout.fillWidth: true - text: i18n("24-Hour Format") - checked: Time.TimeUtil.is24HourTime - onCheckedChanged: { - if (checked !== Time.TimeUtil.is24HourTime) { - Time.TimeUtil.is24HourTime = checked; - } - } + ColumnLayout { + anchors { + fill: parent + topMargin: Kirigami.Units.gridUnit + bottomMargin: Kirigami.Units.largeSpacing } - } - FormCard.FormCard { - maximumWidth: root.cardWidth + width: root.width + spacing: Kirigami.Units.gridUnit - Layout.fillHeight: true - Layout.alignment: Qt.AlignTop | Qt.AlignHCenter - Layout.fillWidth: true - - ListView { - id: listView - - clip: true + Label { + Layout.leftMargin: Kirigami.Units.gridUnit + Layout.rightMargin: Kirigami.Units.gridUnit + Layout.alignment: Qt.AlignTop Layout.fillWidth: true - Layout.fillHeight: true - model: Time.TimeUtil.timeZones - currentIndex: -1 // ensure focus is not on the listview - header: Control { - width: listView.width - leftPadding: Kirigami.Units.largeSpacing - rightPadding: Kirigami.Units.largeSpacing - topPadding: Kirigami.Units.largeSpacing - bottomPadding: Kirigami.Units.largeSpacing + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + text: i18n("Select your time zone and preferred time format.") + } - contentItem: Kirigami.SearchField { - id: searchField + FormCard.FormCard { + maximumWidth: root.cardWidth - onTextChanged: { - Time.TimeUtil.timeZones.filterString = text; + Layout.alignment: Qt.AlignTop | Qt.AlignHCenter + Layout.fillWidth: true + + FormCard.FormSwitchDelegate { + Layout.fillWidth: true + text: i18n("24-Hour Format") + checked: Time.TimeUtil.is24HourTime + onCheckedChanged: { + if (checked !== Time.TimeUtil.is24HourTime) { + Time.TimeUtil.is24HourTime = checked; } } } + } - delegate: FormCard.FormRadioDelegate { - required property string timeZoneId + FormCard.FormCard { + maximumWidth: root.cardWidth - width: ListView.view.width - text: timeZoneId - checked: Time.TimeUtil.currentTimeZone === timeZoneId - onCheckedChanged: { - if (checked && timeZoneId !== Time.TimeUtil.currentTimeZone) { - Time.TimeUtil.currentTimeZone = timeZoneId; - checked = Qt.binding(() => Time.TimeUtil.currentTimeZone === timeZoneId); + Layout.fillHeight: true + Layout.alignment: Qt.AlignTop | Qt.AlignHCenter + Layout.fillWidth: true + + ListView { + id: listView + + clip: true + Layout.fillWidth: true + Layout.fillHeight: true + model: Time.TimeUtil.timeZones + currentIndex: -1 // ensure focus is not on the listview + + header: Control { + width: listView.width + leftPadding: Kirigami.Units.largeSpacing + rightPadding: Kirigami.Units.largeSpacing + topPadding: Kirigami.Units.largeSpacing + bottomPadding: Kirigami.Units.largeSpacing + + contentItem: Kirigami.SearchField { + id: searchField + + onTextChanged: { + Time.TimeUtil.timeZones.filterString = text; + } + } + } + + delegate: FormCard.FormRadioDelegate { + required property string timeZoneId + + width: ListView.view.width + text: timeZoneId + checked: Time.TimeUtil.currentTimeZone === timeZoneId + onCheckedChanged: { + if (checked && timeZoneId !== Time.TimeUtil.currentTimeZone) { + Time.TimeUtil.currentTimeZone = timeZoneId; + checked = Qt.binding(() => Time.TimeUtil.currentTimeZone === timeZoneId); + } } } } @@ -103,4 +107,3 @@ Item { } } } - diff --git a/initialstart/modules/wifi/package/contents/ui/main.qml b/initialstart/modules/wifi/package/contents/ui/main.qml index 24ac4c2c..58ac89f7 100644 --- a/initialstart/modules/wifi/package/contents/ui/main.qml +++ b/initialstart/modules/wifi/package/contents/ui/main.qml @@ -11,121 +11,123 @@ import org.kde.kirigamiaddons.formcard 1.0 as FormCard import org.kde.plasma.networkmanagement as PlasmaNM import org.kde.plasma.mobileinitialstart.wifi 1.0 as WiFi -Item { - id: root - property string name: i18n("Network") +import org.kde.plasma.mobileinitialstart.initialstart - readonly property real cardWidth: Math.min(Kirigami.Units.gridUnit * 30, root.width - Kirigami.Units.gridUnit * 2) +InitialStartModule { + contentItem: Item { + id: root + property string name: i18n("Network") - PlasmaNM.Handler { - id: handler - } + readonly property real cardWidth: Math.min(Kirigami.Units.gridUnit * 30, root.width - Kirigami.Units.gridUnit * 2) - PlasmaNM.EnabledConnections { - id: enabledConnections - } - - PlasmaNM.NetworkModel { - id: connectionModel - } - - PlasmaNM.MobileProxyModel { - id: mobileProxyModel - sourceModel: connectionModel - showSavedMode: false - } - - ConnectDialog { - id: connectionDialog - } - - Component.onCompleted: handler.requestScan() - - Timer { - id: scanTimer - interval: 10200 - repeat: true - running: parent.visible - - onTriggered: handler.requestScan() - } - - ColumnLayout { - anchors { - fill: parent - topMargin: Kirigami.Units.gridUnit - bottomMargin: Kirigami.Units.largeSpacing + PlasmaNM.Handler { + id: handler } - width: root.width - spacing: Kirigami.Units.gridUnit - - Label { - Layout.leftMargin: Kirigami.Units.gridUnit - Layout.rightMargin: Kirigami.Units.gridUnit - Layout.alignment: Qt.AlignTop - Layout.fillWidth: true - - wrapMode: Text.Wrap - horizontalAlignment: Text.AlignHCenter - text: i18n("Connect to a WiFi network for network access.") + PlasmaNM.EnabledConnections { + id: enabledConnections } - FormCard.FormCard { - id: savedCard - maximumWidth: root.cardWidth - visible: enabledConnections.wirelessEnabled && count > 0 + PlasmaNM.NetworkModel { + id: connectionModel + } - // number of visible entries - property int count: 0 - function updateCount() { - count = 0; - for (let i = 0; i < connectedRepeater.count; i++) { - let item = connectedRepeater.itemAt(i); - if (item && item.shouldDisplay) { - count++; + PlasmaNM.MobileProxyModel { + id: mobileProxyModel + sourceModel: connectionModel + showSavedMode: false + } + + ConnectDialog { + id: connectionDialog + } + + Component.onCompleted: handler.requestScan() + + Timer { + id: scanTimer + interval: 10200 + repeat: true + running: parent.visible + + onTriggered: handler.requestScan() + } + + ColumnLayout { + anchors { + fill: parent + topMargin: Kirigami.Units.gridUnit + bottomMargin: Kirigami.Units.largeSpacing + } + + width: root.width + spacing: Kirigami.Units.gridUnit + + Label { + Layout.leftMargin: Kirigami.Units.gridUnit + Layout.rightMargin: Kirigami.Units.gridUnit + Layout.alignment: Qt.AlignTop + Layout.fillWidth: true + + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + text: i18n("Connect to a WiFi network for network access.") + } + + FormCard.FormCard { + id: savedCard + maximumWidth: root.cardWidth + visible: enabledConnections.wirelessEnabled && count > 0 + + // number of visible entries + property int count: 0 + function updateCount() { + count = 0; + for (let i = 0; i < connectedRepeater.count; i++) { + let item = connectedRepeater.itemAt(i); + if (item && item.shouldDisplay) { + count++; + } + } + } + + Repeater { + id: connectedRepeater + model: mobileProxyModel + delegate: ConnectionItemDelegate { + editMode: false + + // connected or saved + property bool shouldDisplay: (Uuid != "") || ConnectionState === PlasmaNM.Enums.Activated + onShouldDisplayChanged: savedCard.updateCount() + + // separate property for visible since visible is false when the whole card is not visible + visible: (Uuid != "") || ConnectionState === PlasmaNM.Enums.Activated } } } - Repeater { - id: connectedRepeater - model: mobileProxyModel - delegate: ConnectionItemDelegate { - editMode: false - - // connected or saved - property bool shouldDisplay: (Uuid != "") || ConnectionState === PlasmaNM.Enums.Activated - onShouldDisplayChanged: savedCard.updateCount() - - // separate property for visible since visible is false when the whole card is not visible - visible: (Uuid != "") || ConnectionState === PlasmaNM.Enums.Activated - } - } - } - - FormCard.FormCard { - Layout.fillHeight: true - maximumWidth: root.cardWidth - visible: enabledConnections.wirelessEnabled - - ListView { - id: listView - - clip: true - Layout.fillWidth: true + FormCard.FormCard { Layout.fillHeight: true - model: mobileProxyModel + maximumWidth: root.cardWidth + visible: enabledConnections.wirelessEnabled - delegate: ConnectionItemDelegate { - width: ListView.view.width - editMode: false - height: visible ? implicitHeight : 0 - visible: !((Uuid != "") || ConnectionState === PlasmaNM.Enums.Activated) + ListView { + id: listView + + clip: true + Layout.fillWidth: true + Layout.fillHeight: true + model: mobileProxyModel + + delegate: ConnectionItemDelegate { + width: ListView.view.width + editMode: false + height: visible ? implicitHeight : 0 + visible: !((Uuid != "") || ConnectionState === PlasmaNM.Enums.Activated) + } } } } } -} - - +} \ No newline at end of file diff --git a/initialstart/qml/Wizard.qml b/initialstart/qml/Wizard.qml index d463d1a3..25549a14 100644 --- a/initialstart/qml/Wizard.qml +++ b/initialstart/qml/Wizard.qml @@ -19,7 +19,7 @@ Kirigami.Page { bottomPadding: 0 property int currentIndex: 0 - property int stepCount: 0 + readonly property int stepCount: InitialStart.Wizard.stepsCount property bool showingLanding: true // filled by items @@ -63,6 +63,11 @@ Kirigami.Page { } } + onStepCountChanged: { + // reset position + requestPreviousPage(); + } + function finishFinalPage() { // the app exits InitialStart.Wizard.wizardFinished(); @@ -207,7 +212,7 @@ Kirigami.Page { delegate: MobileShell.BaseItem { id: item visible: model.index === 0 // the binding is broken later - contentItem: modelData + contentItem: modelData.contentItem transform: Translate { x: { if (item.currentIndex === root.currentIndex - 1) { @@ -238,7 +243,6 @@ Kirigami.Page { } Component.onCompleted: { - root.stepCount++ updateRootItems(); } diff --git a/initialstart/wizard.cpp b/initialstart/wizard.cpp index da88bf40..f11f0e04 100644 --- a/initialstart/wizard.cpp +++ b/initialstart/wizard.cpp @@ -50,12 +50,12 @@ void Wizard::load() QQmlComponent *c = new QQmlComponent(m_engine, this); // load initialstart QML items - for (auto &pair : m_modulePackages) { + for (const auto &[pluginMetadata, package] : m_modulePackages) { // load QML from kpackage - c->loadUrl(pair.second.fileUrl("mainscript"), QQmlComponent::PreferSynchronous); + c->loadUrl(package.fileUrl("mainscript"), QQmlComponent::PreferSynchronous); auto created = c->create(m_engine->rootContext()); - auto createdItem = qobject_cast(created); + InitialStartModule *createdItem = qobject_cast(created); // print errors if there were issues loading if (!createdItem) { @@ -67,12 +67,16 @@ void Wizard::load() continue; } + connect(createdItem, &InitialStartModule::availableChanged, this, &Wizard::determineAvailableModuleItems); m_moduleItems.push_back(createdItem); - qCDebug(LOGGING_CATEGORY) << "Loaded initialstart module" << pair.first->pluginId(); + qCDebug(LOGGING_CATEGORY) << "Loaded initialstart module" << pluginMetadata->pluginId(); } delete c; + + // Populate model + determineAvailableModuleItems(); } void Wizard::setTestingMode(bool testingMode) @@ -88,9 +92,14 @@ bool Wizard::testingMode() return m_testingMode; } -QList Wizard::steps() +QList Wizard::steps() { - return m_moduleItems; + return m_availableModuleItems; +} + +int Wizard::stepsCount() +{ + return m_availableModuleItems.size(); } void Wizard::wizardFinished() @@ -98,3 +107,15 @@ void Wizard::wizardFinished() Settings::self()->setWizardFinished(); QCoreApplication::quit(); } + +void Wizard::determineAvailableModuleItems() +{ + m_availableModuleItems.clear(); + for (auto *moduleItem : m_moduleItems) { + if (moduleItem->available()) { + m_availableModuleItems.push_back(moduleItem); + } + } + + Q_EMIT stepsChanged(); +} diff --git a/initialstart/wizard.h b/initialstart/wizard.h index b984039e..5b61c3b6 100644 --- a/initialstart/wizard.h +++ b/initialstart/wizard.h @@ -10,10 +10,13 @@ #include #include +#include "initialstartmodule.h" + class Wizard : public QObject { Q_OBJECT - Q_PROPERTY(QList steps READ steps CONSTANT) + Q_PROPERTY(QList steps READ steps NOTIFY stepsChanged) + Q_PROPERTY(int stepsCount READ stepsCount NOTIFY stepsChanged) Q_PROPERTY(bool testingMode READ testingMode NOTIFY testingModeChanged) public: @@ -24,17 +27,23 @@ public: void setTestingMode(bool testingMode); bool testingMode(); - QList steps(); + QList steps(); + int stepsCount(); public Q_SLOTS: void wizardFinished(); Q_SIGNALS: + void stepsChanged(); void testingModeChanged(); +private Q_SLOTS: + void determineAvailableModuleItems(); + private: QList> m_modulePackages; - QList m_moduleItems; + QList m_availableModuleItems; + QList m_moduleItems; bool m_testingMode; QQmlEngine *m_engine;