diff options
Diffstat (limited to 'raveos-calamares-module')
28 files changed, 945 insertions, 855 deletions
diff --git a/raveos-calamares-module/PKGBUILD b/raveos-calamares-module/PKGBUILD index 186946e..952a702 100644 --- a/raveos-calamares-module/PKGBUILD +++ b/raveos-calamares-module/PKGBUILD @@ -1,7 +1,7 @@ # Maintainer: nippy <nippy@tuta.io> pkgname=raveos-calamares-module pkgver=2.0.0 -pkgrel=38 +pkgrel=39 pkgdesc="RaveOS Calamares modules: Wi-Fi, Welcome, Desktop Selector, Users" arch=('x86_64') options=('!debug') @@ -9,7 +9,7 @@ url="https://git.rp1.hu/RaveOS" license=('GPL') makedepends=('cmake' 'qt6-tools' 'kcoreaddons' 'calamares' 'libxcrypt') -depends=('qt6-base' 'qt6-declarative' 'networkmanager' 'xorg-setxkbmap' 'calamares') +depends=('qt6-base' 'qt6-declarative' 'networkmanager' 'xorg-setxkbmap' 'calamares' 'libxkbcommon') source=() sha256sums=() diff --git a/raveos-calamares-module/README.md b/raveos-calamares-module/README.md index f670233..20957ae 100644 --- a/raveos-calamares-module/README.md +++ b/raveos-calamares-module/README.md @@ -1,5 +1,8 @@ -RaveOS Calamares Wi-Fi Modul +RaveOS Calamares modulok -Calamares viewmodule WiFi kapcsolat kezeléséhez live ISO telepítés közben. -.. +- ravewelcome: nyelvválasztó első lépés +- wifi: Wi-Fi kapcsolat a live rendszeren +- raveusers: felhasználó, gépnév, jelszó, automatikus bejelentkezés +- desktopselect: asztali környezet választó +A QML felületek a branding mappából regisztrált RaveOS típusokat használják (common/RaveBrandingQml.h). diff --git a/raveos-calamares-module/common/RaveBrandingQml.h b/raveos-calamares-module/common/RaveBrandingQml.h new file mode 100644 index 0000000..6ad3453 --- /dev/null +++ b/raveos-calamares-module/common/RaveBrandingQml.h @@ -0,0 +1,13 @@ +#pragma once + +#include <Branding.h> + +#include <QQmlEngine> + +inline void addRaveBrandingImportPath( QQmlEngine* engine ) +{ + if ( const auto* branding = Calamares::Branding::instance() ) + { + engine->addImportPath( branding->componentDirectory() ); + } +} diff --git a/raveos-calamares-module/desktopselect/desktopselect.conf b/raveos-calamares-module/desktopselect/desktopselect.conf index 7b9939f..d724605 100644 --- a/raveos-calamares-module/desktopselect/desktopselect.conf +++ b/raveos-calamares-module/desktopselect/desktopselect.conf @@ -4,7 +4,7 @@ mandatory_packages: - raveos-keyring - raveos-mirrorlist - raveos-welcome - - raveos-app-installer + - raveos-center - raveos-support - brave-origin-bin - noto-fonts @@ -59,7 +59,7 @@ desktops: badge_hu: "STABIL" badge_de: "STABIL" badge_en: "STABLE" - badge_color: "#2e7d32" + badge_color: "#62a052" packages: - plasma-desktop - plasma-wayland-protocols @@ -97,7 +97,7 @@ desktops: badge_hu: "STABIL" badge_de: "STABIL" badge_en: "STABLE" - badge_color: "#2e7d32" + badge_color: "#62a052" packages: - gnome-session - gnome-console @@ -135,7 +135,7 @@ desktops: badge_hu: "HAMAROSAN" badge_de: "BALD" badge_en: "SOON" - badge_color: "#e65100" + badge_color: "#d9a441" available: false - name: "Hyprland" @@ -145,7 +145,7 @@ desktops: badge_hu: "STABIL" badge_de: "STABIL" badge_en: "STABLE" - badge_color: "#2e7d32" + badge_color: "#62a052" packages: - hyprland - aquamarine diff --git a/raveos-calamares-module/desktopselect/ui/desktopselect.qml b/raveos-calamares-module/desktopselect/ui/desktopselect.qml index 4fd0318..9d717a2 100644 --- a/raveos-calamares-module/desktopselect/ui/desktopselect.qml +++ b/raveos-calamares-module/desktopselect/ui/desktopselect.qml @@ -5,7 +5,7 @@ import "." as DesktopSelectModule Rectangle { id: root - color: "#404040" + color: "#1a1b1d" // Function to update language - called from C++ function updateLanguage() { @@ -21,8 +21,9 @@ Rectangle { Rectangle { anchors.fill: parent anchors.margins: 20 - color: "#2B2B2B" - radius: 10 + color: "#232427" + border.color: "#34363a" + border.width: 1 ColumnLayout { anchors.fill: parent @@ -34,22 +35,21 @@ Rectangle { text: DesktopSelectModule.Translations.title font.pixelSize: 24 font.bold: true - color: "#ffffff" + color: "#e8e8e6" } // Figyelmeztető banner Rectangle { Layout.fillWidth: true height: 50 - color: "#1e1e1e" - border.color: "#e67e22" - border.width: 2 - radius: 6 + color: "#2e2a20" + border.color: "#d9a441" + border.width: 1 Text { anchors.centerIn: parent text: DesktopSelectModule.Translations.banner - color: "#e0e0e0" + color: "#f0dcb0" font.pixelSize: 13 } } @@ -67,13 +67,12 @@ Rectangle { id: card width: desktopList.width height: 78 - radius: 8 property bool selectable: modelData.available !== false - color: !selectable ? "#2a2a2a" : (backend.selectedIndex === index ? "#2a4a2a" : "#333333") - border.color: !selectable ? "#444444" : (backend.selectedIndex === index ? "#5cb85c" : "#555555") - border.width: 2 + color: !selectable ? "#1f2022" : (backend.selectedIndex === index ? "#24301f" : "#1a1b1d") + border.color: !selectable ? "#34363a" : (backend.selectedIndex === index ? "#62a052" : "#44464b") + border.width: backend.selectedIndex === index ? 2 : 1 RowLayout { anchors.fill: parent @@ -87,14 +86,14 @@ Rectangle { Text { text: modelData.name || "" - color: card.selectable ? "#ffffff" : "#9a9a9a" + color: card.selectable ? "#e8e8e6" : "#9a9ca1" font.pixelSize: 15 font.bold: true } Text { text: modelData.description || "" - color: card.selectable ? "#b2b2b2" : "#8a8a8a" + color: card.selectable ? "#b7b9bd" : "#7d7f84" font.pixelSize: 12 width: parent.width elide: Text.ElideRight @@ -104,14 +103,13 @@ Rectangle { Rectangle { width: badgeText.implicitWidth + 20 height: 28 - radius: 4 - color: modelData.badge_color || "#555555" + color: modelData.badge_color || "#44464b" Text { id: badgeText anchors.centerIn: parent text: modelData.badge || "" - color: "#ffffff" + color: "#1a1b1d" font.pixelSize: 11 font.bold: true } diff --git a/raveos-calamares-module/raveusers/RaveUsersBackend.cpp b/raveos-calamares-module/raveusers/RaveUsersBackend.cpp index 6f8eea6..538732f 100644 --- a/raveos-calamares-module/raveusers/RaveUsersBackend.cpp +++ b/raveos-calamares-module/raveusers/RaveUsersBackend.cpp @@ -75,7 +75,7 @@ RaveUsersBackend::hostnameStatus() const QString RaveUsersBackend::passwordStatus() const { - if ( m_password.isEmpty() ) + if ( m_password.isEmpty() || m_passwordSecondary.isEmpty() ) { return QString(); } @@ -93,7 +93,7 @@ RaveUsersBackend::rootPasswordStatus() const { return QString(); } - if ( m_rootPassword.isEmpty() ) + if ( m_rootPassword.isEmpty() || m_rootPasswordSecondary.isEmpty() ) { return QString(); } @@ -115,13 +115,13 @@ RaveUsersBackend::isReady() const { return false; } - if ( m_password.isEmpty() || !passwordStatus().isEmpty() ) + if ( m_password.isEmpty() || m_password != m_passwordSecondary ) { return false; } if ( m_setRootPassword && !m_reuseRootPassword ) { - if ( m_rootPassword.isEmpty() || !rootPasswordStatus().isEmpty() ) + if ( m_rootPassword.isEmpty() || m_rootPassword != m_rootPasswordSecondary ) { return false; } @@ -231,6 +231,16 @@ RaveUsersBackend::setReuseRootPassword( bool b ) } void +RaveUsersBackend::setAutoLogin( bool b ) +{ + if ( b != m_autoLogin ) + { + m_autoLogin = b; + emit autoLoginChanged(); + } +} + +void RaveUsersBackend::checkReady() { const bool ready = isReady(); diff --git a/raveos-calamares-module/raveusers/RaveUsersBackend.h b/raveos-calamares-module/raveusers/RaveUsersBackend.h index 4e06f47..06a6fad 100644 --- a/raveos-calamares-module/raveusers/RaveUsersBackend.h +++ b/raveos-calamares-module/raveusers/RaveUsersBackend.h @@ -17,6 +17,7 @@ class RaveUsersBackend : public QObject Q_PROPERTY( bool ready READ isReady NOTIFY readyChanged ) Q_PROPERTY( bool reuseRootPassword READ reuseRootPassword NOTIFY reuseRootPasswordChanged ) Q_PROPERTY( bool rootReuseVisible READ rootReuseVisible CONSTANT ) + Q_PROPERTY( bool autoLogin READ autoLogin NOTIFY autoLoginChanged ) public: explicit RaveUsersBackend( QObject* parent = nullptr ); @@ -29,6 +30,7 @@ public: QString rootPasswordStatus() const; bool isReady() const; bool reuseRootPassword() const { return m_reuseRootPassword; } + bool autoLogin() const { return m_autoLogin; } bool rootReuseVisible() const { return m_setRootPassword; } QString userPassword() const { return m_password; } @@ -48,6 +50,7 @@ public: Q_INVOKABLE void setRootPasswordText( const QString& s ); Q_INVOKABLE void setRootPasswordSecondaryText( const QString& s ); Q_INVOKABLE void setReuseRootPassword( bool b ); + Q_INVOKABLE void setAutoLogin( bool b ); void setForbiddenLoginNames( const QStringList& names ) { m_forbiddenLoginNames = names; } void setForbiddenHostNames( const QStringList& names ) { m_forbiddenHostNames = names; } @@ -64,6 +67,7 @@ signals: void statusChanged(); void readyChanged(); void reuseRootPasswordChanged(); + void autoLoginChanged(); private: void checkReady(); @@ -76,6 +80,7 @@ private: QString m_rootPasswordSecondary; bool m_customHostname = false; bool m_reuseRootPassword = true; + bool m_autoLogin = false; bool m_setRootPassword = true; QStringList m_forbiddenLoginNames; diff --git a/raveos-calamares-module/raveusers/RaveUsersJobs.cpp b/raveos-calamares-module/raveusers/RaveUsersJobs.cpp index 1923c38..18af3e7 100644 --- a/raveos-calamares-module/raveusers/RaveUsersJobs.cpp +++ b/raveos-calamares-module/raveusers/RaveUsersJobs.cpp @@ -38,7 +38,7 @@ RaveUsersCreateUserJob::prettyName() const QString RaveUsersCreateUserJob::prettyStatusMessage() const { - return tr( "Creating user %1…", "@status" ).arg( m_backend->username() ); + return tr( "Creating user %1...", "@status" ).arg( m_backend->username() ); } Calamares::JobResult @@ -106,7 +106,7 @@ RaveUsersSetPasswordJob::prettyName() const QString RaveUsersSetPasswordJob::prettyStatusMessage() const { - return tr( "Setting password for user %1…", "@status" ).arg( m_userName ); + return tr( "Setting password for user %1...", "@status" ).arg( m_userName ); } static QString @@ -210,7 +210,7 @@ RaveUsersSetupSudoJob::RaveUsersSetupSudoJob( const QString& group, bool configu QString RaveUsersSetupSudoJob::prettyName() const { - return tr( "Configuring sudo users…", "@status" ); + return tr( "Configuring sudo users...", "@status" ); } Calamares::JobResult @@ -250,7 +250,7 @@ RaveUsersSetupGroupsJob::RaveUsersSetupGroupsJob( const QStringList& groups ) QString RaveUsersSetupGroupsJob::prettyName() const { - return tr( "Preparing groups…", "@status" ); + return tr( "Preparing groups...", "@status" ); } Calamares::JobResult diff --git a/raveos-calamares-module/raveusers/RaveUsersViewStep.cpp b/raveos-calamares-module/raveusers/RaveUsersViewStep.cpp index 4014429..fbcd765 100644 --- a/raveos-calamares-module/raveusers/RaveUsersViewStep.cpp +++ b/raveos-calamares-module/raveusers/RaveUsersViewStep.cpp @@ -52,6 +52,44 @@ RaveUsersViewStep::prettyName() const return tr( "User" ); } +QString +RaveUsersViewStep::prettyStatus() const +{ + if ( !m_backend || m_backend->username().isEmpty() ) + { + return QString(); + } + const QString locale = getLocale(); + QString userLabel = QStringLiteral( "User" ); + QString hostLabel = QStringLiteral( "Computer name" ); + QString autoLabel = QStringLiteral( "Automatic login" ); + QString yes = QStringLiteral( "yes" ); + QString no = QStringLiteral( "no" ); + if ( locale.startsWith( QLatin1String( "hu" ) ) ) + { + userLabel = QStringLiteral( "Felhasználó" ); + hostLabel = QStringLiteral( "Gép neve" ); + autoLabel = QStringLiteral( "Automatikus bejelentkezés" ); + yes = QStringLiteral( "igen" ); + no = QStringLiteral( "nem" ); + } + else if ( locale.startsWith( QLatin1String( "de" ) ) ) + { + userLabel = QStringLiteral( "Benutzer" ); + hostLabel = QStringLiteral( "Computername" ); + autoLabel = QStringLiteral( "Automatische Anmeldung" ); + yes = QStringLiteral( "ja" ); + no = QStringLiteral( "nein" ); + } + return QStringLiteral( "%1: <b>%2</b><br/>%3: <b>%4</b><br/>%5: <b>%6</b>" ) + .arg( userLabel, + m_backend->username().toHtmlEscaped(), + hostLabel, + m_backend->hostname().toHtmlEscaped(), + autoLabel, + m_backend->autoLogin() ? yes : no ); +} + void RaveUsersViewStep::buildWidget() { @@ -62,7 +100,7 @@ RaveUsersViewStep::buildWidget() m_quickWidget = new QQuickWidget(); m_quickWidget->setResizeMode( QQuickWidget::SizeRootObjectToView ); - m_quickWidget->setClearColor( QColor( 0x40, 0x40, 0x40 ) ); + m_quickWidget->setClearColor( QColor( 0x1a, 0x1b, 0x1d ) ); QString modulePath = QStringLiteral( "/usr/lib/calamares/modules/raveusers/ui" ); if ( !QDir( modulePath ).exists() ) @@ -189,6 +227,14 @@ RaveUsersViewStep::onLeave() gs->insert( "password", Calamares::String::obscure( m_backend->userPassword() ) ); gs->insert( "setRootPassword", m_backend->rootReuseVisible() ); gs->insert( "reuseRootPassword", m_backend->reuseRootPassword() ); + if ( m_backend->autoLogin() ) + { + gs->insert( "autoLoginUser", username ); + } + else + { + gs->remove( "autoLoginUser" ); + } } void diff --git a/raveos-calamares-module/raveusers/RaveUsersViewStep.h b/raveos-calamares-module/raveusers/RaveUsersViewStep.h index 67593ac..ed096cc 100644 --- a/raveos-calamares-module/raveusers/RaveUsersViewStep.h +++ b/raveos-calamares-module/raveusers/RaveUsersViewStep.h @@ -21,6 +21,7 @@ public: ~RaveUsersViewStep() override; QString prettyName() const override; + QString prettyStatus() const override; QWidget* widget() override; bool isNextEnabled() const override; diff --git a/raveos-calamares-module/raveusers/ui/PasswordField.qml b/raveos-calamares-module/raveusers/ui/PasswordField.qml index 0dffb49..7c9955b 100644 --- a/raveos-calamares-module/raveusers/ui/PasswordField.qml +++ b/raveos-calamares-module/raveusers/ui/PasswordField.qml @@ -10,24 +10,38 @@ TextField { leftPadding: 14 rightPadding: 46 echoMode: reveal ? TextInput.Normal : TextInput.Password - color: "#ffffff" - placeholderTextColor: "#5b6270" + color: "#e8e8e6" + placeholderTextColor: "#9a9ca1" font.pixelSize: 15 background: Rectangle { - radius: 7 - color: "#303030" - border.color: field.activeFocus ? "#3d7839" : "#303030" + color: "#232427" + border.color: field.activeFocus ? "#62a052" : "#44464b" border.width: field.activeFocus ? 1.5 : 1 } - Text { - text: "\uD83D\uDC41" - font.pixelSize: 16 - color: field.reveal ? "#3d7839" : "#9ca3af" + Canvas { + width: 20 + height: 20 anchors.right: parent.right - anchors.rightMargin: 14 + anchors.rightMargin: 12 anchors.verticalCenter: parent.verticalCenter + property bool aktiv: field.reveal + onAktivChanged: requestPaint() + onPaint: { + var c = getContext("2d") + c.reset() + c.strokeStyle = aktiv ? "#62a052" : "#9a9ca1" + c.lineWidth = 1.8 + c.beginPath() + c.moveTo(2, 10) + c.quadraticCurveTo(10, 2, 18, 10) + c.quadraticCurveTo(10, 18, 2, 10) + c.stroke() + c.beginPath() + c.arc(10, 10, 2.8, 0, 2 * Math.PI) + c.stroke() + } } MouseArea { diff --git a/raveos-calamares-module/raveusers/ui/Translations.qml b/raveos-calamares-module/raveusers/ui/Translations.qml index cb267b4..ef2bb67 100644 --- a/raveos-calamares-module/raveusers/ui/Translations.qml +++ b/raveos-calamares-module/raveusers/ui/Translations.qml @@ -12,6 +12,7 @@ QtObject { property string passwordPlaceholder: "Password" property string passwordConfirmLabel: "Confirm password" property string reuseRootLabel: "Use the same password for the administrator (root)" + property string autoLoginLabel: "Log in automatically without a password" property string rootPasswordLabel: "Root password" property string rootPasswordPlaceholder: "Root password" property string rootPasswordConfirmLabel: "Confirm root password" @@ -26,6 +27,7 @@ QtObject { passwordPlaceholder = "Jelszó" passwordConfirmLabel = "Jelszó megerősítése" reuseRootLabel = "Ugyanaz a jelszó az adminisztrátorhoz (root)" + autoLoginLabel = "Automatikus bejelentkezés jelszó nélkül" rootPasswordLabel = "Root jelszó" rootPasswordPlaceholder = "Root jelszó" rootPasswordConfirmLabel = "Root jelszó megerősítése" @@ -38,6 +40,7 @@ QtObject { passwordPlaceholder = "Passwort" passwordConfirmLabel = "Passwort bestätigen" reuseRootLabel = "Dasselbe Passwort für den Administrator (root)" + autoLoginLabel = "Automatisch ohne Passwort anmelden" rootPasswordLabel = "Root-Passwort" rootPasswordPlaceholder = "Root-Passwort" rootPasswordConfirmLabel = "Root-Passwort bestätigen" @@ -50,6 +53,7 @@ QtObject { passwordPlaceholder = "Password" passwordConfirmLabel = "Confirm password" reuseRootLabel = "Use the same password for the administrator (root)" + autoLoginLabel = "Log in automatically without a password" rootPasswordLabel = "Root password" rootPasswordPlaceholder = "Root password" rootPasswordConfirmLabel = "Confirm root password" diff --git a/raveos-calamares-module/raveusers/ui/raveusers.qml b/raveos-calamares-module/raveusers/ui/raveusers.qml index 25e090f..030f3f4 100644 --- a/raveos-calamares-module/raveusers/ui/raveusers.qml +++ b/raveos-calamares-module/raveusers/ui/raveusers.qml @@ -5,18 +5,16 @@ import "." as RaveUsersModule Rectangle { id: root - color: "#2B2B2B" - radius: 14 + color: "#1a1b1d" - readonly property color cCardBg: "#20232a" - readonly property color cCardBorder: "#333947" - readonly property color cInputBg: "#303030" - readonly property color cInputBorder: "#303030" - readonly property color cAccentGreen: "#3d7839" - readonly property color cTextWhite: "#ffffff" - readonly property color cTextMuted: "#8b93a3" - readonly property color cTextFaint: "#5b6270" - readonly property color cErrorRed: "#ff6b6b" + readonly property color cCardBorder: "#34363a" + readonly property color cInputBg: "#232427" + readonly property color cInputBorder: "#44464b" + readonly property color cAccentGreen: "#62a052" + readonly property color cTextWhite: "#e8e8e6" + readonly property color cTextMuted: "#b7b9bd" + readonly property color cTextFaint: "#9a9ca1" + readonly property color cErrorRed: "#d9a441" property bool showUserPassword: false property bool showRootPassword: false @@ -29,20 +27,64 @@ Rectangle { RaveUsersModule.Translations.setLanguage(systemLocale) } + component RegiJelolo: CheckBox { + id: jelolo + + indicator: Rectangle { + implicitWidth: 20 + implicitHeight: 20 + x: jelolo.leftPadding + y: parent.height / 2 - height / 2 + color: jelolo.checked ? cAccentGreen : cInputBg + border.color: jelolo.checked ? cAccentGreen : cInputBorder + border.width: 1 + + Canvas { + anchors.fill: parent + visible: jelolo.checked + onVisibleChanged: if (visible) requestPaint() + onPaint: { + var c = getContext("2d") + c.reset() + c.strokeStyle = "#1a1b1d" + c.lineWidth = 2.5 + c.beginPath() + c.moveTo(5, 10) + c.lineTo(9, 14) + c.lineTo(15, 6) + c.stroke() + } + } + } + + contentItem: Text { + text: jelolo.text + color: cTextWhite + font.pixelSize: 14 + verticalAlignment: Text.AlignVCenter + leftPadding: jelolo.indicator.width + 12 + } + } + ColumnLayout { anchors.fill: parent anchors.margins: 40 spacing: 0 - Item { + Flickable { + id: gorgeto Layout.fillWidth: true Layout.fillHeight: true + contentHeight: tartalom.implicitHeight + 20 + clip: true + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: ScrollBar {} ColumnLayout { - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - anchors.topMargin: 10 - width: Math.min(parent.width - 40, 540) + id: tartalom + x: (gorgeto.width - width) / 2 + y: 10 + width: Math.min(gorgeto.width - 40, 540) spacing: 16 Image { @@ -81,7 +123,7 @@ Rectangle { Text { text: RaveUsersModule.Translations.usernameLabel - color: "#c7ccd6" + color: cTextMuted font.pixelSize: 14 font.weight: Font.Medium } @@ -95,10 +137,9 @@ Rectangle { text: backend.username placeholderText: "raveuser" color: cTextWhite - placeholderTextColor: "#5b6270" + placeholderTextColor: cTextFaint font.pixelSize: 15 background: Rectangle { - radius: 7 color: cInputBg border.color: usernameField.activeFocus ? cAccentGreen : cInputBorder border.width: usernameField.activeFocus ? 1.5 : 1 @@ -120,7 +161,7 @@ Rectangle { Text { text: RaveUsersModule.Translations.hostnameLabel - color: "#c7ccd6" + color: cTextMuted font.pixelSize: 14 font.weight: Font.Medium } @@ -134,10 +175,9 @@ Rectangle { text: backend.hostname placeholderText: "raveos-pc" color: cTextWhite - placeholderTextColor: "#5b6270" + placeholderTextColor: cTextFaint font.pixelSize: 15 background: Rectangle { - radius: 7 color: cInputBg border.color: hostnameField.activeFocus ? cAccentGreen : cInputBorder border.width: hostnameField.activeFocus ? 1.5 : 1 @@ -159,7 +199,7 @@ Rectangle { Text { text: RaveUsersModule.Translations.passwordLabel - color: "#c7ccd6" + color: cTextMuted font.pixelSize: 14 font.weight: Font.Medium } @@ -202,41 +242,19 @@ Rectangle { opacity: 0.6 } - CheckBox { - id: reuseRootCheck + RegiJelolo { + Layout.fillWidth: true + text: RaveUsersModule.Translations.autoLoginLabel + checked: backend.autoLogin + onToggled: backend.setAutoLogin(checked) + } + + RegiJelolo { Layout.fillWidth: true visible: backend.rootReuseVisible text: RaveUsersModule.Translations.reuseRootLabel checked: backend.reuseRootPassword onToggled: backend.setReuseRootPassword(checked) - - indicator: Rectangle { - implicitWidth: 20 - implicitHeight: 20 - x: reuseRootCheck.leftPadding - y: parent.height / 2 - height / 2 - radius: 4 - color: reuseRootCheck.checked ? cAccentGreen : cInputBg - border.color: reuseRootCheck.checked ? cAccentGreen : cInputBorder - border.width: 1 - - Text { - anchors.centerIn: parent - text: "\u2713" - font.pixelSize: 14 - font.bold: true - color: "#0f1713" - visible: reuseRootCheck.checked - } - } - - contentItem: Text { - text: reuseRootCheck.text - color: "#d7dbe2" - font.pixelSize: 14 - verticalAlignment: Text.AlignVCenter - leftPadding: reuseRootCheck.indicator.width + 12 - } } ColumnLayout { @@ -246,7 +264,7 @@ Rectangle { Text { text: RaveUsersModule.Translations.rootPasswordLabel - color: "#c7ccd6" + color: cTextMuted font.pixelSize: 14 font.weight: Font.Medium Layout.topMargin: 4 diff --git a/raveos-calamares-module/welcome/CMakeLists.txt b/raveos-calamares-module/welcome/CMakeLists.txt index 9d28587..063f23b 100644 --- a/raveos-calamares-module/welcome/CMakeLists.txt +++ b/raveos-calamares-module/welcome/CMakeLists.txt @@ -1,17 +1,22 @@ -find_package(Qt6 REQUIRED COMPONENTS Core Widgets) +find_package(Qt6 REQUIRED COMPONENTS Core Widgets Qml) +find_package(PkgConfig REQUIRED) +pkg_check_modules(XKBCOMMON REQUIRED IMPORTED_TARGET xkbcommon) calamares_add_plugin(ravewelcome TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES RaveWelcomeViewStep.cpp + RaveBillentyuzet.cpp LINK_LIBRARIES Qt6::Core Qt6::Widgets + Qt6::Qml + PkgConfig::XKBCOMMON Calamares::calamares ) install( - FILES module.desc ravewelcome.conf + FILES module.desc DESTINATION lib/calamares/modules/ravewelcome ) diff --git a/raveos-calamares-module/welcome/RaveBillentyuzet.cpp b/raveos-calamares-module/welcome/RaveBillentyuzet.cpp new file mode 100644 index 0000000..aeb1205 --- /dev/null +++ b/raveos-calamares-module/welcome/RaveBillentyuzet.cpp @@ -0,0 +1,81 @@ +#include "RaveBillentyuzet.h" + +#include <QQmlEngine> + +#include <xkbcommon/xkbcommon.h> + +namespace +{ +constexpr int EvdevEltolas = 8; + +const QList< QList< int > >& sorKodok() +{ + static const QList< QList< int > > kodok { + { 41, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }, + { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27 }, + { 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 43 }, + { 86, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53 }, + }; + return kodok; +} +} + +QVariantList +RaveBillentyuzet::gombok( const QString& layout, const QString& variant ) const +{ + QVariantList sorok; + if ( layout.isEmpty() ) + { + return sorok; + } + + xkb_context* context = xkb_context_new( XKB_CONTEXT_NO_FLAGS ); + if ( !context ) + { + return sorok; + } + + const QByteArray layoutBytes = layout.toUtf8(); + const QByteArray variantBytes = variant.toUtf8(); + xkb_rule_names names {}; + names.rules = "evdev"; + names.model = "pc105"; + names.layout = layoutBytes.constData(); + names.variant = variantBytes.isEmpty() ? nullptr : variantBytes.constData(); + + xkb_keymap* keymap = xkb_keymap_new_from_names( context, &names, XKB_KEYMAP_COMPILE_NO_FLAGS ); + if ( !keymap ) + { + xkb_context_unref( context ); + return sorok; + } + xkb_state* state = xkb_state_new( keymap ); + + for ( const auto& sor : sorKodok() ) + { + QVariantList cimkek; + for ( int kod : sor ) + { + char buffer[ 16 ] = {}; + xkb_state_key_get_utf8( state, static_cast< xkb_keycode_t >( kod + EvdevEltolas ), buffer, sizeof( buffer ) ); + cimkek << QString::fromUtf8( buffer ).toUpper(); + } + sorok << QVariant( cimkek ); + } + + xkb_state_unref( state ); + xkb_keymap_unref( keymap ); + xkb_context_unref( context ); + return sorok; +} + +void +RaveBillentyuzet::regisztral() +{ + if ( qmlTypeId( "RaveOSNative", 1, 0, "Billentyuzet" ) >= 0 ) + { + return; + } + qmlRegisterSingletonType< RaveBillentyuzet >( + "RaveOSNative", 1, 0, "Billentyuzet", []( QQmlEngine*, QJSEngine* ) -> QObject* { return new RaveBillentyuzet; } ); +} diff --git a/raveos-calamares-module/welcome/RaveBillentyuzet.h b/raveos-calamares-module/welcome/RaveBillentyuzet.h new file mode 100644 index 0000000..4a6b662 --- /dev/null +++ b/raveos-calamares-module/welcome/RaveBillentyuzet.h @@ -0,0 +1,16 @@ +#pragma once + +#include <QObject> +#include <QVariantList> + +class RaveBillentyuzet : public QObject +{ + Q_OBJECT + +public: + using QObject::QObject; + + Q_INVOKABLE QVariantList gombok( const QString& layout, const QString& variant ) const; + + static void regisztral(); +}; diff --git a/raveos-calamares-module/welcome/RaveWelcomeViewStep.cpp b/raveos-calamares-module/welcome/RaveWelcomeViewStep.cpp index c2d58c7..2f7c1ea 100644 --- a/raveos-calamares-module/welcome/RaveWelcomeViewStep.cpp +++ b/raveos-calamares-module/welcome/RaveWelcomeViewStep.cpp @@ -1,25 +1,64 @@ #include "RaveWelcomeViewStep.h" -#include <QComboBox> +#include "RaveBillentyuzet.h" + +#include <QButtonGroup> #include <QFrame> +#include <QGridLayout> #include <QHBoxLayout> #include <QLabel> #include <QLocale> #include <QPainter> #include <QProcess> #include <QPixmap> -#include <QResizeEvent> +#include <QPushButton> #include <QVBoxLayout> #include <Branding.h> #include <GlobalStorage.h> #include <JobQueue.h> +#include <ViewManager.h> #include <locale/Translation.h> -#include <locale/TranslationsModel.h> #include <utils/Retranslator.h> CALAMARES_PLUGIN_FACTORY_DEFINITION(RaveWelcomeViewStepFactory, registerPlugin<RaveWelcomeViewStep>();) +namespace +{ +struct LanguageTexts +{ + QString title; + QString next; + QString installer; +}; + +LanguageTexts textsFor(const QString& localeId) +{ + if (localeId.startsWith(QLatin1String("hu"))) + return { QStringLiteral("VÁLASSZ NYELVET"), QStringLiteral("Tovább"), QStringLiteral("TELEPÍTŐ") }; + if (localeId.startsWith(QLatin1String("de"))) + return { QStringLiteral("SPRACHE WÄHLEN"), QStringLiteral("Weiter"), QStringLiteral("INSTALLATION") }; + return { QStringLiteral("CHOOSE YOUR LANGUAGE"), QStringLiteral("Next"), QStringLiteral("INSTALLER") }; +} + +QString fullLocaleName(const QString& localeId) +{ + QString lang = QLocale(localeId).name(); + if (lang.isEmpty()) + lang = localeId; + return lang.contains('.') ? lang : lang + ".UTF-8"; +} + +QString nativeName(const QString& localeId) +{ + QString name = QLocale(localeId).nativeLanguageName(); + if (name.isEmpty()) + return localeId; + name[0] = name[0].toUpper(); + return name; +} +} + class BgWidget : public QWidget { public: @@ -30,9 +69,16 @@ public: protected: void paintEvent(QPaintEvent*) override { - if (m_pixmap.isNull()) return; QPainter p(this); - p.drawPixmap(rect(), m_pixmap); + p.fillRect(rect(), QColor(0x1a, 0x1b, 0x1d)); + if (m_pixmap.isNull()) return; + const QSize scaled = m_pixmap.size().scaled(size(), Qt::KeepAspectRatioByExpanding); + const QRect target((width() - scaled.width()) / 2, + (height() - scaled.height()) * 4 / 10, + scaled.width(), + scaled.height()); + p.setRenderHint(QPainter::SmoothPixmapTransform); + p.drawPixmap(target, m_pixmap); } private: @@ -42,7 +88,8 @@ private: RaveWelcomeViewStep::RaveWelcomeViewStep(QObject* parent) : Calamares::ViewStep(parent) { - m_localeIds = { "de", "en", "en_GB", "hu" }; + RaveBillentyuzet::regisztral(); + m_localeIds = { "hu", "en", "en_GB", "de" }; } RaveWelcomeViewStep::~RaveWelcomeViewStep() @@ -56,13 +103,13 @@ QString RaveWelcomeViewStep::prettyName() const const QString locale = getLocale(); if (locale.startsWith("hu")) { - return QStringLiteral("Üdvözlés"); + return QStringLiteral("Nyelv"); } if (locale.startsWith("de")) { - return QStringLiteral("Willkommen"); + return QStringLiteral("Sprache"); } - return tr("Welcome"); + return tr("Language"); } QString RaveWelcomeViewStep::getLocale() const @@ -103,53 +150,114 @@ void RaveWelcomeViewStep::buildWidget() if (!imgPath.isEmpty()) bg->setPixmap(QPixmap(imgPath)); - auto* bar = new QFrame(); - bar->setObjectName("ravewelcomeBar"); - bar->setFixedHeight(58); + m_tag = new QLabel(); + m_tag->setObjectName("ravewelcomeTag"); - m_langCombo = new QComboBox(bar); - m_langCombo->setObjectName("ravewelcomeCombo"); - m_langCombo->setFixedHeight(40); - m_langCombo->setMinimumWidth(300); + auto* panel = new QFrame(); + panel->setObjectName("ravewelcomeBar"); - auto* model = new Calamares::Locale::TranslationsModel(m_localeIds, m_langCombo); - m_langCombo->setModel(model); + m_title = new QLabel(); + m_title->setObjectName("ravewelcomeTitle"); + m_localeLabel = new QLabel(); + m_localeLabel->setObjectName("ravewelcomeLocale"); - QLocale sys = QLocale::system(); - QString sysName = sys.name(); - m_currentLocaleIndex = 0; + auto* headerLayout = new QHBoxLayout(); + headerLayout->setContentsMargins(0, 0, 0, 0); + headerLayout->addWidget(m_title); + headerLayout->addStretch(); + headerLayout->addWidget(m_localeLabel, 0, Qt::AlignBottom); + + m_langButtons = new QButtonGroup(panel); + m_langButtons->setExclusive(true); + auto* langLayout = new QGridLayout(); + langLayout->setContentsMargins(0, 0, 0, 0); + langLayout->setHorizontalSpacing(8); for (int i = 0; i < m_localeIds.size(); ++i) { - if (m_localeIds[i] == sysName || sysName.startsWith(m_localeIds[i].left(2))) - { - m_currentLocaleIndex = i; - break; - } + auto* button = new QPushButton(nativeName(m_localeIds[i])); + button->setObjectName("ravewelcomeLang"); + button->setCheckable(true); + button->setMinimumHeight(48); + button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + m_langButtons->addButton(button, i); + langLayout->addWidget(button, 0, i); + } + + m_next = new QPushButton(); + m_next->setObjectName("ravewelcomeNext"); + m_next->setMinimumHeight(48); + connect(m_next, &QPushButton::clicked, this, []() + { + if (auto* vm = Calamares::ViewManager::instance()) + vm->next(); + }); + + auto* actionLayout = new QHBoxLayout(); + actionLayout->setContentsMargins(0, 0, 0, 0); + actionLayout->setSpacing(12); + actionLayout->addLayout(langLayout, 1); + actionLayout->addWidget(m_next); + + auto* panelLayout = new QVBoxLayout(panel); + panelLayout->setContentsMargins(24, 20, 24, 20); + panelLayout->setSpacing(14); + panelLayout->addLayout(headerLayout); + panelLayout->addLayout(actionLayout); + + const QString sysName = QLocale::system().name(); + int exact = -1; + int prefix = -1; + for (int i = 0; i < m_localeIds.size(); ++i) + { + if (m_localeIds[i] == sysName) + exact = i; + else if (prefix < 0 && sysName.startsWith(m_localeIds[i].left(2))) + prefix = i; } - int enIdx = m_localeIds.indexOf("en"); - if (enIdx >= 0 && m_currentLocaleIndex == 0 && m_localeIds[0] != "en") - m_currentLocaleIndex = enIdx; + if (exact >= 0) + m_currentLocaleIndex = exact; + else if (prefix >= 0) + m_currentLocaleIndex = prefix; + else + m_currentLocaleIndex = qMax(0, m_localeIds.indexOf("en")); - m_langCombo->setCurrentIndex(m_currentLocaleIndex); + if (auto* button = m_langButtons->button(m_currentLocaleIndex)) + button->setChecked(true); applyLiveKeyboardLayout(m_localeIds.value(m_currentLocaleIndex)); - connect(m_langCombo, QOverload<int>::of(&QComboBox::activated), + connect(m_langButtons, &QButtonGroup::idClicked, this, &RaveWelcomeViewStep::onLanguageChanged); - auto* barLayout = new QHBoxLayout(bar); - barLayout->setContentsMargins(16, 0, 16, 0); - barLayout->addStretch(); - barLayout->addWidget(m_langCombo); - barLayout->addStretch(); - auto* mainLayout = new QVBoxLayout(bg); - mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); + mainLayout->addWidget(m_tag, 0, Qt::AlignLeft | Qt::AlignTop); mainLayout->addStretch(); - mainLayout->addWidget(bar); + mainLayout->addWidget(panel); m_widget = bg; + updateTexts(); +} + +void RaveWelcomeViewStep::updateTexts() +{ + const QString localeId = m_localeIds.value(m_currentLocaleIndex); + const LanguageTexts texts = textsFor(localeId); + + QString version; + if (Calamares::Branding::instance()) + version = Calamares::Branding::instance()->string(Calamares::Branding::Version); + const QString product = version.isEmpty() ? QStringLiteral("RAVEOS") : QStringLiteral("RAVEOS ") + version; + + m_tag->setText(product + QStringLiteral(" · ") + texts.installer); + m_title->setText(texts.title); + m_localeLabel->setText(fullLocaleName(localeId)); + m_next->setText(texts.next); +} + +QSize RaveWelcomeViewStep::widgetMargins(Qt::Orientations) +{ + return QSize(28, 24); } QWidget* RaveWelcomeViewStep::widget() @@ -172,10 +280,10 @@ void RaveWelcomeViewStep::onLanguageChanged(int index) Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); if (gs) { - QString lang = QLocale(localeId).name(); // e.g. "hu" -> "hu_HU" + QString lang = QLocale(localeId).name(); if (lang.isEmpty()) lang = localeId; - QString fullLocale = lang.contains('.') ? lang : lang + ".UTF-8"; + const QString fullLocale = fullLocaleName(localeId); const char* lcKeys[] = { "LANG", "LC_NUMERIC", "LC_TIME", "LC_MONETARY", "LC_PAPER", @@ -195,6 +303,7 @@ void RaveWelcomeViewStep::onLanguageChanged(int index) Calamares::installTranslator(tid, brandingTranslationsPrefix()); applyLiveKeyboardLayout(localeId); + updateTexts(); } QString RaveWelcomeViewStep::brandingTranslationsPrefix() const diff --git a/raveos-calamares-module/welcome/RaveWelcomeViewStep.h b/raveos-calamares-module/welcome/RaveWelcomeViewStep.h index 87b42dd..10289e9 100644 --- a/raveos-calamares-module/welcome/RaveWelcomeViewStep.h +++ b/raveos-calamares-module/welcome/RaveWelcomeViewStep.h @@ -8,8 +8,9 @@ #include <viewpages/ViewStep.h> #include <Job.h> -class QComboBox; +class QButtonGroup; class QLabel; +class QPushButton; class PLUGINDLLEXPORT RaveWelcomeViewStep : public Calamares::ViewStep { @@ -21,6 +22,7 @@ public: QString prettyName() const override; QWidget* widget() override; + QSize widgetMargins(Qt::Orientations panelSides) override; bool isNextEnabled() const override; bool isBackEnabled() const override; @@ -36,13 +38,17 @@ private slots: private: void buildWidget(); + void updateTexts(); QString getLocale() const; QString brandingTranslationsPrefix() const; void applyLiveKeyboardLayout(const QString& localeId); - QWidget* m_widget = nullptr; - QLabel* m_bgLabel = nullptr; - QComboBox* m_langCombo = nullptr; + QWidget* m_widget = nullptr; + QButtonGroup* m_langButtons = nullptr; + QLabel* m_tag = nullptr; + QLabel* m_title = nullptr; + QLabel* m_localeLabel = nullptr; + QPushButton* m_next = nullptr; QStringList m_localeIds; int m_currentLocaleIndex = 0; diff --git a/raveos-calamares-module/welcome/ravewelcome.conf b/raveos-calamares-module/welcome/ravewelcome.conf deleted file mode 100644 index 6acb1c7..0000000 --- a/raveos-calamares-module/welcome/ravewelcome.conf +++ /dev/null @@ -1,7 +0,0 @@ ---- -# Available languages (must match the branding/lang directory) -languages: - - de - - en - - en_GB - - hu diff --git a/raveos-calamares-module/wifi/CMakeLists.txt b/raveos-calamares-module/wifi/CMakeLists.txt index 28335b2..eb9771f 100644 --- a/raveos-calamares-module/wifi/CMakeLists.txt +++ b/raveos-calamares-module/wifi/CMakeLists.txt @@ -23,7 +23,6 @@ install( install( FILES ui/wifi.qml - ui/Style.qml ui/Translations.qml ui/qmldir DESTINATION lib/calamares/modules/wifi/ui diff --git a/raveos-calamares-module/wifi/NetworkManager.cpp b/raveos-calamares-module/wifi/NetworkManager.cpp index cb88698..94abe2b 100644 --- a/raveos-calamares-module/wifi/NetworkManager.cpp +++ b/raveos-calamares-module/wifi/NetworkManager.cpp @@ -1,5 +1,7 @@ #include "NetworkManager.h" +#include <algorithm> + #include <QDBusInterface> #include <QDBusReply> #include <QDBusObjectPath> @@ -17,6 +19,13 @@ typedef QMap<QString, QVariantMap> NMConnectionSettings; static const QString LOG_FILE = "/tmp/calamares-wifi.log"; +static constexpr uint NmDeviceTypeWifi = 2; +static constexpr uint NmApFlagPrivacy = 0x1; +static constexpr uint NmKeyMgmtPsk = 0x100; +static constexpr uint NmKeyMgmt8021x = 0x200; +static constexpr uint NmKeyMgmtSae = 0x400; +static constexpr int NmPmfRequired = 3; + static void wifiLog(const QString& message) { QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); @@ -55,11 +64,6 @@ NetworkManager::NetworkManager(QObject* parent) timer->start(3000); } -QStringList NetworkManager::networks() const -{ - return m_networks; -} - bool NetworkManager::isConnected() const { return m_connected; @@ -142,7 +146,6 @@ void NetworkManager::updateConnectionState() void NetworkManager::scan() { - m_networks.clear(); wifiLog("Starting scan..."); QDBusInterface nm( @@ -189,7 +192,7 @@ void NetworkManager::scan() uint deviceType = typeReply.isValid() ? typeReply.value().toUInt() : 0; wifiLog(QString("Device %1 type: %2").arg(dev.path()).arg(deviceType)); - if (deviceType != 2) // Not WiFi + if (deviceType != NmDeviceTypeWifi) continue; foundWireless = true; @@ -219,7 +222,6 @@ void NetworkManager::scan() void NetworkManager::fetchAccessPoints() { - m_networks.clear(); wifiLog("Fetching access points..."); QDBusInterface nm( @@ -232,6 +234,7 @@ void NetworkManager::fetchAccessPoints() if (!nm.isValid()) { wifiLog("NM interface not valid in fetchAccessPoints"); + m_accessPoints.clear(); emit networksChanged(); return; } @@ -241,10 +244,13 @@ void NetworkManager::fetchAccessPoints() if (!devices.isValid()) { wifiLog("GetDevices failed in fetchAccessPoints"); + m_accessPoints.clear(); emit networksChanged(); return; } + QMap<QString, QVariantMap> strongest; + for (const auto& dev : devices.value()) { QDBusInterface devProps( @@ -260,8 +266,8 @@ void NetworkManager::fetchAccessPoints() "DeviceType" ); - if (!typeReply.isValid() || typeReply.value().toUInt() != 2) - continue; // Not WiFi + if (!typeReply.isValid() || typeReply.value().toUInt() != NmDeviceTypeWifi) + continue; QDBusInterface wirelessIf( "org.freedesktop.NetworkManager", @@ -289,22 +295,41 @@ void NetworkManager::fetchAccessPoints() QDBusConnection::systemBus() ); - QByteArray ssidRaw = apIf.property("Ssid").toByteArray(); - QString ssid = QString::fromUtf8(ssidRaw); + const QString ssid = QString::fromUtf8(apIf.property("Ssid").toByteArray()); + if (ssid.isEmpty()) + continue; - uint frequency = apIf.property("Frequency").toUInt(); - QString band = (frequency > 4000) ? "5GHz" : "2.4GHz"; + const uint frequency = apIf.property("Frequency").toUInt(); + const int strength = apIf.property("Strength").toInt(); + const bool secured = (apIf.property("Flags").toUInt() & NmApFlagPrivacy) != 0 + || apIf.property("WpaFlags").toUInt() != 0 + || apIf.property("RsnFlags").toUInt() != 0; - wifiLog(QString("Found SSID: %1 (%2, %3 MHz)").arg(ssid, band).arg(frequency)); + wifiLog(QString("Found SSID: %1 (%2 MHz, %3%)").arg(ssid).arg(frequency).arg(strength)); - if (!ssid.isEmpty() && !m_networks.contains(ssid)) - m_networks << ssid; + if (strongest.contains(ssid) && strongest[ssid].value("strength").toInt() >= strength) + continue; + + QVariantMap item; + item.insert("ssid", ssid); + item.insert("strength", strength); + item.insert("secured", secured); + item.insert("band", frequency > 5900 ? QStringLiteral("6 GHz") : frequency > 4000 ? QStringLiteral("5 GHz") : QStringLiteral("2.4 GHz")); + strongest.insert(ssid, item); } } - m_networks.sort(Qt::CaseInsensitive); + QList<QVariantMap> sorted = strongest.values(); + std::sort(sorted.begin(), sorted.end(), [](const QVariantMap& a, const QVariantMap& b) + { + return a.value("strength").toInt() > b.value("strength").toInt(); + }); + + m_accessPoints.clear(); + for (const auto& item : sorted) + m_accessPoints << item; - wifiLog(QString("Total networks found: %1").arg(m_networks.size())); + wifiLog(QString("Total networks found: %1").arg(m_accessPoints.size())); emit networksChanged(); } @@ -402,12 +427,12 @@ void NetworkManager::connectTo(const QString& ssid, const QString& password) } - bool apSupportsPsk = ((apWpaFlags & 0x100) != 0) || ((apRsnFlags & 0x100) != 0); - bool apSupportsSae = (apRsnFlags & 0x400) != 0; // WPA3 - bool apSupportsEnterprise = ((apWpaFlags & 0x200) != 0) || ((apRsnFlags & 0x200) != 0); + bool apSupportsPsk = ((apWpaFlags & NmKeyMgmtPsk) != 0) || ((apRsnFlags & NmKeyMgmtPsk) != 0); + bool apSupportsSae = (apRsnFlags & NmKeyMgmtSae) != 0; + bool apSupportsEnterprise = ((apWpaFlags & NmKeyMgmt8021x) != 0) || ((apRsnFlags & NmKeyMgmt8021x) != 0); bool apIsOpen = (apFlags == 0) && (apWpaFlags == 0) && (apRsnFlags == 0); - bool apHasPrivacy = (apFlags & 0x1) != 0; + bool apHasPrivacy = (apFlags & NmApFlagPrivacy) != 0; wifiLog(QString("Security detection: PSK=%1, SAE=%2, Enterprise=%3, Open=%4, Privacy=%5") .arg(apSupportsPsk).arg(apSupportsSae).arg(apSupportsEnterprise).arg(apIsOpen).arg(apHasPrivacy)); @@ -448,23 +473,13 @@ void NetworkManager::connectTo(const QString& ssid, const QString& password) wifiLog("Using WPA3-SAE security"); wifiSecurity["key-mgmt"] = QString("sae"); wifiSecurity["psk"] = password; - wifiSecurity["pmf"] = 3; + wifiSecurity["pmf"] = NmPmfRequired; } else if (apSupportsPsk) { - if (apSupportsSae) - { - wifiLog("Using WPA3-SAE (transition mode - both PSK and SAE available)"); - wifiSecurity["key-mgmt"] = QString("sae"); - wifiSecurity["psk"] = password; - wifiSecurity["pmf"] = 3; // Required for SAE - } - else - { - wifiLog("Using WPA-PSK security"); - wifiSecurity["key-mgmt"] = QString("wpa-psk"); - wifiSecurity["psk"] = password; - } + wifiLog("Using WPA-PSK security"); + wifiSecurity["key-mgmt"] = QString("wpa-psk"); + wifiSecurity["psk"] = password; } else if (isHiddenNetwork) { @@ -540,17 +555,13 @@ void NetworkManager::connectTo(const QString& ssid, const QString& password) { m_lastSecurityType = "sae"; } - else if (apSupportsPsk && apSupportsSae) - { - m_lastSecurityType = "sae"; // Transition mode, we used SAE - } else if (apSupportsPsk) { m_lastSecurityType = "wpa-psk"; } else { - m_lastSecurityType = ""; // Open network + m_lastSecurityType = ""; } wifiLog(QString("Stored security type: '%1'").arg(m_lastSecurityType)); diff --git a/raveos-calamares-module/wifi/NetworkManager.h b/raveos-calamares-module/wifi/NetworkManager.h index dd58a9a..9f74bcb 100644 --- a/raveos-calamares-module/wifi/NetworkManager.h +++ b/raveos-calamares-module/wifi/NetworkManager.h @@ -3,22 +3,23 @@ #include <QObject> #include <QString> #include <QStringList> +#include <QVariantList> class NetworkManager : public QObject { Q_OBJECT - Q_PROPERTY(QStringList networks READ networks NOTIFY networksChanged) + Q_PROPERTY(QVariantList accessPoints READ accessPoints NOTIFY networksChanged) Q_PROPERTY(bool connected READ isConnected NOTIFY connectionChanged) public: explicit NetworkManager(QObject* parent = nullptr); - QStringList networks() const; + QVariantList accessPoints() const { return m_accessPoints; } bool isConnected() const; QString lastConnectedSsid() const { return m_lastConnectedSsid; } QString lastConnectedPassword() const { return m_lastConnectedPassword; } - QString lastSecurityType() const { return m_lastSecurityType; } // "wpa-psk" or "sae" + QString lastSecurityType() const { return m_lastSecurityType; } public slots: void scan(); @@ -36,11 +37,11 @@ private: void updateConnectionState(); void fetchAccessPoints(); - QStringList m_networks; + QVariantList m_accessPoints; bool m_connected = false; QString m_lastConnectedSsid; QString m_lastConnectedPassword; - QString m_lastSecurityType; // "wpa-psk", "sae", or "" (open) + QString m_lastSecurityType; int m_connectionCheckCount = 0; }; diff --git a/raveos-calamares-module/wifi/WifiViewStep.cpp b/raveos-calamares-module/wifi/WifiViewStep.cpp index 350bd43..7f0e7dc 100644 --- a/raveos-calamares-module/wifi/WifiViewStep.cpp +++ b/raveos-calamares-module/wifi/WifiViewStep.cpp @@ -1,5 +1,7 @@ #include "WifiViewStep.h" +#include "../common/RaveBrandingQml.h" + #include <QVBoxLayout> #include <QQuickWidget> #include <QQmlContext> @@ -50,15 +52,24 @@ WifiViewStep::~WifiViewStep() QString WifiViewStep::prettyName() const { - m_locale = getLocale(); - - if (m_locale.startsWith("hu")) - { - return QStringLiteral("Wi-Fi"); - } return QStringLiteral("Wi-Fi"); } +QString WifiViewStep::prettyStatus() const +{ + const QString ssid = m_networkManager && m_networkManager->isConnected() ? m_networkManager->lastConnectedSsid() : QString(); + if (!ssid.isEmpty()) + return QStringLiteral("Wi-Fi: <b>%1</b>").arg(ssid.toHtmlEscaped()); + if (!hasActiveNetwork()) + return QString(); + const QString locale = getLocale(); + if (locale.startsWith("hu")) + return QStringLiteral("Meglévő hálózati kapcsolat"); + if (locale.startsWith("de")) + return QStringLiteral("Bestehende Netzwerkverbindung"); + return QStringLiteral("Existing network connection"); +} + QWidget* WifiViewStep::widget() { if (!m_widget) @@ -88,6 +99,7 @@ QWidget* WifiViewStep::widget() qmlPath = QDir::currentPath() + QStringLiteral("/wifi/ui/wifi.qml"); } + addRaveBrandingImportPath(m_quickWidget->engine()); m_quickWidget->setSource(QUrl::fromLocalFile(qmlPath)); layout->addWidget(m_quickWidget); diff --git a/raveos-calamares-module/wifi/WifiViewStep.h b/raveos-calamares-module/wifi/WifiViewStep.h index efe3e64..b03102a 100644 --- a/raveos-calamares-module/wifi/WifiViewStep.h +++ b/raveos-calamares-module/wifi/WifiViewStep.h @@ -21,6 +21,7 @@ public: ~WifiViewStep() override; QString prettyName() const override; + QString prettyStatus() const override; QWidget* widget() override; bool isNextEnabled() const override; diff --git a/raveos-calamares-module/wifi/ui/Style.qml b/raveos-calamares-module/wifi/ui/Style.qml deleted file mode 100644 index 360d4d2..0000000 --- a/raveos-calamares-module/wifi/ui/Style.qml +++ /dev/null @@ -1,161 +0,0 @@ -pragma Singleton -import QtQuick 2.15 - -/** - * WiFi Modul Stílus Beállítások - * ============================== - * - * Itt tudod testreszabni a modul kinézetét. - * Minden szín hexadecimális formátumban van megadva: #RRGGBB - * - * Példa színek: - * Fehér: #ffffff - * Fekete: #000000 - * Piros: #ff0000 - * Zöld: #00ff00 - * Kék: #0000ff - */ - -QtObject { - // ========================================= - // HÁTTÉR SZÍNEK - // ========================================= - - // Fő háttérszín (az egész modul háttere) - readonly property color backgroundColor: "#404040" - - // Lista háttérszín (ahol a WiFi hálózatok vannak) - readonly property color listBackgroundColor: "#2B2B2B" - - // Lista fejléc háttérszín ("Elérhető hálózatok" sor) - readonly property color listHeaderColor: "#3d7839" - - // Elem hover háttérszín (amikor az egér fölötte van) - readonly property color itemHoverColor: "#2d3238" - - // Kiválasztott elem háttérszín - readonly property color itemSelectedColor: "#3d7839" - - // ========================================= - // SZÖVEG SZÍNEK - // ========================================= - - // Fő szöveg szín (címek, hálózat nevek) - readonly property color textColor: "#ffffff" - - // Másodlagos szöveg szín (leírások, információk) - readonly property color textSecondaryColor: "#b2b2b2" - - // Halványított szöveg szín (tippek, kihagyható info) - readonly property color textMutedColor: "#707070" - - // Letiltott szöveg szín - readonly property color textDisabledColor: "#606060" - - // ========================================= - // GOMB SZÍNEK - // ========================================= - - // Fő gomb háttérszín (Csatlakozás gomb) - readonly property color buttonPrimaryColor: "#3d7839" - - // Fő gomb hover szín - readonly property color buttonPrimaryHoverColor: "#3d7839" - - // Másodlagos gomb háttérszín (Frissítés gomb) - readonly property color buttonSecondaryColor: "#3d4248" - - // Másodlagos gomb hover szín - readonly property color buttonSecondaryHoverColor: "#4a5058" - - // Letiltott gomb háttérszín - readonly property color buttonDisabledColor: "#3d4248" - - // ========================================= - // INPUT MEZŐ SZÍNEK - // ========================================= - - // Input mező háttérszín - readonly property color inputBackgroundColor: "#2B2B2B" - - // Input mező letiltott háttérszín - readonly property color inputDisabledColor: "#2B2B2B" - - // Input mező placeholder szöveg szín - readonly property color inputPlaceholderColor: "#FFFFFF" - - // Input mező keret szín - readonly property color inputBorderColor: "#3d4248" - - // Input mező fókuszált keret szín - readonly property color inputFocusBorderColor: "#3d7839" - - // ========================================= - // ÁLLAPOT SZÍNEK - // ========================================= - - // Sikeres állapot szín (csatlakozva) - readonly property color successColor: "#2e7d32" - - // Sikeres pipa szín - readonly property color successCheckColor: "#4CAF50" - - // Folyamatban állapot szín (csatlakozás...) - readonly property color progressColor: "#37474f" - - // Toggle bekapcsolt szín - readonly property color toggleOnColor: "#4CAF50" - - // Toggle kikapcsolt szín - readonly property color toggleOffColor: "#555555" - - // ========================================= - // KERET ÉS VONAL SZÍNEK - // ========================================= - - // Lista keret szín - readonly property color borderColor: "#3d4248" - - // Elválasztó vonal szín (lista elemek között) - readonly property color separatorColor: "#3d4248" - - // ========================================= - // MÉRETEK - // ========================================= - - // Címsor betűméret - readonly property int fontSizeTitle: 24 - - // Alcím betűméret - readonly property int fontSizeSubtitle: 12 - - // Normál szöveg betűméret - readonly property int fontSizeNormal: 14 - - // Kis szöveg betűméret - readonly property int fontSizeSmall: 12 - - // Apró szöveg betűméret - readonly property int fontSizeTiny: 11 - - // Lista elem magasság - readonly property int listItemHeight: 48 - - // Gomb magasság - readonly property int buttonHeight: 48 - - // Input mező magasság - readonly property int inputHeight: 44 - - // Kerekítés sugara - readonly property int borderRadius: 6 - - // Nagy kerekítés sugara (lista) - readonly property int borderRadiusLarge: 8 - - // Belső margó - readonly property int spacing: 16 - - // Külső margó - readonly property int margin: 20 -}
\ No newline at end of file diff --git a/raveos-calamares-module/wifi/ui/Translations.qml b/raveos-calamares-module/wifi/ui/Translations.qml index 21ef6df..601e8eb 100644 --- a/raveos-calamares-module/wifi/ui/Translations.qml +++ b/raveos-calamares-module/wifi/ui/Translations.qml @@ -1,183 +1,88 @@ pragma Singleton import QtQuick 2.15 -/** - * WiFi Modul Fordítások - * ====================== - * - * Támogatott nyelvek: - * - hu_HU: Magyar - * - de_DE: Német - * - en_US, en_GB, stb.: Angol (alapértelmezett) - * - * Új nyelv hozzáadása: - * 1. Adj hozzá egy új "else if" blokkot a setLanguage függvényben - * 2. Másold be az összes szöveget és fordítsd le - * - * Használat QML-ben: - * Text { text: Translations.title } - */ - QtObject { - id: root - - // Aktuális nyelv kód (pl. "hu_HU", "en_US") - property string currentLanguage: "en_US" - - // ========================================= - // CÍMEK ÉS FEJLÉCEK - // ========================================= - - // Sidebar név (bal oldali menüben) - property string sidebarName: "Hálózat" - - // Modul fő címe - property string title: "Wi-Fi Network" - - // Alcím / leírás - property string subtitle: "Select a network from the list, or enter a hidden network name manually." - - // Lista fejléc + property string eyebrow: "WI-FI" + property string title: "CONNECT TO A NETWORK" + property string subtitle: "The installer downloads the latest packages from the internet. With a cable connection this step is skipped automatically." property string availableNetworks: "Available networks" - - // ========================================= - // GOMBOK - // ========================================= - - // Frissítés gomb property string refresh: "Refresh" - - // Csatlakozás gomb + property string noNetworks: "No networks found. Click Refresh to search again." + property string selected: "Selected" + property string noSelection: "Select a network from the list" + property string password: "Password" property string connect: "Connect" - - // ========================================= - // INPUT MEZŐK - // ========================================= - - // SSID mező placeholder - property string ssidPlaceholder: "Network name (SSID)" - - // Jelszó mező placeholder - property string passwordPlaceholder: "Password" - - // Jelszó megjelenítő/elrejtő gomb - property string showPassword: "Show" - property string hidePassword: "Hide" - - // ========================================= - // ÁLLAPOT ÜZENETEK - // ========================================= - - // Sikeres csatlakozás - property string connected: "Successfully connected!" - - // Csatlakozás folyamatban - property string connecting: "Connecting..." - - // Nincs hálózat - property string noNetworks: "No networks found.\nClick Refresh to scan." - - // ========================================= - // TOGGLE ÉS OPCIÓK - // ========================================= - - // Rejtett hálózat toggle property string hiddenNetwork: "Hidden network" + property string ssidLabel: "Network name (SSID)" + property string statusLabel: "Status" + property string statusDisconnected: "not connected" + property string statusConnecting: "connecting..." + property string statusConnected: "connected" + property string statusFailed: "connection failed" + property string secured: "Password protected" + property string showPassword: "Show password" - // ========================================= - // INFORMÁCIÓS SZÖVEGEK - // ========================================= - - // Sikeres csatlakozás után - property string clickNextToContinue: "Click Next to continue." - - // Ha van vezetékes kapcsolat - property string canSkipWithEthernet: "If you have a wired connection, you can skip this step." - - // ========================================= - // NYELV BEÁLLÍTÁS FÜGGVÉNY - // ========================================= - - /** - * Nyelv beállítása a locale kód alapján - * @param locale - Nyelv kód (pl. "hu_HU", "en_US") - */ function setLanguage(locale) { - currentLanguage = locale - - // ================== - // MAGYAR - // ================== if (locale.startsWith("hu")) { - sidebarName = "Hálózat" - title = "Wi-Fi hálózat" - subtitle = "Válassz egy hálózatot a listából, vagy add meg kézzel a rejtett hálózat nevét." + eyebrow = "WI-FI" + title = "CSATLAKOZÁS A HÁLÓZATHOZ" + subtitle = "A telepítő az internetről tölti le a legfrissebb csomagokat. Kábellel csatlakozva ez a lépés magától kimarad." availableNetworks = "Elérhető hálózatok" refresh = "Frissítés" + noNetworks = "Nem található hálózat. Kattints a Frissítésre az újbóli kereséshez." + selected = "Kiválasztva" + noSelection = "Válassz egy hálózatot a listából" + password = "Jelszó" connect = "Csatlakozás" - ssidPlaceholder = "Hálózat neve (SSID)" - passwordPlaceholder = "Jelszó" - showPassword = "Mutat" - hidePassword = "Elrejt" - connected = "Sikeresen csatlakozva!" - connecting = "Csatlakozás..." - noNetworks = "Nem található hálózat.\nKattints a Frissítés gombra." hiddenNetwork = "Rejtett hálózat" - clickNextToContinue = "Kattints a Tovább gombra a folytatáshoz." - canSkipWithEthernet = "Ha van vezetékes kapcsolatod, kihagyhatod ezt a lépést." - } - // ================== - // NÉMET - // ================== - else if (locale.startsWith("de")) { - sidebarName = "Netzwerk" - title = "WLAN-Netzwerk" - subtitle = "Wählen Sie ein Netzwerk aus der Liste oder geben Sie den Namen eines versteckten Netzwerks manuell ein." + ssidLabel = "Hálózat neve (SSID)" + statusLabel = "Állapot" + statusDisconnected = "nincs kapcsolat" + statusConnecting = "csatlakozás..." + statusConnected = "csatlakozva" + statusFailed = "a csatlakozás nem sikerült" + secured = "Jelszóval védett" + showPassword = "Jelszó megjelenítése" + } else if (locale.startsWith("de")) { + eyebrow = "WLAN" + title = "MIT EINEM NETZWERK VERBINDEN" + subtitle = "Der Installer lädt die neuesten Pakete aus dem Internet. Mit Kabelverbindung wird dieser Schritt automatisch übersprungen." availableNetworks = "Verfügbare Netzwerke" refresh = "Aktualisieren" + noNetworks = "Keine Netzwerke gefunden. Klicke auf Aktualisieren, um erneut zu suchen." + selected = "Ausgewählt" + noSelection = "Wähle ein Netzwerk aus der Liste" + password = "Passwort" connect = "Verbinden" - ssidPlaceholder = "Netzwerkname (SSID)" - passwordPlaceholder = "Passwort" - showPassword = "Anzeigen" - hidePassword = "Ausblenden" - connected = "Erfolgreich verbunden!" - connecting = "Verbinden..." - noNetworks = "Keine Netzwerke gefunden.\nZum Scannen auf Aktualisieren klicken." hiddenNetwork = "Verstecktes Netzwerk" - clickNextToContinue = "Klicken Sie auf Weiter, um fortzufahren." - canSkipWithEthernet = "Wenn Sie eine Kabelverbindung haben, können Sie diesen Schritt überspringen." - } - // ================== - // ANGOL (alapértelmezett) - // ================== - else { - sidebarName = "Network" - title = "Wi-Fi Network" - subtitle = "Select a network from the list, or enter a hidden network name manually." + ssidLabel = "Netzwerkname (SSID)" + statusLabel = "Status" + statusDisconnected = "nicht verbunden" + statusConnecting = "verbinde..." + statusConnected = "verbunden" + statusFailed = "Verbindung fehlgeschlagen" + secured = "Passwortgeschützt" + showPassword = "Passwort anzeigen" + } else { + eyebrow = "WI-FI" + title = "CONNECT TO A NETWORK" + subtitle = "The installer downloads the latest packages from the internet. With a cable connection this step is skipped automatically." availableNetworks = "Available networks" refresh = "Refresh" + noNetworks = "No networks found. Click Refresh to search again." + selected = "Selected" + noSelection = "Select a network from the list" + password = "Password" connect = "Connect" - ssidPlaceholder = "Network name (SSID)" - passwordPlaceholder = "Password" - showPassword = "Show" - hidePassword = "Hide" - connected = "Successfully connected!" - connecting = "Connecting..." - noNetworks = "No networks found.\nClick Refresh to scan." hiddenNetwork = "Hidden network" - clickNextToContinue = "Click Next to continue." - canSkipWithEthernet = "If you have a wired connection, you can skip this step." + ssidLabel = "Network name (SSID)" + statusLabel = "Status" + statusDisconnected = "not connected" + statusConnecting = "connecting..." + statusConnected = "connected" + statusFailed = "connection failed" + secured = "Password protected" + showPassword = "Show password" } - - // ================== - // TOVÁBBI NYELVEK IDE - // ================== - // Példa német nyelv hozzáadása: - // - // else if (locale.startsWith("de")) { - // title = "WLAN-Netzwerk" - // subtitle = "Wählen Sie ein Netzwerk aus der Liste..." - // // ... stb. - // } } } diff --git a/raveos-calamares-module/wifi/ui/qmldir b/raveos-calamares-module/wifi/ui/qmldir index e80b555..6f9105d 100644 --- a/raveos-calamares-module/wifi/ui/qmldir +++ b/raveos-calamares-module/wifi/ui/qmldir @@ -1,3 +1,2 @@ module WifiModule -singleton Style 1.0 Style.qml singleton Translations 1.0 Translations.qml diff --git a/raveos-calamares-module/wifi/ui/wifi.qml b/raveos-calamares-module/wifi/ui/wifi.qml index aee3ddc..e3b0b0c 100644 --- a/raveos-calamares-module/wifi/ui/wifi.qml +++ b/raveos-calamares-module/wifi/ui/wifi.qml @@ -1,404 +1,405 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 +import RaveOS 1.0 import "." as WifiModule Rectangle { id: root - color: WifiModule.Style.backgroundColor + color: Stilus.hatter - property string selectedSsid: "" - property bool showHiddenNetwork: false - property bool isConnecting: false - property bool showPassword: false + readonly property var t: WifiModule.Translations + property var kivalasztott: null + property bool rejtett: false + property bool csatlakozik: false + property bool sikertelen: false + property bool jelszoLatszik: false + + readonly property string ssid: rejtett ? ssidMezo.text : (kivalasztott ? kivalasztott.ssid : "") + readonly property bool jelszoKell: rejtett || (kivalasztott !== null && kivalasztott.secured) - // Function to update language - called from C++ function updateLanguage() { WifiModule.Translations.setLanguage(systemLocale) } - // Initialize translations on load - Component.onCompleted: { - WifiModule.Translations.setLanguage(systemLocale) + function savok(erosseg) { + if (erosseg >= 75) return 4 + if (erosseg >= 50) return 3 + if (erosseg >= 25) return 2 + return 1 } - ColumnLayout { - anchors.fill: parent - anchors.margins: WifiModule.Style.margin - spacing: WifiModule.Style.spacing + function allapotSzoveg() { + if (nm.connected) return t.statusConnected + if (csatlakozik) return t.statusConnecting + if (sikertelen) return t.statusFailed + return t.statusDisconnected + } + + Component.onCompleted: WifiModule.Translations.setLanguage(systemLocale) - // Header - Label { - text: WifiModule.Translations.title - font.pixelSize: WifiModule.Style.fontSizeTitle - font.bold: true - color: WifiModule.Style.textColor - Layout.alignment: Qt.AlignHCenter + Connections { + target: nm + function onConnectionChanged() { + if (nm.connected) + root.csatlakozik = false + } + function onConnectionFailed(error) { + root.csatlakozik = false + root.sikertelen = true } + } - Label { - text: WifiModule.Translations.subtitle - font.pixelSize: WifiModule.Style.fontSizeSubtitle - color: WifiModule.Style.textSecondaryColor - wrapMode: Text.WordWrap - Layout.fillWidth: true - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter + Timer { + interval: 30000 + running: root.csatlakozik + onTriggered: { + if (!nm.connected) { + root.csatlakozik = false + root.sikertelen = true + } } + } - // Connection status banner - Rectangle { - Layout.fillWidth: true - height: 40 - radius: WifiModule.Style.borderRadius - color: nm.connected ? WifiModule.Style.successColor : WifiModule.Style.progressColor - visible: nm.connected || isConnecting + component SzovegLink: Text { + signal kattint() + color: linkHover.hovered ? Stilus.zoldHover : Stilus.zold + font.family: Stilus.font + font.pixelSize: 13 + font.weight: Font.DemiBold - RowLayout { - anchors.centerIn: parent - spacing: 10 + HoverHandler { + id: linkHover + cursorShape: Qt.PointingHandCursor + } - BusyIndicator { - running: isConnecting && !nm.connected - visible: isConnecting && !nm.connected - Layout.preferredWidth: 24 - Layout.preferredHeight: 24 - } + TapHandler { + onTapped: parent.kattint() + } + } - Label { - text: nm.connected ? WifiModule.Translations.connected : WifiModule.Translations.connecting - color: WifiModule.Style.textColor - font.pixelSize: WifiModule.Style.fontSizeNormal - font.bold: true - } + ColumnLayout { + anchors.fill: parent + anchors.topMargin: 40 + anchors.bottomMargin: 32 + anchors.leftMargin: 56 + anchors.rightMargin: 56 + spacing: 20 + + ColumnLayout { + Layout.fillWidth: true + spacing: 10 + + Fejlec { + Layout.fillWidth: true + felirat: root.t.eyebrow + cim: root.t.title + } + + Text { + Layout.fillWidth: true + text: root.t.subtitle + wrapMode: Text.WordWrap + color: Stilus.szovegMasodlagos + font.family: Stilus.font + font.pixelSize: 14 } } - // Network list - Rectangle { + RowLayout { Layout.fillWidth: true Layout.fillHeight: true - color: WifiModule.Style.listBackgroundColor - radius: WifiModule.Style.borderRadiusLarge - border.color: WifiModule.Style.borderColor - border.width: 1 + spacing: 24 ColumnLayout { - anchors.fill: parent - anchors.margins: 1 - spacing: 0 + Layout.fillWidth: true + Layout.fillHeight: true + spacing: 8 - // List header with refresh button - Rectangle { + RowLayout { Layout.fillWidth: true - height: 44 - color: WifiModule.Style.listHeaderColor - radius: WifiModule.Style.borderRadiusLarge - Rectangle { - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - height: 8 - color: parent.color + Text { + Layout.fillWidth: true + text: root.t.availableNetworks + color: Stilus.szovegHalvany + font.family: Stilus.font + font.pixelSize: 12 + font.weight: Font.Medium + font.letterSpacing: 1 + font.capitalization: Font.AllUppercase } - RowLayout { - anchors.fill: parent - anchors.leftMargin: 12 - anchors.rightMargin: 8 + SzovegLink { + text: root.t.refresh + onKattint: nm.scan() + } + } - Label { - text: WifiModule.Translations.availableNetworks - color: WifiModule.Style.textColor - font.pixelSize: WifiModule.Style.fontSizeSmall - font.bold: true - } + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + color: Stilus.felulet + border.width: 1 + border.color: Stilus.keret - Item { Layout.fillWidth: true } + ListView { + id: lista + anchors.fill: parent + anchors.margins: 1 + clip: true + model: nm.accessPoints + boundsBehavior: Flickable.StopAtBounds + ScrollBar.vertical: Gorgeto {} - Button { - text: WifiModule.Translations.refresh - Layout.preferredHeight: 32 - onClicked: nm.scan() + delegate: Rectangle { + id: sor + readonly property bool kijelolt: !root.rejtett && root.kivalasztott !== null && root.kivalasztott.ssid === modelData.ssid + width: lista.width + height: 48 + color: kijelolt ? Stilus.aktiv : (sorHover.hovered ? Stilus.aktiv : "transparent") - background: Rectangle { - color: parent.hovered ? WifiModule.Style.buttonSecondaryHoverColor : WifiModule.Style.buttonSecondaryColor - radius: 4 + Rectangle { + anchors.left: parent.left + anchors.right: parent.right + anchors.bottom: parent.bottom + height: 1 + color: Stilus.aktiv } - contentItem: Label { - text: parent.text - color: WifiModule.Style.textColor - font.pixelSize: WifiModule.Style.fontSizeSmall - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter + Rectangle { + visible: sor.kijelolt + anchors.left: parent.left + anchors.top: parent.top + anchors.bottom: parent.bottom + width: 2 + color: Stilus.zold } - } - } - } - // WiFi list - ListView { - id: networkList - Layout.fillWidth: true - Layout.fillHeight: true - clip: true - model: nm.networks + RowLayout { + anchors.fill: parent + anchors.leftMargin: 14 + anchors.rightMargin: 14 + spacing: 12 - delegate: Rectangle { - width: networkList.width - height: WifiModule.Style.listItemHeight - color: modelData === selectedSsid ? WifiModule.Style.itemSelectedColor : - (mouseArea.containsMouse ? WifiModule.Style.itemHoverColor : "transparent") + Row { + Layout.alignment: Qt.AlignVCenter + spacing: 2 + height: 14 - RowLayout { - anchors.fill: parent - anchors.leftMargin: 16 - anchors.rightMargin: 16 - spacing: 12 + Repeater { + model: 4 + Rectangle { + anchors.bottom: parent.bottom + width: 3 + height: 4 + index * 3.3 + color: index < root.savok(modelData.strength) + ? (sor.kijelolt ? Stilus.zold : Stilus.szoveg) + : Stilus.keretErosebb + } + } + } - Label { - text: "" - font.pixelSize: 18 - } + Text { + Layout.fillWidth: true + text: modelData.ssid + elide: Text.ElideRight + color: Stilus.szoveg + font.family: Stilus.font + font.pixelSize: 14 + font.weight: sor.kijelolt ? Font.DemiBold : Font.Normal + } - Label { - text: modelData - color: WifiModule.Style.textColor - font.pixelSize: WifiModule.Style.fontSizeNormal - Layout.fillWidth: true - elide: Text.ElideRight - } + Canvas { + visible: modelData.secured + Layout.preferredWidth: 14 + Layout.preferredHeight: 14 + Accessible.name: root.t.secured + onPaint: { + var c = getContext("2d") + c.reset() + c.strokeStyle = Stilus.szovegHalvany + c.lineWidth = 1.5 + c.strokeRect(3, 6.5, 8, 6) + c.beginPath() + c.moveTo(4.5, 6.5) + c.lineTo(4.5, 4.5) + c.arc(7, 4.5, 2.5, Math.PI, 0) + c.lineTo(9.5, 6.5) + c.stroke() + } + } - Label { - text: modelData === selectedSsid ? "✓" : "" - color: WifiModule.Style.successCheckColor - font.pixelSize: 16 - font.bold: true + Text { + Layout.preferredWidth: 52 + horizontalAlignment: Text.AlignRight + text: modelData.band + color: Stilus.szovegHalvany + font.family: Stilus.mono + font.pixelSize: 11 + } } - } - MouseArea { - id: mouseArea - anchors.fill: parent - hoverEnabled: true - onClicked: { - selectedSsid = modelData - showHiddenNetwork = false - ssidField.text = modelData + HoverHandler { id: sorHover } + + TapHandler { + onTapped: { + root.rejtett = false + root.sikertelen = false + root.kivalasztott = modelData + jelszoMezo.text = "" + } } } - Rectangle { - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - anchors.leftMargin: 16 - anchors.rightMargin: 16 - height: 1 - color: WifiModule.Style.separatorColor + Text { + anchors.centerIn: parent + width: parent.width - 40 + visible: lista.count === 0 + text: root.t.noNetworks + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + color: Stilus.szovegHalvany + font.family: Stilus.font + font.pixelSize: 13 } } - - Label { - anchors.centerIn: parent - text: WifiModule.Translations.noNetworks - color: WifiModule.Style.textMutedColor - font.pixelSize: WifiModule.Style.fontSizeSmall - horizontalAlignment: Text.AlignHCenter - visible: nm.networks.length === 0 - } } - } - } - // Hidden network toggle - Rectangle { - Layout.fillWidth: true - height: WifiModule.Style.inputHeight - color: "#3d7839" - radius: WifiModule.Style.borderRadius - - MouseArea { - anchors.fill: parent - onClicked: { - showHiddenNetwork = !showHiddenNetwork - if (showHiddenNetwork) { - selectedSsid = "" - ssidField.text = "" - ssidField.focus = true + SzovegLink { + text: root.t.hiddenNetwork + onKattint: { + root.rejtett = true + root.kivalasztott = null + root.sikertelen = false } } } - RowLayout { - anchors.fill: parent - anchors.leftMargin: 16 - anchors.rightMargin: 16 - - Label { - text: WifiModule.Translations.hiddenNetwork - color: WifiModule.Style.textColor - font.pixelSize: WifiModule.Style.fontSizeNormal - } - - Item { Layout.fillWidth: true } + Rectangle { + Layout.preferredWidth: 300 + Layout.alignment: Qt.AlignTop + implicitHeight: panel.implicitHeight + 36 + color: Stilus.felulet + border.width: 1 + border.color: Stilus.keret - Rectangle { - width: 44 - height: 24 - radius: 12 - color: showHiddenNetwork ? WifiModule.Style.toggleOnColor : WifiModule.Style.toggleOffColor + ColumnLayout { + id: panel + x: 18 + y: 18 + width: parent.width - 36 + spacing: 14 - Rectangle { - width: 20 - height: 20 - radius: 10 - color: WifiModule.Style.textColor - x: showHiddenNetwork ? 22 : 2 - anchors.verticalCenter: parent.verticalCenter + Text { + text: root.t.selected + color: Stilus.szovegHalvany + font.family: Stilus.font + font.pixelSize: 12 + font.letterSpacing: 1 + font.capitalization: Font.AllUppercase + } - Behavior on x { - NumberAnimation { duration: 150 } - } + Text { + visible: !root.rejtett + Layout.fillWidth: true + text: root.kivalasztott ? root.kivalasztott.ssid : root.t.noSelection + elide: Text.ElideRight + color: root.kivalasztott ? Stilus.szoveg : Stilus.szovegHalvany + font.family: Stilus.font + font.pixelSize: root.kivalasztott ? 16 : 13 + font.weight: root.kivalasztott ? Font.DemiBold : Font.Normal } - } - } - } - // SSID field (for hidden networks) - TextField { - id: ssidField - Layout.fillWidth: true - placeholderText: WifiModule.Translations.ssidPlaceholder - visible: showHiddenNetwork - color: WifiModule.Style.textColor - placeholderTextColor: WifiModule.Style.inputPlaceholderColor - font.pixelSize: WifiModule.Style.fontSizeNormal + ColumnLayout { + visible: root.rejtett + Layout.fillWidth: true + spacing: 6 - background: Rectangle { - color: WifiModule.Style.inputBackgroundColor - radius: WifiModule.Style.borderRadius - border.color: ssidField.focus ? WifiModule.Style.inputFocusBorderColor : WifiModule.Style.inputBorderColor - border.width: 1 - } - } + Text { + text: root.t.ssidLabel + color: Stilus.szovegHalvany + font.family: Stilus.font + font.pixelSize: 12 + } - // Password field with show/hide toggle - Item { - Layout.fillWidth: true - Layout.preferredHeight: WifiModule.Style.inputHeight + TextField { + id: ssidMezo + Layout.fillWidth: true + implicitHeight: 44 + leftPadding: 12 + color: Stilus.szoveg + font.family: Stilus.font + font.pixelSize: 14 + background: Rectangle { + color: Stilus.hatter + border.width: 1 + border.color: ssidMezo.activeFocus ? Stilus.zold : Stilus.keretErosebb + } + } + } - TextField { - id: passField - anchors.fill: parent - rightPadding: showPasswordButton.width + 16 - placeholderText: WifiModule.Translations.passwordPlaceholder - echoMode: showPassword ? TextInput.Normal : TextInput.Password - color: WifiModule.Style.textColor - placeholderTextColor: WifiModule.Style.inputPlaceholderColor - font.pixelSize: WifiModule.Style.fontSizeNormal - enabled: selectedSsid !== "" || showHiddenNetwork - opacity: 1 + ColumnLayout { + visible: root.jelszoKell + Layout.fillWidth: true + spacing: 6 - background: Rectangle { - color: passField.enabled ? WifiModule.Style.inputBackgroundColor : WifiModule.Style.inputDisabledColor - radius: WifiModule.Style.borderRadius - border.color: passField.focus ? WifiModule.Style.inputFocusBorderColor : WifiModule.Style.inputBorderColor - border.width: 1 - } - } + Text { + text: root.t.password + color: Stilus.szovegHalvany + font.family: Stilus.font + font.pixelSize: 12 + } - Button { - id: showPasswordButton - anchors.right: parent.right - anchors.rightMargin: 8 - anchors.verticalCenter: parent.verticalCenter - height: 32 - text: showPassword ? WifiModule.Translations.hidePassword : WifiModule.Translations.showPassword - enabled: passField.enabled - onClicked: showPassword = !showPassword + JelszoMezo { + id: jelszoMezo + Layout.fillWidth: true + reveal: root.jelszoLatszik + revealName: root.t.showPassword + onRevealClicked: root.jelszoLatszik = !root.jelszoLatszik + onAccepted: csatlakozGomb.clicked() + } + } - background: Rectangle { - color: parent.hovered ? WifiModule.Style.buttonSecondaryHoverColor : WifiModule.Style.buttonSecondaryColor - radius: 4 - } + Button { + id: csatlakozGomb + Layout.fillWidth: true + implicitHeight: 44 + text: root.t.connect + enabled: root.ssid !== "" && (!root.jelszoKell || jelszoMezo.text !== "") && !root.csatlakozik + onClicked: { + if (!enabled) + return + root.sikertelen = false + root.csatlakozik = true + nm.connectTo(root.ssid, root.jelszoKell ? jelszoMezo.text : "") + } + background: Rectangle { + color: !csatlakozGomb.enabled ? "transparent" : (csatlakozGomb.hovered ? Stilus.zoldHover : Stilus.zold) + border.width: csatlakozGomb.enabled ? 0 : 1 + border.color: Stilus.keret + } + contentItem: Text { + text: csatlakozGomb.text + color: csatlakozGomb.enabled ? Stilus.zoldonSzoveg : Stilus.szovegHalvany + font.family: Stilus.font + font.pixelSize: 14 + font.weight: Font.DemiBold + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } - contentItem: Label { - text: parent.text - color: parent.enabled ? WifiModule.Style.textColor : WifiModule.Style.textDisabledColor - font.pixelSize: WifiModule.Style.fontSizeSmall - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter + Text { + Layout.fillWidth: true + text: root.t.statusLabel + ": " + root.allapotSzoveg() + wrapMode: Text.WordWrap + color: nm.connected ? Stilus.zold : (root.sikertelen ? Stilus.sarga : Stilus.szovegHalvany) + font.family: Stilus.mono + font.pixelSize: 12 + } } } } - - // Connect button - Button { - Layout.fillWidth: true - Layout.preferredHeight: WifiModule.Style.buttonHeight - text: WifiModule.Translations.connect - enabled: (selectedSsid !== "" || (showHiddenNetwork && ssidField.text !== "")) && - passField.text !== "" && !isConnecting && !nm.connected - - onClicked: { - isConnecting = true - var ssid = showHiddenNetwork ? ssidField.text : selectedSsid - nm.connectTo(ssid, passField.text) - } - - background: Rectangle { - color: parent.enabled ? (parent.hovered ? WifiModule.Style.buttonPrimaryHoverColor : WifiModule.Style.buttonPrimaryColor) : WifiModule.Style.buttonDisabledColor - radius: WifiModule.Style.borderRadius - } - - contentItem: Label { - text: parent.text - color: parent.enabled ? WifiModule.Style.textColor : WifiModule.Style.textDisabledColor - font.pixelSize: 15 - font.bold: true - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } - } - - // Skip info - Label { - text: nm.connected ? - WifiModule.Translations.clickNextToContinue : - WifiModule.Translations.canSkipWithEthernet - color: WifiModule.Style.textMutedColor - font.pixelSize: WifiModule.Style.fontSizeTiny - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter - } - } - - // Connection state change handler - Connections { - target: nm - function onConnectionChanged() { - if (nm.connected) { - isConnecting = false - } - } - function onConnectionFailed(error) { - isConnecting = false - console.log("Connection failed: " + error) - } - } - - // Timer to reset connecting state if it takes too long - Timer { - id: connectTimeout - interval: 30000 - running: isConnecting - onTriggered: { - if (!nm.connected) { - isConnecting = false - } - } } -}
\ No newline at end of file +} |