diff --git a/src/modules/finishedq/CMakeLists.txt b/src/modules/finishedq/CMakeLists.txt index fd9edd9f2..278feb5cf 100644 --- a/src/modules/finishedq/CMakeLists.txt +++ b/src/modules/finishedq/CMakeLists.txt @@ -24,7 +24,7 @@ calamares_add_plugin(finishedq FinishedQmlViewStep.cpp ${_finished}/Config.cpp RESOURCES - finishedq.qrc + finishedq${QT_VERSION_SUFFIX}.qrc LINK_PRIVATE_LIBRARIES ${qtname}::DBus SHARED_LIB diff --git a/src/modules/finishedq/finishedq-qt6.qml b/src/modules/finishedq/finishedq-qt6.qml new file mode 100644 index 000000000..bbd5428e7 --- /dev/null +++ b/src/modules/finishedq/finishedq-qt6.qml @@ -0,0 +1,98 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 - 2023 Anke Boersma + * SPDX-License-Identifier: GPL-3.0-or-later + * License-Filename: LICENSE + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +import io.calamares.core 1.0 +import io.calamares.ui 1.0 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import org.kde.kirigami as Kirigami +import QtQuick.Window + +Page { + + id: finished + + width: parent.width + height: parent.height + + header: Kirigami.Heading { + width: parent.width + height: 100 + id: header + Layout.fillWidth: true + horizontalAlignment: Qt.AlignHCenter + color: Kirigami.Theme.textColor + level: 1 + text: qsTr("Installation Completed") + + Text { + anchors.top: header.bottom + anchors.horizontalCenter: parent.horizontalCenter + horizontalAlignment: Text.AlignHCenter + font.pointSize: 12 + text: qsTr("%1 has been installed on your computer.
+ You may now restart into your new system, or continue using the Live environment.").arg(Branding.string(Branding.ProductName)) + } + + Image { + source: "seedling.svg" + anchors.top: header.bottom + anchors.topMargin: 80 + anchors.horizontalCenter: parent.horizontalCenter + width: 64 + height: 64 + mipmap: true + } + } + + RowLayout { + Layout.alignment: Qt.AlignRight|Qt.AlignVCenter + anchors.centerIn: parent + spacing: 6 + + Button { + id: button + text: qsTr("Close Installer") + icon.name: "application-exit" + onClicked: { ViewManager.quit(); } + } + + Button { + text: qsTr("Restart System") + icon.name: "system-reboot" + onClicked: { config.doRestart(true); } + } + } + + Item { + + Layout.fillHeight: true + Layout.fillWidth: true + anchors.bottom: parent.bottom + anchors.bottomMargin : 100 + anchors.horizontalCenter: parent.horizontalCenter + + Text { + anchors.centerIn: parent + anchors.top: parent.top + horizontalAlignment: Text.AlignHCenter + text: qsTr("

A full log of the install is available as installation.log in the home directory of the Live user.
+ This log is copied to /var/log/installation.log of the target system.

") + } + } + + function onActivate() { + } + + function onLeave() { + } +} diff --git a/src/modules/finishedq/finishedq-qt6.qrc b/src/modules/finishedq/finishedq-qt6.qrc new file mode 100644 index 000000000..c0daf36ff --- /dev/null +++ b/src/modules/finishedq/finishedq-qt6.qrc @@ -0,0 +1,6 @@ + + + finishedq-qt6.qml + seedling.svg + + diff --git a/src/modules/keyboardq/CMakeLists.txt b/src/modules/keyboardq/CMakeLists.txt index dcf87a2c6..e14a59e8a 100644 --- a/src/modules/keyboardq/CMakeLists.txt +++ b/src/modules/keyboardq/CMakeLists.txt @@ -22,7 +22,7 @@ calamares_add_plugin(keyboardq ${_keyboard}/SetKeyboardLayoutJob.cpp ${_keyboard}/keyboardwidget/keyboardglobal.cpp RESOURCES - keyboardq.qrc + keyboardq${QT_VERSION_SUFFIX}.qrc SHARED_LIB LINK_LIBRARIES ${qtname}::DBus diff --git a/src/modules/keyboardq/data/Key-qt6.qml b/src/modules/keyboardq/data/Key-qt6.qml new file mode 100644 index 000000000..990f453f2 --- /dev/null +++ b/src/modules/keyboardq/data/Key-qt6.qml @@ -0,0 +1,180 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 - 2023 Anke Boersma + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +import QtQuick + +Item { + id: key + + property string mainLabel: "A" + property var secondaryLabels: []; + + property var iconSource; + + property var keyImageLeft: "" + property var keyImageRight: "" + property var keyImageCenter: "" + + property color keyColor: "#404040" + property color keyPressedColor: "grey" + property int keyBounds: 2 + property var keyPressedColorOpacity: 1 + + property var mainFontFamily: "Roboto" + property color mainFontColor: "white" + property int mainFontSize: 18 + + property var secondaryFontFamily: "Roboto" + property color secondaryFontColor: "white" + property int secondaryFontSize: 10 + + property bool secondaryLabelVisible: true + + property bool isChekable; + property bool isChecked; + + property bool upperCase; + + signal clicked() + signal alternatesClicked(string symbol) + + Item { + anchors.fill: parent + anchors.margins: key.keyBounds + visible: key.keyImageLeft != "" || key.keyImageCenter != "" || key.keyImageRight != "" ? 1 : 0 + Image { + id: backgroundImage_left + anchors.left: parent.left + height: parent.height + fillMode: Image.PreserveAspectFit + source: key.keyImageLeft + } + Image { + id: backgroundImage_right + anchors.right: parent.right + height: parent.height + fillMode: Image.PreserveAspectFit + source: key.keyImageRight + } + Image { + id: backgroundImage_center + anchors.fill: parent + anchors.leftMargin: backgroundImage_left.width - 1 + anchors.rightMargin: backgroundImage_right.width - 1 + height: parent.height + fillMode: Image.Stretch + source: key.keyImageCenter + } + } + + Rectangle { + id: backgroundItem + anchors.fill: parent + anchors.margins: key.keyBounds + color: key.isChecked || mouseArea.pressed ? key.keyPressedColor : key.keyColor; + opacity: key.keyPressedColorOpacity + } + + Column + { + anchors.centerIn: backgroundItem + + Text { + id: secondaryLabelsItem + smooth: true + anchors.right: parent.right + visible: true //secondaryLabelVisible + text: secondaryLabels.length > 0 ? secondaryLabels : "" + color: secondaryFontColor + + font.pixelSize: secondaryFontSize + font.weight: Font.Light + font.family: secondaryFontFamily + font.capitalization: upperCase ? Font.AllUppercase : + Font.MixedCase + } + + Row { + anchors.horizontalCenter: parent.horizontalCenter + + Image { + id: icon + smooth: true + anchors.verticalCenter: parent.verticalCenter + source: iconSource + //sourceSize.width: key.width * 0.6 + sourceSize.height: key.height * 0.4 + } + + Text { + id: mainLabelItem + smooth: true + anchors.verticalCenter: parent.verticalCenter + text: mainLabel + color: mainFontColor + visible: iconSource ? false : true + + font.pixelSize: mainFontSize + font.weight: Font.Light + font.family: mainFontFamily + font.capitalization: upperCase ? Font.AllUppercase : + Font.MixedCase + } + } + } + + Row { + id: alternatesRow + property int selectedIndex: -1 + visible: false + anchors.bottom: backgroundItem.top + anchors.left: backgroundItem.left + + Repeater { + model: secondaryLabels.length + + Rectangle { + property bool isSelected: alternatesRow.selectedIndex === index + color: isSelected ? mainLabelItem.color : key.keyPressedColor + height: backgroundItem.height + width: backgroundItem.width + + Text { + anchors.centerIn: parent + text: secondaryLabels[ index ] + font: mainLabelItem.font + color: isSelected ? key.keyPressedColor : mainLabelItem.color + } + } + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + onPressAndHold: alternatesRow.visible = true + onClicked: { + if (key.isChekable) key.isChecked = !key.isChecked + key.clicked() + } + + onReleased: { + alternatesRow.visible = false + if (alternatesRow.selectedIndex > -1) + key.alternatesClicked(secondaryLabels[alternatesRow.selectedIndex]) + } + + onMouseXChanged: { + alternatesRow.selectedIndex = + (mouseY < 0 && mouseX > 0 && mouseY < alternatesRow.width) ? + Math.floor(mouseX / backgroundItem.width) : + -1; + } + } +} diff --git a/src/modules/keyboardq/data/Keyboard-qt6.qml b/src/modules/keyboardq/data/Keyboard-qt6.qml new file mode 100644 index 000000000..01c5ae94b --- /dev/null +++ b/src/modules/keyboardq/data/Keyboard-qt6.qml @@ -0,0 +1,224 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 - 2023 Anke Boersma + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +import QtQuick +import QtQml.XmlListModel + +Item { + id: keyboard + + width: 1024 + height: 640 + + property int rows: 4; + property int columns: 10; + + property string source: "generic.xml" + property var target; + + property color backgroundColor: "black" + + property var keyImageLeft: "" + property var keyImageRight: "" + property var keyImageCenter: "" + + property color keyColor: "#404040" + property color keyPressedColor: "grey" + property int keyBounds: 2 + property var keyPressedColorOpacity: 1 + + property var mainFontFamily: "Roboto" + property color mainFontColor: "white" + property int mainFontSize: 59 + + property var secondaryFontFamily: "Roboto" + property color secondaryFontColor: "white" + property int secondaryFontSize: 30 + + property bool secondaryLabelsVisible: false + property bool doSwitchSource: true + + property bool allUpperCase: false + + signal keyClicked(string key) + signal switchSource(string source) + signal enterClicked() + + Rectangle { + id: root + anchors.fill: parent + color: backgroundColor + + property int keyWidth: keyboard.width / columns; + property int keyHeight: keyboard.height / rows; + + property int xmlIndex: 1 + + Text { + id: proxyMainTextItem + color: keyboard.mainFontColor + font.pixelSize: keyboard.mainFontSize + font.weight: Font.Light + font.family: keyboard.mainFontFamily + font.capitalization: keyboard.allUpperCase ? Font.AllUppercase : + Font.MixedCase + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + + Text { + id: proxySecondaryTextItem + color: keyboard.secondaryFontColor + font.pixelSize: keyboard.secondaryFontSize + font.weight: Font.Light + font.family: keyboard.secondaryFontFamily + font.capitalization: keyboard.allUpperCase ? Font.AllUppercase : + Font.MixedCase + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + + Column { + id: column + anchors.centerIn: parent + + Repeater { + id: rowRepeater + + model: 4 + //model: XmlListModel { + // id: keyboardModel + // source: keyboard.source + // query: "/Keyboard/Row" + + //Behavior on source { + // NumberAnimation { + // easing.type: Easing.InOutSine + // duration: 100 + // } + //} + //} + + Row { + id: keyRow + property int rowIndex: index + anchors.horizontalCenter: if(parent) parent.horizontalCenter + + Repeater { + id: keyRepeater + + model: XmlListModel { + source: keyboard.source + query: "/Keyboard/Row" + keyRow.rowIndex + "/Key" + + XmlListModelRole { name: "labels"; attributeName: "labels"; elementName: "" } + XmlListModelRole { name: "ratio"; attributeName: "ratio"; elementName: "" } + XmlListModelRole { name: "icon"; attributeName: "icon"; elementName: "" } + XmlListModelRole { name: "checkable"; attributeName: "checkable"; elementName: "" } + } + + Key { + id: key + width: root.keyWidth * ratio + height: root.keyHeight + iconSource: icon + mainFontFamily: proxyMainTextItem.font + mainFontColor: proxyMainTextItem.color + secondaryFontFamily: proxySecondaryTextItem.font + secondaryFontColor: proxySecondaryTextItem.color + secondaryLabelVisible: keyboard.secondaryLabelsVisible + keyColor: keyboard.keyColor + keyImageLeft: keyboard.keyImageLeft + keyImageRight: keyboard.keyImageRight + keyImageCenter: keyboard.keyImageCenter + keyPressedColor: keyboard.keyPressedColor + keyPressedColorOpacity: keyboard.keyPressedColorOpacity + keyBounds: keyboard.keyBounds + isChekable: checkable + isChecked: isChekable && + command && + command === "shift" && + keyboard.allUpperCase + upperCase: keyboard.allUpperCase + + property var command + property var params: labels + + onParamsChanged: { + var labelSplit; + + if(params[0] === '|') + { + mainLabel = '|' + labelSplit = params + } + else + { + labelSplit = params.split(/[|]+/) + + if (labelSplit[0] === '!') + mainLabel = '!'; + else + mainLabel = params.split(/[!|]+/)[0].toString(); + } + + if (labelSplit[1]) secondaryLabels = labelSplit[1]; + + if (labelSplit[0] === '!') + command = params.split(/[!|]+/)[1]; + else + command = params.split(/[!]+/)[1]; + } + + onClicked: { + if (command) + { + var commandList = command.split(":"); + + switch(commandList[0]) + { + case "source": + keyboard.switchSource(commandList[1]) + if(doSwitchSource) keyboard.source = commandList[1] + return; + case "shift": + keyboard.allUpperCase = !keyboard.allUpperCase + return; + case "backspace": + keyboard.keyClicked('\b'); + target.text = target.text.substring(0,target.text.length-1) + return; + case "enter": + keyboard.enterClicked() + return; + case "tab": + keyboard.keyClicked('\t'); + target.text = target.text + " " + return; + default: return; + } + } + if (mainLabel.length === 1) + root.emitKeyClicked(mainLabel); + } + onAlternatesClicked: root.emitKeyClicked(symbol); + } + } + } + } + } + + function emitKeyClicked(text) { + var emitText = keyboard.allUpperCase ? text.toUpperCase() : text; + keyClicked( emitText ); + target.text = target.text + emitText + } + } +} + diff --git a/src/modules/keyboardq/data/afgani-qt6.xml b/src/modules/keyboardq/data/afgani-qt6.xml new file mode 100644 index 000000000..1715a5040 --- /dev/null +++ b/src/modules/keyboardq/data/afgani-qt6.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/keyboardq/data/ar-qt6.xml b/src/modules/keyboardq/data/ar-qt6.xml new file mode 100644 index 000000000..9cce97297 --- /dev/null +++ b/src/modules/keyboardq/data/ar-qt6.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/keyboardq/data/de-qt6.xml b/src/modules/keyboardq/data/de-qt6.xml new file mode 100644 index 000000000..16e6bc592 --- /dev/null +++ b/src/modules/keyboardq/data/de-qt6.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/keyboardq/data/empty-qt6.xml b/src/modules/keyboardq/data/empty-qt6.xml new file mode 100644 index 000000000..94f9a1f4e --- /dev/null +++ b/src/modules/keyboardq/data/empty-qt6.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/keyboardq/data/en-qt6.xml b/src/modules/keyboardq/data/en-qt6.xml new file mode 100644 index 000000000..70d7454ba --- /dev/null +++ b/src/modules/keyboardq/data/en-qt6.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/keyboardq/data/es-qt6.xml b/src/modules/keyboardq/data/es-qt6.xml new file mode 100644 index 000000000..bc627d88e --- /dev/null +++ b/src/modules/keyboardq/data/es-qt6.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/keyboardq/data/fr-qt6.xml b/src/modules/keyboardq/data/fr-qt6.xml new file mode 100644 index 000000000..27ad5a740 --- /dev/null +++ b/src/modules/keyboardq/data/fr-qt6.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/keyboardq/data/generic-qt6.xml b/src/modules/keyboardq/data/generic-qt6.xml new file mode 100644 index 000000000..bcf35bbd8 --- /dev/null +++ b/src/modules/keyboardq/data/generic-qt6.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/keyboardq/data/generic_qz-qt6.xml b/src/modules/keyboardq/data/generic_qz-qt6.xml new file mode 100644 index 000000000..a5e4f5b61 --- /dev/null +++ b/src/modules/keyboardq/data/generic_qz-qt6.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/keyboardq/data/pt-qt6.xml b/src/modules/keyboardq/data/pt-qt6.xml new file mode 100644 index 000000000..a7e970d4b --- /dev/null +++ b/src/modules/keyboardq/data/pt-qt6.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/keyboardq/data/ru-qt6.xml b/src/modules/keyboardq/data/ru-qt6.xml new file mode 100644 index 000000000..472c2198c --- /dev/null +++ b/src/modules/keyboardq/data/ru-qt6.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/modules/keyboardq/keyboardq-qt6.qml b/src/modules/keyboardq/keyboardq-qt6.qml new file mode 100644 index 000000000..a969140e9 --- /dev/null +++ b/src/modules/keyboardq/keyboardq-qt6.qml @@ -0,0 +1,356 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2020 - 2023 Anke Boersma + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +import io.calamares.core 1.0 +import io.calamares.ui 1.0 + +import QtQuick +import QtQuick.Controls +import QtQuick.Window +import QtQuick.Layouts + +import org.kde.kirigami as Kirigami +import "data" + +Item { + width: 800 //parent.width + height: 600 + + readonly property color backgroundColor: "#E6E9EA" //Kirigami.Theme.backgroundColor + readonly property color listBackgroundColor: "white" + readonly property color textFieldColor: "#121212" + readonly property color textFieldBackgroundColor: "#F8F8F8" + readonly property color textColor: Kirigami.Theme.textColor + readonly property color highlightedTextColor: Kirigami.Theme.highlightedTextColor + readonly property color highlightColor: Kirigami.Theme.highlightColor + + property var langXml: ["de", "en", "es", "fr", "ru",] + property var arXml: ["Arabic"] + property var ruXml: ["Azerba", "Belaru", "Kazakh", "Kyrgyz", "Mongol", + "Russia", "Tajik", "Ukrain"] + property var frXml: ["Bambar", "Belgia","French", "Wolof"] + property var enXml: ["Bikol", "Chines", "Englis", "Irish", "Lithua", "Maori"] + property var esXml: ["Spanis"] + property var deXml: ["German"] + property var ptXml: ["Portug"] + property var scanXml: ["Danish", "Finnis", "Norweg", "Swedis"] + property var afganiXml: ["Afghan"] + property var genericXml: ["Armeni", "Bulgar", "Dutch", "Estoni", "Icelan", + "Indone", "Italia", "Latvia", "Maltes", "Moldav", "Romani", "Swahil", "Turkis"] + property var genericQzXml: ["Albani", "Bosnia", "Croati", "Czech", "Hungar", + "Luxemb", "Monten", "Polish", "Serbia", "Sloven", "Slovak"] + property var genericAzXml: [] + + property var keyIndex: [] + + Rectangle { + id: backgroundItem + anchors.fill: parent + width: 800 + color: backgroundColor + + Label { + id: header + anchors.horizontalCenter: parent.horizontalCenter + text: qsTr("To activate keyboard preview, select a layout.") + color: textColor + font.bold: true + } + + Drawer { + id: drawer + width: 0.4 * backgroundItem.width + height: backgroundItem.height + edge: Qt.RightEdge + + ScrollView { + id: scroll1 + anchors.fill: parent + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + + ListView { + id: models + focus: true + clip: true + boundsBehavior: Flickable.StopAtBounds + width: parent.width + + model: config.keyboardModelsModel + Component.onCompleted: positionViewAtIndex(model.currentIndex, ListView.Center) + currentIndex: model.currentIndex + delegate: ItemDelegate { + + property variant currentModel: model + hoverEnabled: true + width: 0.4 * backgroundItem.width + implicitHeight: 24 + highlighted: ListView.isCurrentItem + Label { + Layout.fillHeight: true + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + width: parent.width + height: 24 + color: highlighted ? "#eff0f1" : "#1F1F1F" + text: model.label + background: Rectangle { + + color: highlighted || hovered ? "#3498DB" : "#ffffff" + opacity: highlighted || hovered ? 0.5 : 0.9 + } + + MouseArea { + hoverEnabled: true + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + models.currentIndex = index + drawer.close() + } + } + } + } + onCurrentItemChanged: { config.keyboardModels = model[currentIndex] } /* This works because model is a stringlist */ + } + } + } + + Rectangle { + id: modelLabel + anchors.top: header.bottom + anchors.topMargin: 10 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width / 1.5 + height: 36 + color: mouseBar.containsMouse ? "#eff0f1" : "transparent"; + + MouseArea { + id: mouseBar + anchors.fill: parent; + cursorShape: Qt.PointingHandCursor + hoverEnabled: true + + onClicked: { + drawer.open() + } + Text { + anchors.centerIn: parent + text: qsTr("Keyboard Model:  ") + models.currentItem.currentModel.label + color: textColor + } + Image { + source: "data/pan-end-symbolic.svg" + anchors.centerIn: parent + anchors.horizontalCenterOffset : parent.width / 2.5 + fillMode: Image.PreserveAspectFit + height: 22 + } + } + } + + RowLayout { + id: stack + anchors.top: modelLabel.bottom + anchors.topMargin: 10 + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width / 1.1 + spacing: 10 + + ListView { + id: layouts + + ScrollBar.vertical: ScrollBar { + active: true + } + + Layout.preferredWidth: parent.width / 2 + height: 220 + focus: true + clip: true + boundsBehavior: Flickable.StopAtBounds + spacing: 2 + headerPositioning: ListView.OverlayHeader + header: Rectangle{ + height: 24 + width: parent.width + z: 2 + color:backgroundColor + Text { + text: qsTr("Layout") + anchors.centerIn: parent + color: textColor + font.bold: true + } + } + + Rectangle { + z: parent.z - 1 + anchors.fill: parent + color: listBackgroundColor + opacity: 0.7 + } + + model: config.keyboardLayoutsModel + currentIndex: model.currentIndex + Component.onCompleted: positionViewAtIndex(model.currentIndex, ListView.Center) + delegate: ItemDelegate { + + hoverEnabled: true + width: parent.width + implicitHeight: 24 + highlighted: ListView.isCurrentItem + + RowLayout { + anchors.fill: parent + + Label { + id: label1 + text: model.label + horizontalAlignment: Text.AlignHCenter + Layout.fillHeight: true + Layout.fillWidth: true + width: parent.width + height: 24 + color: highlighted ? highlightedTextColor : textColor + + background: Rectangle { + color: highlighted || hovered ? highlightColor : listBackgroundColor + opacity: highlighted || hovered ? 0.5 : 0.3 + } + } + } + + onClicked: { + + layouts.model.currentIndex = index + keyIndex = label1.text.substring(0,6) + layouts.positionViewAtIndex(index, ListView.Center) + } + } + } + + ListView { + id: variants + + ScrollBar.vertical: ScrollBar { + active: true + } + + Layout.preferredWidth: parent.width / 2 + height: 220 + focus: true + clip: true + boundsBehavior: Flickable.StopAtBounds + spacing: 2 + headerPositioning: ListView.OverlayHeader + header: Rectangle{ + height: 24 + width: parent.width + z: 2 + color:backgroundColor + Text { + text: qsTr("Variant") + anchors.centerIn: parent + color: textColor + font.bold: true + } + } + + Rectangle { + z: parent.z - 1 + anchors.fill: parent + color: listBackgroundColor + opacity: 0.7 + } + + model: config.keyboardVariantsModel + currentIndex: model.currentIndex + Component.onCompleted: positionViewAtIndex(model.currentIndex, ListView.Center) + + delegate: ItemDelegate { + hoverEnabled: true + width: parent.width + implicitHeight: 24 + highlighted: ListView.isCurrentItem + + RowLayout { + anchors.fill: parent + + Label { + text: model.label + horizontalAlignment: Text.AlignHCenter + Layout.fillHeight: true + Layout.fillWidth: true + width: parent.width + height: 24 + color: highlighted ? highlightedTextColor : textColor + + background: Rectangle { + color: highlighted || hovered ? highlightColor : listBackgroundColor + opacity: highlighted || hovered ? 0.5 : 0.3 + } + } + } + + onClicked: { + variants.model.currentIndex = index + variants.positionViewAtIndex(index, ListView.Center) + } + } + } + } + + TextField { + id: textInput + placeholderText: qsTr("Type here to test your keyboard") + height: 36 + width: parent.width / 1.6 + horizontalAlignment: TextInput.AlignHCenter + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: keyboard.top + anchors.bottomMargin: parent.height / 25 + color: textFieldColor + + background:Rectangle { + z: parent.z - 1 + anchors.fill: parent + color: textFieldBackgroundColor + radius: 2 + } + } + + Keyboard { + id: keyboard + width: parent.width + height: parent.height / 3 + anchors.bottom: parent.bottom + source: langXml.includes(keyIndex) ? (keyIndex + ".xml") : + afganiXml.includes(keyIndex) ? "afgani.xml" : + scanXml.includes(keyIndex) ? "scan.xml" : + genericXml.includes(keyIndex) ? "generic.xml" : + genericQzXml.includes(keyIndex) ? "generic_qz.xml" : + arXml.includes(keyIndex) ? "ar.xml" : + deXml.includes(keyIndex) ? "de.xml" : + enXml.includes(keyIndex) ? "en.xml" : + esXml.includes(keyIndex) ? "es.xml" : + frXml.includes(keyIndex) ? "fr.xml" : + ptXml.includes(keyIndex) ? "pt.xml" : + ruXml.includes(keyIndex) ? "ru.xml" :"empty.xml" + rows: 4 + columns: 10 + keyColor: "transparent" + keyPressedColorOpacity: 0.2 + keyImageLeft: "button_bkg_left.png" + keyImageRight: "button_bkg_right.png" + keyImageCenter: "button_bkg_center.png" + target: textInput + onEnterClicked: console.log("Enter!") + } + } +} diff --git a/src/modules/keyboardq/keyboardq-qt6.qrc b/src/modules/keyboardq/keyboardq-qt6.qrc new file mode 100644 index 000000000..c90b24bdc --- /dev/null +++ b/src/modules/keyboardq/keyboardq-qt6.qrc @@ -0,0 +1,29 @@ + + + ../keyboard/kbd-model-map + ../keyboard/images/restore.png + ../keyboard/non-ascii-layouts + keyboardq-qt6.qml + data/Keyboard-qt6.qml + data/Key-qt6.qml + data/backspace.svg + data/enter.svg + data/shift.svg + data/afgani-qt6.xml + data/ar-qt6.xml + data/de-qt6.xml + data/en-qt6.xml + data/empty-qt6.xml + data/es-qt6.xml + data/fr-qt6.xml + data/generic_qz-qt6.xml + data/generic-qt6.xml + data/pt-qt6.xml + data/ru-qt6.xml + data/scan.xml + data/button_bkg_center.png + data/button_bkg_left.png + data/button_bkg_right.png + data/pan-end-symbolic.svg + + diff --git a/src/modules/localeq/CMakeLists.txt b/src/modules/localeq/CMakeLists.txt index 1ac8fc9cb..0eace3e2d 100644 --- a/src/modules/localeq/CMakeLists.txt +++ b/src/modules/localeq/CMakeLists.txt @@ -36,7 +36,7 @@ calamares_add_plugin(localeq ${_locale}/LocaleNames.cpp ${_locale}/SetTimezoneJob.cpp RESOURCES - localeq.qrc + localeq${QT_VERSION_SUFFIX}.qrc LINK_PRIVATE_LIBRARIES ${qtname}::Network SHARED_LIB diff --git a/src/modules/localeq/Map-qt6.qml b/src/modules/localeq/Map-qt6.qml new file mode 100644 index 000000000..bba8629cc --- /dev/null +++ b/src/modules/localeq/Map-qt6.qml @@ -0,0 +1,263 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +import QtQuick +import QtQuick.Controls +import QtQuick.Window +import QtQuick.Layouts + +import org.kde.kirigami as Kirigami + +import QtLocation +import QtPositioning + +Column { + width: parent.width + + // These are used by the map query to initially center the + // map on the user's likely location. They are updated by + // getIp() which does a more accurate GeoIP lookup than + // the default one in Calamares + property var cityName: "" + property var countryName: "" + + /* This is an extra GeoIP lookup, which will find better-accuracy + * location data for the user's IP, and then sets the current timezone + * and map location. Call it from Component.onCompleted so that + * it happens "on time" before the page is shown. + */ + function getIpOnline() { + var xhr = new XMLHttpRequest + + xhr.onreadystatechange = function() { + if (xhr.readyState === XMLHttpRequest.DONE) { + var responseJSON = JSON.parse(xhr.responseText) + var tz = responseJSON.timezone + var ct = responseJSON.city + var cy = responseJSON.country + + cityName = ct + countryName = cy + + config.setCurrentLocation(tz) + } + } + + // Define the target of the request + xhr.open("GET", "https://get.geojs.io/v1/ip/geo.json") + // Execute the request + xhr.send() + } + + /* This is an "offline" GeoIP lookup -- it just follows what + * Calamares itself has figured out with its GeoIP or configuration. + * Call it from the **Component** onActivate() -- in localeq.qml -- + * so it happens as the page is shown. + */ + function getIpOffline() { + cityName = config.currentLocation.zone + countryName = config.currentLocation.countryCode + } + + /* This is an **accurate** TZ lookup method: it queries an + * online service for the TZ at the given coordinates. It + * requires an internet connection, though, and the distribution + * will need to have an account with geonames to not hit the + * daily query limit. + * + * See below, in MouseArea, for calling the right method. + */ + function getTzOnline() { + var xhr = new XMLHttpRequest + var latC = map.center.latitude + var lonC = map.center.longitude + + xhr.onreadystatechange = function() { + if (xhr.readyState === XMLHttpRequest.DONE) { + var responseJSON = JSON.parse(xhr.responseText) + var tz2 = responseJSON.timezoneId + + config.setCurrentLocation(tz2) + } + } + + console.log("Online lookup", latC, lonC) + // Needs to move to localeq.conf, each distribution will need their own account + xhr.open("GET", "http://api.geonames.org/timezoneJSON?lat=" + latC + "&lng=" + lonC + "&username=SOME_USERNAME") + xhr.send() + } + + /* This is a quick TZ lookup method: it uses the existing + * Calamares "closest TZ" code, which has lots of caveats. + * + * See below, in MouseArea, for calling the right method. + */ + function getTzOffline() { + var latC = map.center.latitude + var lonC = map.center.longitude + var tz = config.zonesModel.lookup(latC, lonC) + console.log("Offline lookup", latC, lonC) + config.setCurrentLocation(tz.region, tz.zone) + } + + Rectangle { + width: parent.width + height: parent.height / 1.28 + + Plugin { + id: mapPlugin + preferred: ["osm", "esri"] // "esri", "here", "itemsoverlay", "mapbox", "mapboxgl", "osm" + } + + Map { + id: map + anchors.fill: parent + plugin: mapPlugin + activeMapType: supportedMapTypes[0] + //might be desirable to set zoom level configurable? + zoomLevel: 7 + bearing: 0 + tilt: 0 + copyrightsVisible : true + fieldOfView : 0 + + GeocodeModel { + id: geocodeModel + plugin: mapPlugin + autoUpdate: true + query: Address { + id: address + city: cityName + country: countryName + } + + onLocationsChanged: { + if (count == 1) { + map.center.latitude = get(0).coordinate.latitude + map.center.longitude = get(0).coordinate.longitude + } + } + } + + MapQuickItem { + id: marker + anchorPoint.x: image.width/4 + anchorPoint.y: image.height + coordinate: QtPositioning.coordinate( + map.center.latitude, + map.center.longitude) + //coordinate: QtPositioning.coordinate(40.730610, -73.935242) // New York + + sourceItem: Image { + id: image + width: 32 + height: 32 + source: "img/pin.svg" + } + } + + MouseArea { + acceptedButtons: Qt.LeftButton + anchors.fill: map + hoverEnabled: true + property var coordinate: map.toCoordinate(Qt.point(mouseX, mouseY)) + + onClicked: { + marker.coordinate = coordinate + map.center.latitude = coordinate.latitude + map.center.longitude = coordinate.longitude + + // Pick a TZ lookup method here (quick:offline, accurate:online) + getTzOffline(); + } + } + } + + Column { + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.bottomMargin: 5 + anchors.rightMargin: 10 + + MouseArea { + width: 32 + height:32 + cursorShape: Qt.PointingHandCursor + Image { + source: "img/plus.png" + anchors.centerIn: parent + width: 36 + height: 36 + } + + onClicked: map.zoomLevel++ + } + + MouseArea { + width: 32 + height:32 + cursorShape: Qt.PointingHandCursor + Image { + source: "img/minus.png" + anchors.centerIn: parent + width: 32 + height: 32 + } + + onClicked: map.zoomLevel-- + } + } + } + + Rectangle { + width: parent.width + height: 100 + anchors.horizontalCenter: parent.horizontalCenter + + Item { + id: location + Kirigami.Theme.inherit: false + Kirigami.Theme.colorSet: Kirigami.Theme.Complementary + anchors.horizontalCenter: parent.horizontalCenter + + Rectangle { + anchors.centerIn: parent + width: 300 + height: 30 + color: Kirigami.Theme.backgroundColor + + Text { + id: tzText + text: qsTr("Timezone: %1").arg(config.currentTimezoneName) + color: Kirigami.Theme.textColor + anchors.centerIn: parent + } + + /* If you want an extra (and accurate) GeoIP lookup, + * enable this one and disable the offline lookup in + * onActivate(). + Component.onCompleted: getIpOnline(); + */ + } + } + + Text { + anchors.top: location.bottom + anchors.topMargin: 20 + padding: 10 + width: parent.width + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + Kirigami.Theme.backgroundColor: Kirigami.Theme.backgroundColor + text: qsTr("Please select your preferred location on the map so the installer can suggest the locale + and timezone settings for you. You can fine-tune the suggested settings below. Search the map by dragging + to move and using the +/- buttons to zoom in/out or use mouse scrolling for zooming.") + } + } +} diff --git a/src/modules/localeq/Offline-qt6.qml b/src/modules/localeq/Offline-qt6.qml new file mode 100644 index 000000000..c980c4ed6 --- /dev/null +++ b/src/modules/localeq/Offline-qt6.qml @@ -0,0 +1,243 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2020-2022 Anke Boersma + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +import io.calamares.core 1.0 +import io.calamares.ui 1.0 + +import QtQuick +import QtQuick.Controls +import QtQuick.Window +import QtQuick.Layouts + +import org.kde.kirigami as Kirigami + +Page { + width: 800 //parent.width + height: 500 + + id: control + property string currentRegion + property string currentZone + + readonly property color backgroundColor: Kirigami.Theme.backgroundColor //"#F5F5F5" + readonly property color backgroundLighterColor: "#ffffff" + readonly property color highlightColor: Kirigami.Theme.highlightColor //"#3498DB" + readonly property color textColor: Kirigami.Theme.textColor + readonly property color highlightedTextColor: Kirigami.Theme.highlightedTextColor + + StackView { + id: stack + anchors.fill: parent + clip: true + + initialItem: Item { + + Label { + + id: region + anchors.horizontalCenter: parent.horizontalCenter + color: textColor + horizontalAlignment: Text.AlignCenter + text: qsTr("Select your preferred Region, or use the default settings.") + } + + ListView { + + id: list + ScrollBar.vertical: ScrollBar { + active: true + } + + width: parent.width / 2 + height: parent.height / 1.5 + anchors.centerIn: parent + anchors.verticalCenterOffset: -30 + focus: true + clip: true + boundsBehavior: Flickable.StopAtBounds + spacing: 2 + + Rectangle { + + z: parent.z - 1 + anchors.fill: parent + color: backgroundLighterColor + } + + model: config.regionModel + currentIndex: 1 // offline install, means locale from config + delegate: ItemDelegate { + + hoverEnabled: true + width: parent.width + height: 28 + highlighted: ListView.isCurrentItem + + Label { + + text: model.name + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + width: parent.width + height: 28 + color: highlighted ? highlightedTextColor : textColor + + background: Rectangle { + + color: highlighted || hovered ? highlightColor : backgroundLighterColor + opacity: highlighted || hovered ? 0.5 : 1 + } + } + + onClicked: { + + list.currentIndex = index + control.currentRegion = model.name + config.regionalZonesModel.region = control.currentRegion + tztext.text = qsTr("Timezone: %1").arg(config.currentTimezoneName) + stack.push(zoneView) + } + } + } + } + + Component { + id: zoneView + + Item { + + Label { + + id: zone + anchors.horizontalCenter: parent.horizontalCenter + color: textColor + text: qsTr("Select your preferred Zone within your Region.") + } + + ListView { + + id: list2 + ScrollBar.vertical: ScrollBar { + active: true + } + + width: parent.width / 2 + height: parent.height / 1.5 + anchors.centerIn: parent + anchors.verticalCenterOffset: -30 + focus: true + clip: true + boundsBehavior: Flickable.StopAtBounds + spacing: 2 + + Rectangle { + + z: parent.z - 1 + anchors.fill: parent + color: backgroundLighterColor + //radius: 5 + //opacity: 0.7 + } + + model: config.regionalZonesModel + currentIndex : 99 // index of New York + Component.onCompleted: positionViewAtIndex(currentIndex, ListView.Center) + delegate: ItemDelegate { + + hoverEnabled: true + width: parent.width + height: 24 + highlighted: ListView.isCurrentItem + + Label { + + text: model.name + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + width: parent.width + height: 24 + color: highlighted ? highlightedTextColor : textColor + + background: Rectangle { + + color: highlighted || hovered ? highlightColor : backgroundLighterColor + opacity: highlighted || hovered ? 0.5 : 1 + } + } + + onClicked: { + + list2.currentIndex = index + list2.positionViewAtIndex(index, ListView.Center) + control.currentZone = model.name + config.setCurrentLocation(control.currentRegion, control.currentZone) + tztext.text = qsTr("Timezone: %1").arg(config.currentTimezoneName) + } + } + } + + Button { + + Layout.fillWidth: true + anchors.verticalCenter: parent.verticalCenter + anchors.verticalCenterOffset: -30 + anchors.left: parent.left + anchors.leftMargin: parent.width / 15 + icon.name: "go-previous" + text: qsTr("Zones") + onClicked: stack.pop() + } + } + } + } + + Rectangle { + + width: parent.width + height: 60 + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + + Item { + + id: location + Kirigami.Theme.inherit: false + Kirigami.Theme.colorSet: Kirigami.Theme.Complementary + anchors.horizontalCenter: parent.horizontalCenter + + Rectangle { + + anchors.centerIn: parent + width: 300 + height: 30 + color: Kirigami.Theme.backgroundColor + + Text { + + id: tztext + text: qsTr("Timezone: %1").arg(config.currentTimezoneName) + color: Kirigami.Theme.textColor + anchors.centerIn: parent + } + } + } + + Text { + + anchors.top: location.bottom + anchors.topMargin: 20 + padding: 10 + width: parent.width + wrapMode: Text.WordWrap + horizontalAlignment: Text.AlignHCenter + Kirigami.Theme.backgroundColor: Kirigami.Theme.backgroundColor + text: qsTr("You can fine-tune Language and Locale settings below.") + } + } +} diff --git a/src/modules/localeq/localeq-qt6.qml b/src/modules/localeq/localeq-qt6.qml new file mode 100644 index 000000000..4a030e776 --- /dev/null +++ b/src/modules/localeq/localeq-qt6.qml @@ -0,0 +1,259 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2020 Adriaan de Groot + * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +import io.calamares.core 1.0 +import io.calamares.ui 1.0 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import org.kde.kirigami as Kirigami + +Page { + id: root + width: parent.width + height: parent.height + + readonly property color headerBackgroundColor: Kirigami.Theme.alternateBackgroundColor //"#eff0f1" + readonly property color backgroundLighterColor: "#ffffff" + readonly property color highlightColor: Kirigami.Theme.highlightColor //"#3498DB" + readonly property color textColor: Kirigami.Theme.textColor //"#1F1F1F" + readonly property color highlightedTextColor: Kirigami.Theme.highlightedTextColor + + function onActivate() { + /* If you want the map to follow Calamares's GeoIP + * lookup or configuration, call the update function + * here, and disable the one at onCompleted in Map.qml. + */ + if (Network.hasInternet) { image.item.getIpOffline() } + } + + Loader { + id: image + anchors.horizontalCenter: parent.horizontalCenter + width: parent.width + height: parent.height / 1.28 + // Network is in io.calamares.core + source: Network.hasInternet ? "Map.qml" : "Offline.qml" + } + + RowLayout { + anchors.bottom: parent.bottom + anchors.bottomMargin : 20 + width: parent.width + spacing: 50 + + GridLayout { + rowSpacing: Kirigami.Units.largeSpacing + columnSpacing: Kirigami.Units.largeSpacing + + Kirigami.Icon { + source: "qrc:/img/locale.svg" + Layout.fillHeight: true + Layout.maximumHeight: Kirigami.Units.iconSizes.large + Layout.preferredWidth: height + } + + ColumnLayout { + Label { + Layout.fillWidth: true + wrapMode: Text.WordWrap + text: config.currentLanguageStatus + } + Kirigami.Separator { + Layout.fillWidth: true + } + Button { + Layout.alignment: Qt.AlignRight|Qt.AlignVCenter + Layout.columnSpan: 2 + text: qsTr("Change") + onClicked: { + drawerLanguage.open() + } + } + } + } + + GridLayout { + rowSpacing: Kirigami.Units.largeSpacing + columnSpacing: Kirigami.Units.largeSpacing + + Kirigami.Icon { + source: "qrc:/img/locale.svg" + Layout.fillHeight: true + Layout.maximumHeight: Kirigami.Units.iconSizes.large + Layout.preferredWidth: height + } + ColumnLayout { + Label { + Layout.fillWidth: true + wrapMode: Text.WordWrap + text: config.currentLCStatus + } + Kirigami.Separator { + Layout.fillWidth: true + } + Button { + Layout.alignment: Qt.AlignRight|Qt.AlignVCenter + Layout.columnSpan: 2 + text: qsTr("Change") + onClicked: { + drawerLocale.open() + } + } + } + } + + Drawer { + id: drawerLanguage + width: 0.33 * root.width + height: root.height + edge: Qt.LeftEdge + + ScrollView { + id: scroll1 + anchors.fill: parent + contentHeight: 800 + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + + ListView { + id: list1 + focus: true + clip: true + width: parent.width + + model: config.supportedLocales + currentIndex: -1 //config.localeIndex + + header: Rectangle { + width: parent.width + height: 100 + color: "#eff0f1" //headerBackgroundColor + Text { + anchors.fill: parent + wrapMode: Text.WordWrap + text: qsTr("

Languages


+ The system locale setting affects the language and character set for some command line user interface elements. The current setting is %1.").arg(config.currentLanguageCode) + font.pointSize: 10 + } + } + + delegate: ItemDelegate { + + property variant myData: model + hoverEnabled: true + width: drawerLanguage.width + implicitHeight: 24 + highlighted: ListView.isCurrentItem + Label { + Layout.fillHeight: true + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + width: parent.width + height: 24 + color: highlighted ? "#eff0f1" : "#1F1F1F" // headerBackgroundColor : textColor + text: modelData + background: Rectangle { + + color: highlighted || hovered ? highlightColor : backgroundLighterColor + opacity: highlighted || hovered ? 0.5 : 0.9 + } + + MouseArea { + hoverEnabled: true + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + list1.currentIndex = index + drawerLanguage.close() + } + } + } + } + onCurrentItemChanged: { config.currentLanguageCode = model[currentIndex] } /* This works because model is a stringlist */ + } + } + } + + Drawer { + id: drawerLocale + width: 0.33 * root.width + height: root.height + edge: Qt.RightEdge + + ScrollView { + id: scroll2 + anchors.fill: parent + contentHeight: 800 + ScrollBar.horizontal.policy: ScrollBar.AlwaysOff + + ListView { + id: list2 + focus: true + clip: true + width: parent.width + + model: config.supportedLocales + currentIndex: -1 //model.currentLCCodeIndex + + header: Rectangle { + width: parent.width + height: 100 + color: "#eff0f1" // headerBackgroundColor + Text { + anchors.fill: parent + wrapMode: Text.WordWrap + text: qsTr("

Locales


+ The system locale setting affects the numbers and dates format. The current setting is %1.").arg(config.currentLCCode) + font.pointSize: 10 + } + } + + delegate: ItemDelegate { + + hoverEnabled: true + width: drawerLocale.width + implicitHeight: 24 + highlighted: ListView.isCurrentItem + Label { + Layout.fillHeight: true + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + width: parent.width + height: 24 + color: highlighted ? "#eff0f1" : "#1F1F1F" // headerBackgroundColor : textColor + text: modelData + background: Rectangle { + + color: highlighted || hovered ? highlightColor : backgroundLighterColor + opacity: highlighted || hovered ? 0.5 : 0.9 + } + + MouseArea { + hoverEnabled: true + anchors.fill: parent + cursorShape: Qt.PointingHandCursor + onClicked: { + list2.currentIndex = index + drawerLocale.close() + } + } + } + } + onCurrentItemChanged: { config.currentLCCode = model[currentIndex]; } /* This works because model is a stringlist */ + } + } + } + } + Loader { + id:load + anchors.fill: parent + } +} diff --git a/src/modules/localeq/localeq-qt6.qrc b/src/modules/localeq/localeq-qt6.qrc new file mode 100644 index 000000000..e4414a26f --- /dev/null +++ b/src/modules/localeq/localeq-qt6.qrc @@ -0,0 +1,11 @@ + + + localeq-qt6.qml + Map-qt6.qml + Offline-qt6.qml + img/locale.svg + img/minus.png + img/pin.svg + img/plus.png + + diff --git a/src/modules/packagechooserq/CMakeLists.txt b/src/modules/packagechooserq/CMakeLists.txt index 5591f5a8f..52a89f88e 100644 --- a/src/modules/packagechooserq/CMakeLists.txt +++ b/src/modules/packagechooserq/CMakeLists.txt @@ -61,7 +61,7 @@ calamares_add_plugin(packagechooserq ${_packagechooser}/PackageModel.cpp ${_extra_src} RESOURCES - packagechooserq.qrc + packagechooserq${QT_VERSION_SUFFIX}.qrc LINK_PRIVATE_LIBRARIES calamaresui ${_extra_libraries} diff --git a/src/modules/packagechooserq/packagechooserq-qt6.qml b/src/modules/packagechooserq/packagechooserq-qt6.qml new file mode 100644 index 000000000..d951a2ee1 --- /dev/null +++ b/src/modules/packagechooserq/packagechooserq-qt6.qml @@ -0,0 +1,241 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 Anke Boersma + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +import io.calamares.core 1.0 +import io.calamares.ui 1.0 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Item { + width: parent.width + height: parent.height + + Rectangle { + anchors.fill: parent + color: "#f2f2f2" + + ButtonGroup { + id: switchGroup + } + + Column { + id: column + anchors.centerIn: parent + spacing: 5 + + Rectangle { + //id: rectangle + width: 700 + height: 150 + color: "#ffffff" + radius: 10 + border.width: 0 + Text { + width: 450 + height: 104 + anchors.centerIn: parent + text: qsTr("LibreOffice is a powerful and free office suite, used by millions of people around the world. It includes several applications that make it the most versatile Free and Open Source office suite on the market.
+ Default option.") + font.pointSize: 10 + anchors.verticalCenterOffset: -10 + anchors.horizontalCenterOffset: 100 + wrapMode: Text.WordWrap + } + + Switch { + id: element2 + x: 500 + y: 110 + width: 187 + height: 14 + text: qsTr("LibreOffice") + checked: true + hoverEnabled: true + ButtonGroup.group: switchGroup + + indicator: Rectangle { + implicitWidth: 40 + implicitHeight: 14 + radius: 10 + color: element2.checked ? "#3498db" : "#B9B9B9" + border.color: element2.checked ? "#3498db" : "#cccccc" + + Rectangle { + x: element2.checked ? parent.width - width : 0 + y: (parent.height - height) / 2 + width: 20 + height: 20 + radius: 10 + color: element2.down ? "#cccccc" : "#ffffff" + border.color: element2.checked ? (element1.down ? "#3498db" : "#3498db") : "#999999" + } + } + + onCheckedChanged: { + if ( checked ) { + config.packageChoice = "libreoffice" + } + } + } + + Image { + id: image2 + x: 8 + y: 25 + height: 100 + fillMode: Image.PreserveAspectFit + source: "images/libreoffice.jpg" + } + } + + Rectangle { + width: 700 + height: 150 + radius: 10 + border.width: 0 + Text { + width: 450 + height: 104 + anchors.centerIn: parent + text: qsTr("If you don't want to install an office suite, just select No Office Suite. You can always add one (or more) later on your installed system as the need arrives.") + font.pointSize: 10 + anchors.verticalCenterOffset: -10 + anchors.horizontalCenterOffset: 100 + wrapMode: Text.WordWrap + } + + Switch { + id: element1 + x: 500 + y: 110 + width: 187 + height: 14 + text: qsTr("No Office Suite") + checked: false + hoverEnabled: true + ButtonGroup.group: switchGroup + + indicator: Rectangle { + implicitWidth: 40 + implicitHeight: 14 + radius: 10 + color: element1.checked ? "#3498db" : "#B9B9B9" + border.color: element1.checked ? "#3498db" : "#cccccc" + + Rectangle { + x: element1.checked ? parent.width - width : 0 + y: (parent.height - height) / 2 + width: 20 + height: 20 + radius: 10 + color: element1.down ? "#cccccc" : "#ffffff" + border.color: element1.checked ? (element1.down ? "#3498db" : "#3498db") : "#999999" + } + } + + onCheckedChanged: { + if ( checked ) { + config.packageChoice = "no_office_suite" + } + } + } + + Image { + id: image + x: 8 + y: 25 + height: 100 + fillMode: Image.PreserveAspectFit + source: "images/no-selection.png" + } + + } + + Rectangle { + width: 700 + height: 150 + color: "#ffffff" + radius: 10 + border.width: 0 + Text { + width: 450 + height: 104 + anchors.centerIn: parent + text: qsTr("Create a minimal Desktop install, remove all extra applications and decide later on what you would like to add to your system. Examples of what won't be on such an install, there will be no Office Suite, no media players, no image viewer or print support. It will be just a desktop, file browser, package manager, text editor and simple web-browser.") + font.pointSize: 10 + anchors.verticalCenterOffset: -10 + anchors.horizontalCenterOffset: 100 + wrapMode: Text.WordWrap + } + + Switch { + id: element3 + x: 500 + y: 110 + width: 187 + height: 14 + text: qsTr("Minimal Install") + checked: false + hoverEnabled: true + ButtonGroup.group: switchGroup + + indicator: Rectangle { + implicitWidth: 40 + implicitHeight: 14 + radius: 10 + color: element3.checked ? "#3498db" : "#B9B9B9" + border.color: element3.checked ? "#3498db" : "#cccccc" + + Rectangle { + x: element3.checked ? parent.width - width : 0 + y: (parent.height - height) / 2 + width: 20 + height: 20 + radius: 10 + color: element3.down ? "#cccccc" : "#ffffff" + border.color: element3.checked ? (element3.down ? "#3498db" : "#3498db") : "#999999" + } + } + + onCheckedChanged: { + if ( checked ) { + config.packageChoice = "minimal_install" + } + } + } + + Image { + id: image3 + x: 8 + y: 25 + height: 100 + fillMode: Image.PreserveAspectFit + source: "images/plasma.png" + } + } + + Rectangle { + width: 700 + height: 25 + color: "#f2f2f2" + border.width: 0 + Text { + height: 25 + anchors.centerIn: parent + text: qsTr("Please select an option for your install, or use the default: LibreOffice included.") + font.pointSize: 10 + wrapMode: Text.WordWrap + } + } + } + } + +} diff --git a/src/modules/packagechooserq/packagechooserq-qt6.qrc b/src/modules/packagechooserq/packagechooserq-qt6.qrc new file mode 100644 index 000000000..d243f9335 --- /dev/null +++ b/src/modules/packagechooserq/packagechooserq-qt6.qrc @@ -0,0 +1,8 @@ + + + packagechooserq-qt6.qml + images/libreoffice.jpg + images/no-selection.png + images/plasma.png + + diff --git a/src/modules/summaryq/CMakeLists.txt b/src/modules/summaryq/CMakeLists.txt index 071c344ef..9ec8327fa 100644 --- a/src/modules/summaryq/CMakeLists.txt +++ b/src/modules/summaryq/CMakeLists.txt @@ -19,7 +19,7 @@ calamares_add_plugin(summaryq ${_summary}/Config.cpp UI RESOURCES - summaryq.qrc + summaryq${QT_VERSION_SUFFIX}.qrc LINK_PRIVATE_LIBRARIES calamaresui SHARED_LIB diff --git a/src/modules/summaryq/summaryq-qt6.qml b/src/modules/summaryq/summaryq-qt6.qml new file mode 100644 index 000000000..22dac588f --- /dev/null +++ b/src/modules/summaryq/summaryq-qt6.qml @@ -0,0 +1,111 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 Anke Boersma + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +import io.calamares.core 1.0 +import io.calamares.ui 1.0 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import org.kde.kirigami as Kirigami +import QtQuick.Window + +Kirigami.ScrollablePage { + width: 860 //parent.width + height: 640 //parent.height + + Kirigami.Theme.backgroundColor: "#EFF0F1" + Kirigami.Theme.textColor: "#1F1F1F" + + header: Kirigami.Heading { + Layout.fillWidth: true + height: 100 + horizontalAlignment: Qt.AlignHCenter + color: Kirigami.Theme.textColor + font.weight: Font.Medium + font.pointSize: 12 + text: config.message + + } + + RowLayout { + width: parent.width + + Component { + id: _delegate + + Rectangle { + id: rect + border.color: "#BDC3C7" + width: parent.width - 80 + implicitHeight: message.implicitHeight + title.implicitHeight + 20 + anchors.horizontalCenter: parent.horizontalCenter + + Item { + width: parent.width - 80 + implicitHeight: message.implicitHeight + title.implicitHeight + 20 + + Kirigami.FormLayout { + + GridLayout { + anchors { + //left: parent.left + top: parent.top + right: parent.right + } + rowSpacing: Kirigami.Units.largeSpacing + columnSpacing: Kirigami.Units.largeSpacing + columns: width > Kirigami.Units.gridUnit * 20 ? 4 : 2 + + Image { + id: image + Layout.maximumHeight: Kirigami.Units.iconSizes.huge + Layout.preferredWidth: height + Layout.alignment: Qt.AlignTop + fillMode: Image.PreserveAspectFit + source: index === 0 ? "img/lokalize.svg" + : ( index === 1 ? "img/keyboard.svg" + : ( index === 2 ? "qrc:/data/images/partition-manual.svg" + : "qrc:/data/images/partition-partition.svg" ) ) + } + ColumnLayout { + + Label { + id: title + Layout.fillWidth: true + wrapMode: Text.WordWrap + text: model.title + font.weight: Font.Medium + font.pointSize: 16 + } + Rectangle { + height: 2 + width: 200 + border.color: "#BDC3C7" + } + Label { + id: message + Layout.fillWidth: true + text: model.message + } + } + } + } + } + } + } + } + + ListView { + anchors.fill: parent + spacing: 20 + model: config.summaryModel + delegate: _delegate + } +} diff --git a/src/modules/summaryq/summaryq-qt6.qrc b/src/modules/summaryq/summaryq-qt6.qrc new file mode 100644 index 000000000..c2cfc07cc --- /dev/null +++ b/src/modules/summaryq/summaryq-qt6.qrc @@ -0,0 +1,7 @@ + + + summaryq-qt6.qml + img/keyboard.svg + img/lokalize.svg + + diff --git a/src/modules/usersq/CMakeLists.txt b/src/modules/usersq/CMakeLists.txt index 6409f7f55..5cfd55818 100644 --- a/src/modules/usersq/CMakeLists.txt +++ b/src/modules/usersq/CMakeLists.txt @@ -41,7 +41,7 @@ calamares_add_plugin(usersq SOURCES UsersQmlViewStep.cpp RESOURCES - usersq.qrc + usersq${QT_VERSION_SUFFIX}.qrc LINK_PRIVATE_LIBRARIES users_internal ${CRYPT_LIBRARIES} diff --git a/src/modules/usersq/usersq-qt6.qml b/src/modules/usersq/usersq-qt6.qml new file mode 100644 index 000000000..4b379e6dc --- /dev/null +++ b/src/modules/usersq/usersq-qt6.qml @@ -0,0 +1,425 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2020 - 2022 Anke Boersma + * SPDX-FileCopyrightText: 2021 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +import io.calamares.core 1.0 +import io.calamares.ui 1.0 + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import org.kde.kirigami as Kirigami +import QtQuick.Window + +Kirigami.ScrollablePage { + // You can hard-code a color here, or bind to a Kirigami theme color, + // or use a color from Calamares branding, or .. + readonly property color unfilledFieldColor: "#FBFBFB" //Kirigami.Theme.backgroundColor + readonly property color positiveFieldColor: "#F0FFF0" //Kirigami.Theme.positiveBackgroundColor + readonly property color negativeFieldColor: "#EBCED1" //Kirigami.Theme.negativeBackgroundColor + readonly property color unfilledFieldOutlineColor: "#F1F1F1" + readonly property color positiveFieldOutlineColor: "#DCFFDC" + readonly property color negativeFieldOutlineColor: "#BE5F68" + readonly property color headerTextColor: "#1F1F1F" + readonly property color commentsColor: "#6D6D6D" + + width: parent.width + height: parent.height + + header: Kirigami.Heading { + Layout.fillWidth: true + height: 50 + horizontalAlignment: Qt.AlignHCenter + color: headerTextColor + font.weight: Font.Medium + font.pointSize: 12 + text: qsTr("Pick your user name and credentials to login and perform admin tasks") + } + + ColumnLayout { + id: _formLayout + spacing: Kirigami.Units.smallSpacing + + Column { + Layout.fillWidth: true + spacing: Kirigami.Units.smallSpacing + + Label { + width: parent.width + text: qsTr("What is your name?") + } + + TextField { + id: _userNameField + width: parent.width + enabled: config.isEditable("fullName") + placeholderText: qsTr("Your Full Name") + text: config.fullName + onTextChanged: config.setFullName(text) + + palette.base: _userNameField.text.length + ? positiveFieldColor : unfilledFieldColor + palette.highlight : _userNameField.text.length + ? positiveFieldOutlineColor : unfilledFieldOutlineColor + } + } + + Column { + Layout.fillWidth: true + spacing: Kirigami.Units.smallSpacing + + Label { + width: parent.width + text: qsTr("What name do you want to use to log in?") + } + + TextField { + id: _userLoginField + width: parent.width + enabled: config.isEditable("loginName") + placeholderText: qsTr("Login Name") + text: config.loginName + validator: RegularExpressionValidator { regularExpression: /[a-z_][a-z0-9_-]*[$]?$/ } + + onTextChanged: acceptableInput + ? ( _userLoginField.text === "root" + ? forbiddenMessage.visible=true + : ( config.setLoginName(text), + userMessage.visible = false,forbiddenMessage.visible=false ) ) + : ( userMessage.visible = true,console.log("Invalid") ) + + palette.base: _userLoginField.text.length + ? ( acceptableInput + ? ( _userLoginField.text === "root" + ? negativeFieldColor + : positiveFieldColor ) + : negativeFieldColor ) + : unfilledFieldColor + palette.highlight : _userLoginField.text.length + ? ( acceptableInput + ? ( _userLoginField.text === "root" + ? negativeFieldOutlineColor + : positiveFieldOutlineColor ) + : negativeFieldOutlineColor ) + : unfilledFieldOutlineColor + } + + Label { + width: parent.width + text: qsTr("If more than one person will use this computer, you can create multiple accounts after installation.") + font.weight: Font.Thin + font.pointSize: 8 + color: commentsColor + } + } + + Kirigami.InlineMessage { + id: userMessage + Layout.fillWidth: true + showCloseButton: true + visible: false + type: Kirigami.MessageType.Error + text: qsTr("Only lowercase letters, numbers, underscore and hyphen are allowed.") + } + + Kirigami.InlineMessage { + id: forbiddenMessage + Layout.fillWidth: true + showCloseButton: true + visible: false + type: Kirigami.MessageType.Error + text: qsTr("root is not allowed as username.") + } + + Column { + Layout.fillWidth: true + spacing: Kirigami.Units.smallSpacing + + Label { + width: parent.width + text: qsTr("What is the name of this computer?") + } + + TextField { + id: _hostName + width: parent.width + placeholderText: qsTr("Computer Name") + text: config.hostname + validator: RegularExpressionValidator { regularExpression: /[a-zA-Z0-9][-a-zA-Z0-9_]+/ } + + onTextChanged: acceptableInput + ? ( _hostName.text === "localhost" + ? forbiddenHost.visible=true + : ( config.setHostName(text), + hostMessage.visible = false,forbiddenHost.visible = false ) ) + : hostMessage.visible = true + + palette.base: _hostName.text.length + ? ( acceptableInput + ? ( _hostName.text === "localhost" + ? negativeFieldColor : positiveFieldColor ) + : negativeFieldColor) + : unfilledFieldColor + palette.highlight : _hostName.text.length + ? ( acceptableInput + ? ( _hostName.text === "localhost" + ? negativeFieldOutlineColor : positiveFieldOutlineColor ) + : negativeFieldOutlineColor) + : unfilledFieldOutlineColor + } + + Label { + width: parent.width + text: qsTr("This name will be used if you make the computer visible to others on a network.") + font.weight: Font.Thin + font.pointSize: 8 + color: commentsColor + } + } + + Kirigami.InlineMessage { + id: hostMessage + Layout.fillWidth: true + showCloseButton: true + visible: false + type: Kirigami.MessageType.Error + text: qsTr("Only letters, numbers, underscore and hyphen are allowed, minimal of two characters.") + } + + Kirigami.InlineMessage { + id: forbiddenHost + Layout.fillWidth: true + showCloseButton: true + visible: false + type: Kirigami.MessageType.Error + text: qsTr("localhost is not allowed as hostname.") + } + + Column { + Layout.fillWidth: true + spacing: Kirigami.Units.smallSpacing + + Label { + width: parent.width + text: qsTr("Choose a password to keep your account safe.") + } + + Row { + width: parent.width + spacing: 20 + + TextField { + id: _passwordField + width: parent.width / 2 - 10 + placeholderText: qsTr("Password") + text: config.userPassword + onTextChanged: config.setUserPassword(text) + + palette.base: _passwordField.text.length + ? positiveFieldColor : unfilledFieldColor + palette.highlight : _passwordField.text.length + ? positiveFieldOutlineColor : unfilledFieldOutlineColor + + echoMode: TextInput.Password + passwordMaskDelay: 300 + inputMethodHints: Qt.ImhNoAutoUppercase + } + + TextField { + id: _verificationPasswordField + width: parent.width / 2 - 10 + placeholderText: qsTr("Repeat Password") + text: config.userPasswordSecondary + + onTextChanged: _passwordField.text === _verificationPasswordField.text + ? ( config.setUserPasswordSecondary(text), + passMessage.visible = false, + validityMessage.visible = true ) + : ( passMessage.visible = true, + validityMessage.visible = false ) + + palette.base: _verificationPasswordField.text.length + ? ( _passwordField.text === _verificationPasswordField.text + ? positiveFieldColor : negativeFieldColor ) + : unfilledFieldColor + palette.highlight : _verificationPasswordField.text.length + ? ( _passwordField.text === _verificationPasswordField.text + ? positiveFieldOutlineColor : negativeFieldOutlineColor ) + : unfilledFieldOutlineColor + + echoMode: TextInput.Password + passwordMaskDelay: 300 + inputMethodHints: Qt.ImhNoAutoUppercase + } + } + + Label { + width: parent.width + text: qsTr("Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.") + font.weight: Font.Thin + font.pointSize: 8 + wrapMode: Text.WordWrap + color: commentsColor + } + } + + Kirigami.InlineMessage { + id: passMessage + Layout.fillWidth: true + showCloseButton: true + visible: false + type: Kirigami.MessageType.Error + text: config.userPasswordMessage + } + + Kirigami.InlineMessage { + id: validityMessage + Layout.fillWidth: true + showCloseButton: true + visible: false + type: config.userPasswordValidity + ? ( config.requireStrongPasswords + ? Kirigami.MessageType.Error : Kirigami.MessageType.Warning ) + : Kirigami.MessageType.Positive + text: config.userPasswordMessage + } + + CheckBox { + id: root + visible: config.writeRootPassword + text: qsTr("Reuse user password as root password") + checked: config.reuseUserPasswordForRoot + onCheckedChanged: config.setReuseUserPasswordForRoot(checked) + } + + Label { + visible: root.checked + width: parent.width + text: qsTr("Use the same password for the administrator account.") + font.weight: Font.Thin + font.pointSize: 8 + color: commentsColor + } + + Column { + visible: ! root.checked + Layout.fillWidth: true + spacing: Kirigami.Units.smallSpacing + + Label { + width: parent.width + text: qsTr("Choose a root password to keep your account safe.") + } + + Row { + width: parent.width + spacing: 20 + + TextField { + id: _rootPasswordField + width: parent.width / 2 -10 + placeholderText: qsTr("Root Password") + text: config.rootPassword + + onTextChanged: config.setRootPassword(text) + + palette.base: _rootPasswordField.text.length + ? positiveFieldColor : unfilledFieldColor + palette.highlight : _rootPasswordField.text.length + ? positiveFieldOutlineColor : unfilledFieldOutlineColor + + echoMode: TextInput.Password + passwordMaskDelay: 300 + inputMethodHints: Qt.ImhNoAutoUppercase + } + + TextField { + id: _verificationRootPasswordField + width: parent.width / 2 -10 + placeholderText: qsTr("Repeat Root Password") + text: config.rootPasswordSecondary + + onTextChanged: _rootPasswordField.text === _verificationRootPasswordField.text + ? ( config.setRootPasswordSecondary(text), + rootPassMessage.visible = false,rootValidityMessage.visible = true ) + : ( rootPassMessage.visible = true,rootValidityMessage.visible = false ) + + palette.base: _verificationRootPasswordField.text.length + ? ( _rootPasswordField.text === _verificationRootPasswordField.text + ? positiveFieldColor : negativeFieldColor) + : unfilledFieldColor + palette.highlight : _verificationRootPasswordField.text.length + ? ( _rootPasswordField.text === _verificationRootPasswordField.text + ? positiveFieldOutlineColor : negativeFieldOutlineColor) + : unfilledFieldOutlineColor + + echoMode: TextInput.Password + passwordMaskDelay: 300 + inputMethodHints: Qt.ImhNoAutoUppercase + } + } + + Label { + visible: ! root.checked + width: parent.width + text: qsTr("Enter the same password twice, so that it can be checked for typing errors.") + font.weight: Font.Thin + font.pointSize: 8 + color: commentsColor + } + } + + Kirigami.InlineMessage { + id: rootPassMessage + Layout.fillWidth: true + showCloseButton: true + visible: false + type: Kirigami.MessageType.Error + text: config.rootPasswordMessage + } + + Kirigami.InlineMessage { + id: rootValidityMessage + Layout.fillWidth: true + showCloseButton: true + visible: false + type: config.rootPasswordValidity + ? ( config.requireStrongPasswords + ? Kirigami.MessageType.Error : Kirigami.MessageType.Warning ) + : Kirigami.MessageType.Positive + text: config.rootPasswordMessage + } + + CheckBox { + Layout.alignment: Qt.AlignCenter + text: qsTr("Log in automatically without asking for the password") + checked: config.doAutoLogin + onCheckedChanged: config.setAutoLogin(checked) + } + + CheckBox { + visible: config.permitWeakPasswords + Layout.alignment: Qt.AlignCenter + text: qsTr("Validate passwords quality") + checked: config.requireStrongPasswords + onCheckedChanged: config.setRequireStrongPasswords(checked), + rootPassMessage.visible = false + } + + Label { + visible: config.permitWeakPasswords + width: parent.width + Layout.alignment: Qt.AlignCenter + text: qsTr("When this box is checked, password-strength checking is done and you will not be able to use a weak password.") + font.weight: Font.Thin + font.pointSize: 8 + color: commentsColor + } + } +} diff --git a/src/modules/usersq/usersq-qt6.qrc b/src/modules/usersq/usersq-qt6.qrc new file mode 100644 index 000000000..98dcf61be --- /dev/null +++ b/src/modules/usersq/usersq-qt6.qrc @@ -0,0 +1,5 @@ + + + usersq-qt6.qml + +