|
|
|
/*
|
|
|
|
* Copyright (C) 2022-2023 Lubuntu Developers <lubuntu-devel@lists.ubuntu.com>
|
|
|
|
* Authored by: Simon Quigley <tsimonq2@lubuntu.me>
|
|
|
|
* Aaron Rainbolt <arraybolt3@lubuntu.me>
|
|
|
|
*
|
|
|
|
* This is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, version 3 of the License.
|
|
|
|
*
|
|
|
|
* This is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <KBusyIndicatorWidget>
|
|
|
|
#include <KLed>
|
|
|
|
#include <NetworkManagerQt/ConnectionSettings>
|
|
|
|
#include <NetworkManagerQt/Manager>
|
|
|
|
#include <NetworkManagerQt/Device>
|
|
|
|
#include <NetworkManagerQt/Ipv4Setting>
|
|
|
|
#include <NetworkManagerQt/Ipv6Setting>
|
|
|
|
#include <NetworkManagerQt/WirelessDevice>
|
|
|
|
#include <NetworkManagerQt/WirelessNetwork>
|
|
|
|
#include <NetworkManagerQt/WirelessSecuritySetting>
|
|
|
|
#include <NetworkManagerQt/WirelessSetting>
|
|
|
|
#include <NetworkManagerQt/Settings>
|
|
|
|
#include <QProcess>
|
|
|
|
#include <QScreen>
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QUuid>
|
|
|
|
#include <QDBusPendingReply>
|
|
|
|
#include "installerprompt.h"
|
|
|
|
#include "./ui_installerprompt.h"
|
|
|
|
|
|
|
|
InstallerPrompt::InstallerPrompt(QWidget *parent)
|
|
|
|
: QMainWindow(parent)
|
|
|
|
, ui(new Ui::InstallerPrompt) {
|
|
|
|
ui->setupUi(this);
|
|
|
|
|
|
|
|
// Hide the Incorrect Password and loading text
|
|
|
|
ui->incorrectPassword->setVisible(false);
|
|
|
|
ui->changingLanguageLabel->setVisible(false);
|
|
|
|
ui->changingLanguageLoader->setVisible(false);
|
|
|
|
|
|
|
|
// Set the background image and scale it
|
|
|
|
QPixmap bg(":/background");
|
|
|
|
if (bg.isNull()) {
|
|
|
|
QMessageBox::warning(this, tr("Error"), tr("Background image cannot be loaded."));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QScreen *screen = QGuiApplication::primaryScreen();
|
|
|
|
QRect screenGeometry = screen->geometry();
|
|
|
|
bg = bg.scaled(screenGeometry.size(), Qt::IgnoreAspectRatio);
|
|
|
|
|
|
|
|
QPalette palette;
|
|
|
|
palette.setBrush(QPalette::Window, bg);
|
|
|
|
this->setPalette(palette);
|
|
|
|
|
|
|
|
// Initialize process for external app launch
|
|
|
|
process = new QProcess(this);
|
|
|
|
|
|
|
|
// Set up signal-slot connections for buttons
|
|
|
|
connect(ui->tryLubuntu, &QAbstractButton::clicked, this, &InstallerPrompt::tryLubuntu);
|
|
|
|
connect(ui->installLubuntu, &QAbstractButton::clicked, this, &InstallerPrompt::installLubuntu);
|
|
|
|
connect(ui->connectWiFiButton, &QAbstractButton::clicked, this, &InstallerPrompt::onConnectWifiClicked);
|
|
|
|
connect(ui->confirmButton, &QAbstractButton::clicked, this, &InstallerPrompt::onLanguageConfirm);
|
|
|
|
|
|
|
|
// Set up the language combo box with available languages
|
|
|
|
initLanguageComboBox();
|
|
|
|
|
|
|
|
// Connect the appropriate language slots
|
|
|
|
connect(ui->languageComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onLanguageChanged(int)));
|
|
|
|
|
|
|
|
// Check initial network status and update UI
|
|
|
|
updateConnectionStatus();
|
|
|
|
|
|
|
|
// Find and store the Wi-Fi device
|
|
|
|
foreach (const NetworkManager::Device::Ptr &device, NetworkManager::networkInterfaces()) {
|
|
|
|
if (device->type() == NetworkManager::Device::Wifi) {
|
|
|
|
wifiDevice = device.objectCast<NetworkManager::WirelessDevice>();
|
|
|
|
connect(wifiDevice.data(), &NetworkManager::Device::stateChanged, this, &InstallerPrompt::handleWiFiConnectionChange);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set up network manager signals for dynamic updates
|
|
|
|
auto nm = NetworkManager::notifier();
|
|
|
|
connect(nm, &NetworkManager::Notifier::deviceAdded, this, &InstallerPrompt::updateConnectionStatus);
|
|
|
|
connect(nm, &NetworkManager::Notifier::deviceRemoved, this, &InstallerPrompt::updateConnectionStatus);
|
|
|
|
connect(nm, &NetworkManager::Notifier::activeConnectionsChanged, this, &InstallerPrompt::updateConnectionStatus);
|
|
|
|
connect(nm, &NetworkManager::Notifier::wirelessEnabledChanged, this, &InstallerPrompt::updateConnectionStatus);
|
|
|
|
connect(nm, &NetworkManager::Notifier::activeConnectionAdded, this, &InstallerPrompt::updateConnectionStatus);
|
|
|
|
connect(nm, &NetworkManager::Notifier::connectivityChanged, this, &InstallerPrompt::updateConnectionStatus);
|
|
|
|
connect(nm, &NetworkManager::Notifier::primaryConnectionChanged, this, &InstallerPrompt::updateConnectionStatus);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::updateConnectionStatus() {
|
|
|
|
auto status = NetworkManager::status();
|
|
|
|
bool online = false;
|
|
|
|
QString statusText;
|
|
|
|
|
|
|
|
switch (status) {
|
|
|
|
case NetworkManager::Status::Disconnected:
|
|
|
|
case NetworkManager::ConnectedLinkLocal:
|
|
|
|
case NetworkManager::Asleep:
|
|
|
|
statusText = tr("Not Connected");
|
|
|
|
ui->connectionLED->setColor(Qt::red);
|
|
|
|
ui->connectionLED->setState(KLed::Off);
|
|
|
|
break;
|
|
|
|
case NetworkManager::Status::Connected:
|
|
|
|
online = true;
|
|
|
|
statusText = tr("Connected");
|
|
|
|
ui->connectionLED->setColor(Qt::green);
|
|
|
|
ui->connectionLED->setState(KLed::On);
|
|
|
|
break;
|
|
|
|
case NetworkManager::Status::Connecting:
|
|
|
|
statusText = tr("Connecting...");
|
|
|
|
ui->connectionLED->setColor(Qt::yellow);
|
|
|
|
ui->connectionLED->setState(KLed::On);
|
|
|
|
break;
|
|
|
|
case NetworkManager::Status::Disconnecting:
|
|
|
|
statusText = tr("Disconnecting...");
|
|
|
|
ui->connectionLED->setColor(Qt::yellow);
|
|
|
|
ui->connectionLED->setState(KLed::On);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
qDebug() << "Unknown status:" << status;
|
|
|
|
statusText = tr("Unknown Status");
|
|
|
|
ui->connectionLED->setColor(Qt::gray);
|
|
|
|
ui->connectionLED->setState(KLed::Off);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ui->connectionStatusLabel->setText(statusText);
|
|
|
|
|
|
|
|
const auto devices = NetworkManager::networkInterfaces();
|
|
|
|
bool wifiEnabled = false;
|
|
|
|
if (NetworkManager::isNetworkingEnabled()) {
|
|
|
|
for (const auto &device : devices) {
|
|
|
|
if (device->type() == NetworkManager::Device::Wifi && NetworkManager::isWirelessEnabled()) wifiEnabled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool connectable = !online && wifiEnabled;
|
|
|
|
if (connectable) refreshNetworkList();
|
|
|
|
|
|
|
|
ui->connectWiFiButton->setVisible(connectable);
|
|
|
|
ui->WiFiLabel->setVisible(connectable);
|
|
|
|
ui->networkComboBox->setVisible(connectable);
|
|
|
|
ui->WiFiInfoLabel->setVisible(connectable);
|
|
|
|
ui->WiFiSpacer->changeSize(connectable ? 40 : 0, connectable ? 20 : 0, QSizePolicy::Fixed, QSizePolicy::Fixed);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::handleWiFiConnectionChange(NetworkManager::Device::State newstate, NetworkManager::Device::State oldstate, NetworkManager::Device::StateChangeReason reason)
|
|
|
|
{
|
|
|
|
QMutexLocker locker(&wifiChangeMutex);
|
|
|
|
if (reason == NetworkManager::Device::NoSecretsReason && !wifiWrongHandling) {
|
|
|
|
wifiWrongHandling = true;
|
|
|
|
qDebug() << wifiSSID;
|
|
|
|
|
|
|
|
foreach (const NetworkManager::Connection::Ptr &connection, NetworkManager::listConnections()) {
|
|
|
|
if (connection->settings()->connectionType() == NetworkManager::ConnectionSettings::Wireless) {
|
|
|
|
auto wirelessSetting = connection->settings()->setting(NetworkManager::Setting::Wireless).dynamicCast<NetworkManager::WirelessSetting>();
|
|
|
|
if (wirelessSetting && wirelessSetting->ssid() == wifiSSID) {
|
|
|
|
qDebug() << "Wiping connection with wrong password: " << wifiSSID;
|
|
|
|
// Show the Incorrect Password text
|
|
|
|
ui->incorrectPassword->setVisible(true);
|
|
|
|
QDBusPendingReply removeReply = connection->remove();
|
|
|
|
removeReply.waitForFinished();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wifiWrongHandling = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NetworkManager::Connection::Ptr InstallerPrompt::findConnectionBySsid(const QString &ssid) {
|
|
|
|
foreach (const NetworkManager::Connection::Ptr &connection, NetworkManager::listConnections()) {
|
|
|
|
if (connection->settings()->connectionType() == NetworkManager::ConnectionSettings::Wireless) {
|
|
|
|
auto wirelessSetting = connection->settings()->setting(NetworkManager::Setting::Wireless).dynamicCast<NetworkManager::WirelessSetting>();
|
|
|
|
if (wirelessSetting && wirelessSetting->ssid() == ssid) {
|
|
|
|
return connection;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NetworkManager::Connection::Ptr(); // Return null pointer if not found
|
|
|
|
}
|
|
|
|
|
|
|
|
QString InstallerPrompt::promptForWifiPassword(const QString &ssid, bool isWrongPassword) {
|
|
|
|
QDialog passwordDialog(this);
|
|
|
|
passwordDialog.setModal(true);
|
|
|
|
passwordDialog.setWindowTitle(tr("Wi-Fi Password Required"));
|
|
|
|
passwordDialog.setWindowIcon(QIcon::fromTheme("network-wireless"));
|
|
|
|
passwordDialog.setStyleSheet("QLabel { color: black; } ");
|
|
|
|
passwordDialog.setMinimumWidth(250);
|
|
|
|
passwordDialog.setMinimumHeight(120);
|
|
|
|
passwordDialog.setMaximumWidth(5000);
|
|
|
|
passwordDialog.setMaximumHeight(500);
|
|
|
|
|
|
|
|
QVBoxLayout layout;
|
|
|
|
QLabel passwordLabel(tr("Enter password for \"%1\":").arg(ssid), &passwordDialog);
|
|
|
|
QLineEdit passwordLineEdit(&passwordDialog);
|
|
|
|
QPushButton passwordButton(tr("Connect"), &passwordDialog);
|
|
|
|
|
|
|
|
passwordLineEdit.setEchoMode(QLineEdit::Password);
|
|
|
|
layout.addWidget(&passwordLabel);
|
|
|
|
layout.addWidget(&passwordLineEdit);
|
|
|
|
layout.addWidget(&passwordButton);
|
|
|
|
|
|
|
|
passwordDialog.setLayout(&layout);
|
|
|
|
|
|
|
|
// Connect with a lambda function for inline validation
|
|
|
|
connect(&passwordLineEdit, &QLineEdit::textChanged, this, [&passwordLineEdit](const QString &text) {
|
|
|
|
int minLength = 8;
|
|
|
|
int maxLength = 64;
|
|
|
|
bool isValid = text.length() >= minLength && text.length() <= maxLength;
|
|
|
|
passwordLineEdit.setStyleSheet(isValid ? "" : "border: 1px solid red;");
|
|
|
|
});
|
|
|
|
|
|
|
|
connect(&passwordButton, &QPushButton::clicked, &passwordDialog, &QDialog::accept);
|
|
|
|
|
|
|
|
if (passwordDialog.exec() == QDialog::Accepted) {
|
|
|
|
return passwordLineEdit.text();
|
|
|
|
}
|
|
|
|
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::handleWifiConnection(const QString &ssid, bool recoverFromWrongPassword) {
|
|
|
|
ui->incorrectPassword->setVisible(false);
|
|
|
|
ui->networkComboBox->setEnabled(false);
|
|
|
|
wifiSSID = ssid;
|
|
|
|
qDebug() << "Attempting to find connection for SSID:" << ssid;
|
|
|
|
|
|
|
|
// Check for existing connection
|
|
|
|
NetworkManager::Connection::Ptr connection = findConnectionBySsid(ssid);
|
|
|
|
if (connection && !recoverFromWrongPassword) {
|
|
|
|
qDebug() << "Using existing connection for:" << ssid;
|
|
|
|
NetworkManager::activateConnection(connection->path(), wifiDevice->uni(), QString());
|
|
|
|
ui->networkComboBox->setEnabled(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prompt for Wi-Fi password
|
|
|
|
QString password = promptForWifiPassword(ssid);
|
|
|
|
if (password.isEmpty()) {
|
|
|
|
ui->networkComboBox->setEnabled(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create new Wi-Fi connection
|
|
|
|
NMVariantMapMap settings = createSettingsBySSID(ssid);
|
|
|
|
if (settings.isEmpty()) {
|
|
|
|
QMessageBox::warning(this, tr("Error"), tr("Failed to create Wi-Fi settings."));
|
|
|
|
ui->networkComboBox->setEnabled(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the wireless security settings
|
|
|
|
QVariantMap wirelessSecurity;
|
|
|
|
wirelessSecurity["key-mgmt"] = "wpa-psk";
|
|
|
|
wirelessSecurity["psk"] = password;
|
|
|
|
settings["802-11-wireless-security"] = wirelessSecurity;
|
|
|
|
|
|
|
|
// Add the new connection
|
|
|
|
QDBusPendingReply<QDBusObjectPath> reply = NetworkManager::addConnection(settings);
|
|
|
|
reply.waitForFinished();
|
|
|
|
if (reply.isError()) {
|
|
|
|
QMessageBox::warning(this, tr("Error"), tr("Failed to add Wi-Fi connection."));
|
|
|
|
ui->networkComboBox->setEnabled(true);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Activate the new connection
|
|
|
|
QDBusObjectPath path = reply.value();
|
|
|
|
NetworkManager::activateConnection(path.path(), wifiDevice->uni(), QString());
|
|
|
|
ui->networkComboBox->setEnabled(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
NMVariantMapMap InstallerPrompt::createSettingsBySSID(const QString &ssid) {
|
|
|
|
NMVariantMapMap convertedSettings;
|
|
|
|
|
|
|
|
if (!wifiDevice) {
|
|
|
|
qWarning() << "Wi-Fi device not found. Unable to set interface name.";
|
|
|
|
return convertedSettings;
|
|
|
|
}
|
|
|
|
|
|
|
|
NetworkManager::ConnectionSettings::Ptr newConnectionSettings(new NetworkManager::ConnectionSettings(NetworkManager::ConnectionSettings::Wireless));
|
|
|
|
newConnectionSettings->setId(ssid);
|
|
|
|
newConnectionSettings->setUuid(NetworkManager::ConnectionSettings::createNewUuid());
|
|
|
|
newConnectionSettings->setInterfaceName(wifiDevice->interfaceName());
|
|
|
|
|
|
|
|
// Configure wireless settings
|
|
|
|
QVariantMap wirelessSetting;
|
|
|
|
wirelessSetting.insert("ssid", ssid.toUtf8());
|
|
|
|
convertedSettings.insert("802-11-wireless", wirelessSetting);
|
|
|
|
|
|
|
|
// Convert other settings
|
|
|
|
const auto settingsMap = newConnectionSettings->toMap();
|
|
|
|
for (const auto &key : settingsMap.keys()) {
|
|
|
|
QVariant value = settingsMap.value(key);
|
|
|
|
convertedSettings.insert(key, value.toMap());
|
|
|
|
}
|
|
|
|
|
|
|
|
return convertedSettings;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::onConnectWifiClicked() {
|
|
|
|
QString selectedSSID = ui->networkComboBox->currentText();
|
|
|
|
handleWifiConnection(selectedSSID);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::showWifiOptions() {
|
|
|
|
bool foundWifiDevice = false;
|
|
|
|
for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) {
|
|
|
|
if (device->type() == NetworkManager::Device::Wifi) {
|
|
|
|
foundWifiDevice = true;
|
|
|
|
auto wifiDevice = device.staticCast<NetworkManager::WirelessDevice>();
|
|
|
|
ui->networkComboBox->clear(); // Use the combo box from the UI file, clear existing items
|
|
|
|
for (const NetworkManager::WirelessNetwork::Ptr &network : wifiDevice->networks()) {
|
|
|
|
ui->networkComboBox->addItem(network->ssid()); // Add Wi-Fi networks to the combo box
|
|
|
|
}
|
|
|
|
break; // Handle the first Wi-Fi device
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!foundWifiDevice) {
|
|
|
|
QMessageBox::information(this, tr("WiFi Not Available"), tr("No WiFi devices were found on this system."));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::refreshNetworkList() {
|
|
|
|
NetworkManager::WirelessDevice::Ptr wirelessDevice;
|
|
|
|
|
|
|
|
// Iterate over network interfaces to find a wireless device
|
|
|
|
const auto devices = NetworkManager::networkInterfaces();
|
|
|
|
for (const auto &device : devices) {
|
|
|
|
if (device->type() == NetworkManager::Device::Wifi) {
|
|
|
|
wirelessDevice = device.staticCast<NetworkManager::WirelessDevice>();
|
|
|
|
break; // Break after finding the first wireless device
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!wirelessDevice) {
|
|
|
|
// No wireless device found, handle appropriately
|
|
|
|
ui->networkComboBox->setVisible(false);
|
|
|
|
ui->connectWiFiButton->setVisible(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QMap<QString, NetworkManager::WirelessNetwork::Ptr> tempWifiNetworkMap;
|
|
|
|
QStringList ssidList;
|
|
|
|
|
|
|
|
const auto networks = wirelessDevice->networks();
|
|
|
|
for (const auto &network : networks) {
|
|
|
|
QString ssid = network->ssid();
|
|
|
|
tempWifiNetworkMap[ssid] = network;
|
|
|
|
ssidList.append(ssid);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Update the main map and combo box only after the new list is ready
|
|
|
|
ui->networkComboBox->clear();
|
|
|
|
ui->networkComboBox->addItems(ssidList);
|
|
|
|
|
|
|
|
// Adjust visibility
|
|
|
|
ui->networkComboBox->setVisible(!networks.isEmpty());
|
|
|
|
ui->connectWiFiButton->setVisible(!networks.isEmpty());
|
|
|
|
}
|
|
|
|
|
|
|
|
QString InstallerPrompt::getDisplayNameForLocale(const QLocale &locale) {
|
|
|
|
auto sanitize = [](QString s) -> QString {
|
|
|
|
s.replace("St.", "Saint", Qt::CaseInsensitive);
|
|
|
|
s.replace("&", "and", Qt::CaseInsensitive);
|
|
|
|
return s;
|
|
|
|
};
|
|
|
|
|
|
|
|
QString nativeName = locale.nativeLanguageName();
|
|
|
|
QString nativeCountryName = sanitize(locale.nativeCountryName());
|
|
|
|
QString englishLanguageName = QLocale::languageToString(locale.language());
|
|
|
|
QString englishCountryName = sanitize(QLocale::countryToString(locale.country()));
|
|
|
|
|
|
|
|
// Rename "American English" to "English"
|
|
|
|
if (locale.language() == QLocale::English) {
|
|
|
|
nativeName = "English";
|
|
|
|
englishLanguageName = "English";
|
|
|
|
}
|
|
|
|
|
|
|
|
QString displayName = nativeName + " (" + nativeCountryName + ")";
|
|
|
|
if (nativeName.compare(englishLanguageName, Qt::CaseInsensitive) != 0 &&
|
|
|
|
nativeCountryName.compare(englishCountryName, Qt::CaseInsensitive) != 0) {
|
|
|
|
displayName += " - " + englishLanguageName + " (" + englishCountryName + ")";
|
|
|
|
}
|
|
|
|
|
|
|
|
return displayName;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::initLanguageComboBox() {
|
|
|
|
languageLocaleMap.clear();
|
|
|
|
QStringList languages = getAvailableLanguages();
|
|
|
|
for (const auto &language : languages) {
|
|
|
|
ui->languageComboBox->addItem(language);
|
|
|
|
}
|
|
|
|
|
|
|
|
QLocale currentLocale = QLocale::system();
|
|
|
|
QString currentLocaleDisplayName = getDisplayNameForLocale(currentLocale);
|
|
|
|
|
|
|
|
int defaultIndex = ui->languageComboBox->findText(currentLocaleDisplayName);
|
|
|
|
if (defaultIndex != -1) {
|
|
|
|
ui->languageComboBox->setCurrentIndex(defaultIndex);
|
|
|
|
} else {
|
|
|
|
// Fallback to English (United States) if current locale is not in the list
|
|
|
|
defaultIndex = ui->languageComboBox->findText("English (United States)");
|
|
|
|
if (defaultIndex != -1) {
|
|
|
|
ui->languageComboBox->setCurrentIndex(defaultIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
QStringList InstallerPrompt::getAvailableLanguages() {
|
|
|
|
QMap<QString, QString> languageMap; // Default sorting by QString is case-sensitive
|
|
|
|
|
|
|
|
for (int language = QLocale::C; language <= QLocale::LastLanguage; ++language) {
|
|
|
|
foreach (int country, QLocale::countriesForLanguage(static_cast<QLocale::Language>(language))) {
|
|
|
|
QLocale locale(static_cast<QLocale::Language>(language), static_cast<QLocale::Country>(country));
|
|
|
|
|
|
|
|
QString displayName = getDisplayNameForLocale(locale);
|
|
|
|
if (displayName.isEmpty()) continue;
|
|
|
|
|
|
|
|
languageMap.insert(displayName, locale.name());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Sort the language display names
|
|
|
|
QStringList sortedLanguages = languageMap.keys();
|
|
|
|
std::sort(sortedLanguages.begin(), sortedLanguages.end(), [](const QString &a, const QString &b) {
|
|
|
|
return a.compare(b, Qt::CaseInsensitive) < 0;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Clear the existing languageLocaleMap and repopulate it based on sortedLanguages
|
|
|
|
languageLocaleMap.clear();
|
|
|
|
for (const QString &languageName : sortedLanguages) {
|
|
|
|
languageLocaleMap.insert(languageName, languageMap[languageName]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return sortedLanguages;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::onLanguageChanged(int index) {
|
|
|
|
selectedLanguage = ui->languageComboBox->itemText(index);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::onLanguageConfirm() {
|
|
|
|
ui->changingLanguageLabel->setVisible(true);
|
|
|
|
ui->changingLanguageLoader->setVisible(true);
|
|
|
|
ui->languageComboBox->setEnabled(false);
|
|
|
|
ui->tryLubuntu->setEnabled(false);
|
|
|
|
ui->installLubuntu->setEnabled(false);
|
|
|
|
|
|
|
|
localeName = languageLocaleMap.value(selectedLanguage);
|
|
|
|
qDebug() << selectedLanguage << localeName;
|
|
|
|
|
|
|
|
// Split the locale name to get language and country code
|
|
|
|
QStringList localeParts = localeName.split('_');
|
|
|
|
QString languageCode = localeParts.value(0);
|
|
|
|
QString countryCode = localeParts.value(1);
|
|
|
|
|
|
|
|
// If there is no internet connection and we don't ship the langpack, tell them
|
|
|
|
QStringList allowedLanguages = {"zh-hans", "hi", "es", "fr", "ar", "en"};
|
|
|
|
bool only_lxqt = false;
|
|
|
|
if (!allowedLanguages.contains(languageCode) && NetworkManager::status() != NetworkManager::Status::Connected) {
|
|
|
|
ui->changingLanguageLabel->setText(tr("Unable to download full language support, changing anyway..."));
|
|
|
|
only_lxqt = true;
|
|
|
|
} else {
|
|
|
|
ui->changingLanguageLabel->setText(tr("Changing language..."));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Some of the LibreOffice language packs need special-casing, do that here
|
|
|
|
QString libreOfficeLang;
|
|
|
|
if (localeParts[0] == "zh") {
|
|
|
|
libreOfficeLang = (countryCode == "CN" || countryCode == "SG" || countryCode == "MY") ? "zh-cn" : "zh-tw";
|
|
|
|
} else {
|
|
|
|
static const QMap<QString, QString> localeMap = {
|
|
|
|
{"en_GB", "en-gb"}, {"en_ZA", "en-za"}, {"pa_IN", "pa-in"}, {"pt_BR", "pt-br"}
|
|
|
|
};
|
|
|
|
libreOfficeLang = localeMap.value(localeParts.join('_'), languageCode);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Construct the command to run the script with parameters
|
|
|
|
QProcess *process = new QProcess(this);
|
|
|
|
QStringList arguments;
|
|
|
|
|
|
|
|
process->setProgram("/usr/libexec/change-system-language");
|
|
|
|
arguments << languageCode << countryCode << libreOfficeLang;
|
|
|
|
if (only_lxqt) arguments << "1";
|
|
|
|
process->setArguments(arguments);
|
|
|
|
|
|
|
|
connect(process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, &InstallerPrompt::languageProcessFinished);
|
|
|
|
connect(process, &QProcess::errorOccurred, this, &InstallerPrompt::languageProcessError);
|
|
|
|
process->start();
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::languageProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) {
|
|
|
|
qDebug() << "Process finished. Exit code:" << exitCode << "Exit status:" << exitStatus;
|
|
|
|
ui->changingLanguageLabel->setVisible(false);
|
|
|
|
ui->changingLanguageLoader->setVisible(false);
|
|
|
|
ui->languageComboBox->setEnabled(true);
|
|
|
|
ui->tryLubuntu->setEnabled(true);
|
|
|
|
ui->installLubuntu->setEnabled(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::languageProcessError(QProcess::ProcessError error) {
|
|
|
|
qDebug() << "Process failed with error:" << error;
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::tryLubuntu()
|
|
|
|
{
|
|
|
|
QApplication::quit();
|
|
|
|
}
|
|
|
|
|
|
|
|
void InstallerPrompt::installLubuntu()
|
|
|
|
{
|
|
|
|
ui->tryLubuntu->setVisible(false);
|
|
|
|
ui->installLubuntu->setVisible(false);
|
|
|
|
ui->confirmButton->setVisible(false);
|
|
|
|
ui->languageComboBox->setEnabled(false);
|
|
|
|
QProcess *calamares = new QProcess(this);
|
|
|
|
QStringList args;
|
|
|
|
calamares->start("/usr/libexec/lubuntu-installer", args);
|
|
|
|
|
|
|
|
// If Calamares exits, it either crashed or the user cancelled the installation. Exit the installer prompt (and start LXQt).
|
|
|
|
connect(calamares, SIGNAL(finished(int)), this, SLOT(tryLubuntu()));
|
|
|
|
}
|
|
|
|
|
|
|
|
InstallerPrompt::~InstallerPrompt()
|
|
|
|
{
|
|
|
|
delete ui;
|
|
|
|
}
|