From f2d269033dbdc02960465790d37e7e1d53b91d93 Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Mon, 15 Aug 2022 21:10:32 +0200 Subject: [PATCH 01/19] purging old cold, some new --- src/apps/userapps.cpp | 2 +- src/eink.qrc | 2 + src/functions.h | 144 +++++++--------- src/homeWidget/mainwindow.cpp | 127 +++----------- src/homeWidget/mainwindow.h | 10 +- src/main.cpp | 6 +- src/resources/refresh.png | Bin 0 -> 13021 bytes src/resources/stop.png | Bin 0 -> 11604 bytes src/resources/wifi-standby.png | Bin 3559 -> 15784 bytes src/settings/settings.cpp | 2 +- src/widgets/dialogs/generaldialog.cpp | 16 +- src/widgets/dialogs/generaldialog.h | 1 - src/widgets/dialogs/wifi/wifidialog.cpp | 219 +++++++++++++----------- src/widgets/dialogs/wifi/wifidialog.h | 12 -- src/widgets/dialogs/wifi/wifidialog.ui | 187 ++++++++++++++------ src/widgets/interfaceWidgets/toast.cpp | 37 +--- src/widgets/interfaceWidgets/toast.h | 3 - 17 files changed, 357 insertions(+), 411 deletions(-) create mode 100644 src/resources/refresh.png create mode 100644 src/resources/stop.png diff --git a/src/apps/userapps.cpp b/src/apps/userapps.cpp index 1517aa2..29c156b 100644 --- a/src/apps/userapps.cpp +++ b/src/apps/userapps.cpp @@ -185,7 +185,7 @@ bool userapps::manageRequiredFeatures() if(featureId == 0) { // Double 'if' conditions to avoid launching unnecesery testPing() in emu if(global::deviceID != "emu\n") { - if(testPing(true) != 0) { + if(testPing() != 0) { global::userApps::appCompatibilityText = "This app needs a Wi-Fi connection, continue anyway?"; launchDialog = true; } diff --git a/src/eink.qrc b/src/eink.qrc index ab45a56..2cac456 100644 --- a/src/eink.qrc +++ b/src/eink.qrc @@ -84,5 +84,7 @@ resources/highlight.png resources/unhighlight.png resources/view-highlights.png + resources/stop.png + resources/refresh.png diff --git a/src/functions.h b/src/functions.h index 7c9c4b5..e28eeb6 100644 --- a/src/functions.h +++ b/src/functions.h @@ -92,7 +92,6 @@ namespace global { } namespace toast { inline QString message; - inline bool wifiToast; inline bool modalToast; inline bool indefiniteToast; inline int delay; @@ -100,9 +99,6 @@ namespace global { namespace device { inline bool isWifiAble; } - namespace network { - inline bool isConnected; - } namespace otaUpdate { inline bool isUpdateOta; inline bool downloadOta; @@ -169,6 +165,17 @@ namespace global { namespace highlightsListDialog { inline QString bookPath; } + namespace wifi { + // This is the correct way to do this. + enum class WifiState + { + Configured, + Enabled, + Disabled, + Unknown, // to not confuse lastWifiState + }; + inline bool isConnected; + } inline QString systemInfoText; inline bool forbidOpenSearchDialog; inline bool isN705 = false; @@ -780,41 +787,6 @@ namespace { } } } - bool connectToNetwork(QString essid, QString passphrase) { - log("Connecting to network '" + essid + "'", "functions"); - std::string essid_str = essid.toStdString(); - std::string passphrase_str = passphrase.toStdString(); - string_writeconfig("/run/wifi_network_essid", essid_str); - string_writeconfig("/run/wifi_network_passphrase", passphrase_str); - string_writeconfig("/opt/ibxd", "connect_to_wifi_network\n"); - - int connectionSuccessful = 0; - - while(connectionSuccessful == 0) { - if(QFile::exists("/run/wifi_connected_successfully")) { - if(checkconfig("/run/wifi_connected_successfully") == true) { - QFile::remove("/run/wifi_connected_successfully"); - connectionSuccessful = 1; - global::network::isConnected = true; - setDefaultWorkDir(); - string_writeconfig(".config/17-wifi_connection_information/essid", essid_str); - string_writeconfig(".config/17-wifi_connection_information/passphrase", passphrase_str); - QString function = __func__; log(function + ": Connection successful", "functions"); - return true; - } - else { - QFile::remove("/run/wifi_connected_successfully"); - connectionSuccessful = 0; - global::network::isConnected = false; - QString function = __func__; log(function + ": Connection failed", "functions"); - return false; - } - } - else { - QThread::msleep(100); - } - } - } int get_warmth() { QString sysfsWarmthPath; if(global::deviceID == "n873\n") { @@ -866,51 +838,6 @@ namespace { return !!ptr; } } - int testPing(bool blocking) { - QProcess *pingProcess = new QProcess(); - if(blocking == true) { - QString pingProg = "ping"; - QStringList pingArgs; - pingArgs << "-c" << "1" << "1.1.1.1"; - pingProcess->start(pingProg, pingArgs); - pingProcess->waitForFinished(); - int exitCode = pingProcess->exitCode(); - pingProcess->deleteLater(); - if(exitCode == 0) { - global::network::isConnected = true; - } - else { - global::network::isConnected = false; - } - return exitCode; - } - /* For some reason, implementing a non-blocking version of this functions triggers a "terminate called without an active exception" error with a platform plugin compiled with a newer GCC 11 toolchain. The problem has been solved by transplanting this function into the related area which uses it. - else { - QString pingProg = "sh"; - QStringList pingArgs; - pingArgs << "/mnt/onboard/.adds/inkbox/test_ping.sh"; - pingProcess->startDetached(pingProg, pingArgs); - } - */ - pingProcess->deleteLater(); - } - bool getTestPingResults() { - // To be used when the testPing() function is used in non-blocking mode. - if(QFile::exists("/run/test_ping_status")) { - if(checkconfig("/run/test_ping_status") == true) { - global::network::isConnected = true; - return true; - } - else { - global::network::isConnected = false; - return false; - } - } - else { - global::network::isConnected = false; - return false; - } - } void updateUserAppsMainJsonFile() { QDirIterator appsDir("/mnt/onboard/onboard/.apps", QDirIterator::NoIteratorFlags); QFile newJsonFile = QFile{"/mnt/onboard/onboard/.apps/apps.json"}; @@ -1135,6 +1062,55 @@ namespace { return 2; } } + global::wifi::WifiState checkWifiState() { + QProcess *wifiStateProcess = new QProcess(); + // Important to remember thats its in chroot... + QString path = "/external_root/usr/local/bin/wifi/wifi_status.sh"; + QStringList args; + wifiStateProcess->start(path, args); + wifiStateProcess->waitForFinished(); + wifiStateProcess->deleteLater(); + QString currentWifiState; + if(QFile("/run/wifi_status").exists() == true) { + currentWifiState = readFile("/run/wifi_status"); + } else { + log("/run/wifi_status doesnt exist"); + } + if (currentWifiState.contains("configured") == true) { + global::wifi::isConnected = true; + return global::wifi::WifiState::Configured; + } + else if (currentWifiState.contains("enabled") == true) { + global::wifi::isConnected = false; + return global::wifi::WifiState::Enabled; + } + else if (currentWifiState.contains("disabled") == true) { + global::wifi::isConnected = false; + return global::wifi::WifiState::Disabled; + } else { + global::wifi::isConnected = false; + log("Critical error, checkWifiState()", "functions.h"); + return global::wifi::WifiState::Unknown; + } + } + int testPing() { + // For some reason, implementing a non-blocking version of this functions triggers a "terminate called without an active exception" error with a platform plugin compiled with a newer GCC 11 toolchain. The problem has been solved by transplanting this function into the related area which uses it. + QProcess *pingProcess = new QProcess(); + QString pingProg = "ping"; + QStringList pingArgs; + pingArgs << "-c" << "1" << "1.1.1.1"; + pingProcess->start(pingProg, pingArgs); + pingProcess->waitForFinished(); + int exitCode = pingProcess->exitCode(); + pingProcess->deleteLater(); + if(exitCode == 0) { + global::wifi::isConnected = true; + } + else { + global::wifi::isConnected = false; + } + return exitCode; + } } #endif // FUNCTIONS_H diff --git a/src/homeWidget/mainwindow.cpp b/src/homeWidget/mainwindow.cpp index e2e9cef..d7d4d56 100644 --- a/src/homeWidget/mainwindow.cpp +++ b/src/homeWidget/mainwindow.cpp @@ -65,8 +65,6 @@ MainWindow::MainWindow(QWidget *parent) global::usbms::koboxExportExtensions = false; global::mainwindow::tabSwitcher::repaint = true; resetFullWindowException = false; - wifiIconClickedWhileReconnecting = false; - lastWifiState = 0; // Getting the screen's size sW = QGuiApplication::screens()[0]->size().width(); @@ -134,9 +132,13 @@ MainWindow::MainWindow(QWidget *parent) ui->brightnessBtn->setIcon(QIcon(":/resources/frontlight.png")); ui->brightnessBtn->setIconSize(QSize(brightnessIconWidth, brightnessIconHeight)); - setWifiIcon(); + updateWifiState(); if(global::device::isWifiAble == true) { - updateWifiIcon(0); + // Start wifi updater + QTimer *wifiIconTimer = new QTimer(this); + wifiIconTimer->setInterval(5000); + connect(wifiIconTimer, SIGNAL(timeout()), this, SLOT(updateWifiState())); + wifiIconTimer->start(); } setBatteryIcon(); @@ -749,90 +751,34 @@ void MainWindow::setupSearchDialog() { } } -void MainWindow::updateWifiIcon(int mode) { +void MainWindow::updateWifiIcon(global::wifi::WifiState mode) { /* Usage: - * mode 0: auto - * mode 1: off - * mode 2: standby - * mode 3: connected + * mode 0 is handled in mainwindow() */ - if(mode == 0) { - lastWifiState = 0; - QTimer *wifiIconTimer = new QTimer(this); - wifiIconTimer->setInterval(10000); - connect(wifiIconTimer, SIGNAL(timeout()), this, SLOT(setWifiIcon())); - wifiIconTimer->start(); - } - if(mode == 1) { - lastWifiState = 1; + if(mode == global::wifi::WifiState::Disabled) { + lastWifiState = global::wifi::WifiState::Disabled; ui->wifiBtn->setIcon(QIcon(":/resources/wifi-off.png")); ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); } - if(mode == 2) { - lastWifiState = 2; + if(mode == global::wifi::WifiState::Enabled) { + lastWifiState = global::wifi::WifiState::Enabled; ui->wifiBtn->setIcon(QIcon(":/resources/wifi-standby.png")); ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); } - if(mode == 3) { - lastWifiState = 3; + if(mode == global::wifi::WifiState::Configured) { + lastWifiState = global::wifi::WifiState::Configured; ui->wifiBtn->setIcon(QIcon(":/resources/wifi-connected.png")); ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); } } -bool MainWindow::checkWifiState() { - /* Return value: - * true: interface UP - * false: interface DOWN - */ - if(global::deviceID == "n437\n") { - string_checkconfig_ro("/sys/class/net/wlan0/operstate"); - } - else { - string_checkconfig_ro("/sys/class/net/eth0/operstate"); - } - - if(checkconfig_str_val == "up\n") { - return true; - } - else { - return false; - } -} - -void MainWindow::setWifiIcon() { +void MainWindow::updateWifiState() { if(global::device::isWifiAble == true) { - if(checkWifiState() == true) { - // testPing() the non-blocking way - QProcess * pingProcess = new QProcess(); - QString pingProg = "sh"; - QStringList pingArgs; - pingArgs << "/mnt/onboard/.adds/inkbox/test_ping.sh"; - pingProcess->startDetached(pingProg, pingArgs); - pingProcess->deleteLater(); - - getTestPingResults(); - if(global::network::isConnected == true) { - if(lastWifiState != 3) { - lastWifiState = 3; - ui->wifiBtn->setIcon(QIcon(":/resources/wifi-connected.png")); - ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); - } - } - else { - if(lastWifiState != 2) { - lastWifiState = 2; - ui->wifiBtn->setIcon(QIcon(":/resources/wifi-standby.png")); - ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); - } - } - } - else { - if(lastWifiState != 1) { - lastWifiState = 1; - ui->wifiBtn->setIcon(QIcon(":/resources/wifi-off.png")); - ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); - } + global::wifi::WifiState currentWifiState = checkWifiState(); + if(lastWifiState != currentWifiState) { + // This is handled by updateWifiIcon() + //lastWifiState = currentWifiState; + updateWifiIcon(currentWifiState); } } else { @@ -841,31 +787,10 @@ void MainWindow::setWifiIcon() { } } -void MainWindow::openWifiDialog() { - log("Opening Wi-Fi connection interface", className); - if(checkconfig("/external_root/run/was_connected_to_wifi") == true and wifiIconClickedWhileReconnecting == false) { - showToast("Reconnection in progress\nTap again to cancel"); - wifiIconClickedWhileReconnecting = true; - QTimer::singleShot(10000, this, SLOT(resetWifiIconClickedWhileReconnecting())); - } - else { - if(wifiIconClickedWhileReconnecting == true) { - string_writeconfig("/opt/ibxd", "stop_wifi_reconnection\n"); - while(true) { - if(QFile::exists("/run/stop_wifi_reconnection_done")) { - QFile::remove("/run/stop_wifi_reconnection_done"); - break; - } - } - } - global::toast::wifiToast = true; - showToast("Searching for networks"); - } -} - void MainWindow::on_wifiBtn_clicked() { - openWifiDialog(); + wifiDialog* newWIfiDialog = new wifiDialog(); + newWIfiDialog->exec(); } void MainWindow::showToast(QString messageToDisplay) { @@ -963,7 +888,7 @@ void MainWindow::openEncfsRepackDialog() { void MainWindow::on_libraryButton_clicked() { log("Launching Online Library", className); - if(testPing(true) == 0 or global::deviceID == "emu\n") { + if(testPing() == 0 or global::deviceID == "emu\n") { resetFullWindowException = true; resetWindow(false); if(global::mainwindow::tabSwitcher::libraryWidgetSelected != true) { @@ -1000,7 +925,7 @@ void MainWindow::resetFullWindow() { } void MainWindow::checkForOtaUpdate() { - if(global::network::isConnected == true) { + if(global::wifi::isConnected == true) { string_checkconfig_ro("/external_root/opt/storage/update/last_sync"); if(!checkconfig_str_val.isEmpty()) { unsigned long currentEpoch = QDateTime::currentSecsSinceEpoch(); @@ -1016,10 +941,6 @@ void MainWindow::checkForOtaUpdate() { } } -void MainWindow::resetWifiIconClickedWhileReconnecting() { - wifiIconClickedWhileReconnecting = false; -} - void MainWindow::setupLocalLibraryWidget() { localLibraryWidgetWindow = new localLibraryWidget(this); QObject::connect(localLibraryWidgetWindow, &localLibraryWidget::openBookSignal, this, &MainWindow::openBookFile); diff --git a/src/homeWidget/mainwindow.h b/src/homeWidget/mainwindow.h index 9cebc0c..fc76401 100644 --- a/src/homeWidget/mainwindow.h +++ b/src/homeWidget/mainwindow.h @@ -51,8 +51,7 @@ public: bool existing_recent_books = false; bool reboot_after_update = false; bool resetFullWindowException; - bool wifiIconClickedWhileReconnecting; - int lastWifiState; + global::wifi::WifiState lastWifiState = global::wifi::WifiState::Unknown; int timerTime = 0; QString relative_path; QString usbmsStatus; @@ -62,7 +61,6 @@ public: void openUsbmsDialog(); void resetIcons(); void setBatteryIcon(); - bool checkWifiState(); public slots: @@ -74,14 +72,13 @@ private slots: void on_quitBtn_clicked(); void on_brightnessBtn_clicked(); void openUpdateDialog(); - void openWifiDialog(); void setInitialBrightness(); void on_homeBtn_clicked(); void refreshScreen(); void setupSearchDialog(); - void setWifiIcon(); + void updateWifiState(); void on_wifiBtn_clicked(); - void updateWifiIcon(int mode); + void updateWifiIcon(global::wifi::WifiState mode); void hello(int testNumber); void showToast(QString messageToDisplay); void closeIndefiniteToast(); @@ -95,7 +92,6 @@ private slots: void on_libraryButton_clicked(); void resetWindow(bool resetStackedWidget); void resetFullWindow(); - void resetWifiIconClickedWhileReconnecting(); void setupLocalLibraryWidget(); void setupHomePageWidget(); diff --git a/src/main.cpp b/src/main.cpp index 6fc6653..a924a69 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,6 +41,9 @@ int main(int argc, char *argv[]) global::logger::status = true; } } + // Szybet testing + global::logger::status = true; + global::deviceID = readFile("/opt/inkbox_device"); log("Running on device " + global::deviceID, "main", true); @@ -226,7 +229,8 @@ int main(int argc, char *argv[]) } const QScreen * screen = qApp->primaryScreen(); - w.setGeometry(QRect(QPoint(0,0), screen->geometry ().size())); + w.setGeometry(QRect(QPoint(0,0), screen->geometry().size())); + w.setFixedSize(QSize(screen->geometry().height(), screen->geometry().width())); w.show(); return a.exec(); } diff --git a/src/resources/refresh.png b/src/resources/refresh.png new file mode 100644 index 0000000000000000000000000000000000000000..6f07016a5014a83d051d467cd5b30c01ff8f93c7 GIT binary patch literal 13021 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 rQk^^@VK6v1QvQzv9)qhm0 literal 0 HcmV?d00001 diff --git a/src/resources/stop.png b/src/resources/stop.png new file mode 100644 index 0000000000000000000000000000000000000000..b813bb05b43a84babbbafddbf7d61084f0601b9a GIT binary patch literal 11604 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 literal 0 HcmV?d00001 diff --git a/src/resources/wifi-standby.png b/src/resources/wifi-standby.png index 5fa26f2985c2504edd114e132f33eef64d59f120..de669fbe7e6c4bf9436c7f2b547d98a01a0d09cc 100644 GIT binary patch literal 15784 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 NOi@FjLe4zoe*x;fBIE!7 literal 3559 zcmdUxd010d7QoMYSp~A7fFNKJ&;b=SRE1cO1fmtn)U_&%3jvFkRtbu-2!RJdUv{pwEZPM05}2ui&p{QNX3E8MB;Va-9Z2>EkZ6|5g?ZfqjoB{L~IKOaNV!k zzsSF4h1K5WtB*U)=Jp8N_Z7bz%(vcgccxXb-%0D=>=wuWSuj7sf7J#DMsuoKnze>C zdFw{U4GdoctG2N*;P#UDFVCHEKC|yihwAItn{C=5C=L$)>fSu=$CtKmSry=(7h)|x z%NC`&;+gdg?{rO@!D$`5bi(IU1^wpB-k~z5PpZRYvT29I(<3G+`OB3Lm`_#hwzF=` z>|5BEA24}ZQs<@iKKrM?yMf=#F1X*|y(2rwZTGo5btT(Asa;*WW6cjULaxV`>}+W- zS@XO^wS4qSly69I*SlvzztLn)_vaTE<(Qq)>@V8rQs49F{zk(dzW9~_M`*i8K}Ki5NX z$jI6i@WB$+6BcI@E@_f?L;#p~1}ygdFz!LmW8X;oz=^Q(+oH|U_xmqQW^Rj{zVf5M zjn=(qSo!X23ha(bM;}E}FZh2LWb)Oe@ae_Y-m0~x)_8{uEsjIbKz^k^l%G!~hWrpfe$Ujl2tT7CfG`Ded?+9pCip*t8Xo)K0HTH`r1Oyy(3EKQiKFuu zVu}f&ZHhVWc{rI`?N|LMERsPmQjez;T>Z5R_ zz-ppWRN?C;KuwyO7n3(K9V~cUscx&W0K{(TbWLlwC#DcvFceSk$K#~X7D(=S8iQEc zdz%(>ROJfZyK)^g&OQE^J~ZJjp^6CU!b!O?6Z5*u{hUE$Jim<_f3KQi4!QT_jPA7+ z3#?%3iDNunxpBK2c)yn+&?NM<1VJ3Zl`41-Yl^|3cSw@4bvMp|;rh6C8)=$xtr^jM z<60}S#Zj6ex+2lrHkUze>g{>c=kLu2ugda{YsU<(&^_GJB;Zv$gJvvYD0$f6m<;7b zv8=1SM{O)VradH1x<#e$+2f2p^==cEChOglE%>$rC45ip=3#J50?S(!q7K$ml-HD& zMRroRYXTYl^^1CwXdy~?QS9ccysIb_u1%PiWSb);*v}pp_Q|8hLou}j*Bz3f;=PwzwTf1B-uqo>Wm-jkp#*B$eNU*b@4yY)Wo=vDPAXHksOVEI z$Rxdq!TQf;zaqtEXbt`%UVaiB&C9>m+Ld0m}v7aeo9R`cfP^8l4Ib= z&K-1fb%=@195~&y#sl0O-Rz>xp4jJEKp-Ql)nvVmF2w#=z4fmiCCNK^Nr77wsk!1XaQ>k9i`LeQV(;#$d|Zn{*|}A&jk1JBJ(XKWnw=jJilK)|MW;T zC$|j~$yB-8_K}8}$x$_73YmrCtoDVr;og{@SrbL@$Sb!CGPG@Wi94W9-3f}$WeEMGJ)4Kx=uCF0dxW|(4S z=)%yZ2Gj%muDo-lyTFT1Fw&l=gXd?l!JL)FEQ|241e@$Se9OHOCvcl|gWgd3oizjr z53=&Z%iKUCb~6(ZQ@x0t&@xhxGT zu@wf?V_bC8agv;}RaLKsAr=X%kG*3dlzf!RkgTEh%4OK;$$D32h;ir@Lo3lZ2 z;8>E)Idt#SnQob*hMes6)@0{xjf8 z{r(CJ7B_omWTkz5QyGZz~9WsdFwiy2~=r}gN~nEov4_jZ0cnOXPnx< zUgJ-wj>ezV?D2Y_rsYT}f61s2*T*EhvIO=9It1mQe+r7T00J##0Kzy+P}t#Y0Q6wU zQ&yt1ro!7taEa@;Bz>AjV;hHN+4F(CnlXBNY*Q$;DxEs%P}NE+0>Hz|6fzJ^T?oi@ zRtO(i97ZyHXztLeOr#H=uYVc)TFX-67!>bSexES8g|V*lERZ{^hPOUDOD$rJV06P? zxSSJSH@&1%=a|%6mr(5qde5XpXS7iX$K=z|Cat5Ah4w|Osqb?@dogC@gQmXzoXa9Q zq#Z0j-s2d*lnw0JO7n;7UmoNGfBhqy3+0`&MIbzXarURZ-zWHiY+J@J^v(1o;NOqZkuUnb+6gT0IpCi^E!@$tO%JL)*%y$ ziINS;rqgCHst=U^cQW>_EcK@UBt+v={6wgq12~D$^$)%Be>sly*}uHRx@kImvx@qR NfF;Wom-;DE{{lkv$f5uM diff --git a/src/settings/settings.cpp b/src/settings/settings.cpp index a0a85ff..8a626d6 100644 --- a/src/settings/settings.cpp +++ b/src/settings/settings.cpp @@ -846,7 +846,7 @@ void settings::on_globalReadingSettingsCheckBox_toggled(bool checked) void settings::on_checkOtaUpdateBtn_clicked() { log("'Check for OTA update' button clicked", className); - if(testPing(true) == 0 or global::deviceID == "emu\n") { + if(testPing() == 0 or global::deviceID == "emu\n") { launchOtaUpdater(); } else { diff --git a/src/widgets/dialogs/generaldialog.cpp b/src/widgets/dialogs/generaldialog.cpp index 0a8cd1c..997dab6 100644 --- a/src/widgets/dialogs/generaldialog.cpp +++ b/src/widgets/dialogs/generaldialog.cpp @@ -419,7 +419,7 @@ void generalDialog::on_okBtn_clicked() } } else if(ui->searchComboBox->currentText() == "Online library") { - if(testPing(true) == 0 or global::deviceID == "emu\n") { + if(testPing() == 0 or global::deviceID == "emu\n") { string_writeconfig("/inkbox/searchComboBoxFunction", "Online library"); log("Searching online library for '" + global::keyboard::keyboardText + "'", className); @@ -648,20 +648,6 @@ void generalDialog::startVNC(QString server, QString password, QString port) { qApp->quit(); } -void generalDialog::connectToNetworkSlot() { - if(connectToNetwork(wifiEssid, wifiPassphrase) == true) { - emit updateWifiIcon(3); - emit closeIndefiniteToast(); - emit showToast("Connection successful"); - } - else { - emit updateWifiIcon(2); - emit closeIndefiniteToast(); - emit showToast("Connection failed"); - } - generalDialog::close(); -} - void generalDialog::startOtaUpdate(bool wasDownloadSuccessful) { emit closeIndefiniteToast(); if(wasDownloadSuccessful == true) { diff --git a/src/widgets/dialogs/generaldialog.h b/src/widgets/dialogs/generaldialog.h index 08d1001..a1e742c 100644 --- a/src/widgets/dialogs/generaldialog.h +++ b/src/widgets/dialogs/generaldialog.h @@ -63,7 +63,6 @@ private slots: void adjust_size(); void restartSearchDialog(); void refreshScreenNative(); - void connectToNetworkSlot(); void startOtaUpdate(bool wasDownloadSuccessful); void openBookFileNative(QString book, bool relativePath); void showToastNative(QString messageToDisplay); diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 34e3f6c..9fec05c 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -14,7 +14,6 @@ wifiDialog::wifiDialog(QWidget *parent) : ui(new Ui::wifiDialog) { ui->setupUi(this); - wifiListTimer = new QTimer(this); // Stylesheet, style & misc. QFile stylesheetFile("/mnt/onboard/.adds/inkbox/eink.qss"); @@ -23,15 +22,34 @@ wifiDialog::wifiDialog(QWidget *parent) : stylesheetFile.close(); this->setModal(true); - ui->cancelBtn->setProperty("type", "borderless"); - ui->connectBtn->setProperty("type", "borderless"); - ui->cancelBtn->setStyleSheet("font-size: 9pt; padding: 10px; font-weight: bold; background: lightGrey"); - ui->connectBtn->setStyleSheet("font-size: 9pt; padding: 10px; font-weight: bold; background: lightGrey"); - ui->mainLabel->setStyleSheet("padding-left: 125px; padding-right: 125px"); - ui->networksListWidget->setFont(QFont("u001")); - ui->networksListWidget->setStyleSheet("font-size: 9pt"); + ui->stopBtn->setIcon(QIcon(":/resources/stop.png")); + ui->logBtn->setIcon(QIcon(":/resources/file-text.png")); + ui->refreshBtn->setIcon(QIcon(":/resources/refresh.png")); + + ui->Wificheckbox->setStyleSheet("QCheckBox::indicator { width:50px; height: 50px; }"); + + // Size + QRect screenGeometry = QGuiApplication::screens()[0]->geometry(); + this->setFixedWidth(screenGeometry.width()); + + int halfOfHalfHeight = ((screenGeometry.height() / 2) / 2) / 2; + int finalHeight = screenGeometry.height() - halfOfHalfHeight * 2; + + this->setFixedHeight(finalHeight); + this->move(0, halfOfHalfHeight); + + // Button sizes + ui->stopBtn->setFixedWidth(screenGeometry.width() / 8); + ui->logBtn->setFixedWidth(screenGeometry.width() / 8); + ui->refreshBtn->setFixedWidth(screenGeometry.width() / 8); + + int heighIncrease = 20; + ui->stopBtn->setFixedHeight(ui->stopBtn->height() + heighIncrease); + ui->logBtn->setFixedHeight(ui->logBtn->height() + heighIncrease); + ui->refreshBtn->setFixedHeight(ui->refreshBtn->height() + heighIncrease); + + //ui->cancelBtn->setProperty("type", "borderless"); - checkWifiNetworks(); } wifiDialog::~wifiDialog() @@ -39,93 +57,6 @@ wifiDialog::~wifiDialog() delete ui; } -void wifiDialog::checkWifiNetworks() { - string_writeconfig("/opt/ibxd", "list_wifi_networks\n"); - wifiListTimer->setInterval(100); - connect(wifiListTimer, &QTimer::timeout, [&]() { - if(QFile::exists("/run/wifi_networks_list")) { - printWifiNetworks(); - wifiListTimer->stop(); - } - } ); - wifiListTimer->start(); -} - -void wifiDialog::printWifiNetworks() { - if(readFile("/run/wifi_networks_list").isEmpty()) { - log("Wi-Fi networks list empty", className); - QFile::remove("/run/wifi_networks_list"); - emit quit(1); - wifiDialog::close(); - } - else { - log("Parsing Wi-Fi networks list", className); - QFile wifiNetworksListFile("/run/wifi_networks_list"); - wifiNetworksListFile.open(QIODevice::ReadWrite); - QTextStream in (&wifiNetworksListFile); - wifiNetworksList = in.readAll(); - wifiNetworksListFile.close(); - QFile::remove("/run/wifi_networks_list"); - - QStringListModel* model = new QStringListModel(this); - QStringList list = wifiNetworksList.split("\n", QString::SkipEmptyParts); - model->setStringList(list); - ui->networksListWidget->setModel(model); - ui->networksListWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); - - emit wifiNetworksListReady(1); - } -} - -void wifiDialog::centerDialog() { - // Centering dialog - // Get current screen size - QRect rec = QGuiApplication::screenAt(this->pos())->geometry(); - // Using minimum size of window - QSize size = this->minimumSize(); - // Set top left point - QPoint topLeft = QPoint((rec.width() / 2) - (size.width() / 2), (rec.height() / 2) - (size.height() / 2)); - // set window position - setGeometry(QRect(topLeft, size)); -} - -void wifiDialog::on_cancelBtn_clicked() -{ - string_writeconfig("/opt/ibxd", "toggle_wifi_off\n"); - while(true) { - if(QFile::exists("/run/toggle_wifi_off_done")) { - QFile::remove("/run/toggle_wifi_off_done"); - break; - } - } - emit quit(0); - wifiDialog::close(); -} - -void wifiDialog::on_connectBtn_clicked() -{ - index = ui->networksListWidget->currentIndex(); - itemText = index.data(Qt::DisplayRole).toString(); - if(itemText.isEmpty()) { - showToast("You must select a network"); - } - else { - this->hide(); - global::keyboard::keyboardDialog = true; - global::keyboard::wifiPassphraseDialog = true; - global::keyboard::keyboardText = ""; - generalDialogWindow = new generalDialog(); - generalDialogWindow->setAttribute(Qt::WA_DeleteOnClose); - generalDialogWindow->wifiEssid = itemText; - connect(generalDialogWindow, SIGNAL(refreshScreen()), SLOT(refreshScreenNative())); - connect(generalDialogWindow, SIGNAL(updateWifiIcon(int)), SLOT(updateWifiIcon(int))); - connect(generalDialogWindow, SIGNAL(showToast(QString)), SLOT(showToastNative(QString))); - connect(generalDialogWindow, SIGNAL(closeIndefiniteToast()), SLOT(closeIndefiniteToastNative())); - connect(generalDialogWindow, SIGNAL(destroyed(QObject*)), SLOT(close())); - generalDialogWindow->show(); - } -} - void wifiDialog::refreshScreenNative() { emit refreshScreen(); } @@ -141,3 +72,99 @@ void wifiDialog::showToastNative(QString messageToDisplay) { void wifiDialog::closeIndefiniteToastNative() { emit closeIndefiniteToast(); } + +/* + + this->hide(); + global::keyboard::keyboardDialog = true; + global::keyboard::wifiPassphraseDialog = true; + global::keyboard::keyboardText = ""; + generalDialogWindow = new generalDialog(); + generalDialogWindow->setAttribute(Qt::WA_DeleteOnClose); + generalDialogWindow->wifiEssid = itemText; + connect(generalDialogWindow, SIGNAL(refreshScreen()), SLOT(refreshScreenNative())); + connect(generalDialogWindow, SIGNAL(updateWifiIcon(int)), SLOT(updateWifiIcon(int))); + connect(generalDialogWindow, SIGNAL(showToast(QString)), SLOT(showToastNative(QString))); + connect(generalDialogWindow, SIGNAL(closeIndefiniteToast()), SLOT(closeIndefiniteToastNative())); + connect(generalDialogWindow, SIGNAL(destroyed(QObject*)), SLOT(close())); + generalDialogWindow->show(); + +*/ + +/* + bool connectToNetwork(QString essid, QString passphrase) { + log("Connecting to network '" + essid + "'", "functions"); + std::string essid_str = essid.toStdString(); + std::string passphrase_str = passphrase.toStdString(); + string_writeconfig("/run/wifi_network_essid", essid_str); + string_writeconfig("/run/wifi_network_passphrase", passphrase_str); + string_writeconfig("/opt/ibxd", "connect_to_wifi_network\n"); + + int connectionSuccessful = 0; + + while(connectionSuccessful == 0) { + if(QFile::exists("/run/wifi_connected_successfully")) { + if(checkconfig("/run/wifi_connected_successfully") == true) { + QFile::remove("/run/wifi_connected_successfully"); + connectionSuccessful = 1; + global::network::isConnected = true; + setDefaultWorkDir(); + string_writeconfig(".config/17-wifi_connection_information/essid", essid_str); + string_writeconfig(".config/17-wifi_connection_information/passphrase", passphrase_str); + QString function = __func__; log(function + ": Connection successful", "functions"); + return true; + } + else { + QFile::remove("/run/wifi_connected_successfully"); + connectionSuccessful = 0; + global::network::isConnected = false; + QString function = __func__; log(function + ": Connection failed", "functions"); + return false; + } + } + else { + QThread::msleep(100); + } + } + } +*/ +/* + int testPing(bool blocking) { + QProcess *pingProcess = new QProcess(); + if(blocking == true) { + QString pingProg = "ping"; + QStringList pingArgs; + pingArgs << "-c" << "1" << "1.1.1.1"; + pingProcess->start(pingProg, pingArgs); + pingProcess->waitForFinished(); + int exitCode = pingProcess->exitCode(); + pingProcess->deleteLater(); + if(exitCode == 0) { + global::network::isConnected = true; + } + else { + global::network::isConnected = false; + } + return exitCode; + } + // For some reason, implementing a non-blocking version of this functions triggers a "terminate called without an active exception" error with a platform plugin compiled with a newer GCC 11 toolchain. The problem has been solved by transplanting this function into the related area which uses it. + pingProcess->deleteLater(); + } + bool getTestPingResults() { + // To be used when the testPing() function is used in non-blocking mode. + if(QFile::exists("/run/test_ping_status")) { + if(checkconfig("/run/test_ping_status") == true) { + global::network::isConnected = true; + return true; + } + else { + global::network::isConnected = false; + return false; + } + } + else { + global::network::isConnected = false; + return false; + } + } +*/ diff --git a/src/widgets/dialogs/wifi/wifidialog.h b/src/widgets/dialogs/wifi/wifidialog.h index cd98c92..78173ee 100644 --- a/src/widgets/dialogs/wifi/wifidialog.h +++ b/src/widgets/dialogs/wifi/wifidialog.h @@ -18,29 +18,17 @@ public: QString className = this->metaObject()->className(); explicit wifiDialog(QWidget *parent = nullptr); ~wifiDialog(); - QString wifiNetworksList; - QString itemText; - QModelIndex index; - void checkWifiNetworks(); - void printWifiNetworks(); - void centerDialog(); private: Ui::wifiDialog *ui; - QTimer * wifiListTimer; - generalDialog * generalDialogWindow; signals: - void wifiNetworksListReady(int networksFound); - void quit(int exitCode); void refreshScreen(); void updateWifiIconSig(int mode); void showToast(QString messageToDisplay); void closeIndefiniteToast(); private slots: - void on_cancelBtn_clicked(); - void on_connectBtn_clicked(); void refreshScreenNative(); void updateWifiIcon(int mode); void showToastNative(QString messageToDisplay); diff --git a/src/widgets/dialogs/wifi/wifidialog.ui b/src/widgets/dialogs/wifi/wifidialog.ui index 10409eb..94702a2 100644 --- a/src/widgets/dialogs/wifi/wifidialog.ui +++ b/src/widgets/dialogs/wifi/wifidialog.ui @@ -6,8 +6,8 @@ 0 0 - 400 - 300 + 783 + 679 @@ -15,83 +15,162 @@ - - - - - 0 + + + QLayout::SetFixedSize + + + + + QLayout::SetMaximumSize - + - - 0 - - - 0 - - - 0 - - - 0 + + 2 - - - + + + - + 0 0 + + + - - + + + + + 0 + 0 + + + + + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + - 75 - true + 9 - Select a network - - - Qt::AlignCenter + Wifi status - - - - 0 - - - - - Connect - - - - - - - Cancel - - - - - - - + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Wifi + + + + + + + + + + + + + + + QFrame::Box + + + QFrame::Plain + + + 3 + + + Qt::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 759 + 570 + + + + + + + + + + + 0 + 0 + + + + Return + + + diff --git a/src/widgets/interfaceWidgets/toast.cpp b/src/widgets/interfaceWidgets/toast.cpp index 305d4f8..c89a439 100644 --- a/src/widgets/interfaceWidgets/toast.cpp +++ b/src/widgets/interfaceWidgets/toast.cpp @@ -27,27 +27,12 @@ toast::toast(QWidget *parent) : global::toast::delay = 5000; } } - if(global::toast::wifiToast == true) { - global::toast::wifiToast = false; - this->setModal(true); - wifiDialogWindow = new wifiDialog(this); - wifiDialogWindow->setAttribute(Qt::WA_DeleteOnClose); - connect(wifiDialogWindow, SIGNAL(wifiNetworksListReady(int)), SLOT(showWifiDialog(int))); - connect(wifiDialogWindow, SIGNAL(quit(int)), SLOT(exitSlot(int))); - connect(wifiDialogWindow, SIGNAL(refreshScreen()), SLOT(refreshScreenNative())); - connect(wifiDialogWindow, SIGNAL(updateWifiIconSig(int)), SLOT(updateWifiIcon(int))); - connect(wifiDialogWindow, SIGNAL(showToast(QString)), SLOT(showToastNative(QString))); - connect(wifiDialogWindow, SIGNAL(closeIndefiniteToast()), SLOT(closeIndefiniteToastNative())); - connect(wifiDialogWindow, SIGNAL(destroyed(QObject*)), SLOT(close())); + if(global::toast::indefiniteToast == false) { + QTimer::singleShot(global::toast::delay, this, SLOT(close())); + global::toast::delay = 0; } else { - if(global::toast::indefiniteToast == false) { - QTimer::singleShot(global::toast::delay, this, SLOT(close())); - global::toast::delay = 0; - } - else { - global::toast::indefiniteToast = false; - } + global::toast::indefiniteToast = false; } } @@ -56,16 +41,6 @@ toast::~toast() delete ui; } -void toast::showWifiDialog(int networksFound) { - if(networksFound == 1) { - emit updateWifiIconSig(2); - this->hide(); - wifiDialogWindow->show(); - wifiDialogWindow->adjustSize(); - wifiDialogWindow->centerDialog(); - } -} - void toast::centerToast() { // Centering toast (https://stackoverflow.com/a/58682351) // Get current screen size @@ -91,10 +66,6 @@ void toast::refreshScreenNative() { emit refreshScreen(); } -void toast::updateWifiIcon(int mode) { - emit updateWifiIconSig(mode); -} - void toast::showToastNative(QString messageToDisplay) { emit showToast(messageToDisplay); } diff --git a/src/widgets/interfaceWidgets/toast.h b/src/widgets/interfaceWidgets/toast.h index fa1cac8..5b4b427 100644 --- a/src/widgets/interfaceWidgets/toast.h +++ b/src/widgets/interfaceWidgets/toast.h @@ -21,13 +21,10 @@ public: private: Ui::toast *ui; - wifiDialog *wifiDialogWindow; private slots: - void showWifiDialog(int networksFound); void exitSlot(int exitCode); void refreshScreenNative(); - void updateWifiIcon(int mode); void showToastNative(QString messageToDisplay); void closeIndefiniteToastNative(); From ec81f72d2dc88eb42f2a15c40133194af1f4a856 Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Tue, 16 Aug 2022 15:25:01 +0200 Subject: [PATCH 02/19] scanning networks --- src/functions.h | 7 ++ src/widgets/dialogs/wifi/network.cpp | 14 +++ src/widgets/dialogs/wifi/network.h | 26 +++++ src/widgets/dialogs/wifi/network.ui | 92 +++++++++++++++++ src/widgets/dialogs/wifi/wifidialog.cpp | 126 +++++++++++++++++++++--- src/widgets/dialogs/wifi/wifidialog.h | 12 ++- src/widgets/dialogs/wifi/wifidialog.ui | 14 ++- 7 files changed, 265 insertions(+), 26 deletions(-) create mode 100644 src/widgets/dialogs/wifi/network.cpp create mode 100644 src/widgets/dialogs/wifi/network.h create mode 100644 src/widgets/dialogs/wifi/network.ui diff --git a/src/functions.h b/src/functions.h index e28eeb6..88cb271 100644 --- a/src/functions.h +++ b/src/functions.h @@ -175,6 +175,13 @@ namespace global { Unknown, // to not confuse lastWifiState }; inline bool isConnected; + class wifiNetworkData { + public: + QString mac; + QString name; + bool encryption; + int signal; + }; } inline QString systemInfoText; inline bool forbidOpenSearchDialog; diff --git a/src/widgets/dialogs/wifi/network.cpp b/src/widgets/dialogs/wifi/network.cpp new file mode 100644 index 0000000..9dd9a60 --- /dev/null +++ b/src/widgets/dialogs/wifi/network.cpp @@ -0,0 +1,14 @@ +#include "network.h" +#include "ui_network.h" + +network::network(QWidget *parent) : + QWidget(parent), + ui(new Ui::network) +{ + ui->setupUi(this); +} + +network::~network() +{ + delete ui; +} diff --git a/src/widgets/dialogs/wifi/network.h b/src/widgets/dialogs/wifi/network.h new file mode 100644 index 0000000..ab12625 --- /dev/null +++ b/src/widgets/dialogs/wifi/network.h @@ -0,0 +1,26 @@ +#ifndef NETWORK_H +#define NETWORK_H + +#include + +#include "functions.h" + +namespace Ui { +class network; +} + +class network : public QWidget +{ + Q_OBJECT + +public: + explicit network(QWidget *parent = nullptr); + ~network(); + global::wifi::wifiNetworkData mainData; + QString currentlyConnectedNetwork; + +private: + Ui::network *ui; +}; + +#endif // NETWORK_H diff --git a/src/widgets/dialogs/wifi/network.ui b/src/widgets/dialogs/wifi/network.ui new file mode 100644 index 0000000..152a22c --- /dev/null +++ b/src/widgets/dialogs/wifi/network.ui @@ -0,0 +1,92 @@ + + + network + + + + 0 + 0 + 605 + 62 + + + + + 0 + 0 + + + + Form + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + SIgnal strenth + + + + + + + wifi name + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + + + + + :/resources/chevron-right.png:/resources/chevron-right.png + + + + + + + + + + + + + diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 9fec05c..5ec212f 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -8,6 +8,7 @@ #include "ui_wifidialog.h" #include "functions.h" #include "mainwindow.h" +#include "network.h" wifiDialog::wifiDialog(QWidget *parent) : QDialog(parent), @@ -57,22 +58,6 @@ wifiDialog::~wifiDialog() delete ui; } -void wifiDialog::refreshScreenNative() { - emit refreshScreen(); -} - -void wifiDialog::updateWifiIcon(int mode) { - emit updateWifiIconSig(mode); -} - -void wifiDialog::showToastNative(QString messageToDisplay) { - emit showToast(messageToDisplay); -} - -void wifiDialog::closeIndefiniteToastNative() { - emit closeIndefiniteToast(); -} - /* this->hide(); @@ -168,3 +153,112 @@ void wifiDialog::closeIndefiniteToastNative() { } } */ + +void wifiDialog::on_refreshBtn_clicked() +{ + if(checkWifiState() == global::wifi::WifiState::Disabled) { + emit showToast("To scan, turn on wi-fi first"); + log("To scan, turn on wi-fi first", className); + } + else { + if(launchRefresh() == true) { + refreshNetworksList(); + } + } +} + +bool wifiDialog::launchRefresh() { + QFile fullList = QFile("/external_root/run/wifi_list_full"); + QFile formattedList = QFile("/external_root/run/wifi_list_format"); + fullList.remove(); + formattedList.remove(); + string_writeconfig("/opt/ibxd", "list_wifi_networks\n"); + QElapsedTimer elapsedTime; + elapsedTime.start(); + bool continueLoop = true; + while(fullList.exists() == false and formattedList.exists() == false and continueLoop == true) { + sleep(1); + if(elapsedTime.elapsed() > 6000) { + log("Searching for networks took too long"); + continueLoop = false; + } + } + if(fullList.exists() == false or formattedList.exists() == false) { + emit showToast("Failed to get network list"); + log("Failed to get network list", className); + return false; + } + log("Happily got network list", className); + return true; +} + +void wifiDialog::refreshNetworksList() { + emit killNetworkWidgets(); + QStringList networkList = readFile("/external_root/run/wifi_list_format").split("%%==SPLIT==%%\n"); + QVector pureNetworkList; + for(QString network: networkList) { + QStringList data = network.split("\n"); + int count = 1; + global::wifi::wifiNetworkData singleNetwork; + if(data.count() < 4) { + log("Data lines count is below 4, skipping"); + continue; + } + for(QString singleData: data) { + if(count == 1) { + singleNetwork.mac = singleData; + log("Mac is: " + singleData, className); + } + if(count == 2) { + log("wifi name is: " + singleData, className); + if(singleData.isEmpty() == true) { + log("Wifi name is empty", className); + } + singleNetwork.name = singleData; + } + if(count == 3) { + log("encryption is: " + singleData, className); + singleNetwork.encryption = QVariant(singleData).toBool(); + } + if(count == 4) { + log("signal strength is: " + singleData, className); + singleNetwork.signal = QVariant(singleData).toInt(); + } + if(count >= 5) { + log("Skipping additionall items in wifi", className); + } + count = count + 1; + } + pureNetworkList.append(singleNetwork); + } + log("found valid networks: " + QString::number(pureNetworkList.count())); + QFile currentWifiNameFile = QFile("/external_root/run/current_wifi_name"); + currentWifiNameFile.remove(); + string_writeconfig("/opt/ibxd", "get_current_wifi_name\n"); + usleep(300000); // 0.3s + // Here its looking for the now connected network to put it on top + QString currentNetwork = ""; + if(currentWifiNameFile.exists() == true) { + QString currentWifiNetwork = readFile(currentWifiNameFile.fileName()); + currentWifiNetwork = currentWifiNetwork.replace("\n", ""); + log("current network name is: " + currentWifiNetwork, className); + int countVec = 0; + int vectorNetworkLocation = 9999; + for(global::wifi::wifiNetworkData wifiNetwork: pureNetworkList) { + if(wifiNetwork.name.contains(currentWifiNetwork) == true) { + log("Found current network in vector", className); + vectorNetworkLocation = countVec; + currentNetwork = wifiNetwork.name; + network* connectedNetwork = new network; + connectedNetwork->mainData = wifiNetwork; + connectedNetwork->currentlyConnectedNetwork = currentNetwork; + // this doesnt work so a layout is needed + // ui->scrollArea->addScrollBarWidget(connectedNetwork, Qt::AlignTop); + ui->scrollBarLayout->addWidget(connectedNetwork, Qt::AlignTop); + } + countVec = countVec + 1; + } + } + +} + diff --git a/src/widgets/dialogs/wifi/wifidialog.h b/src/widgets/dialogs/wifi/wifidialog.h index 78173ee..072647f 100644 --- a/src/widgets/dialogs/wifi/wifidialog.h +++ b/src/widgets/dialogs/wifi/wifidialog.h @@ -22,17 +22,19 @@ public: private: Ui::wifiDialog *ui; +public slots: + bool launchRefresh(); + void refreshNetworksList(); + signals: void refreshScreen(); void updateWifiIconSig(int mode); void showToast(QString messageToDisplay); - void closeIndefiniteToast(); + + void killNetworkWidgets(); private slots: - void refreshScreenNative(); - void updateWifiIcon(int mode); - void showToastNative(QString messageToDisplay); - void closeIndefiniteToastNative(); + void on_refreshBtn_clicked(); }; #endif // WIFIDIALOG_H diff --git a/src/widgets/dialogs/wifi/wifidialog.ui b/src/widgets/dialogs/wifi/wifidialog.ui index 94702a2..60a2f32 100644 --- a/src/widgets/dialogs/wifi/wifidialog.ui +++ b/src/widgets/dialogs/wifi/wifidialog.ui @@ -131,13 +131,13 @@ - QFrame::Box + QFrame::NoFrame QFrame::Plain - 3 + 0 Qt::ScrollBarAlwaysOff @@ -150,11 +150,15 @@ 0 0 - 759 - 570 + 765 + 576 - + + + + + From 2cf679a303bef28ecac1e53fd7a98a8ce12bdfd6 Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Tue, 16 Aug 2022 21:44:57 +0200 Subject: [PATCH 03/19] full scanning networks, turning on --- src/eink.qrc | 2 + src/functions.h | 1 + src/resources/lock-fill.png | Bin 0 -> 315 bytes src/resources/lock-unlock-fill.png | Bin 0 -> 291 bytes src/widgets/dialogs/wifi/network.cpp | 40 +++++++++++ src/widgets/dialogs/wifi/network.h | 3 + src/widgets/dialogs/wifi/network.ui | 42 ++++++++++- src/widgets/dialogs/wifi/wifidialog.cpp | 88 +++++++++++++++++++++--- src/widgets/dialogs/wifi/wifidialog.h | 6 +- src/widgets/dialogs/wifi/wifidialog.ui | 55 ++++++++++++++- 10 files changed, 224 insertions(+), 13 deletions(-) create mode 100644 src/resources/lock-fill.png create mode 100644 src/resources/lock-unlock-fill.png diff --git a/src/eink.qrc b/src/eink.qrc index 2cac456..08704b5 100644 --- a/src/eink.qrc +++ b/src/eink.qrc @@ -86,5 +86,7 @@ resources/view-highlights.png resources/stop.png resources/refresh.png + resources/lock-fill.png + resources/lock-unlock-fill.png diff --git a/src/functions.h b/src/functions.h index 88cb271..81e7e26 100644 --- a/src/functions.h +++ b/src/functions.h @@ -1072,6 +1072,7 @@ namespace { global::wifi::WifiState checkWifiState() { QProcess *wifiStateProcess = new QProcess(); // Important to remember thats its in chroot... + // What can be run in the chroot, should be run here. ibxd is a bit a mess QString path = "/external_root/usr/local/bin/wifi/wifi_status.sh"; QStringList args; wifiStateProcess->start(path, args); diff --git a/src/resources/lock-fill.png b/src/resources/lock-fill.png new file mode 100644 index 0000000000000000000000000000000000000000..b6de0730d08f35ff196e58c6799dfdb4491de5a4 GIT binary patch literal 315 zcmV-B0mS}^P)Px#^+`lQR7gwhl;I5lK@f$%s{kD+feO%p4nzl3fC}h9bf5!NKnXga1M*~7+_|}3 z&LtA&-zKx~d-HB?6DqExVtrx&bzlJWftE9L0M@_?I2V}=0lL5vXc{6%U^VC;4;0k@uF&XI%FJAxv N002ovPDHLkV1k~ye`x>! literal 0 HcmV?d00001 diff --git a/src/resources/lock-unlock-fill.png b/src/resources/lock-unlock-fill.png new file mode 100644 index 0000000000000000000000000000000000000000..8795cdfd48f7ad078fbb19d6ba9d61d58f269391 GIT binary patch literal 291 zcmV+;0o?wHP)Px#-AP12R7gwhmC+T!Pz;8@Zo&pOzyxf72`~vZU;`sCi4|O~lTl3O~ zCi(vU$w>=3j-uoK`~nyNGhhjfN`lV70l0V~BftjO1z))Wj#iEb*aK@VJZY1pb`DHR z@3(;De}x4QTW*@|DHP=k;0_G+S%Fx9R4B^DdoM(}%%gS|7C@56z%&|Sw1pPnp@q>B zME%V*?F^8t36(hs(nG9$#is>Hc^g2bZx0ABM2setupUi(this); + + // Stylesheet, style & misc. + QFile stylesheetFile("/mnt/onboard/.adds/inkbox/eink.qss"); + stylesheetFile.open(QFile::ReadOnly); + this->setStyleSheet(stylesheetFile.readAll()); + stylesheetFile.close(); + + // Buttons + ui->encryptionIcon->setProperty("type", "borderless"); + ui->encryptionIcon->setStyleSheet("QPushButton[type='borderless']:pressed { background: white; color: white; border: none; }"); + + ui->enterButton->setProperty("type", "borderless"); + + } network::~network() { delete ui; } + +void network::applyVariables() { + ui->signalStrengthLabel->setText(QString::number(mainData.signal) + "%"); + + // limit name size, maybe device specific + QString cuttedSingleData = mainData.name; + if(cuttedSingleData.count() > 27) + { + cuttedSingleData = cuttedSingleData.remove(24, cuttedSingleData.count() - 24); + cuttedSingleData.append("..."); + } + ui->nameLabel->setText(cuttedSingleData); + + if(mainData.encryption == true) { + ui->encryptionIcon->setIcon(QIcon("://resources/lock-fill.png")); + } + else { + ui->encryptionIcon->setIcon(QIcon("://resources/lock-unlock-fill.png")); + } + + if(currentlyConnectedNetwork == mainData.name) { + ui->frame->setStyleSheet(".QFrame{background-color: grey; border: 3px solid black; border-radius: 10px;}"); + } else { + ui->frame->setStyleSheet(".QFrame{background-color: white; border: 3px solid black; border-radius: 10px;}"); + } +} diff --git a/src/widgets/dialogs/wifi/network.h b/src/widgets/dialogs/wifi/network.h index ab12625..171d5bc 100644 --- a/src/widgets/dialogs/wifi/network.h +++ b/src/widgets/dialogs/wifi/network.h @@ -19,6 +19,9 @@ public: global::wifi::wifiNetworkData mainData; QString currentlyConnectedNetwork; +public slots: + void applyVariables(); + private: Ui::network *ui; }; diff --git a/src/widgets/dialogs/wifi/network.ui b/src/widgets/dialogs/wifi/network.ui index 152a22c..6487348 100644 --- a/src/widgets/dialogs/wifi/network.ui +++ b/src/widgets/dialogs/wifi/network.ui @@ -20,6 +20,18 @@ Form + + 17 + + + 4 + + + 17 + + + 4 + @@ -32,9 +44,24 @@ QFrame::StyledPanel - QFrame::Raised + QFrame::Plain + + + 3 + + 3 + + + 3 + + + 3 + + + 3 + @@ -42,6 +69,19 @@ + + + + QFrame::Plain + + + 3 + + + Qt::Vertical + + + diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 5ec212f..2c81f13 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "wifidialog.h" #include "ui_wifidialog.h" @@ -29,6 +30,12 @@ wifiDialog::wifiDialog(QWidget *parent) : ui->Wificheckbox->setStyleSheet("QCheckBox::indicator { width:50px; height: 50px; }"); + ui->returnBtn->setProperty("type", "borderless"); + + // Scroll bar + // Needed for the nia. + ui->scrollArea->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 50px; }"); + // Size QRect screenGeometry = QGuiApplication::screens()[0]->geometry(); this->setFixedWidth(screenGeometry.width()); @@ -49,7 +56,13 @@ wifiDialog::wifiDialog(QWidget *parent) : ui->logBtn->setFixedHeight(ui->logBtn->height() + heighIncrease); ui->refreshBtn->setFixedHeight(ui->refreshBtn->height() + heighIncrease); - //ui->cancelBtn->setProperty("type", "borderless"); + // And set wifi checkbox state. also ignore this first call + global::wifi::WifiState currentWifiState = checkWifiState(); + if(currentWifiState != global::wifi::WifiState::Disabled and currentWifiState != global::wifi::WifiState::Unknown) { + ui->Wificheckbox->setChecked(true); + } else { + wifiButtonEnabled = true; + } } @@ -161,13 +174,11 @@ void wifiDialog::on_refreshBtn_clicked() log("To scan, turn on wi-fi first", className); } else { - if(launchRefresh() == true) { - refreshNetworksList(); - } + QTimer::singleShot(0, this, SLOT(launchRefresh())); } } -bool wifiDialog::launchRefresh() { +void wifiDialog::launchRefresh() { QFile fullList = QFile("/external_root/run/wifi_list_full"); QFile formattedList = QFile("/external_root/run/wifi_list_format"); fullList.remove(); @@ -186,10 +197,9 @@ bool wifiDialog::launchRefresh() { if(fullList.exists() == false or formattedList.exists() == false) { emit showToast("Failed to get network list"); log("Failed to get network list", className); - return false; } log("Happily got network list", className); - return true; + refreshNetworksList(); } void wifiDialog::refreshNetworksList() { @@ -229,7 +239,10 @@ void wifiDialog::refreshNetworksList() { } count = count + 1; } - pureNetworkList.append(singleNetwork); + // Really filter out empty networks + if(singleNetwork.name.isEmpty() == false) { + pureNetworkList.append(singleNetwork); + } } log("found valid networks: " + QString::number(pureNetworkList.count())); QFile currentWifiNameFile = QFile("/external_root/run/current_wifi_name"); @@ -245,7 +258,7 @@ void wifiDialog::refreshNetworksList() { int countVec = 0; int vectorNetworkLocation = 9999; for(global::wifi::wifiNetworkData wifiNetwork: pureNetworkList) { - if(wifiNetwork.name.contains(currentWifiNetwork) == true) { + if(currentWifiNetwork.isEmpty() == false and wifiNetwork.name.contains(currentWifiNetwork) == true) { log("Found current network in vector", className); vectorNetworkLocation = countVec; currentNetwork = wifiNetwork.name; @@ -254,11 +267,68 @@ void wifiDialog::refreshNetworksList() { connectedNetwork->currentlyConnectedNetwork = currentNetwork; // this doesnt work so a layout is needed // ui->scrollArea->addScrollBarWidget(connectedNetwork, Qt::AlignTop); + connectedNetwork->applyVariables(); ui->scrollBarLayout->addWidget(connectedNetwork, Qt::AlignTop); } countVec = countVec + 1; } + if(vectorNetworkLocation != 9999) { + pureNetworkList.removeAt(vectorNetworkLocation); + } + } + // Sort based on signal strength + QVector sortedPureNetworkList; + sortedPureNetworkList.append(pureNetworkList.first()); + pureNetworkList.removeFirst(); + for(global::wifi::wifiNetworkData wifiNetwork: pureNetworkList) { + bool stopIterating = false; + int counter = 0; + for(global::wifi::wifiNetworkData wifiNetworkToSort: sortedPureNetworkList) { + if(stopIterating == false) { + if(wifiNetwork.signal > wifiNetworkToSort.signal) { + sortedPureNetworkList.insert(counter, wifiNetwork); + stopIterating = true; + } + counter = counter + 1; + } + } + } + + // And now rest of the networks + for(global::wifi::wifiNetworkData wifiNetwork: sortedPureNetworkList) { + network* connectedNetwork = new network; + connectedNetwork->mainData = wifiNetwork; + connectedNetwork->currentlyConnectedNetwork = currentNetwork; + connectedNetwork->applyVariables(); + connect(this, SIGNAL(killNetworkWidgets()), connectedNetwork, SLOT(close())); + ui->scrollBarLayout->addWidget(connectedNetwork, Qt::AlignTop); } } + +void wifiDialog::on_Wificheckbox_stateChanged(int arg1) +{ + log("wifi dialog clicked: " + QString::number(arg1), className); + if(wifiButtonEnabled == true) { + if(arg1 == 2) { + log("turning wifi on", className); + QTimer::singleShot(0, this, SLOT(turnOnWifi())); + } else { + log("turning wifi off", className); + QTimer::singleShot(0, this, SLOT(turnOffWifi())); + } + } + + if(wifiButtonEnabled == false){ + wifiButtonEnabled = true; + } +} + +void wifiDialog::turnOnWifi() { + string_writeconfig("/opt/ibxd", "toggle_wifi_on\n"); +} + +void wifiDialog::turnOffWifi() { + string_writeconfig("/opt/ibxd", "toggle_wifi_off\n"); +} diff --git a/src/widgets/dialogs/wifi/wifidialog.h b/src/widgets/dialogs/wifi/wifidialog.h index 072647f..1f30049 100644 --- a/src/widgets/dialogs/wifi/wifidialog.h +++ b/src/widgets/dialogs/wifi/wifidialog.h @@ -21,9 +21,10 @@ public: private: Ui::wifiDialog *ui; + bool wifiButtonEnabled = false; public slots: - bool launchRefresh(); + void launchRefresh(); void refreshNetworksList(); signals: @@ -35,6 +36,9 @@ signals: private slots: void on_refreshBtn_clicked(); + void on_Wificheckbox_stateChanged(int arg1); + void turnOnWifi(); + void turnOffWifi(); }; #endif // WIFIDIALOG_H diff --git a/src/widgets/dialogs/wifi/wifidialog.ui b/src/widgets/dialogs/wifi/wifidialog.ui index 60a2f32..f25e754 100644 --- a/src/widgets/dialogs/wifi/wifidialog.ui +++ b/src/widgets/dialogs/wifi/wifidialog.ui @@ -31,6 +31,9 @@ + + 10 + @@ -139,6 +142,9 @@ 0 + + Qt::ScrollBarAsNeeded + Qt::ScrollBarAlwaysOff @@ -151,17 +157,62 @@ 0 0 765 - 576 + 567 + + 0 + + + 9 + + + 0 + - + + + 0 + + + 0 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + QFrame::Plain + + + 3 + + + Qt::Horizontal + + + From dc191269f34c1eb76f2008b54793aaae9f8b3d54 Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Wed, 17 Aug 2022 15:57:33 +0200 Subject: [PATCH 04/19] almost working logging and info wifi dialog --- src/homeWidget/mainwindow.cpp | 1 + src/homeWidget/mainwindow.h | 4 +- src/settings/settings.ui | 4 +- src/widgets/dialogs/wifi/network.h | 1 + src/widgets/dialogs/wifi/wifidialog.cpp | 18 +- src/widgets/dialogs/wifi/wifidialog.h | 3 + src/widgets/dialogs/wifi/wifilogger.cpp | 139 ++++++++ src/widgets/dialogs/wifi/wifilogger.h | 45 +++ src/widgets/dialogs/wifi/wifilogger.ui | 400 ++++++++++++++++++++++++ 9 files changed, 610 insertions(+), 5 deletions(-) create mode 100644 src/widgets/dialogs/wifi/wifilogger.cpp create mode 100644 src/widgets/dialogs/wifi/wifilogger.h create mode 100644 src/widgets/dialogs/wifi/wifilogger.ui diff --git a/src/homeWidget/mainwindow.cpp b/src/homeWidget/mainwindow.cpp index d7d4d56..cb24d71 100644 --- a/src/homeWidget/mainwindow.cpp +++ b/src/homeWidget/mainwindow.cpp @@ -790,6 +790,7 @@ void MainWindow::updateWifiState() { void MainWindow::on_wifiBtn_clicked() { wifiDialog* newWIfiDialog = new wifiDialog(); + QObject::connect(newWIfiDialog, &wifiDialog::showToast, this, &MainWindow::showToast); newWIfiDialog->exec(); } diff --git a/src/homeWidget/mainwindow.h b/src/homeWidget/mainwindow.h index fc76401..43110d7 100644 --- a/src/homeWidget/mainwindow.h +++ b/src/homeWidget/mainwindow.h @@ -63,6 +63,8 @@ public: void setBatteryIcon(); public slots: + void showToast(QString messageToDisplay); + void closeIndefiniteToast(); private slots: void on_settingsBtn_clicked(); @@ -80,8 +82,6 @@ private slots: void on_wifiBtn_clicked(); void updateWifiIcon(global::wifi::WifiState mode); void hello(int testNumber); - void showToast(QString messageToDisplay); - void closeIndefiniteToast(); void openUpdateDialogOTA(bool open); void launchOtaUpdater(); void openBookFile(QString book, bool relativePath); diff --git a/src/settings/settings.ui b/src/settings/settings.ui index a63a5ab..a121f64 100644 --- a/src/settings/settings.ui +++ b/src/settings/settings.ui @@ -49,7 +49,7 @@ 0 0 457 - 657 + 667 @@ -71,7 +71,7 @@ 0 - 0 + 1 diff --git a/src/widgets/dialogs/wifi/network.h b/src/widgets/dialogs/wifi/network.h index 171d5bc..9ef91f9 100644 --- a/src/widgets/dialogs/wifi/network.h +++ b/src/widgets/dialogs/wifi/network.h @@ -14,6 +14,7 @@ class network : public QWidget Q_OBJECT public: + QString className = this->metaObject()->className(); explicit network(QWidget *parent = nullptr); ~network(); global::wifi::wifiNetworkData mainData; diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 2c81f13..a5fdf28 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -10,6 +10,7 @@ #include "functions.h" #include "mainwindow.h" #include "network.h" +#include "wifilogger.h" wifiDialog::wifiDialog(QWidget *parent) : QDialog(parent), @@ -265,6 +266,7 @@ void wifiDialog::refreshNetworksList() { network* connectedNetwork = new network; connectedNetwork->mainData = wifiNetwork; connectedNetwork->currentlyConnectedNetwork = currentNetwork; + connectedNetworkDataParent = wifiNetwork; // this doesnt work so a layout is needed // ui->scrollArea->addScrollBarWidget(connectedNetwork, Qt::AlignTop); connectedNetwork->applyVariables(); @@ -303,7 +305,7 @@ void wifiDialog::refreshNetworksList() { connect(this, SIGNAL(killNetworkWidgets()), connectedNetwork, SLOT(close())); ui->scrollBarLayout->addWidget(connectedNetwork, Qt::AlignTop); } - + scannedAtLeastOnce = true; } @@ -332,3 +334,17 @@ void wifiDialog::turnOnWifi() { void wifiDialog::turnOffWifi() { string_writeconfig("/opt/ibxd", "toggle_wifi_off\n"); } + +void wifiDialog::on_logBtn_clicked() +{ + // To avoid half informations + if(scannedAtLeastOnce == false and checkWifiState() == global::wifi::WifiState::Configured) { + log("Scanning at least once is needed"); + emit showToast("Scan at least once"); + } else { + wifilogger* wifiLoggerDialog = new wifilogger; + wifiLoggerDialog->connectedNetworkData = connectedNetworkDataParent; + wifiLoggerDialog->exec(); + } + +} diff --git a/src/widgets/dialogs/wifi/wifidialog.h b/src/widgets/dialogs/wifi/wifidialog.h index 1f30049..1ce10f2 100644 --- a/src/widgets/dialogs/wifi/wifidialog.h +++ b/src/widgets/dialogs/wifi/wifidialog.h @@ -18,10 +18,12 @@ public: QString className = this->metaObject()->className(); explicit wifiDialog(QWidget *parent = nullptr); ~wifiDialog(); + global::wifi::wifiNetworkData connectedNetworkDataParent; private: Ui::wifiDialog *ui; bool wifiButtonEnabled = false; + bool scannedAtLeastOnce = false; public slots: void launchRefresh(); @@ -39,6 +41,7 @@ private slots: void on_Wificheckbox_stateChanged(int arg1); void turnOnWifi(); void turnOffWifi(); + void on_logBtn_clicked(); }; #endif // WIFIDIALOG_H diff --git a/src/widgets/dialogs/wifi/wifilogger.cpp b/src/widgets/dialogs/wifi/wifilogger.cpp new file mode 100644 index 0000000..d6bd22b --- /dev/null +++ b/src/widgets/dialogs/wifi/wifilogger.cpp @@ -0,0 +1,139 @@ +#include + +#include "wifilogger.h" +#include "ui_wifilogger.h" +#include "functions.h" + +wifilogger::wifilogger(QWidget *parent) : + QDialog(parent), + ui(new Ui::wifilogger) +{ + ui->setupUi(this); + + // Stylesheet, style & misc. + QFile stylesheetFile("/mnt/onboard/.adds/inkbox/eink.qss"); + stylesheetFile.open(QFile::ReadOnly); + this->setStyleSheet(stylesheetFile.readAll()); + stylesheetFile.close(); + this->setModal(true); + + + setWifiInfoPage(); + QObject::connect(&updateLogsTimer, &QTimer::timeout, this, &wifilogger::updateLogs); + updateLogsTimer.start(1000); +} + +wifilogger::~wifilogger() +{ + delete ui; +} + +void wifilogger::setWifiInfoPage() { + if(checkWifiState() == global::wifi::WifiState::Configured) { + QTimer::singleShot(0, this, SLOT(getWifiInformations())); + ui->stackedWidget->setCurrentIndex(0); + ui->nameLabel->setText("Network informations"); + } + else { + ui->stackedWidget->setCurrentIndex(1); + ui->nameLabel->setText("No network connected"); + } +} + +void wifilogger::setFancyLoggingPage() { + ui->stackedWidget->setCurrentIndex(2); + ui->nameLabel->setText("Important logs"); +} + +void wifilogger::setAllLogsPage() { + ui->stackedWidget->setCurrentIndex(3); + ui->nameLabel->setText("All logs"); +} + +void wifilogger::on_nextBtn_clicked() +{ + if(currentPage == 2) { + currentPage = 0; + } + else { + currentPage = currentPage + 1; + } + changePage(); +} + +void wifilogger::on_previousBtn_clicked() +{ + if(currentPage == 0) { + currentPage = 2; + } + else { + currentPage = currentPage - 1; + } + changePage(); +} + +void wifilogger::changePage() { + if(currentPage == 0) { + setWifiInfoPage(); + } + else if(currentPage == 1) { + setFancyLoggingPage(); + } + else if(currentPage == 2) { + setAllLogsPage(); + } else { + log("This shouldnt happen.", className); + } +} + +void wifilogger::getWifiInformations() { + QFile wifiInformationsPath = QFile("/external_root/run/wifi_informations"); + wifiInformationsPath.remove(); + + string_writeconfig("/opt/ibxd", "get_wifi_informations\n"); + while(wifiInformationsPath.exists() == false) { + sleep(1); + } + + QString wifiInfo = readFile(wifiInformationsPath.fileName()); + QStringList wifiInfoList = wifiInfo.split("\n"); + int counter = 0; + for(QString infomation: wifiInfoList) { + if(counter == 0) { + ui->netNameLabel->setText(infomation); + } + if(counter == 1) { + ui->ipLabel->setText(infomation); + } + if(counter == 2) { + ui->maskLabel->setText(infomation); + } + if(counter == 3) { + ui->gatewayLabel->setText(infomation); + } + counter = counter + 1; + } + + ui->encryptionLabel->setText(QVariant(connectedNetworkData.encryption).toString()); + + ui->signalLabel->setText(QString::number(connectedNetworkData.signal) + "%"); + + ui->macLabel->setText(connectedNetworkData.mac); +} + + +void wifilogger::on_returnBtn_clicked() +{ + updateLogsTimer.stop(); + this->deleteLater(); +} + +void wifilogger::updateLogs() { + if(fancyLogs.exists() == true and allLogs.exists() == true) { + QString fancyLogsText = readFile(fancyLogs.fileName()); + QString allLogsText = readFile(allLogs.fileName()); + + ui->fancyLogsText->setText(fancyLogsText); + ui->allLogsText->setText(allLogsText); + } +} diff --git a/src/widgets/dialogs/wifi/wifilogger.h b/src/widgets/dialogs/wifi/wifilogger.h new file mode 100644 index 0000000..4776844 --- /dev/null +++ b/src/widgets/dialogs/wifi/wifilogger.h @@ -0,0 +1,45 @@ +#ifndef WIFILOGGER_H +#define WIFILOGGER_H + +#include +#include "functions.h" + +namespace Ui { +class wifilogger; +} + +class wifilogger : public QDialog +{ + Q_OBJECT + +public: + QString className = this->metaObject()->className(); + explicit wifilogger(QWidget *parent = nullptr); + ~wifilogger(); + global::wifi::wifiNetworkData connectedNetworkData; + +private: + Ui::wifilogger *ui; + /* + * 0 is wifi info / no wifi info page + * 1 is fancy logs page + * 2 is all logs + */ + int currentPage = 0; + QTimer updateLogsTimer; + QFile fancyLogs = QFile("/external_root/run/wifi_stats"); + QFile allLogs = QFile("/external_root/run/wifi_logs"); + +private slots: + void setWifiInfoPage(); + void setFancyLoggingPage(); + void setAllLogsPage(); + void on_nextBtn_clicked(); + void on_previousBtn_clicked(); + void changePage(); + void getWifiInformations(); + void on_returnBtn_clicked(); + void updateLogs(); +}; + +#endif // WIFILOGGER_H diff --git a/src/widgets/dialogs/wifi/wifilogger.ui b/src/widgets/dialogs/wifi/wifilogger.ui new file mode 100644 index 0000000..ff5344b --- /dev/null +++ b/src/widgets/dialogs/wifi/wifilogger.ui @@ -0,0 +1,400 @@ + + + wifilogger + + + + 0 + 0 + 755 + 613 + + + + Dialog + + + + + + 0 + + + 0 + + + + + + + + + + 75 + true + + + + Network name: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + false + true + + + + IP address: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + true + + + + Mask: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + true + + + + Gateway: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + true + + + + Password protected: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + true + + + + Signal strength: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + true + + + + MAC address: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 75 + true + + + + 0 + + + No wifi connected + + + Qt::AlignCenter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + :/resources/chevron-left.png:/resources/chevron-left.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + :/resources/chevron-right.png:/resources/chevron-right.png + + + + + + + + + Return + + + + + + + + + + From b9617a52acb20f2e9c1d3d5f3a98072975429e37 Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Wed, 17 Aug 2022 21:36:23 +0200 Subject: [PATCH 05/19] further work --- src/eink.qrc | 2 + src/resources/hide.png | Bin 0 -> 1026 bytes src/resources/show.png | Bin 0 -> 993 bytes src/widgets/dialogs/wifi/connectiondialog.cpp | 44 ++++ src/widgets/dialogs/wifi/connectiondialog.h | 29 +++ src/widgets/dialogs/wifi/connectiondialog.ui | 189 ++++++++++++++++++ src/widgets/dialogs/wifi/network.cpp | 22 +- src/widgets/dialogs/wifi/network.h | 3 + src/widgets/dialogs/wifi/wifidialog.cpp | 17 +- src/widgets/dialogs/wifi/wifidialog.h | 3 + src/widgets/dialogs/wifi/wifilogger.cpp | 35 +++- src/widgets/dialogs/wifi/wifilogger.h | 2 +- src/widgets/dialogs/wifi/wifilogger.ui | 19 +- 13 files changed, 353 insertions(+), 12 deletions(-) create mode 100644 src/resources/hide.png create mode 100644 src/resources/show.png create mode 100644 src/widgets/dialogs/wifi/connectiondialog.cpp create mode 100644 src/widgets/dialogs/wifi/connectiondialog.h create mode 100644 src/widgets/dialogs/wifi/connectiondialog.ui diff --git a/src/eink.qrc b/src/eink.qrc index 08704b5..618565f 100644 --- a/src/eink.qrc +++ b/src/eink.qrc @@ -88,5 +88,7 @@ resources/refresh.png resources/lock-fill.png resources/lock-unlock-fill.png + resources/hide.png + resources/show.png diff --git a/src/resources/hide.png b/src/resources/hide.png new file mode 100644 index 0000000000000000000000000000000000000000..5b643fd51b9569b5168578465098ab842f5613f8 GIT binary patch literal 1026 zcmV+d1pWJoP)Px&yh%hsRA@u(n1QiPK@5iTDxd>YfC^9nDnJFO02QDDRDcRl0V+TTRKR>@b0#l# zlkB-?=AJuaXYRav-`$hVpZxigy=QXb>+Hn+m;V5coxxrPE{e#{V>?zo-vhw;4^R)9CM!qpw3@w4!u4F5IzGqea}R6_aJ&Tum%L#yCEWEj~AbBI%<7vpP?u3zlzBB zL+Lk?(FzEhye%U4JI+@90?Z2$dB0XTqCSv;AkswgLe<+~AF9WB&t`#Sjcf+Qr>0(j z!Xcuoa(r1tcv*V!-h*fVQxSPt4N3+8I~fQZW6kmz3PQg}B67(&4ES4>Y*YXcsn70! ztl5#qI`s~uK5!_an-_;L6C(gV^2i*~QMHIbWa?BYRBR9krPL6_XqY4NI#Q5&-;}b# z=2?o9NOL%!?>N9nhAHT{R+c-4}Kb0FC8gdkEU#d~Z6)SlGm& zh)#gudzD+{mB1{^1F*dR)trx1U={=i+h>R{N)s(I_ttD+zm6sU+{lnirB0S&Y!cOP z?(~Yp5>@4Qri7TsVN^}uFQDzi7U_@XToRnWh3#ceqa58QEKScvbZ{Vnf(c5cm0Mwe!U0n+KV&M>sXX|&ip(&583ES+h6b3cAv0g2F{a(W%ltA$pEn5&*uD(Ly*Ox;UM(c0H{IJ zK6B8OQvD#U^aW21jN{Oo$_3njs({eDM5t7i3|Irb%eQ_{HUPwn!x;$etWOY7He?ri zVau+pu)9EJ0bm42r~_UV#mTh(AP{Q+SXxnFM6#kfJs_GT`}|ZU4gp{t(jRjvKpn~b zFK_CsDw5I-J6TN(v$z$28Jdjtt^%wHvrQh_6T4K#9jgPKykN^Mx07*qoM6N<$g8e|wQ2+n{ literal 0 HcmV?d00001 diff --git a/src/resources/show.png b/src/resources/show.png new file mode 100644 index 0000000000000000000000000000000000000000..0c0be28daacb9c7d185fe3ef7cbc47560b4a4605 GIT binary patch literal 993 zcmV<710MW|P)Px&n@L1LRA@u(nSqfFK@f)fA|L}qfCvx)B0vO)01+SpWN;!t1c(3`5CQd7_5Z40 zznSUTw|8}}YNtxw+MDj_zyE)Fdgo5;l8=*19=~k>E}FrOfsKKc8Q3J`3A}1%cg*aT zncekwJoBFM+swZC^Jjnl;_p{+u$F;GX7)G)y)+oWyf?ECOAR&uSO71~>{-b0vFpnY zhTfRjtEG;X0ze+`%?i5_T;llUnL`E& zc4}cy!UJdWS~9{PK*})#fb4zp49X#azjXbUi%d))G5Cu>*!1_R#8d#Fo8VPVh=mP@ z{;Q0uDq%w~NNhA%gMC0@&|nQfsDd5Xj{u_%sRa&06Tg2Bs5bY{yPZ~P-J1ILSUm!4CwBO8Fa-a{t-_2nN3V7 zWgjs1ipyD)(FmH&`LNgoODo-?GRoRf*E3S0bW-M276C!O(>loLlXOnZRJ!t9>d_ao zT6TnuRsx$=D-rvosxi!+aPwRmHFE@@!-IfWaMaAf9CXKir==z`&)iX0OEX7rCBWbP z%sDtDt9Cj{L-HDRk;sX_TAz#BfCM+{t>|j$L^Xydd{qH*M~G7bJ4iZtF zwq%>E$IsTX6RrRdFpi^~ct-}2%hA^%Nn3n{;V)hmbY&B5X8>qEnU9})0s`IiK_gkT z_5#7um9ii5EeDCo7YNPjyaa$wUV!9V1Ra9$T7?Y8YZVHDu2+y(tJCGOfWRxc?Z7Mr zAVcUTb5+HeY3!JT)?sqC8C(rO4#*b&dR3 +#include + +#include "connectiondialog.h" +#include "ui_connectiondialog.h" + +connectiondialog::connectiondialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::connectiondialog) +{ + ui->setupUi(this); + + // Stylesheet, style & misc. + QFile stylesheetFile("/mnt/onboard/.adds/inkbox/eink.qss"); + stylesheetFile.open(QFile::ReadOnly); + this->setStyleSheet(stylesheetFile.readAll()); + stylesheetFile.close(); + + ui->CancelBtn->setStyleSheet("font-size: 9pt"); + ui->connectBtn->setStyleSheet("font-size: 9pt"); + ui->showPasswordBtn->setStyleSheet("font-size: 9pt"); + + // Size + QRect screenGeometry = QGuiApplication::screens()[0]->geometry(); + this->setFixedWidth(screenGeometry.width() - 50); + + +} + +connectiondialog::~connectiondialog() +{ + delete ui; +} + +void connectiondialog::applyVariables() { + ui->nameLabel->setText(connectedNetworkData.name); + ui->macLabel->setText(connectedNetworkData.mac); + ui->signalLabel->setText(QString::number(connectedNetworkData.signal) + "%"); + + if(connectedNetworkData.encryption == false) { + ui->showPasswordBtn->hide(); + ui->passwordTextEdit->setText("No password required"); + } +} diff --git a/src/widgets/dialogs/wifi/connectiondialog.h b/src/widgets/dialogs/wifi/connectiondialog.h new file mode 100644 index 0000000..fa9b320 --- /dev/null +++ b/src/widgets/dialogs/wifi/connectiondialog.h @@ -0,0 +1,29 @@ +#ifndef CONNECTIONDIALOG_H +#define CONNECTIONDIALOG_H + +#include +#include "functions.h" + +namespace Ui { +class connectiondialog; +} + +class connectiondialog : public QDialog +{ + Q_OBJECT + +public: + QString className = this->metaObject()->className(); + explicit connectiondialog(QWidget *parent = nullptr); + ~connectiondialog(); + global::wifi::wifiNetworkData connectedNetworkData; + QString currentlyConnectedNetworkName; + +public slots: + void applyVariables(); + +private: + Ui::connectiondialog *ui; +}; + +#endif // CONNECTIONDIALOG_H diff --git a/src/widgets/dialogs/wifi/connectiondialog.ui b/src/widgets/dialogs/wifi/connectiondialog.ui new file mode 100644 index 0000000..a7b27a8 --- /dev/null +++ b/src/widgets/dialogs/wifi/connectiondialog.ui @@ -0,0 +1,189 @@ + + + connectiondialog + + + + 0 + 0 + 529 + 335 + + + + Dialog + + + + + + QLayout::SetFixedSize + + + + + Cancel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Connect + + + + + + + + + + + BlankCursor + + + true + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + + 75 + true + + + + Signal strength: + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + true + + + + MAC address: + + + + + + + TextLabel + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/src/widgets/dialogs/wifi/network.cpp b/src/widgets/dialogs/wifi/network.cpp index 0b6ed15..320f44c 100644 --- a/src/widgets/dialogs/wifi/network.cpp +++ b/src/widgets/dialogs/wifi/network.cpp @@ -1,5 +1,6 @@ #include "network.h" #include "ui_network.h" +#include "connectiondialog.h" network::network(QWidget *parent) : QWidget(parent), @@ -19,7 +20,7 @@ network::network(QWidget *parent) : ui->enterButton->setProperty("type", "borderless"); - + ui->enterButton->setFixedWidth(40); } network::~network() @@ -48,7 +49,26 @@ void network::applyVariables() { if(currentlyConnectedNetwork == mainData.name) { ui->frame->setStyleSheet(".QFrame{background-color: grey; border: 3px solid black; border-radius: 10px;}"); + ui->signalStrengthLabel->setStyleSheet("background-color:grey;"); + ui->nameLabel->setStyleSheet("background-color:grey;"); + ui->encryptionIcon->setStyleSheet("background-color:grey;"); + ui->enterButton->setStyleSheet("background-color:grey;"); + + // Some stylesheet magician could make it work that it cant be clicked + ui->encryptionIcon->setStyleSheet("QPushButton {background-color: grey; border: none}; QPushButton[type='borderless']:pressed { background: grey; color: grey; border: none; }"); + + ui->enterButton->setStyleSheet("QPushButton {background-color: grey; border: none}; QPushButton[type='borderless']:pressed { background: grey; color: grey; border: none; }"); + } else { ui->frame->setStyleSheet(".QFrame{background-color: white; border: 3px solid black; border-radius: 10px;}"); } } + +void network::on_enterButton_clicked() +{ + connectiondialog* newConnectionDiallog = new connectiondialog; + newConnectionDiallog->connectedNetworkData = mainData; + newConnectionDiallog->currentlyConnectedNetworkName = currentlyConnectedNetwork; + newConnectionDiallog->applyVariables(); + newConnectionDiallog->exec(); +} diff --git a/src/widgets/dialogs/wifi/network.h b/src/widgets/dialogs/wifi/network.h index 9ef91f9..75a79ab 100644 --- a/src/widgets/dialogs/wifi/network.h +++ b/src/widgets/dialogs/wifi/network.h @@ -23,6 +23,9 @@ public: public slots: void applyVariables(); +private slots: + void on_enterButton_clicked(); + private: Ui::network *ui; }; diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index a5fdf28..387fc3f 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -170,12 +170,16 @@ wifiDialog::~wifiDialog() void wifiDialog::on_refreshBtn_clicked() { + log("Clicked refresh button", className); if(checkWifiState() == global::wifi::WifiState::Disabled) { emit showToast("To scan, turn on wi-fi first"); log("To scan, turn on wi-fi first", className); } else { - QTimer::singleShot(0, this, SLOT(launchRefresh())); + ui->refreshBtn->setEnabled(false); + // for some reason this doesnt work here + //ui->refreshBtn->setStyleSheet("background-color:grey;"); + QTimer::singleShot(100, this, SLOT(launchRefresh())); } } @@ -188,6 +192,7 @@ void wifiDialog::launchRefresh() { QElapsedTimer elapsedTime; elapsedTime.start(); bool continueLoop = true; + ui->refreshBtn->setStyleSheet("background-color:grey;"); while(fullList.exists() == false and formattedList.exists() == false and continueLoop == true) { sleep(1); if(elapsedTime.elapsed() > 6000) { @@ -265,16 +270,21 @@ void wifiDialog::refreshNetworksList() { currentNetwork = wifiNetwork.name; network* connectedNetwork = new network; connectedNetwork->mainData = wifiNetwork; + // to be really sure that the the info is put there connectedNetwork->currentlyConnectedNetwork = currentNetwork; connectedNetworkDataParent = wifiNetwork; + wifiLoggerDialog->connectedNetworkData = connectedNetworkDataParent; + // this doesnt work so a layout is needed // ui->scrollArea->addScrollBarWidget(connectedNetwork, Qt::AlignTop); connectedNetwork->applyVariables(); + connect(this, &wifiDialog::killNetworkWidgets, connectedNetwork, &network::close); ui->scrollBarLayout->addWidget(connectedNetwork, Qt::AlignTop); } countVec = countVec + 1; } if(vectorNetworkLocation != 9999) { + log("pureNetworkList size is: " + QString::number(pureNetworkList.count()) + " And i want to remove at: " + QString::number(vectorNetworkLocation), className); pureNetworkList.removeAt(vectorNetworkLocation); } } @@ -302,10 +312,12 @@ void wifiDialog::refreshNetworksList() { connectedNetwork->mainData = wifiNetwork; connectedNetwork->currentlyConnectedNetwork = currentNetwork; connectedNetwork->applyVariables(); - connect(this, SIGNAL(killNetworkWidgets()), connectedNetwork, SLOT(close())); + connect(this, &wifiDialog::killNetworkWidgets, connectedNetwork, &network::close); ui->scrollBarLayout->addWidget(connectedNetwork, Qt::AlignTop); } scannedAtLeastOnce = true; + ui->refreshBtn->setEnabled(true); + ui->refreshBtn->setStyleSheet("background-color:white;"); } @@ -342,7 +354,6 @@ void wifiDialog::on_logBtn_clicked() log("Scanning at least once is needed"); emit showToast("Scan at least once"); } else { - wifilogger* wifiLoggerDialog = new wifilogger; wifiLoggerDialog->connectedNetworkData = connectedNetworkDataParent; wifiLoggerDialog->exec(); } diff --git a/src/widgets/dialogs/wifi/wifidialog.h b/src/widgets/dialogs/wifi/wifidialog.h index 1ce10f2..b0a826e 100644 --- a/src/widgets/dialogs/wifi/wifidialog.h +++ b/src/widgets/dialogs/wifi/wifidialog.h @@ -5,6 +5,7 @@ #include #include "generaldialog.h" +#include "wifilogger.h" namespace Ui { class wifiDialog; @@ -19,6 +20,8 @@ public: explicit wifiDialog(QWidget *parent = nullptr); ~wifiDialog(); global::wifi::wifiNetworkData connectedNetworkDataParent; + wifilogger* wifiLoggerDialog = new wifilogger; + private: Ui::wifiDialog *ui; diff --git a/src/widgets/dialogs/wifi/wifilogger.cpp b/src/widgets/dialogs/wifi/wifilogger.cpp index d6bd22b..3095f41 100644 --- a/src/widgets/dialogs/wifi/wifilogger.cpp +++ b/src/widgets/dialogs/wifi/wifilogger.cpp @@ -19,8 +19,10 @@ wifilogger::wifilogger(QWidget *parent) : setWifiInfoPage(); - QObject::connect(&updateLogsTimer, &QTimer::timeout, this, &wifilogger::updateLogs); - updateLogsTimer.start(1000); + ui->refreshBtn->setProperty("type", "borderless"); + + ui->nextBtn->setFixedWidth(70); + ui->previousBtn->setFixedWidth(70); } wifilogger::~wifilogger() @@ -41,11 +43,13 @@ void wifilogger::setWifiInfoPage() { } void wifilogger::setFancyLoggingPage() { + updateLogs(); ui->stackedWidget->setCurrentIndex(2); ui->nameLabel->setText("Important logs"); } void wifilogger::setAllLogsPage() { + updateLogs(); ui->stackedWidget->setCurrentIndex(3); ui->nameLabel->setText("All logs"); } @@ -114,17 +118,26 @@ void wifilogger::getWifiInformations() { counter = counter + 1; } - ui->encryptionLabel->setText(QVariant(connectedNetworkData.encryption).toString()); + if(connectedNetworkData.mac.isEmpty() == false) { + ui->encryptionLabel->setText(QVariant(connectedNetworkData.encryption).toString()); - ui->signalLabel->setText(QString::number(connectedNetworkData.signal) + "%"); + ui->signalLabel->setText(QString::number(connectedNetworkData.signal) + "%"); - ui->macLabel->setText(connectedNetworkData.mac); + ui->macLabel->setText(connectedNetworkData.mac); + } + else { + // Shouldn't happen for 99%, but if anyway... its designed to be non blocking, so i cant really wait for this. + ui->encryptionLabel->setText("Rescan needed"); + + ui->signalLabel->setText("Rescan needed"); + + ui->macLabel->setText("Rescan needed"); + } } void wifilogger::on_returnBtn_clicked() { - updateLogsTimer.stop(); this->deleteLater(); } @@ -137,3 +150,13 @@ void wifilogger::updateLogs() { ui->allLogsText->setText(allLogsText); } } + +void wifilogger::on_refreshBtn_clicked() +{ + if(currentPage == 0) { + setWifiInfoPage(); + } + else { + updateLogs(); + } +} diff --git a/src/widgets/dialogs/wifi/wifilogger.h b/src/widgets/dialogs/wifi/wifilogger.h index 4776844..36c51ff 100644 --- a/src/widgets/dialogs/wifi/wifilogger.h +++ b/src/widgets/dialogs/wifi/wifilogger.h @@ -26,7 +26,6 @@ private: * 2 is all logs */ int currentPage = 0; - QTimer updateLogsTimer; QFile fancyLogs = QFile("/external_root/run/wifi_stats"); QFile allLogs = QFile("/external_root/run/wifi_logs"); @@ -40,6 +39,7 @@ private slots: void getWifiInformations(); void on_returnBtn_clicked(); void updateLogs(); + void on_refreshBtn_clicked(); }; #endif // WIFILOGGER_H diff --git a/src/widgets/dialogs/wifi/wifilogger.ui b/src/widgets/dialogs/wifi/wifilogger.ui index ff5344b..fd99ec5 100644 --- a/src/widgets/dialogs/wifi/wifilogger.ui +++ b/src/widgets/dialogs/wifi/wifilogger.ui @@ -20,7 +20,7 @@ 0 - 0 + 2 @@ -358,6 +358,23 @@ + + + + + 0 + 0 + + + + + + + + :/resources/refresh.png:/resources/refresh.png + + + From d2ba6dc80c3056554ad5b35add97175fa857cca4 Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Thu, 18 Aug 2022 15:49:56 +0200 Subject: [PATCH 06/19] further incompleted work --- src/widgets/dialogs/generaldialog.cpp | 13 +- src/widgets/dialogs/wifi/connectiondialog.cpp | 127 +++++++++++++++++- src/widgets/dialogs/wifi/connectiondialog.h | 16 +++ src/widgets/dialogs/wifi/connectiondialog.ui | 4 +- src/widgets/dialogs/wifi/network.cpp | 10 ++ src/widgets/dialogs/wifi/network.h | 5 + src/widgets/dialogs/wifi/wifidialog.cpp | 74 ++++++---- src/widgets/dialogs/wifi/wifidialog.h | 8 ++ src/widgets/dialogs/wifi/wifilogger.cpp | 1 + 9 files changed, 220 insertions(+), 38 deletions(-) diff --git a/src/widgets/dialogs/generaldialog.cpp b/src/widgets/dialogs/generaldialog.cpp index 997dab6..b60536e 100644 --- a/src/widgets/dialogs/generaldialog.cpp +++ b/src/widgets/dialogs/generaldialog.cpp @@ -495,15 +495,10 @@ void generalDialog::on_okBtn_clicked() } else if(global::keyboard::wifiPassphraseDialog == true) { if(!global::keyboard::keyboardText.isEmpty()) { - log("Attempting connection to Wi-Fi network '" + wifiEssid + "'", className); - this->hide(); - wifiPassphrase = global::keyboard::keyboardText; - global::toast::indefiniteToast = true; - global::toast::modalToast = true; - emit showToast("Connecting"); - QTimer::singleShot(100, this, SLOT(connectToNetworkSlot())); - global::keyboard::wifiPassphraseDialog = false; - global::keyboard::keyboardDialog = false; + if(global::keyboard::keyboardText.count() < 8) { + global::toast::delay = 3000; + showToast("Minimum password length is 8 characters"); + } } else { global::toast::delay = 3000; diff --git a/src/widgets/dialogs/wifi/connectiondialog.cpp b/src/widgets/dialogs/wifi/connectiondialog.cpp index 7b29636..d4d990c 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.cpp +++ b/src/widgets/dialogs/wifi/connectiondialog.cpp @@ -3,6 +3,7 @@ #include "connectiondialog.h" #include "ui_connectiondialog.h" +#include "generaldialog.h" connectiondialog::connectiondialog(QWidget *parent) : QDialog(parent), @@ -22,7 +23,7 @@ connectiondialog::connectiondialog(QWidget *parent) : // Size QRect screenGeometry = QGuiApplication::screens()[0]->geometry(); - this->setFixedWidth(screenGeometry.width() - 50); + this->setFixedWidth(screenGeometry.width()); } @@ -40,5 +41,129 @@ void connectiondialog::applyVariables() { if(connectedNetworkData.encryption == false) { ui->showPasswordBtn->hide(); ui->passwordTextEdit->setText("No password required"); + ui->passwordTextEdit->setDisabled(true); + } + else { + if(passwordDatabase.exists() == false) { + log("Creating empty database", className); + // https://forum.qt.io/topic/104791/how-i-can-create-json-format-in-qt/5 + QJsonObject root; + QJsonArray array; + QJsonDocument newJsonDocument; + root["list"] = array; + newJsonDocument.setObject(root); + + passwordDatabase.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); + passwordDatabase.write(newJsonDocument.toJson()); + passwordDatabase.flush(); + passwordDatabase.close(); + } + else { + QString password = searchDatabase(connectedNetworkData.name); + if(password.isEmpty() == false) { + log("found password: " + password, className); + ui->passwordTextEdit->setText(password); + } + else { + log("No password found", className); + ui->passwordTextEdit->setText("No password found"); + } + } } } + +QString connectiondialog::searchDatabase(QString key) { + passwordDatabase.open(QIODevice::ReadOnly | QIODevice::Text); + QString fileRead = passwordDatabase.readAll(); + passwordDatabase.close(); + QJsonDocument jsonDocument = QJsonDocument::fromJson(fileRead.toUtf8()); + + if(jsonDocument["list"].isArray() == true) { + QJsonArray jsonArray = jsonDocument["list"].toArray(); + for(QJsonValueRef refJsonObject: jsonArray) { + QJsonObject jsonMainObject = refJsonObject.toObject(); + QString searchedName = jsonMainObject.keys().first().toUtf8(); + log("Found in database: " + searchedName, className); + if(searchedName == key) { + return jsonMainObject.take(key).toString(); + } + + } + return ""; + } + else { + log("Something went horribly wrong", className); + } +} + +void connectiondialog::writeToDatabase(QString name, QString password) { + passwordDatabase.open(QIODevice::ReadOnly | QIODevice::Text); + QString fileRead = passwordDatabase.readAll(); + passwordDatabase.close(); + QJsonDocument jsonDocument = QJsonDocument::fromJson(fileRead.toUtf8()); + + if(jsonDocument["list"].isArray() == true) { + QJsonArray jsonArray = jsonDocument["list"].toArray(); + QJsonValue newValue; + + // https://stackoverflow.com/questions/26804660/how-to-initialize-qjsonobject-from-qstring + // I hoped this will be easier + QJsonObject newObject = QJsonDocument::fromJson(QString("{\"" + name + "\" : \"" + password + "\" }").toUtf8()).object(); + jsonArray.append(newObject); + + QJsonDocument newJsonDocument; + QJsonObject root; + root["list"] = jsonArray; + newJsonDocument.setObject(root); + + passwordDatabase.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); + passwordDatabase.write(newJsonDocument.toJson()); + passwordDatabase.flush(); + passwordDatabase.close(); + } + else { + log("Something went horribly wrong", className); + } +} + +void connectiondialog::on_CancelBtn_clicked() +{ + this->deleteLater(); + this->close(); +} + +void connectiondialog::on_passwordTextEdit_selectionChanged() +{ + ui->passwordTextEdit->setSelection(0, 0); +} + +void connectiondialog::on_passwordTextEdit_cursorPositionChanged(int arg1, int arg2) +{ + log("detected click on textedit"); + if(cursorPositionIgnore == true) { + global::keyboard::keyboardDialog = true; + global::keyboard::wifiPassphraseDialog = true; + global::keyboard::keyboardText = ""; + generalDialog* generalDialogWindow = new generalDialog(); + generalDialogWindow->setAttribute(Qt::WA_DeleteOnClose); + generalDialogWindow->wifiEssid = connectedNetworkData.name; + connect(generalDialogWindow, &generalDialog::showToast, this, &connectiondialog::showToastSlot); + generalDialogWindow->exec(); + + global::keyboard::keyboardDialog = false; + global::keyboard::wifiPassphraseDialog = false; + if(global::keyboard::keyboardText.isEmpty() == false) { + ui->passwordTextEdit->setText(global::keyboard::keyboardText); + } + global::keyboard::keyboardText = ""; + + } + else { + cursorPositionIgnore = true; + } + ui->passwordTextEdit->setCursorPosition(0); +} + +void connectiondialog::showToastSlot(QString message) { + emit showToastSignal(message); +} diff --git a/src/widgets/dialogs/wifi/connectiondialog.h b/src/widgets/dialogs/wifi/connectiondialog.h index fa9b320..a5a9ec9 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.h +++ b/src/widgets/dialogs/wifi/connectiondialog.h @@ -18,12 +18,28 @@ public: ~connectiondialog(); global::wifi::wifiNetworkData connectedNetworkData; QString currentlyConnectedNetworkName; + QFile passwordDatabase = QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/passwords.json"); + +signals: + void showToastSignal(QString message); public slots: void applyVariables(); + void showToastSlot(QString message); + +private slots: + void on_CancelBtn_clicked(); + QString searchDatabase(QString key); + void writeToDatabase(QString name, QString password); + + + void on_passwordTextEdit_selectionChanged(); + + void on_passwordTextEdit_cursorPositionChanged(int arg1, int arg2); private: Ui::connectiondialog *ui; + bool cursorPositionIgnore = false; }; #endif // CONNECTIONDIALOG_H diff --git a/src/widgets/dialogs/wifi/connectiondialog.ui b/src/widgets/dialogs/wifi/connectiondialog.ui index a7b27a8..0e9c693 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.ui +++ b/src/widgets/dialogs/wifi/connectiondialog.ui @@ -6,8 +6,8 @@ 0 0 - 529 - 335 + 263 + 136 diff --git a/src/widgets/dialogs/wifi/network.cpp b/src/widgets/dialogs/wifi/network.cpp index 320f44c..c2c693f 100644 --- a/src/widgets/dialogs/wifi/network.cpp +++ b/src/widgets/dialogs/wifi/network.cpp @@ -70,5 +70,15 @@ void network::on_enterButton_clicked() newConnectionDiallog->connectedNetworkData = mainData; newConnectionDiallog->currentlyConnectedNetworkName = currentlyConnectedNetwork; newConnectionDiallog->applyVariables(); + connect(newConnectionDiallog, &connectiondialog::showToastSignal, this, &network::showToastSlot); newConnectionDiallog->exec(); } + +void network::closeWrapper() { + this->deleteLater(); + this->close(); +} + +void network::showToastSlot(QString message) { + emit showToastSignal(message); +} diff --git a/src/widgets/dialogs/wifi/network.h b/src/widgets/dialogs/wifi/network.h index 75a79ab..294c307 100644 --- a/src/widgets/dialogs/wifi/network.h +++ b/src/widgets/dialogs/wifi/network.h @@ -20,8 +20,13 @@ public: global::wifi::wifiNetworkData mainData; QString currentlyConnectedNetwork; +signals: + void showToastSignal(QString message); + public slots: void applyVariables(); + void closeWrapper(); + void showToastSlot(QString message); private slots: void on_enterButton_clicked(); diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 387fc3f..9c3ed32 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -176,36 +176,36 @@ void wifiDialog::on_refreshBtn_clicked() log("To scan, turn on wi-fi first", className); } else { - ui->refreshBtn->setEnabled(false); - // for some reason this doesnt work here - //ui->refreshBtn->setStyleSheet("background-color:grey;"); - QTimer::singleShot(100, this, SLOT(launchRefresh())); + launchRefresh(); } } void wifiDialog::launchRefresh() { - QFile fullList = QFile("/external_root/run/wifi_list_full"); - QFile formattedList = QFile("/external_root/run/wifi_list_format"); + // Order is important + ui->refreshBtn->setStyleSheet("background-color:grey;"); + ui->refreshBtn->setEnabled(false); + + elapsedSeconds = 0; fullList.remove(); formattedList.remove(); string_writeconfig("/opt/ibxd", "list_wifi_networks\n"); - QElapsedTimer elapsedTime; - elapsedTime.start(); - bool continueLoop = true; - ui->refreshBtn->setStyleSheet("background-color:grey;"); - while(fullList.exists() == false and formattedList.exists() == false and continueLoop == true) { - sleep(1); - if(elapsedTime.elapsed() > 6000) { - log("Searching for networks took too long"); - continueLoop = false; + QTimer::singleShot(0, this, SLOT(refreshWait())); +} + +void wifiDialog::refreshWait() { + if(fullList.exists() == false and formattedList.exists() == false) { + if(elapsedSeconds == 6) { + emit showToast("Failed to get network list"); + log("Failed to get network list", className); } + else { + elapsedSeconds = elapsedSeconds + 1; + QTimer::singleShot(1000, this, SLOT(refreshWait())); + } + } else { + log("Happily got network list", className); + refreshNetworksList(); } - if(fullList.exists() == false or formattedList.exists() == false) { - emit showToast("Failed to get network list"); - log("Failed to get network list", className); - } - log("Happily got network list", className); - refreshNetworksList(); } void wifiDialog::refreshNetworksList() { @@ -217,7 +217,7 @@ void wifiDialog::refreshNetworksList() { int count = 1; global::wifi::wifiNetworkData singleNetwork; if(data.count() < 4) { - log("Data lines count is below 4, skipping"); + log("Data lines count is below 4, skipping", className); continue; } for(QString singleData: data) { @@ -250,7 +250,7 @@ void wifiDialog::refreshNetworksList() { pureNetworkList.append(singleNetwork); } } - log("found valid networks: " + QString::number(pureNetworkList.count())); + log("found valid networks: " + QString::number(pureNetworkList.count()), className); QFile currentWifiNameFile = QFile("/external_root/run/current_wifi_name"); currentWifiNameFile.remove(); string_writeconfig("/opt/ibxd", "get_current_wifi_name\n"); @@ -278,7 +278,8 @@ void wifiDialog::refreshNetworksList() { // this doesnt work so a layout is needed // ui->scrollArea->addScrollBarWidget(connectedNetwork, Qt::AlignTop); connectedNetwork->applyVariables(); - connect(this, &wifiDialog::killNetworkWidgets, connectedNetwork, &network::close); + connect(this, &wifiDialog::killNetworkWidgets, connectedNetwork, &network::closeWrapper); + connect(connectedNetwork, &network::showToastSignal, this, &wifiDialog::showToastSlot); ui->scrollBarLayout->addWidget(connectedNetwork, Qt::AlignTop); } countVec = countVec + 1; @@ -288,6 +289,11 @@ void wifiDialog::refreshNetworksList() { pureNetworkList.removeAt(vectorNetworkLocation); } } + for(global::wifi::wifiNetworkData wifiNetwork: pureNetworkList) { + log("signal strength without sorting: " + QString::number(wifiNetwork.signal), className); + } + + // Sort based on signal strength QVector sortedPureNetworkList; sortedPureNetworkList.append(pureNetworkList.first()); @@ -297,13 +303,23 @@ void wifiDialog::refreshNetworksList() { int counter = 0; for(global::wifi::wifiNetworkData wifiNetworkToSort: sortedPureNetworkList) { if(stopIterating == false) { - if(wifiNetwork.signal > wifiNetworkToSort.signal) { + if(wifiNetwork.signal >= wifiNetworkToSort.signal) { sortedPureNetworkList.insert(counter, wifiNetwork); stopIterating = true; } counter = counter + 1; } } + // this happens if its the smallest value, so insert it at the end + if(stopIterating == false) { + sortedPureNetworkList.append(wifiNetwork); + } + } + + log("There are " + QString::number(sortedPureNetworkList.count()) + " sorted networks", className); + + for(global::wifi::wifiNetworkData wifiNetwork: sortedPureNetworkList) { + log("signal strength with sorting: " + QString::number(wifiNetwork.signal), className); } // And now rest of the networks @@ -312,7 +328,8 @@ void wifiDialog::refreshNetworksList() { connectedNetwork->mainData = wifiNetwork; connectedNetwork->currentlyConnectedNetwork = currentNetwork; connectedNetwork->applyVariables(); - connect(this, &wifiDialog::killNetworkWidgets, connectedNetwork, &network::close); + connect(this, &wifiDialog::killNetworkWidgets, connectedNetwork, &network::closeWrapper); + connect(connectedNetwork, &network::showToastSignal, this, &wifiDialog::showToastSlot); ui->scrollBarLayout->addWidget(connectedNetwork, Qt::AlignTop); } scannedAtLeastOnce = true; @@ -332,6 +349,7 @@ void wifiDialog::on_Wificheckbox_stateChanged(int arg1) log("turning wifi off", className); QTimer::singleShot(0, this, SLOT(turnOffWifi())); } + emit killNetworkWidgets(); } if(wifiButtonEnabled == false){ @@ -359,3 +377,7 @@ void wifiDialog::on_logBtn_clicked() } } + +void wifiDialog::showToastSlot(QString message) { + emit showToast(message); +} diff --git a/src/widgets/dialogs/wifi/wifidialog.h b/src/widgets/dialogs/wifi/wifidialog.h index b0a826e..348e8d7 100644 --- a/src/widgets/dialogs/wifi/wifidialog.h +++ b/src/widgets/dialogs/wifi/wifidialog.h @@ -28,9 +28,15 @@ private: bool wifiButtonEnabled = false; bool scannedAtLeastOnce = false; + // variables for refreshWait() and network refresh in general + int elapsedSeconds = 0; + QFile fullList = QFile("/external_root/run/wifi_list_full"); + QFile formattedList = QFile("/external_root/run/wifi_list_format"); + public slots: void launchRefresh(); void refreshNetworksList(); + void showToastSlot(QString message); signals: void refreshScreen(); @@ -45,6 +51,8 @@ private slots: void turnOnWifi(); void turnOffWifi(); void on_logBtn_clicked(); + // This function is a more clever sleep(1), non blocking + void refreshWait(); }; #endif // WIFIDIALOG_H diff --git a/src/widgets/dialogs/wifi/wifilogger.cpp b/src/widgets/dialogs/wifi/wifilogger.cpp index 3095f41..9ce0b89 100644 --- a/src/widgets/dialogs/wifi/wifilogger.cpp +++ b/src/widgets/dialogs/wifi/wifilogger.cpp @@ -139,6 +139,7 @@ void wifilogger::getWifiInformations() { void wifilogger::on_returnBtn_clicked() { this->deleteLater(); + this->close(); } void wifilogger::updateLogs() { From 2acd7adf1f7ca858327f34af583622c7cdc19cba Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Thu, 18 Aug 2022 21:47:08 +0200 Subject: [PATCH 07/19] almost finished --- inkbox.pro | 9 + src/functions.h | 17 ++ src/widgets/dialogs/generaldialog.cpp | 7 +- src/widgets/dialogs/wifi/connectiondialog.cpp | 180 ++++++++++++++++-- src/widgets/dialogs/wifi/connectiondialog.h | 19 +- src/widgets/dialogs/wifi/network.cpp | 5 + src/widgets/dialogs/wifi/network.h | 2 + src/widgets/dialogs/wifi/wifidialog.cpp | 100 ++++++++++ src/widgets/dialogs/wifi/wifidialog.h | 10 + 9 files changed, 328 insertions(+), 21 deletions(-) diff --git a/inkbox.pro b/inkbox.pro index 0b7c70d..a0c19d7 100644 --- a/inkbox.pro +++ b/inkbox.pro @@ -32,6 +32,9 @@ SOURCES += \ src/apps/calendarapp.cpp \ src/widgets/dialogs/reader/highlightslistdialog.cpp \ src/widgets/dialogs/reader/textdialog.cpp \ + src/widgets/dialogs/wifi/connectiondialog.cpp \ + src/widgets/dialogs/wifi/network.cpp \ + src/widgets/dialogs/wifi/wifilogger.cpp \ src/widgets/reader/dictionarywidget.cpp \ src/encfs/encryptionmanager.cpp \ src/widgets/dialogs/generaldialog.cpp \ @@ -72,6 +75,9 @@ HEADERS += \ src/apps/calendarapp.h \ src/widgets/dialogs/reader/highlightslistdialog.h \ src/widgets/dialogs/reader/textdialog.h \ + src/widgets/dialogs/wifi/connectiondialog.h \ + src/widgets/dialogs/wifi/network.h \ + src/widgets/dialogs/wifi/wifilogger.h \ src/widgets/reader/dictionarywidget.h \ src/encfs/encryptionmanager.h \ src/functions.h \ @@ -112,6 +118,9 @@ FORMS += \ src/apps/calendarapp.ui \ src/widgets/dialogs/reader/highlightslistdialog.ui \ src/widgets/dialogs/reader/textdialog.ui \ + src/widgets/dialogs/wifi/connectiondialog.ui \ + src/widgets/dialogs/wifi/network.ui \ + src/widgets/dialogs/wifi/wifilogger.ui \ src/widgets/reader/dictionarywidget.ui \ src/encfs/encryptionmanager.ui \ src/widgets/dialogs/generaldialog.ui \ diff --git a/src/functions.h b/src/functions.h index 81e7e26..818507e 100644 --- a/src/functions.h +++ b/src/functions.h @@ -1119,6 +1119,23 @@ namespace { } return exitCode; } + bool checkProcessName(QString name) { + QDirIterator appsDir("/proc", QDirIterator::NoIteratorFlags); + while (appsDir.hasNext()) { + QDir dir(appsDir.next()); + QFile process = QFile(dir.path() + "/cmdline"); + if(process.exists() == true) { + process.open(QIODevice::ReadOnly); + QTextStream stream(&process); + if(stream.readLine().contains(name) == true) { + process.close(); + return true; + } + process.close(); + } + } + return false; + } } #endif // FUNCTIONS_H diff --git a/src/widgets/dialogs/generaldialog.cpp b/src/widgets/dialogs/generaldialog.cpp index b60536e..2d01897 100644 --- a/src/widgets/dialogs/generaldialog.cpp +++ b/src/widgets/dialogs/generaldialog.cpp @@ -499,6 +499,9 @@ void generalDialog::on_okBtn_clicked() global::toast::delay = 3000; showToast("Minimum password length is 8 characters"); } + else { + generalDialog::close(); + } } else { global::toast::delay = 3000; @@ -591,6 +594,7 @@ void generalDialog::restartSearchDialog() { } void generalDialog::setupKeyboardDialog() { + adjust_size(); ui->stackedWidget->setCurrentIndex(0); keyboardDialog = true; ui->stackedWidget->setVisible(true); @@ -607,7 +611,7 @@ void generalDialog::setupKeyboardDialog() { } else if(global::keyboard::wifiPassphraseDialog == true) { ui->headerLabel->setText("Enter the network's passphrase"); - ui->okBtn->setText("Connect"); + ui->okBtn->setText("Enter"); ui->cancelBtn->setText("Cancel"); } else if(global::keyboard::encfsDialog == true) { @@ -624,6 +628,7 @@ void generalDialog::setupKeyboardDialog() { connect(keyboardWidget, SIGNAL(adjust_size()), SLOT(adjust_size())); ui->mainStackedWidget->insertWidget(1, keyboardWidget); ui->mainStackedWidget->setCurrentIndex(1); + adjust_size(); QTimer::singleShot(1000, this, SLOT(adjust_size())); } diff --git a/src/widgets/dialogs/wifi/connectiondialog.cpp b/src/widgets/dialogs/wifi/connectiondialog.cpp index d4d990c..0c04018 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.cpp +++ b/src/widgets/dialogs/wifi/connectiondialog.cpp @@ -4,6 +4,7 @@ #include "connectiondialog.h" #include "ui_connectiondialog.h" #include "generaldialog.h" +#include "functions.h" connectiondialog::connectiondialog(QWidget *parent) : QDialog(parent), @@ -34,6 +35,7 @@ connectiondialog::~connectiondialog() } void connectiondialog::applyVariables() { + // Here for some devices it will be propably needed to limit the size. the nia is fine ui->nameLabel->setText(connectedNetworkData.name); ui->macLabel->setText(connectedNetworkData.mac); ui->signalLabel->setText(QString::number(connectedNetworkData.signal) + "%"); @@ -62,11 +64,16 @@ void connectiondialog::applyVariables() { QString password = searchDatabase(connectedNetworkData.name); if(password.isEmpty() == false) { log("found password: " + password, className); - ui->passwordTextEdit->setText(password); + ui->showPasswordBtn->setIcon(QIcon("://resources/show.png")); + showedPasword = false; + savedPassword = password; + + ui->passwordTextEdit->setText("********"); } else { log("No password found", className); - ui->passwordTextEdit->setText("No password found"); + ui->passwordTextEdit->setText("No password was saved"); + ui->showPasswordBtn->hide(); } } } @@ -97,6 +104,10 @@ QString connectiondialog::searchDatabase(QString key) { } void connectiondialog::writeToDatabase(QString name, QString password) { + if(searchDatabase(name).isEmpty() == false) { + removeFromDatabase(name); + } + passwordDatabase.open(QIODevice::ReadOnly | QIODevice::Text); QString fileRead = passwordDatabase.readAll(); passwordDatabase.close(); @@ -126,6 +137,45 @@ void connectiondialog::writeToDatabase(QString name, QString password) { } } +void connectiondialog::removeFromDatabase(QString name) { + passwordDatabase.open(QIODevice::ReadOnly | QIODevice::Text); + QString fileRead = passwordDatabase.readAll(); + passwordDatabase.close(); + QJsonDocument jsonDocument = QJsonDocument::fromJson(fileRead.toUtf8()); + + int counter = 0; + bool remove = false; + if(jsonDocument["list"].isArray() == true) { + QJsonArray jsonArray = jsonDocument["list"].toArray(); + for(QJsonValueRef refJsonObject: jsonArray) { + QJsonObject jsonMainObject = refJsonObject.toObject(); + QString searchedName = jsonMainObject.keys().first().toUtf8(); + log("Found in database: " + searchedName, className); + if(searchedName == name) { + remove = true; + } + if(remove == false) { + counter = counter + 1; + } + } + if(remove == true) { + jsonArray.removeAt(counter); + QJsonDocument newJsonDocument; + QJsonObject root; + root["list"] = jsonArray; + newJsonDocument.setObject(root); + + passwordDatabase.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); + passwordDatabase.write(newJsonDocument.toJson()); + passwordDatabase.flush(); + passwordDatabase.close(); + } + else { + log("ERROR: tryied to remove from database, but couldn't find key", className); + } + } +} + void connectiondialog::on_CancelBtn_clicked() { this->deleteLater(); @@ -137,33 +187,125 @@ void connectiondialog::on_passwordTextEdit_selectionChanged() ui->passwordTextEdit->setSelection(0, 0); } -void connectiondialog::on_passwordTextEdit_cursorPositionChanged(int arg1, int arg2) +void connectiondialog::on_passwordTextEdit_cursorPositionChanged(int oldpos, int newpos) { - log("detected click on textedit"); + log("detected click on text edit", className); if(cursorPositionIgnore == true) { - global::keyboard::keyboardDialog = true; - global::keyboard::wifiPassphraseDialog = true; - global::keyboard::keyboardText = ""; - generalDialog* generalDialogWindow = new generalDialog(); - generalDialogWindow->setAttribute(Qt::WA_DeleteOnClose); - generalDialogWindow->wifiEssid = connectedNetworkData.name; - connect(generalDialogWindow, &generalDialog::showToast, this, &connectiondialog::showToastSlot); - generalDialogWindow->exec(); + if(newpos != 0) { + if(showedPasword == true) { + ui->passwordTextEdit->setCursorPosition(0); + global::keyboard::keyboardDialog = true; + global::keyboard::wifiPassphraseDialog = true; + global::keyboard::keyboardText = ""; + generalDialog* generalDialogWindow = new generalDialog(); + generalDialogWindow->setAttribute(Qt::WA_DeleteOnClose); + generalDialogWindow->wifiEssid = connectedNetworkData.name; + connect(generalDialogWindow, &generalDialog::showToast, this, &connectiondialog::showToastSlot); + connect(generalDialogWindow, &generalDialog::refreshScreen, this, &connectiondialog::refreshScreenSlot); - global::keyboard::keyboardDialog = false; - global::keyboard::wifiPassphraseDialog = false; - if(global::keyboard::keyboardText.isEmpty() == false) { - ui->passwordTextEdit->setText(global::keyboard::keyboardText); + generalDialogWindow->exec(); + + global::keyboard::keyboardDialog = false; + global::keyboard::wifiPassphraseDialog = false; + if(global::keyboard::keyboardText.isEmpty() == false) { + // A bit hacky: avoid summoning the keyboard back when the text is changing ( and the cursor too ) showedPasword shouldnt be used for this, but it works and adding another bool would start being messy + showedPasword = false; + ui->passwordTextEdit->setText(global::keyboard::keyboardText); + ui->showPasswordBtn->setIcon(QIcon("://resources/hide.png")); + ui->showPasswordBtn->show(); + showedPasword = true; + savedPassword = global::keyboard::keyboardText; + } + global::keyboard::keyboardText = ""; + } } - global::keyboard::keyboardText = ""; - } else { + log("Ignoring click on text edit", className); cursorPositionIgnore = true; } - ui->passwordTextEdit->setCursorPosition(0); } void connectiondialog::showToastSlot(QString message) { emit showToastSignal(message); } + +void connectiondialog::on_showPasswordBtn_clicked() +{ + if(showedPasword == false) { + ui->showPasswordBtn->setIcon(QIcon("://resources/hide.png")); + ui->passwordTextEdit->setText(savedPassword); + showedPasword = true; + } + else { + showedPasword = false; + ui->showPasswordBtn->setIcon(QIcon("://resources/show.png")); + ui->passwordTextEdit->setText("********"); + } +} + +void connectiondialog::refreshScreenSlot() { + this->repaint(); + emit refreshScreenSignal(); +} + +void connectiondialog::on_connectBtn_clicked() +{ + QString finalPassword; + if(connectedNetworkData.encryption == false) { + finalPassword = "NONE"; + } + else { + finalPassword = savedPassword; + writeToDatabase(connectedNetworkData.name, savedPassword); + } + + ui->CancelBtn->setEnabled(false); + if(checkWifiState() == global::wifi::WifiState::Configured) { + string_writeconfig("/opt/ibxd", "stop_wifi_operations\n"); + } + string_writeconfig("/run/wifi_network_essid", connectedNetworkData.name.toStdString()); + string_writeconfig("/run/wifi_network_passphrase", finalPassword.toStdString()); + setDefaultWorkDir(); + // this will be deleited later in mainwindow icon updater if it failed + string_writeconfig(".config/17-wifi_connection_information/essid", connectedNetworkData.name.toStdString()); + string_writeconfig(".config/17-wifi_connection_information/passphrase", finalPassword.toStdString()); + finalConnectWait(); + +} + +void connectiondialog::finalConnectWait() { + if(checkIfWifiBussy() == true) { + // To be sure + if(waitTry == 10) { + string_writeconfig("/opt/ibxd", "stop_wifi_operations\n"); + } + // Max 10s to wait for everything to shut down + if(waitTry == 20) { + string_writeconfig("/opt/ibxd", "stop_wifi_operations\n"); + emit showToastSignal("Failed to stop other wifi processes"); + ui->CancelBtn->setEnabled(true); + } + else { + QTimer::singleShot(500, this, SLOT(finalConnectWait())); + waitTry = waitTry + 1; + } + } + else { + string_writeconfig("/opt/ibxd", "connect_to_wifi_network\n"); + ui->CancelBtn->setEnabled(true); + this->deleteLater(); + this->close(); + } +} + +bool connectiondialog::checkIfWifiBussy() { + if(checkProcessName("connect_to_network.sh") == true or + checkProcessName("connection_manager.sh") == true or + checkProcessName("only_connect_to_network.sh") == true) { + return true; + } + else { + return false; + } +} diff --git a/src/widgets/dialogs/wifi/connectiondialog.h b/src/widgets/dialogs/wifi/connectiondialog.h index a5a9ec9..df6cc03 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.h +++ b/src/widgets/dialogs/wifi/connectiondialog.h @@ -22,24 +22,41 @@ public: signals: void showToastSignal(QString message); + void refreshScreenSignal(); public slots: void applyVariables(); void showToastSlot(QString message); + void refreshScreenSlot(); private slots: - void on_CancelBtn_clicked(); + // I know im opening / loading json many times, its maybe not efficient but: + // 1. its modular + // 2. those operations are rare QString searchDatabase(QString key); void writeToDatabase(QString name, QString password); + void removeFromDatabase(QString name); + void finalConnectWait(); + bool checkIfWifiBussy(); + + void on_CancelBtn_clicked(); + void on_passwordTextEdit_selectionChanged(); void on_passwordTextEdit_cursorPositionChanged(int arg1, int arg2); + void on_showPasswordBtn_clicked(); + + void on_connectBtn_clicked(); + private: Ui::connectiondialog *ui; bool cursorPositionIgnore = false; + bool showedPasword; + QString savedPassword; + int waitTry = 0; }; #endif // CONNECTIONDIALOG_H diff --git a/src/widgets/dialogs/wifi/network.cpp b/src/widgets/dialogs/wifi/network.cpp index c2c693f..b3e2f71 100644 --- a/src/widgets/dialogs/wifi/network.cpp +++ b/src/widgets/dialogs/wifi/network.cpp @@ -71,6 +71,7 @@ void network::on_enterButton_clicked() newConnectionDiallog->currentlyConnectedNetworkName = currentlyConnectedNetwork; newConnectionDiallog->applyVariables(); connect(newConnectionDiallog, &connectiondialog::showToastSignal, this, &network::showToastSlot); + connect(newConnectionDiallog, &connectiondialog::refreshScreenSignal, this, &network::refreshScreenSlot); newConnectionDiallog->exec(); } @@ -82,3 +83,7 @@ void network::closeWrapper() { void network::showToastSlot(QString message) { emit showToastSignal(message); } + +void network::refreshScreenSlot() { + emit refreshScreenSignal(); +} diff --git a/src/widgets/dialogs/wifi/network.h b/src/widgets/dialogs/wifi/network.h index 294c307..2649b0d 100644 --- a/src/widgets/dialogs/wifi/network.h +++ b/src/widgets/dialogs/wifi/network.h @@ -22,11 +22,13 @@ public: signals: void showToastSignal(QString message); + void refreshScreenSignal(); public slots: void applyVariables(); void closeWrapper(); void showToastSlot(QString message); + void refreshScreenSlot(); private slots: void on_enterButton_clicked(); diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 9c3ed32..3d3b9c1 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -65,6 +65,7 @@ wifiDialog::wifiDialog(QWidget *parent) : wifiButtonEnabled = true; } + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); } wifiDialog::~wifiDialog() @@ -280,6 +281,7 @@ void wifiDialog::refreshNetworksList() { connectedNetwork->applyVariables(); connect(this, &wifiDialog::killNetworkWidgets, connectedNetwork, &network::closeWrapper); connect(connectedNetwork, &network::showToastSignal, this, &wifiDialog::showToastSlot); + connect(connectedNetwork, &network::refreshScreenSignal, this, &wifiDialog::refreshScreenSlot); ui->scrollBarLayout->addWidget(connectedNetwork, Qt::AlignTop); } countVec = countVec + 1; @@ -330,6 +332,7 @@ void wifiDialog::refreshNetworksList() { connectedNetwork->applyVariables(); connect(this, &wifiDialog::killNetworkWidgets, connectedNetwork, &network::closeWrapper); connect(connectedNetwork, &network::showToastSignal, this, &wifiDialog::showToastSlot); + connect(connectedNetwork, &network::refreshScreenSignal, this, &wifiDialog::refreshScreenSlot); ui->scrollBarLayout->addWidget(connectedNetwork, Qt::AlignTop); } scannedAtLeastOnce = true; @@ -381,3 +384,100 @@ void wifiDialog::on_logBtn_clicked() void wifiDialog::showToastSlot(QString message) { emit showToast(message); } + +void wifiDialog::refreshScreenSlot() { + this->repaint(); +} + +/* +Some documentation used by the watcher +connection_manager.sh - manages all things, launches other processes +connect_to_network.sh - all in one connection manager. manages everything, used by ipd, should be used for recconections after sleeping / booting +get_dhcp.sh - Gets dhcp addresses +prepare_changing_wifi.sh - Kills everything, prepares to changing network +smarter_time_sync.sh - synces time +toggle.sh - turns on / off +list_networks.bin - well lists networks +the watcher first watches at processes that could kill other ones +*/ + +void wifiDialog::theWatcher() { + + bool killing = checkProcessName("toggle.sh"); + bool changing = checkProcessName("prepare_changing_wifi.sh"); + if(killing == true) { + setStatusText("Changing wifi state"); + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + return void(); + } + + if(changing == true) { + setStatusText("Disconnecting from a network or cleaning"); + forceRefresh = true; + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + return void(); + } + + bool recconection = checkProcessName("connect_to_network.sh"); + if(recconection == true) { + forceRefresh = true; + QFile recName = QFile(".config/17-wifi_connection_information/essid"); + if(recName.exists() == true) { + setStatusText("Recconecting after suspending to " + readFile(recName.fileName()).replace("\n", "")); + } + else { + // Shouldn't be possible + setStatusText("Recconecting after sleep, but no network found?"); + } + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + return void(); + } + + bool listing = checkProcessName("list_networks.bin"); + if(listing == true) { + setStatusText("Scanning networks..."); + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + return void(); + } + + bool time = checkProcessName("smarter_time_sync.sh"); + if(time == true) { + forceRefresh = true; + setStatusText("Syncing time"); + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + return void(); + } + + bool dhcp = checkProcessName("get_dhcp.sh"); + if(dhcp == true) { + forceRefresh = true; + setStatusText("Getting IP address"); + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + return void(); + } + + bool connecting = checkProcessName("connect_to_network.sh"); + if(connecting == true) { + forceRefresh = true; + setStatusText("Connecting to wifi..."); + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + return void(); + } + + setStatusText("Idling"); + if(forceRefresh == true) { + forceRefresh = false; + ui->refreshBtn->click(); + } + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); +} + +void wifiDialog::setStatusText(QString message) { + ui->statusLabel->setText(message); +} + +void wifiDialog::on_stopBtn_clicked() +{ + // Maybe limit this, idk + string_writeconfig("/opt/ibxd", "stop_wifi_operations\n"); +} diff --git a/src/widgets/dialogs/wifi/wifidialog.h b/src/widgets/dialogs/wifi/wifidialog.h index 348e8d7..4d21f99 100644 --- a/src/widgets/dialogs/wifi/wifidialog.h +++ b/src/widgets/dialogs/wifi/wifidialog.h @@ -33,10 +33,18 @@ private: QFile fullList = QFile("/external_root/run/wifi_list_full"); QFile formattedList = QFile("/external_root/run/wifi_list_format"); + // Used by watcher + bool forceRefresh = false; + int relaunchMs = 300; + public slots: void launchRefresh(); void refreshNetworksList(); void showToastSlot(QString message); + void refreshScreenSlot(); + + // Shows status of wifi processes, like recconection and others. Also manages refreshing the network list after connection + void theWatcher(); signals: void refreshScreen(); @@ -53,6 +61,8 @@ private slots: void on_logBtn_clicked(); // This function is a more clever sleep(1), non blocking void refreshWait(); + void setStatusText(QString message); + void on_stopBtn_clicked(); }; #endif // WIFIDIALOG_H From e310544fb5689f8f7bbe2a87623d7dd8f20bc2b9 Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Fri, 19 Aug 2022 21:35:39 +0200 Subject: [PATCH 08/19] fixes :( --- src/homeWidget/mainwindow.cpp | 109 +++++++++++----- src/homeWidget/mainwindow.h | 8 +- src/widgets/dialogs/wifi/connectiondialog.cpp | 20 +-- src/widgets/dialogs/wifi/connectiondialog.h | 6 +- src/widgets/dialogs/wifi/network.cpp | 3 +- src/widgets/dialogs/wifi/wifidialog.cpp | 122 ++++++++++++++---- src/widgets/dialogs/wifi/wifidialog.h | 10 +- src/widgets/dialogs/wifi/wifidialog.ui | 32 +++++ src/widgets/dialogs/wifi/wifilogger.cpp | 27 +++- src/widgets/dialogs/wifi/wifilogger.h | 3 + src/widgets/dialogs/wifi/wifilogger.ui | 14 +- 11 files changed, 271 insertions(+), 83 deletions(-) diff --git a/src/homeWidget/mainwindow.cpp b/src/homeWidget/mainwindow.cpp index cb24d71..0b5303f 100644 --- a/src/homeWidget/mainwindow.cpp +++ b/src/homeWidget/mainwindow.cpp @@ -132,12 +132,12 @@ MainWindow::MainWindow(QWidget *parent) ui->brightnessBtn->setIcon(QIcon(":/resources/frontlight.png")); ui->brightnessBtn->setIconSize(QSize(brightnessIconWidth, brightnessIconHeight)); - updateWifiState(); + updateWifiAble(); if(global::device::isWifiAble == true) { // Start wifi updater QTimer *wifiIconTimer = new QTimer(this); - wifiIconTimer->setInterval(5000); - connect(wifiIconTimer, SIGNAL(timeout()), this, SLOT(updateWifiState())); + wifiIconTimer->setInterval(2500); + connect(wifiIconTimer, SIGNAL(timeout()), this, SLOT(updateWifiIcon())); wifiIconTimer->start(); } setBatteryIcon(); @@ -751,37 +751,84 @@ void MainWindow::setupSearchDialog() { } } -void MainWindow::updateWifiIcon(global::wifi::WifiState mode) { +void MainWindow::updateWifiIcon() { /* Usage: - * mode 0 is handled in mainwindow() + * Mode 0 (looping it) is handled in mainwindow() */ - if(mode == global::wifi::WifiState::Disabled) { - lastWifiState = global::wifi::WifiState::Disabled; - ui->wifiBtn->setIcon(QIcon(":/resources/wifi-off.png")); - ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); - } - if(mode == global::wifi::WifiState::Enabled) { - lastWifiState = global::wifi::WifiState::Enabled; - ui->wifiBtn->setIcon(QIcon(":/resources/wifi-standby.png")); - ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); - } - if(mode == global::wifi::WifiState::Configured) { - lastWifiState = global::wifi::WifiState::Configured; - ui->wifiBtn->setIcon(QIcon(":/resources/wifi-connected.png")); - ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); - } -} -void MainWindow::updateWifiState() { - if(global::device::isWifiAble == true) { - global::wifi::WifiState currentWifiState = checkWifiState(); - if(lastWifiState != currentWifiState) { - // This is handled by updateWifiIcon() - //lastWifiState = currentWifiState; - updateWifiIcon(currentWifiState); + + global::wifi::WifiState currentWifiState = checkWifiState(); + + // Its executing only in Enabled mode, which is a mode between connected and disabled so don't worry about performance + if(isConnecting == false and isReconecting == false) { + if(currentWifiState == global::wifi::WifiState::Enabled) { + if(checkProcessName("connection_manager.sh") == true) { + isConnecting = true; + } + else if(checkProcessName("connect_to_network.sh") == true){ + isConnecting = true; + isReconecting = true; + } } } - else { + + if(lastWifiState != currentWifiState) { + if(currentWifiState == global::wifi::WifiState::Disabled) { + if(isConnecting == true) { + setDefaultWorkDir(); + if(checkconfig(".config/17-wifi_connection_information/stopped") == false) { + QString wifiName = readFile(".config/17-wifi_connection_information/essid").replace("\n", ""); + if(isReconecting == true) { + showToast("Failed to reconnect to " + wifiName); + isReconecting = false; + } + else { + showToast("Failed to connect to " + wifiName); + } + isConnecting = false; + QFile(".config/17-wifi_connection_information/essid").remove(); + QFile(".config/17-wifi_connection_information/passphrase").remove(); + } + else { + QFile(".config/17-wifi_connection_information/stopped").remove(); + } + } + lastWifiState = global::wifi::WifiState::Disabled; + ui->wifiBtn->setIcon(QIcon(":/resources/wifi-off.png")); + ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); + } + if(currentWifiState == global::wifi::WifiState::Enabled) { + lastWifiState = global::wifi::WifiState::Enabled; + ui->wifiBtn->setIcon(QIcon(":/resources/wifi-standby.png")); + ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); + } + if(currentWifiState == global::wifi::WifiState::Configured) { + if(isConnecting == true) { + setDefaultWorkDir(); + QString wifiName = readFile(".config/17-wifi_connection_information/essid").replace("\n", ""); + if(isReconecting == true) { + showToast("Reconnected successfully to " + wifiName); + isReconecting = false; + } + else { + showToast("Connected successfully to " + wifiName); + } + isConnecting = false; + QFile(".config/17-wifi_connection_information/essid").remove(); + QFile(".config/17-wifi_connection_information/passphrase").remove(); + QFile(".config/17-wifi_connection_information/stopped").remove(); + } + lastWifiState = global::wifi::WifiState::Configured; + ui->wifiBtn->setIcon(QIcon(":/resources/wifi-connected.png")); + ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); + } + } + + +} + +void MainWindow::updateWifiAble() { + if(global::device::isWifiAble == false) { ui->wifiBtn->hide(); ui->line_9->hide(); } @@ -798,13 +845,13 @@ void MainWindow::showToast(QString messageToDisplay) { global::toast::message = messageToDisplay; toastWindow = new toast(this); toastWindow->setAttribute(Qt::WA_DeleteOnClose); - connect(toastWindow, SIGNAL(updateWifiIconSig(int)), SLOT(updateWifiIcon(int))); connect(toastWindow, SIGNAL(refreshScreen()), SLOT(refreshScreen())); connect(toastWindow, SIGNAL(showToast(QString)), SLOT(showToast(QString))); connect(toastWindow, SIGNAL(closeIndefiniteToast()), SLOT(closeIndefiniteToast())); toastWindow->show(); - if(messageToDisplay == "Connection successful") { + // I will soon manage the update thing in a more propper way somewhere else... ~ Szybet + if(messageToDisplay.contains("onnected successfully") == true) { // Give the toast some time to vanish away, then launch OTA updater QTimer::singleShot(5000, this, SLOT(launchOtaUpdater())); } diff --git a/src/homeWidget/mainwindow.h b/src/homeWidget/mainwindow.h index 43110d7..7ddf5ca 100644 --- a/src/homeWidget/mainwindow.h +++ b/src/homeWidget/mainwindow.h @@ -51,7 +51,11 @@ public: bool existing_recent_books = false; bool reboot_after_update = false; bool resetFullWindowException; + global::wifi::WifiState lastWifiState = global::wifi::WifiState::Unknown; + bool isConnecting = false; + bool isReconecting = false; + int timerTime = 0; QString relative_path; QString usbmsStatus; @@ -78,9 +82,9 @@ private slots: void on_homeBtn_clicked(); void refreshScreen(); void setupSearchDialog(); - void updateWifiState(); + void updateWifiAble(); void on_wifiBtn_clicked(); - void updateWifiIcon(global::wifi::WifiState mode); + void updateWifiIcon(); void hello(int testNumber); void openUpdateDialogOTA(bool open); void launchOtaUpdater(); diff --git a/src/widgets/dialogs/wifi/connectiondialog.cpp b/src/widgets/dialogs/wifi/connectiondialog.cpp index 0c04018..d6b2064 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.cpp +++ b/src/widgets/dialogs/wifi/connectiondialog.cpp @@ -65,7 +65,7 @@ void connectiondialog::applyVariables() { if(password.isEmpty() == false) { log("found password: " + password, className); ui->showPasswordBtn->setIcon(QIcon("://resources/show.png")); - showedPasword = false; + showedPassword = false; savedPassword = password; ui->passwordTextEdit->setText("********"); @@ -189,10 +189,10 @@ void connectiondialog::on_passwordTextEdit_selectionChanged() void connectiondialog::on_passwordTextEdit_cursorPositionChanged(int oldpos, int newpos) { - log("detected click on text edit", className); + log("Detected click on text edit", className); if(cursorPositionIgnore == true) { if(newpos != 0) { - if(showedPasword == true) { + if(showedPassword == true) { ui->passwordTextEdit->setCursorPosition(0); global::keyboard::keyboardDialog = true; global::keyboard::wifiPassphraseDialog = true; @@ -208,12 +208,12 @@ void connectiondialog::on_passwordTextEdit_cursorPositionChanged(int oldpos, int global::keyboard::keyboardDialog = false; global::keyboard::wifiPassphraseDialog = false; if(global::keyboard::keyboardText.isEmpty() == false) { - // A bit hacky: avoid summoning the keyboard back when the text is changing ( and the cursor too ) showedPasword shouldnt be used for this, but it works and adding another bool would start being messy - showedPasword = false; + // A bit hacky: avoid summoning the keyboard back when the text is changing ( and the cursor too ) showedPassword shouldnt be used for this, but it works and adding another bool would start being messy + showedPassword = false; ui->passwordTextEdit->setText(global::keyboard::keyboardText); ui->showPasswordBtn->setIcon(QIcon("://resources/hide.png")); ui->showPasswordBtn->show(); - showedPasword = true; + showedPassword = true; savedPassword = global::keyboard::keyboardText; } global::keyboard::keyboardText = ""; @@ -232,13 +232,13 @@ void connectiondialog::showToastSlot(QString message) { void connectiondialog::on_showPasswordBtn_clicked() { - if(showedPasword == false) { + if(showedPassword == false) { ui->showPasswordBtn->setIcon(QIcon("://resources/hide.png")); ui->passwordTextEdit->setText(savedPassword); - showedPasword = true; + showedPassword = true; } else { - showedPasword = false; + showedPassword = false; ui->showPasswordBtn->setIcon(QIcon("://resources/show.png")); ui->passwordTextEdit->setText("********"); } @@ -267,7 +267,7 @@ void connectiondialog::on_connectBtn_clicked() string_writeconfig("/run/wifi_network_essid", connectedNetworkData.name.toStdString()); string_writeconfig("/run/wifi_network_passphrase", finalPassword.toStdString()); setDefaultWorkDir(); - // this will be deleited later in mainwindow icon updater if it failed + // This will be deleited later in mainwindow icon updater if it failed string_writeconfig(".config/17-wifi_connection_information/essid", connectedNetworkData.name.toStdString()); string_writeconfig(".config/17-wifi_connection_information/passphrase", finalPassword.toStdString()); finalConnectWait(); diff --git a/src/widgets/dialogs/wifi/connectiondialog.h b/src/widgets/dialogs/wifi/connectiondialog.h index df6cc03..3d167b7 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.h +++ b/src/widgets/dialogs/wifi/connectiondialog.h @@ -31,8 +31,8 @@ public slots: private slots: // I know im opening / loading json many times, its maybe not efficient but: - // 1. its modular - // 2. those operations are rare + // 1. Its modular + // 2. Those operations are rare QString searchDatabase(QString key); void writeToDatabase(QString name, QString password); void removeFromDatabase(QString name); @@ -54,7 +54,7 @@ private slots: private: Ui::connectiondialog *ui; bool cursorPositionIgnore = false; - bool showedPasword; + bool showedPassword; QString savedPassword; int waitTry = 0; }; diff --git a/src/widgets/dialogs/wifi/network.cpp b/src/widgets/dialogs/wifi/network.cpp index b3e2f71..bc5f017 100644 --- a/src/widgets/dialogs/wifi/network.cpp +++ b/src/widgets/dialogs/wifi/network.cpp @@ -29,9 +29,10 @@ network::~network() } void network::applyVariables() { + log("Applying variables for network", className); ui->signalStrengthLabel->setText(QString::number(mainData.signal) + "%"); - // limit name size, maybe device specific + // Limit name size, maybe device specific QString cuttedSingleData = mainData.name; if(cuttedSingleData.count() > 27) { diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 3d3b9c1..54fa778 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -61,8 +61,13 @@ wifiDialog::wifiDialog(QWidget *parent) : global::wifi::WifiState currentWifiState = checkWifiState(); if(currentWifiState != global::wifi::WifiState::Disabled and currentWifiState != global::wifi::WifiState::Unknown) { ui->Wificheckbox->setChecked(true); + // To be sure nothing breaks + refreshFromWatcher = true; + ui->refreshBtn->click(); } else { wifiButtonEnabled = true; + ui->stopBtn->setStyleSheet("background-color:grey;"); + ui->stopBtn->setEnabled(false); } QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); @@ -173,24 +178,31 @@ void wifiDialog::on_refreshBtn_clicked() { log("Clicked refresh button", className); if(checkWifiState() == global::wifi::WifiState::Disabled) { - emit showToast("To scan, turn on wi-fi first"); - log("To scan, turn on wi-fi first", className); + if(refreshFromWatcher == true) { + refreshFromWatcher = false; + emit showToast("To scan, turn on wi-fi first"); + log("To scan, turn on wi-fi first", className); + } } else { + refreshFromWatcher = false; launchRefresh(); } } void wifiDialog::launchRefresh() { // Order is important - ui->refreshBtn->setStyleSheet("background-color:grey;"); - ui->refreshBtn->setEnabled(false); + if(scanInProgress == false) { + scanInProgress = true; + ui->refreshBtn->setStyleSheet("background-color:grey;"); + ui->refreshBtn->setEnabled(false); - elapsedSeconds = 0; - fullList.remove(); - formattedList.remove(); - string_writeconfig("/opt/ibxd", "list_wifi_networks\n"); - QTimer::singleShot(0, this, SLOT(refreshWait())); + elapsedSeconds = 0; + fullList.remove(); + formattedList.remove(); + string_writeconfig("/opt/ibxd", "list_wifi_networks\n"); + QTimer::singleShot(0, this, SLOT(refreshWait())); + } } void wifiDialog::refreshWait() { @@ -198,6 +210,9 @@ void wifiDialog::refreshWait() { if(elapsedSeconds == 6) { emit showToast("Failed to get network list"); log("Failed to get network list", className); + ui->refreshBtn->setStyleSheet("background-color:white;"); + ui->refreshBtn->setEnabled(true); + scanInProgress = false; } else { elapsedSeconds = elapsedSeconds + 1; @@ -252,6 +267,14 @@ void wifiDialog::refreshNetworksList() { } } log("found valid networks: " + QString::number(pureNetworkList.count()), className); + if(pureNetworkList.count() == 0) { + log("No networks found, skipping", className); + showToastSlot("No networks found"); + ui->refreshBtn->setEnabled(true); + ui->refreshBtn->setStyleSheet("background-color:white;"); + scanInProgress = false; + return void(); + } QFile currentWifiNameFile = QFile("/external_root/run/current_wifi_name"); currentWifiNameFile.remove(); string_writeconfig("/opt/ibxd", "get_current_wifi_name\n"); @@ -269,22 +292,29 @@ void wifiDialog::refreshNetworksList() { log("Found current network in vector", className); vectorNetworkLocation = countVec; currentNetwork = wifiNetwork.name; + log("Test", className); network* connectedNetwork = new network; connectedNetwork->mainData = wifiNetwork; - // to be really sure that the the info is put there + log("Test", className); + // To be really sure that the the info is put there connectedNetwork->currentlyConnectedNetwork = currentNetwork; + log("Test", className); connectedNetworkDataParent = wifiNetwork; - wifiLoggerDialog->connectedNetworkData = connectedNetworkDataParent; + connectedNetworkDataParentSetted = true; + log("Test", className); - // this doesnt work so a layout is needed + // This doesnt work so a layout is needed // ui->scrollArea->addScrollBarWidget(connectedNetwork, Qt::AlignTop); connectedNetwork->applyVariables(); + log("Test", className); connect(this, &wifiDialog::killNetworkWidgets, connectedNetwork, &network::closeWrapper); connect(connectedNetwork, &network::showToastSignal, this, &wifiDialog::showToastSlot); connect(connectedNetwork, &network::refreshScreenSignal, this, &wifiDialog::refreshScreenSlot); ui->scrollBarLayout->addWidget(connectedNetwork, Qt::AlignTop); } - countVec = countVec + 1; + else { + countVec = countVec + 1; + } } if(vectorNetworkLocation != 9999) { log("pureNetworkList size is: " + QString::number(pureNetworkList.count()) + " And i want to remove at: " + QString::number(vectorNetworkLocation), className); @@ -312,7 +342,7 @@ void wifiDialog::refreshNetworksList() { counter = counter + 1; } } - // this happens if its the smallest value, so insert it at the end + // This happens if its the smallest value, so insert it at the end if(stopIterating == false) { sortedPureNetworkList.append(wifiNetwork); } @@ -338,19 +368,27 @@ void wifiDialog::refreshNetworksList() { scannedAtLeastOnce = true; ui->refreshBtn->setEnabled(true); ui->refreshBtn->setStyleSheet("background-color:white;"); + scanInProgress = false; } void wifiDialog::on_Wificheckbox_stateChanged(int arg1) { + connectedNetworkDataParentSetted = false; log("wifi dialog clicked: " + QString::number(arg1), className); if(wifiButtonEnabled == true) { if(arg1 == 2) { log("turning wifi on", className); + // the watcher will scan wifi + forceRefresh = true; QTimer::singleShot(0, this, SLOT(turnOnWifi())); + ui->stopBtn->setStyleSheet("background-color:white;"); + ui->stopBtn->setEnabled(true); } else { log("turning wifi off", className); QTimer::singleShot(0, this, SLOT(turnOffWifi())); + ui->stopBtn->setStyleSheet("background-color:grey;"); + ui->stopBtn->setEnabled(false); } emit killNetworkWidgets(); } @@ -375,10 +413,13 @@ void wifiDialog::on_logBtn_clicked() log("Scanning at least once is needed"); emit showToast("Scan at least once"); } else { - wifiLoggerDialog->connectedNetworkData = connectedNetworkDataParent; + wifilogger* wifiLoggerDialog = new wifilogger; + if(connectedNetworkDataParentSetted == true) { + wifiLoggerDialog->connectedNetworkData = connectedNetworkDataParent; + wifiLoggerDialog->isThereData = true; + } wifiLoggerDialog->exec(); } - } void wifiDialog::showToastSlot(QString message) { @@ -391,14 +432,14 @@ void wifiDialog::refreshScreenSlot() { /* Some documentation used by the watcher -connection_manager.sh - manages all things, launches other processes -connect_to_network.sh - all in one connection manager. manages everything, used by ipd, should be used for recconections after sleeping / booting +connection_manager.sh - Manages all things, launches other processes +connect_to_network.sh - All in one connection manager. manages everything, used by ipd, should be used for recconections after sleeping / booting get_dhcp.sh - Gets dhcp addresses prepare_changing_wifi.sh - Kills everything, prepares to changing network -smarter_time_sync.sh - synces time -toggle.sh - turns on / off -list_networks.bin - well lists networks -the watcher first watches at processes that could kill other ones +smarter_time_sync.sh - Synces time +toggle.sh - Turns on / off +list_networks.bin - Well lists networks +theWatcher() first watches at processes that could kill other ones */ void wifiDialog::theWatcher() { @@ -407,12 +448,14 @@ void wifiDialog::theWatcher() { bool changing = checkProcessName("prepare_changing_wifi.sh"); if(killing == true) { setStatusText("Changing wifi state"); + log("toggle.sh is active", className); QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); return void(); } if(changing == true) { setStatusText("Disconnecting from a network or cleaning"); + log("prepare_changing_wifi.sh is active", className); forceRefresh = true; QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); return void(); @@ -456,7 +499,7 @@ void wifiDialog::theWatcher() { return void(); } - bool connecting = checkProcessName("connect_to_network.sh"); + bool connecting = checkProcessName("connection_manager.sh"); if(connecting == true) { forceRefresh = true; setStatusText("Connecting to wifi..."); @@ -464,11 +507,21 @@ void wifiDialog::theWatcher() { return void(); } - setStatusText("Idling"); + if(ui->statusLabel->text() != "Idling") { + setStatusText("Idling"); + } + if(forceRefresh == true) { forceRefresh = false; + refreshFromWatcher = true; ui->refreshBtn->click(); } + + if(unlockCheckbox == true) { + ui->Wificheckbox->setEnabled(true); + unlockCheckbox = false; + } + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); } @@ -478,6 +531,27 @@ void wifiDialog::setStatusText(QString message) { void wifiDialog::on_stopBtn_clicked() { + connectedNetworkDataParentSetted = false; + ui->Wificheckbox->setEnabled(false); + unlockCheckbox = true; + + // To inform the wifi icon GUI to don't show the connected / failed to connect message + string_writeconfig(".config/17-wifi_connection_information/stopped", "true"); + // Maybe limit this, idk string_writeconfig("/opt/ibxd", "stop_wifi_operations\n"); + + setDefaultWorkDir(); + QFile(".config/17-wifi_connection_information/essid").remove(); + QFile(".config/17-wifi_connection_information/passphrase").remove(); + + // This variable just avoids showing the toast so i can use it here too... + refreshFromWatcher = true; + ui->refreshBtn->click(); +} + +void wifiDialog::on_returnBtn_clicked() +{ + this->deleteLater(); + this->close(); } diff --git a/src/widgets/dialogs/wifi/wifidialog.h b/src/widgets/dialogs/wifi/wifidialog.h index 4d21f99..8c93bd3 100644 --- a/src/widgets/dialogs/wifi/wifidialog.h +++ b/src/widgets/dialogs/wifi/wifidialog.h @@ -20,15 +20,15 @@ public: explicit wifiDialog(QWidget *parent = nullptr); ~wifiDialog(); global::wifi::wifiNetworkData connectedNetworkDataParent; - wifilogger* wifiLoggerDialog = new wifilogger; - + // well dont touch this until there is something, *** Error in `/tmp/exec': double free or corruption (fasttop): 0x025ed170 *** + bool connectedNetworkDataParentSetted = false; private: Ui::wifiDialog *ui; bool wifiButtonEnabled = false; bool scannedAtLeastOnce = false; - // variables for refreshWait() and network refresh in general + // Variables for refreshWait() and network refresh in general int elapsedSeconds = 0; QFile fullList = QFile("/external_root/run/wifi_list_full"); QFile formattedList = QFile("/external_root/run/wifi_list_format"); @@ -36,6 +36,9 @@ private: // Used by watcher bool forceRefresh = false; int relaunchMs = 300; + bool refreshFromWatcher = false; + bool unlockCheckbox = false; + bool scanInProgress = false; public slots: void launchRefresh(); @@ -63,6 +66,7 @@ private slots: void refreshWait(); void setStatusText(QString message); void on_stopBtn_clicked(); + void on_returnBtn_clicked(); }; #endif // WIFIDIALOG_H diff --git a/src/widgets/dialogs/wifi/wifidialog.ui b/src/widgets/dialogs/wifi/wifidialog.ui index f25e754..6fdeb0f 100644 --- a/src/widgets/dialogs/wifi/wifidialog.ui +++ b/src/widgets/dialogs/wifi/wifidialog.ui @@ -47,6 +47,22 @@ + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + @@ -60,6 +76,22 @@ + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + diff --git a/src/widgets/dialogs/wifi/wifilogger.cpp b/src/widgets/dialogs/wifi/wifilogger.cpp index 9ce0b89..8c6cd13 100644 --- a/src/widgets/dialogs/wifi/wifilogger.cpp +++ b/src/widgets/dialogs/wifi/wifilogger.cpp @@ -18,6 +18,7 @@ wifilogger::wifilogger(QWidget *parent) : this->setModal(true); + log("Entered wifilogger", className); setWifiInfoPage(); ui->refreshBtn->setProperty("type", "borderless"); @@ -91,14 +92,25 @@ void wifilogger::changePage() { } void wifilogger::getWifiInformations() { + log("getting wifi informations", className); QFile wifiInformationsPath = QFile("/external_root/run/wifi_informations"); - wifiInformationsPath.remove(); + if(waitingForFile == false) { + wifiInformationsPath.remove(); - string_writeconfig("/opt/ibxd", "get_wifi_informations\n"); - while(wifiInformationsPath.exists() == false) { - sleep(1); + log("Launching get_wifi_informations ibxd call", className); + string_writeconfig("/opt/ibxd", "get_wifi_informations\n"); + waitingForFile = true; } + if(waitingForFile == true) { + if(wifiInformationsPath.exists() == false) { + QTimer::singleShot(1000, this, SLOT(getWifiInformations())); + return void(); + } + } + + waitingForFile = false; + log("Setting variables", className); QString wifiInfo = readFile(wifiInformationsPath.fileName()); QStringList wifiInfoList = wifiInfo.split("\n"); int counter = 0; @@ -118,7 +130,7 @@ void wifilogger::getWifiInformations() { counter = counter + 1; } - if(connectedNetworkData.mac.isEmpty() == false) { + if(isThereData == true) { ui->encryptionLabel->setText(QVariant(connectedNetworkData.encryption).toString()); ui->signalLabel->setText(QString::number(connectedNetworkData.signal) + "%"); @@ -138,6 +150,7 @@ void wifilogger::getWifiInformations() { void wifilogger::on_returnBtn_clicked() { + log("Exiting wifilogger", className); this->deleteLater(); this->close(); } @@ -155,7 +168,9 @@ void wifilogger::updateLogs() { void wifilogger::on_refreshBtn_clicked() { if(currentPage == 0) { - setWifiInfoPage(); + if(waitingForFile == false) { + setWifiInfoPage(); + } } else { updateLogs(); diff --git a/src/widgets/dialogs/wifi/wifilogger.h b/src/widgets/dialogs/wifi/wifilogger.h index 36c51ff..3781656 100644 --- a/src/widgets/dialogs/wifi/wifilogger.h +++ b/src/widgets/dialogs/wifi/wifilogger.h @@ -17,6 +17,8 @@ public: explicit wifilogger(QWidget *parent = nullptr); ~wifilogger(); global::wifi::wifiNetworkData connectedNetworkData; + // to the above value + bool isThereData = false; private: Ui::wifilogger *ui; @@ -28,6 +30,7 @@ private: int currentPage = 0; QFile fancyLogs = QFile("/external_root/run/wifi_stats"); QFile allLogs = QFile("/external_root/run/wifi_logs"); + bool waitingForFile = false; private slots: void setWifiInfoPage(); diff --git a/src/widgets/dialogs/wifi/wifilogger.ui b/src/widgets/dialogs/wifi/wifilogger.ui index fd99ec5..6424d22 100644 --- a/src/widgets/dialogs/wifi/wifilogger.ui +++ b/src/widgets/dialogs/wifi/wifilogger.ui @@ -20,7 +20,7 @@ 0 - 2 + 3 @@ -312,14 +312,22 @@ - + + + Qt::NoTextInteraction + + - + + + Qt::NoTextInteraction + + From 6e9e5176c59802f1a7d9ddd3c23d5051136cf043 Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Sat, 20 Aug 2022 21:21:50 +0200 Subject: [PATCH 09/19] some fixes and checking wifi password --- src/widgets/dialogs/wifi/wifidialog.cpp | 96 ++++++++++++++++++------- src/widgets/dialogs/wifi/wifidialog.h | 3 + 2 files changed, 73 insertions(+), 26 deletions(-) diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 54fa778..18f99ef 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -203,6 +203,9 @@ void wifiDialog::launchRefresh() { string_writeconfig("/opt/ibxd", "list_wifi_networks\n"); QTimer::singleShot(0, this, SLOT(refreshWait())); } + else { + log("Scan is already in progress", className); + } } void wifiDialog::refreshWait() { @@ -374,28 +377,40 @@ void wifiDialog::refreshNetworksList() { void wifiDialog::on_Wificheckbox_stateChanged(int arg1) { - connectedNetworkDataParentSetted = false; - log("wifi dialog clicked: " + QString::number(arg1), className); - if(wifiButtonEnabled == true) { - if(arg1 == 2) { - log("turning wifi on", className); - // the watcher will scan wifi - forceRefresh = true; - QTimer::singleShot(0, this, SLOT(turnOnWifi())); - ui->stopBtn->setStyleSheet("background-color:white;"); - ui->stopBtn->setEnabled(true); - } else { - log("turning wifi off", className); - QTimer::singleShot(0, this, SLOT(turnOffWifi())); - ui->stopBtn->setStyleSheet("background-color:grey;"); - ui->stopBtn->setEnabled(false); + if(ignoreCheckboxCall == false) { + connectedNetworkDataParentSetted = false; + log("wifi dialog clicked: " + QString::number(arg1), className); + if(wifiButtonEnabled == true) { + if(arg1 == 2) { + log("turning wifi on", className); + // the watcher will scan wifi + forceRefresh = true; + QTimer::singleShot(0, this, SLOT(turnOnWifi())); + ui->stopBtn->setStyleSheet("background-color:white;"); + ui->stopBtn->setEnabled(true); + } else { + log("turning wifi off", className); + QTimer::singleShot(0, this, SLOT(turnOffWifi())); + ui->stopBtn->setStyleSheet("background-color:grey;"); + ui->stopBtn->setEnabled(false); + } + emit killNetworkWidgets(); + } + if(wifiButtonEnabled == false){ + wifiButtonEnabled = true; + } + } + else { + ignoreCheckboxCall = true; + if(checkWifiState() != global::wifi::WifiState::Disabled) { + emit killNetworkWidgets(); + forceRefresh = true; + } + else { + emit killNetworkWidgets(); } - emit killNetworkWidgets(); } - if(wifiButtonEnabled == false){ - wifiButtonEnabled = true; - } } void wifiDialog::turnOnWifi() { @@ -439,6 +454,7 @@ prepare_changing_wifi.sh - Kills everything, prepares to changing network smarter_time_sync.sh - Synces time toggle.sh - Turns on / off list_networks.bin - Well lists networks +check_wifi_password.sh - Checks wifi password theWatcher() first watches at processes that could kill other ones */ @@ -449,6 +465,7 @@ void wifiDialog::theWatcher() { if(killing == true) { setStatusText("Changing wifi state"); log("toggle.sh is active", className); + isToggleRunning = true; QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); return void(); } @@ -483,6 +500,23 @@ void wifiDialog::theWatcher() { return void(); } + bool dhcp = checkProcessName("get_dhcp.sh"); + if(dhcp == true) { + forceRefresh = true; + setStatusText("Getting IP address"); + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + return void(); + } + + + bool passwordCheck = checkProcessName("check_wifi_password.sh"); + if(passwordCheck == true) { + forceRefresh = true; + setStatusText("Checking wi-fi password"); + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + return void(); + } + bool time = checkProcessName("smarter_time_sync.sh"); if(time == true) { forceRefresh = true; @@ -491,13 +525,6 @@ void wifiDialog::theWatcher() { return void(); } - bool dhcp = checkProcessName("get_dhcp.sh"); - if(dhcp == true) { - forceRefresh = true; - setStatusText("Getting IP address"); - QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); - return void(); - } bool connecting = checkProcessName("connection_manager.sh"); if(connecting == true) { @@ -522,6 +549,23 @@ void wifiDialog::theWatcher() { unlockCheckbox = false; } + if(isToggleRunning == true) { + isToggleRunning = false; + // To make sure the checkbox is in the right state + if(checkWifiState() == global::wifi::WifiState::Disabled) { + if(ui->Wificheckbox->isChecked() == true) { + ignoreCheckboxCall = true; + ui->Wificheckbox->setChecked(false); + } + } + else { + if(ui->Wificheckbox->isChecked() == false) { + ignoreCheckboxCall = true; + ui->Wificheckbox->setChecked(true); + } + } + } + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); } diff --git a/src/widgets/dialogs/wifi/wifidialog.h b/src/widgets/dialogs/wifi/wifidialog.h index 8c93bd3..459e052 100644 --- a/src/widgets/dialogs/wifi/wifidialog.h +++ b/src/widgets/dialogs/wifi/wifidialog.h @@ -40,6 +40,9 @@ private: bool unlockCheckbox = false; bool scanInProgress = false; + bool isToggleRunning = false; + bool ignoreCheckboxCall = false; + public slots: void launchRefresh(); void refreshNetworksList(); From 14a9f9081723aa9573f889abfd201d2690cc84da Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Sun, 21 Aug 2022 19:38:31 +0200 Subject: [PATCH 10/19] fixes fixes fixes --- src/eink.qrc | 11 +- src/homeWidget/mainwindow.cpp | 23 ++- src/resources/lock-fill.png | Bin 315 -> 0 bytes src/resources/lock-unlock-fill.png | Bin 291 -> 0 bytes src/resources/lock.png | Bin 0 -> 6413 bytes src/resources/public.png | Bin 0 -> 11832 bytes src/resources/refresh.png | Bin 13021 -> 8452 bytes src/resources/wifi-0.png | Bin 0 -> 6218 bytes src/resources/wifi-100.png | Bin 0 -> 5228 bytes src/resources/wifi-25.png | Bin 0 -> 6697 bytes src/resources/wifi-50.png | Bin 0 -> 6962 bytes src/resources/wifi-75.png | Bin 0 -> 7529 bytes src/resources/wifi-off.png | Bin 6498 -> 6487 bytes src/resources/wifi-standby.png | Bin 15784 -> 10108 bytes src/widgets/dialogs/wifi/connectiondialog.cpp | 63 +++--- src/widgets/dialogs/wifi/connectiondialog.h | 1 + src/widgets/dialogs/wifi/network.cpp | 10 +- src/widgets/dialogs/wifi/wifidialog.cpp | 181 ++++++------------ src/widgets/dialogs/wifi/wifidialog.h | 3 + src/widgets/dialogs/wifi/wifilogger.cpp | 6 + 20 files changed, 131 insertions(+), 167 deletions(-) delete mode 100644 src/resources/lock-fill.png delete mode 100644 src/resources/lock-unlock-fill.png create mode 100644 src/resources/lock.png create mode 100644 src/resources/public.png create mode 100644 src/resources/wifi-0.png create mode 100644 src/resources/wifi-100.png create mode 100644 src/resources/wifi-25.png create mode 100644 src/resources/wifi-50.png create mode 100644 src/resources/wifi-75.png diff --git a/src/eink.qrc b/src/eink.qrc index 618565f..79fe6e3 100644 --- a/src/eink.qrc +++ b/src/eink.qrc @@ -86,9 +86,16 @@ resources/view-highlights.png resources/stop.png resources/refresh.png - resources/lock-fill.png - resources/lock-unlock-fill.png resources/hide.png resources/show.png + resources/christie.jpg + resources/encryption-small.png + resources/lock.png + resources/public.png + resources/wifi-0.png + resources/wifi-100.png + resources/wifi-25.png + resources/wifi-50.png + resources/wifi-75.png diff --git a/src/homeWidget/mainwindow.cpp b/src/homeWidget/mainwindow.cpp index 0b5303f..a4ff543 100644 --- a/src/homeWidget/mainwindow.cpp +++ b/src/homeWidget/mainwindow.cpp @@ -756,7 +756,6 @@ void MainWindow::updateWifiIcon() { * Mode 0 (looping it) is handled in mainwindow() */ - global::wifi::WifiState currentWifiState = checkWifiState(); // Its executing only in Enabled mode, which is a mode between connected and disabled so don't worry about performance @@ -772,12 +771,14 @@ void MainWindow::updateWifiIcon() { } } + // Ms can make diffrence so: + currentWifiState = checkWifiState(); + if(lastWifiState != currentWifiState) { if(currentWifiState == global::wifi::WifiState::Disabled) { if(isConnecting == true) { - setDefaultWorkDir(); - if(checkconfig(".config/17-wifi_connection_information/stopped") == false) { - QString wifiName = readFile(".config/17-wifi_connection_information/essid").replace("\n", ""); + if(checkconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped") == false) { + QString wifiName = readFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid").replace("\n", ""); if(isReconecting == true) { showToast("Failed to reconnect to " + wifiName); isReconecting = false; @@ -786,11 +787,11 @@ void MainWindow::updateWifiIcon() { showToast("Failed to connect to " + wifiName); } isConnecting = false; - QFile(".config/17-wifi_connection_information/essid").remove(); - QFile(".config/17-wifi_connection_information/passphrase").remove(); + QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid").remove(); + QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/passphrase").remove(); } else { - QFile(".config/17-wifi_connection_information/stopped").remove(); + QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped").remove(); } } lastWifiState = global::wifi::WifiState::Disabled; @@ -805,7 +806,7 @@ void MainWindow::updateWifiIcon() { if(currentWifiState == global::wifi::WifiState::Configured) { if(isConnecting == true) { setDefaultWorkDir(); - QString wifiName = readFile(".config/17-wifi_connection_information/essid").replace("\n", ""); + QString wifiName = readFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid").replace("\n", ""); if(isReconecting == true) { showToast("Reconnected successfully to " + wifiName); isReconecting = false; @@ -814,12 +815,10 @@ void MainWindow::updateWifiIcon() { showToast("Connected successfully to " + wifiName); } isConnecting = false; - QFile(".config/17-wifi_connection_information/essid").remove(); - QFile(".config/17-wifi_connection_information/passphrase").remove(); - QFile(".config/17-wifi_connection_information/stopped").remove(); + QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped").remove(); } lastWifiState = global::wifi::WifiState::Configured; - ui->wifiBtn->setIcon(QIcon(":/resources/wifi-connected.png")); + ui->wifiBtn->setIcon(QIcon("://resources/wifi-100.png")); ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); } } diff --git a/src/resources/lock-fill.png b/src/resources/lock-fill.png deleted file mode 100644 index b6de0730d08f35ff196e58c6799dfdb4491de5a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 315 zcmV-B0mS}^P)Px#^+`lQR7gwhl;I5lK@f$%s{kD+feO%p4nzl3fC}h9bf5!NKnXga1M*~7+_|}3 z&LtA&-zKx~d-HB?6DqExVtrx&bzlJWftE9L0M@_?I2V}=0lL5vXc{6%U^VC;4;0k@uF&XI%FJAxv N002ovPDHLkV1k~ye`x>! diff --git a/src/resources/lock-unlock-fill.png b/src/resources/lock-unlock-fill.png deleted file mode 100644 index 8795cdfd48f7ad078fbb19d6ba9d61d58f269391..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 291 zcmV+;0o?wHP)Px#-AP12R7gwhmC+T!Pz;8@Zo&pOzyxf72`~vZU;`sCi4|O~lTl3O~ zCi(vU$w>=3j-uoK`~nyNGhhjfN`lV70l0V~BftjO1z))Wj#iEb*aK@VJZY1pb`DHR z@3(;De}x4QTW*@|DHP=k;0_G+S%Fx9R4B^DdoM(}%%gS|7C@56z%&|Sw1pPnp@q>B zME%V*?F^8t36(hs(nG9$#is>Hc^g2bZx0ABM2)**Lt4ytnYf0ZLG~O z>lD@j05Ik!j-3HO1bGwzYsHY}d&FA-0I1)*j~=x#KYDaq(1k!xZ$AtWI{ItoexoUK@?JV5mRDrqV#xR1dYLHW^oX2^MAQ1ih79kC+jGe+WxMx0|NPuT z%;k^y^vTEVfwv{4B@GYw-M8gFcR%~+&(;fyPww57J+;B?C%dAU?H?XLi%faqSpIn2 zXhHI*oMYZi%(V@9bLb9uMPic zTU`Q&u^e48$dUn(7b4fC)1#5Fh@CxYb_@tt|L!mzWFiuYpc4)uNCf*=|4~PF--|7v!PbQimopQezddhH$<|W$o$Pu3i}mT9OrH#&Ehn_nqlz0ACX<N^mq3`_+@F}P}efDj*K&Zii>Nd++Vs}Aq6nbwQ z$a%$oVlL!hQaF7Y6Jb_7A>^ey(yjn#gVF`DiwvJ+)#ag~a_We!k$SEQiU6W!FaVyZ<#EId&UqY&?VV`U^v$uCc4o;l^Zl6y;upB~ zBp^t_>;riBNUUfwrHe1tJ9i)tv8g{Yh!802oE~jCdDwm@|8Ri}I z^da7pN1{z=qvnr+L)SQo?9IwM$=;EEq50--=r@PbD5`>kkACmljgtJ54kuBRa%;qL z?O0Ux(gxOSSc@8@wm1_saKIA~{!`0c?EAcyalBwhPbo=i)!ueo zZoO=^Z^*83@GOHo!7&a4TwcbS8SD}oeN4KEE3 z(;@%6Jc@uAi-fmf*%ycX5;@}|n+8B0LWp2`37 z+$<+CSN2h4YH7oPyA6eRNI-4Udt)Bjx_tUBNo{-@PTt5C+Ez*tNmKSNTImVGLao~k zo+STwv*$nVxpqmC;)3*Xmr1=fBSI0XV`!IuP0`t@4`ZjQ))Bc|?5K(h%_|UF!m;Yb zk`J#aJuNvDGr0*2pq=d86c#S6^swELE~TD%*8ce`gPX;OI~laEhs5~XnOeHyTF!yW z+|3J0{vrbh>vX2QmgB3Lr*4f02pu$9x5$R~sgN;qc^j19YIsN7Qu?5`G3eFrZS7wj z(KPqz-iSi+cvAU7T6Y&dH|^pZ=UiPe5x+llQ@@+US%uc{ul2Q1e9iR3R;u}6_z{Dm ztlOE(Ftm$4K69gWVTG)WUpz0<#98E~$0bBR>a%Q(-!ic|s;CbP(-*ZmAJi`w_gQuh z9gmVDYEV%%Rfo2Y9bV+Ze8&TNzLW#U4;Huv1}POa!_HEilJ@Hr>`g{z=$ zPTL#?HRwIo!!8r0SC`8~Lplh%1tN9SHH-_kzRx zTO=z$PM@Sg|2odQs&np~?pby5igjX}FP%#LLSEXzAw+1%cSjhQ8jwl65KRAYThKn^ zI_B|{awBvMWwz~GTynIx1oy(GUBuJ^W<)?zly_)R4z^wq%Dw(&e(~I1R8F_~_0PeL z)9tQXeIbq1b5qL+VW8bJt(D8{^QiQgFeLrrG1JNpV4|>@Ua23!5{b2v%f~i3?37RF z`crzmSpkfburfoDoT+VZE;zU`I=xWD_BtY(RgV-6CLyPn4;Sy;oV4lunodB&N<-5| zmzN_#LK$IL>ZC&3&d3=TPKDB1fK6z-PE_v02Xim!?G#kg@6zAnt5xdfF#fa%0 zi(e_5K6f_`GxOLP<3fT@kQn(&r9Y3XH`8)xd{r(;thVj!jf49fFM*~V%nGJw=i;on z|7ci@g~@S1h9v^(l}gS=j|EqJ zScCKjJ;3SZ9EA&oP!3RRDP4HoJ=a0gYi5J~Q$a5L;rJ|O&8U})OFn@?5txKBGS&jW zr;9j^hjDdG2R(A~ygRRttqrevy&cfT_|S?I?~RY*C!oSkWLH3k%GA%K1`k?D94Ae( zS$JW!VAnEAj+h!r;9d3^VrRk~uir}{6)Z6HNQ=lJvg!9hwl0O6eRjoAoVcaHIp6)8 zxZLn|coXD-$Znr4X#4;j3M5R((7wGlAlDH?nR&GS&+cIsu?a< z8=L4U8O(`n*RR(v9*ZL&HMEso%HC+P9m&~u3IXwhW_v(D?;2RcK3DApo4bX)_cKN% z9?9cEcIfL-siqx~&Mi)lK}|?n$2}7i5#?taTg!CY19VPZuIsc2*^2MCi(sUV zDl5pRoP??@P&D)MifM;sn?1KtH!@UjEunPUne6kV^`K<@#4Zqo{TbwRZLk2N1bzEH zP?l<>SS}Q$?QeT~GP_xxyk~Y)nViiv*@X;0>xK-sTphlg1&A+(-6YWDhXZyJ!2XT8 z#WrC1BGm%W&W4>4K@ooqvk?I(6F@L_QbUnFAY==yMKbUIX^@-hHe|@(Y5oiA|7pnI zb@>my|74bo%;X<^We_zReL!!sW0uycLdv11!Wuz&^&SmHTWD z_$J)%xl!0U@PyeIb)GlCe(7)msUE~*>SZJL%T~Mv_ISsVFgBi^@5pFiLi#mP7kEyv ztA%v0Ck9ydKV>h&-LNsNjPojM`WWvNP;P9?sASgZd&=qbd5f+EO*xMm1Wi+l3$_%Q z@}B$gX6~b+uq`BxpULNJL}oI^U1;g_|@ zRqb?nd4chm`FGW^PyLGOZb+bmRMpG2o@NB1;&NqhX1Gn>Y6wJ5T}@OBuXv3hztb-w zWAqAB5*av@DfCbXpgL)N#+gZ=5Tw=L8Hu)^yfkKK<}=sN8gax>pmb89;7fR?>{9t> zEyL$u6#T_eAZJj(u7xK~em96Oj|vOefJQ_EGx!Ehxmq=X-zv#-BieSh3e z$yIBi)|WlS$s_8fp~F~o&`JDw`Rb8#IF=rjvVXW-x622;7SL>5(_aLHpL5}v{ZP%& z@ET(!&J%g2B;@drdqD~55+)MdmXr6B0Z19GgQK(D6Y}>_79@*!%ourqzV+so$YDT!rEe~wGx*8^L222IfhS(m zUK#6AwyzqyecGi+>edv~0fRyTl~0zt2K?k~kaIjUBvrO_`&vN!b_9c1*cDVD>qigC zMv~x0UVAq2iOXFyqW;#IiuOTbip{-6napy3;$lGAg@}Kt5xVVN)vBb*mfhfFt!iDZ zf^}Zg2I(7+laTyy@U(=^ko6Bh9WL1>t4C%|*N6pekbhbP!S1uQ^e?-G;=3;?AaL5f z;t^zvdr-)PwbN`acktW)Qf9;?yu&WyqxY;Xg{j%EmzYTAwSWFd$c4SsE* z`nfR<|CI2TLoG1-m~Abq|X9mh7()PHs|8qdw zbg|_)8QmMpd2WVVRMSOj%e>)v`tsypqZ=#8f2Dq~FxS4{4v#;Sx13+sNw30Gj5CCO z?;9Hf=e7aRTNxIXIBHT1R`h%UlDvPPjiLUP7XBx0h9unol0g0&Li*o%{@2NlhLzch zfHoY8xZq4d1GRCVRYLGyVHbiHP5#8)`OgRcU4Wp;`auCY|EY1iXjQ{`7a`I&iwHa8 z-kp>OI_+~1BWsml=vhesogwp80?~mKD%zm+>C5n#Y!iEsBCxK?K7)M43PnEuU9lLG zYRYoP1(;tiEQjnjLf5fqpKWi7cBZs8h8PfX^4H01O|x0S085(QU))4fQzz4My2!Zl}=Of z>rlkgQ*NBqOJ zB_P)`V`n9tQt3~?ZrO!5oM&(2 zUuzyxx&8GZG}eKi!>uD8c5yVSbJx`B1pBzu#C~yBksxwRim+{xQjI_LuoEZk1!`i= za23?8B|kMik1ZF-VAAGE$FL$>9@s(&6f-+z8)@QY<8IoY3pSaJ2N3=)O7Wn?!?RZ{ z$(jOdo-RBDb*UvGq+kEem~3+qlw`kXKcpr}yW)b+cZz*DR`zKR+@EC%i0y*f#5(b? yf-9Glve5+h{x>Si6exuvnT=e9{^vjY9-%mEpMIBYPwK>~adT7aW93JPm;Vo5WyWU! literal 0 HcmV?d00001 diff --git a/src/resources/public.png b/src/resources/public.png new file mode 100644 index 0000000000000000000000000000000000000000..76f1ccc555b22e39e38a26493eb76267fcfad197 GIT binary patch literal 11832 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 literal 0 HcmV?d00001 diff --git a/src/resources/refresh.png b/src/resources/refresh.png index 6f07016a5014a83d051d467cd5b30c01ff8f93c7..6b34e09251b66b0840b66aecc46b0161b5d0b360 100644 GIT binary patch literal 8452 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 R!b6*wEiPJ{mY>JO{XZ*|f4Tqw literal 13021 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 rQk^^@VK6v1QvQzv9)qhm0 diff --git a/src/resources/wifi-0.png b/src/resources/wifi-0.png new file mode 100644 index 0000000000000000000000000000000000000000..a7589e1d1cf001fda9275415e5cb8622d785eea9 GIT binary patch literal 6218 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 Z^sG?FPIT@De{KeV3+JrQ7N7C@@vkVp`{4ip literal 0 HcmV?d00001 diff --git a/src/resources/wifi-100.png b/src/resources/wifi-100.png new file mode 100644 index 0000000000000000000000000000000000000000..bdc870f79375e482f4b996228534fa3fb3ddcf6a GIT binary patch literal 5228 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 literal 0 HcmV?d00001 diff --git a/src/resources/wifi-50.png b/src/resources/wifi-50.png new file mode 100644 index 0000000000000000000000000000000000000000..c39408a3c91991c5a8e1504ccccd474a4b40803b GIT binary patch literal 6962 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 literal 0 HcmV?d00001 diff --git a/src/resources/wifi-75.png b/src/resources/wifi-75.png new file mode 100644 index 0000000000000000000000000000000000000000..fdcd12391d5e7d883e7d9a05501da6b3ed1a7968 GIT binary patch literal 7529 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 R2x~)%{TY|jgj4=k{so0r?ezcv literal 0 HcmV?d00001 diff --git a/src/resources/wifi-off.png b/src/resources/wifi-off.png index a1612f041109eff4dc3a8667172fedff292414f0..f4324dbb73a745f65b18b33acda9f3110ba910ca 100644 GIT binary patch literal 6487 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 diff --git a/src/resources/wifi-standby.png b/src/resources/wifi-standby.png index de669fbe7e6c4bf9436c7f2b547d98a01a0d09cc..b280ac0bcf4fb0812d92ecad49e96310b8f4a927 100644 GIT binary patch literal 10108 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 Q?`6R)QJZ5`M?J6p51m--@c;k- literal 15784 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 NOi@FjLe4zoe*x;fBIE!7 diff --git a/src/widgets/dialogs/wifi/connectiondialog.cpp b/src/widgets/dialogs/wifi/connectiondialog.cpp index d6b2064..bbbd53f 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.cpp +++ b/src/widgets/dialogs/wifi/connectiondialog.cpp @@ -60,21 +60,20 @@ void connectiondialog::applyVariables() { passwordDatabase.flush(); passwordDatabase.close(); } - else { - QString password = searchDatabase(connectedNetworkData.name); - if(password.isEmpty() == false) { - log("found password: " + password, className); - ui->showPasswordBtn->setIcon(QIcon("://resources/show.png")); - showedPassword = false; - savedPassword = password; + QString password = searchDatabase(connectedNetworkData.name); + if(password.isEmpty() == false) { + log("found password: " + password, className); + ui->showPasswordBtn->setIcon(QIcon("://resources/show.png")); + showedPassword = false; + savedPassword = password; - ui->passwordTextEdit->setText("********"); - } - else { - log("No password found", className); - ui->passwordTextEdit->setText("No password was saved"); - ui->showPasswordBtn->hide(); - } + ui->passwordTextEdit->setText("********"); + } + else { + log("No password found", className); + ui->passwordTextEdit->setText("No password was saved"); + showedPassword = true; + ui->showPasswordBtn->hide(); } } } @@ -92,7 +91,12 @@ QString connectiondialog::searchDatabase(QString key) { QString searchedName = jsonMainObject.keys().first().toUtf8(); log("Found in database: " + searchedName, className); if(searchedName == key) { - return jsonMainObject.take(key).toString(); + QString returnedPassword = jsonMainObject.value(key).toString(); + log("Searched name " + searchedName + " matched " + key + " and the password is: " + returnedPassword, className); + return returnedPassword; + } + else { + log("Searched name " + searchedName + " Doesn't match " + key, className); } } @@ -215,9 +219,13 @@ void connectiondialog::on_passwordTextEdit_cursorPositionChanged(int oldpos, int ui->showPasswordBtn->show(); showedPassword = true; savedPassword = global::keyboard::keyboardText; + ui->showPasswordBtn->show(); } global::keyboard::keyboardText = ""; } + else { + log("Password is not saved so ignoring text edit call", className); + } } } else { @@ -256,9 +264,16 @@ void connectiondialog::on_connectBtn_clicked() finalPassword = "NONE"; } else { - finalPassword = savedPassword; - writeToDatabase(connectedNetworkData.name, savedPassword); + if(savedPassword.isEmpty() == false) { + finalPassword = savedPassword; + writeToDatabase(connectedNetworkData.name, savedPassword); + } + else { + showToastSlot("Provide a password first"); + return void(); + } } + passwordForReconnecting = finalPassword; ui->CancelBtn->setEnabled(false); if(checkWifiState() == global::wifi::WifiState::Configured) { @@ -266,12 +281,7 @@ void connectiondialog::on_connectBtn_clicked() } string_writeconfig("/run/wifi_network_essid", connectedNetworkData.name.toStdString()); string_writeconfig("/run/wifi_network_passphrase", finalPassword.toStdString()); - setDefaultWorkDir(); - // This will be deleited later in mainwindow icon updater if it failed - string_writeconfig(".config/17-wifi_connection_information/essid", connectedNetworkData.name.toStdString()); - string_writeconfig(".config/17-wifi_connection_information/passphrase", finalPassword.toStdString()); finalConnectWait(); - } void connectiondialog::finalConnectWait() { @@ -293,7 +303,12 @@ void connectiondialog::finalConnectWait() { } else { string_writeconfig("/opt/ibxd", "connect_to_wifi_network\n"); - ui->CancelBtn->setEnabled(true); + + // This will be deleted later in mainwindow icon updater if it failed. Its also deleted in stop wifi script + log("Writing to config dir with connection data", className); + string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid", connectedNetworkData.name.toStdString()); + string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/passphrase", passwordForReconnecting.toStdString()); + this->deleteLater(); this->close(); } @@ -302,7 +317,7 @@ void connectiondialog::finalConnectWait() { bool connectiondialog::checkIfWifiBussy() { if(checkProcessName("connect_to_network.sh") == true or checkProcessName("connection_manager.sh") == true or - checkProcessName("only_connect_to_network.sh") == true) { + checkProcessName("prepare_changing_wifi.sh") == true) { return true; } else { diff --git a/src/widgets/dialogs/wifi/connectiondialog.h b/src/widgets/dialogs/wifi/connectiondialog.h index 3d167b7..d0d9d46 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.h +++ b/src/widgets/dialogs/wifi/connectiondialog.h @@ -57,6 +57,7 @@ private: bool showedPassword; QString savedPassword; int waitTry = 0; + QString passwordForReconnecting; }; #endif // CONNECTIONDIALOG_H diff --git a/src/widgets/dialogs/wifi/network.cpp b/src/widgets/dialogs/wifi/network.cpp index bc5f017..35e310d 100644 --- a/src/widgets/dialogs/wifi/network.cpp +++ b/src/widgets/dialogs/wifi/network.cpp @@ -30,7 +30,11 @@ network::~network() void network::applyVariables() { log("Applying variables for network", className); - ui->signalStrengthLabel->setText(QString::number(mainData.signal) + "%"); + QString percent = "%"; + if(mainData.signal < 100) { + percent.append(" "); + } + ui->signalStrengthLabel->setText(QString::number(mainData.signal) + percent); // Limit name size, maybe device specific QString cuttedSingleData = mainData.name; @@ -42,10 +46,10 @@ void network::applyVariables() { ui->nameLabel->setText(cuttedSingleData); if(mainData.encryption == true) { - ui->encryptionIcon->setIcon(QIcon("://resources/lock-fill.png")); + ui->encryptionIcon->setIcon(QIcon("://resources/lock.png")); } else { - ui->encryptionIcon->setIcon(QIcon("://resources/lock-unlock-fill.png")); + ui->encryptionIcon->setIcon(QIcon("://resources/public.png")); } if(currentlyConnectedNetwork == mainData.name) { diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 18f99ef..5d2a0e8 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -70,7 +70,8 @@ wifiDialog::wifiDialog(QWidget *parent) : ui->stopBtn->setEnabled(false); } - QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + // To avoid confussion with reconnecting + QTimer::singleShot(2000, this, SLOT(theWatcher())); } wifiDialog::~wifiDialog() @@ -78,102 +79,6 @@ wifiDialog::~wifiDialog() delete ui; } -/* - - this->hide(); - global::keyboard::keyboardDialog = true; - global::keyboard::wifiPassphraseDialog = true; - global::keyboard::keyboardText = ""; - generalDialogWindow = new generalDialog(); - generalDialogWindow->setAttribute(Qt::WA_DeleteOnClose); - generalDialogWindow->wifiEssid = itemText; - connect(generalDialogWindow, SIGNAL(refreshScreen()), SLOT(refreshScreenNative())); - connect(generalDialogWindow, SIGNAL(updateWifiIcon(int)), SLOT(updateWifiIcon(int))); - connect(generalDialogWindow, SIGNAL(showToast(QString)), SLOT(showToastNative(QString))); - connect(generalDialogWindow, SIGNAL(closeIndefiniteToast()), SLOT(closeIndefiniteToastNative())); - connect(generalDialogWindow, SIGNAL(destroyed(QObject*)), SLOT(close())); - generalDialogWindow->show(); - -*/ - -/* - bool connectToNetwork(QString essid, QString passphrase) { - log("Connecting to network '" + essid + "'", "functions"); - std::string essid_str = essid.toStdString(); - std::string passphrase_str = passphrase.toStdString(); - string_writeconfig("/run/wifi_network_essid", essid_str); - string_writeconfig("/run/wifi_network_passphrase", passphrase_str); - string_writeconfig("/opt/ibxd", "connect_to_wifi_network\n"); - - int connectionSuccessful = 0; - - while(connectionSuccessful == 0) { - if(QFile::exists("/run/wifi_connected_successfully")) { - if(checkconfig("/run/wifi_connected_successfully") == true) { - QFile::remove("/run/wifi_connected_successfully"); - connectionSuccessful = 1; - global::network::isConnected = true; - setDefaultWorkDir(); - string_writeconfig(".config/17-wifi_connection_information/essid", essid_str); - string_writeconfig(".config/17-wifi_connection_information/passphrase", passphrase_str); - QString function = __func__; log(function + ": Connection successful", "functions"); - return true; - } - else { - QFile::remove("/run/wifi_connected_successfully"); - connectionSuccessful = 0; - global::network::isConnected = false; - QString function = __func__; log(function + ": Connection failed", "functions"); - return false; - } - } - else { - QThread::msleep(100); - } - } - } -*/ -/* - int testPing(bool blocking) { - QProcess *pingProcess = new QProcess(); - if(blocking == true) { - QString pingProg = "ping"; - QStringList pingArgs; - pingArgs << "-c" << "1" << "1.1.1.1"; - pingProcess->start(pingProg, pingArgs); - pingProcess->waitForFinished(); - int exitCode = pingProcess->exitCode(); - pingProcess->deleteLater(); - if(exitCode == 0) { - global::network::isConnected = true; - } - else { - global::network::isConnected = false; - } - return exitCode; - } - // For some reason, implementing a non-blocking version of this functions triggers a "terminate called without an active exception" error with a platform plugin compiled with a newer GCC 11 toolchain. The problem has been solved by transplanting this function into the related area which uses it. - pingProcess->deleteLater(); - } - bool getTestPingResults() { - // To be used when the testPing() function is used in non-blocking mode. - if(QFile::exists("/run/test_ping_status")) { - if(checkconfig("/run/test_ping_status") == true) { - global::network::isConnected = true; - return true; - } - else { - global::network::isConnected = false; - return false; - } - } - else { - global::network::isConnected = false; - return false; - } - } -*/ - void wifiDialog::on_refreshBtn_clicked() { log("Clicked refresh button", className); @@ -271,12 +176,27 @@ void wifiDialog::refreshNetworksList() { } log("found valid networks: " + QString::number(pureNetworkList.count()), className); if(pureNetworkList.count() == 0) { - log("No networks found, skipping", className); - showToastSlot("No networks found"); - ui->refreshBtn->setEnabled(true); - ui->refreshBtn->setStyleSheet("background-color:white;"); - scanInProgress = false; - return void(); + if(secondScanTry == false) { + secondScanTry = true; + if(checkWifiState() != global::wifi::WifiState::Disabled) { + scanInProgress = false; + QTimer::singleShot(0, this, SLOT(launchRefresh())); + log("No networks found. Trying one more time"); + return void(); + } + else { + return void(); + } + } + else { + secondScanTry = false; + log("No networks found, skipping", className); + showToastSlot("No networks found"); + ui->refreshBtn->setEnabled(true); + ui->refreshBtn->setStyleSheet("background-color:white;"); + scanInProgress = false; + return void(); + } } QFile currentWifiNameFile = QFile("/external_root/run/current_wifi_name"); currentWifiNameFile.remove(); @@ -295,21 +215,16 @@ void wifiDialog::refreshNetworksList() { log("Found current network in vector", className); vectorNetworkLocation = countVec; currentNetwork = wifiNetwork.name; - log("Test", className); network* connectedNetwork = new network; connectedNetwork->mainData = wifiNetwork; - log("Test", className); // To be really sure that the the info is put there connectedNetwork->currentlyConnectedNetwork = currentNetwork; - log("Test", className); connectedNetworkDataParent = wifiNetwork; connectedNetworkDataParentSetted = true; - log("Test", className); // This doesnt work so a layout is needed // ui->scrollArea->addScrollBarWidget(connectedNetwork, Qt::AlignTop); connectedNetwork->applyVariables(); - log("Test", className); connect(this, &wifiDialog::killNetworkWidgets, connectedNetwork, &network::closeWrapper); connect(connectedNetwork, &network::showToastSignal, this, &wifiDialog::showToastSlot); connect(connectedNetwork, &network::refreshScreenSignal, this, &wifiDialog::refreshScreenSlot); @@ -372,6 +287,7 @@ void wifiDialog::refreshNetworksList() { ui->refreshBtn->setEnabled(true); ui->refreshBtn->setStyleSheet("background-color:white;"); scanInProgress = false; + secondScanTry = false; } @@ -384,7 +300,6 @@ void wifiDialog::on_Wificheckbox_stateChanged(int arg1) if(arg1 == 2) { log("turning wifi on", className); // the watcher will scan wifi - forceRefresh = true; QTimer::singleShot(0, this, SLOT(turnOnWifi())); ui->stopBtn->setStyleSheet("background-color:white;"); ui->stopBtn->setEnabled(true); @@ -401,7 +316,7 @@ void wifiDialog::on_Wificheckbox_stateChanged(int arg1) } } else { - ignoreCheckboxCall = true; + ignoreCheckboxCall = false; if(checkWifiState() != global::wifi::WifiState::Disabled) { emit killNetworkWidgets(); forceRefresh = true; @@ -415,6 +330,8 @@ void wifiDialog::on_Wificheckbox_stateChanged(int arg1) void wifiDialog::turnOnWifi() { string_writeconfig("/opt/ibxd", "toggle_wifi_on\n"); + // No one will notice this freeze :> + waitToScan(); } void wifiDialog::turnOffWifi() { @@ -464,7 +381,7 @@ void wifiDialog::theWatcher() { bool changing = checkProcessName("prepare_changing_wifi.sh"); if(killing == true) { setStatusText("Changing wifi state"); - log("toggle.sh is active", className); + //log("toggle.sh is active", className); isToggleRunning = true; QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); return void(); @@ -473,7 +390,6 @@ void wifiDialog::theWatcher() { if(changing == true) { setStatusText("Disconnecting from a network or cleaning"); log("prepare_changing_wifi.sh is active", className); - forceRefresh = true; QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); return void(); } @@ -481,13 +397,13 @@ void wifiDialog::theWatcher() { bool recconection = checkProcessName("connect_to_network.sh"); if(recconection == true) { forceRefresh = true; - QFile recName = QFile(".config/17-wifi_connection_information/essid"); + QFile recName = QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid"); if(recName.exists() == true) { setStatusText("Recconecting after suspending to " + readFile(recName.fileName()).replace("\n", "")); } else { // Shouldn't be possible - setStatusText("Recconecting after sleep, but no network found?"); + setStatusText("Recconecting after sleep"); } QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); return void(); @@ -538,12 +454,6 @@ void wifiDialog::theWatcher() { setStatusText("Idling"); } - if(forceRefresh == true) { - forceRefresh = false; - refreshFromWatcher = true; - ui->refreshBtn->click(); - } - if(unlockCheckbox == true) { ui->Wificheckbox->setEnabled(true); unlockCheckbox = false; @@ -553,6 +463,8 @@ void wifiDialog::theWatcher() { isToggleRunning = false; // To make sure the checkbox is in the right state if(checkWifiState() == global::wifi::WifiState::Disabled) { + // In this state, ignore forceRefresh to avoid message + forceRefresh = false; if(ui->Wificheckbox->isChecked() == true) { ignoreCheckboxCall = true; ui->Wificheckbox->setChecked(false); @@ -566,6 +478,12 @@ void wifiDialog::theWatcher() { } } + if(forceRefresh == true) { + forceRefresh = false; + refreshFromWatcher = true; + QTimer::singleShot(1500, this, SLOT(waitToScan())); + } + QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); } @@ -575,23 +493,25 @@ void wifiDialog::setStatusText(QString message) { void wifiDialog::on_stopBtn_clicked() { + log("Stop button was clicked", className); connectedNetworkDataParentSetted = false; ui->Wificheckbox->setEnabled(false); unlockCheckbox = true; // To inform the wifi icon GUI to don't show the connected / failed to connect message - string_writeconfig(".config/17-wifi_connection_information/stopped", "true"); + string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped", "true"); // Maybe limit this, idk string_writeconfig("/opt/ibxd", "stop_wifi_operations\n"); - setDefaultWorkDir(); - QFile(".config/17-wifi_connection_information/essid").remove(); - QFile(".config/17-wifi_connection_information/passphrase").remove(); + QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid").remove(); + QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/passphrase").remove(); // This variable just avoids showing the toast so i can use it here too... - refreshFromWatcher = true; - ui->refreshBtn->click(); + // Actually refreshing from watcher is smarter so this isin't needed + //refreshFromWatcher = true; + //ui->refreshBtn->click(); + waitToScan(); } void wifiDialog::on_returnBtn_clicked() @@ -599,3 +519,12 @@ void wifiDialog::on_returnBtn_clicked() this->deleteLater(); this->close(); } + +void wifiDialog::waitToScan() { + if(checkWifiState() != global::wifi::WifiState::Disabled) { + ui->refreshBtn->click(); + } + else { + QTimer::singleShot(750, this, SLOT(waitToScan())); + } +} diff --git a/src/widgets/dialogs/wifi/wifidialog.h b/src/widgets/dialogs/wifi/wifidialog.h index 459e052..04b3c0e 100644 --- a/src/widgets/dialogs/wifi/wifidialog.h +++ b/src/widgets/dialogs/wifi/wifidialog.h @@ -43,6 +43,8 @@ private: bool isToggleRunning = false; bool ignoreCheckboxCall = false; + bool secondScanTry = false; + public slots: void launchRefresh(); void refreshNetworksList(); @@ -70,6 +72,7 @@ private slots: void setStatusText(QString message); void on_stopBtn_clicked(); void on_returnBtn_clicked(); + void waitToScan(); }; #endif // WIFIDIALOG_H diff --git a/src/widgets/dialogs/wifi/wifilogger.cpp b/src/widgets/dialogs/wifi/wifilogger.cpp index 8c6cd13..fb62aff 100644 --- a/src/widgets/dialogs/wifi/wifilogger.cpp +++ b/src/widgets/dialogs/wifi/wifilogger.cpp @@ -1,4 +1,5 @@ #include +#include #include "wifilogger.h" #include "ui_wifilogger.h" @@ -17,6 +18,11 @@ wifilogger::wifilogger(QWidget *parent) : stylesheetFile.close(); this->setModal(true); + // Scroll bar + // Needed for the nia. + ui->allLogsText->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 50px; }"); + ui->fancyLogsText->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 50px; }"); + log("Entered wifilogger", className); setWifiInfoPage(); From 94257927f3e32a2d14dbd01a95405ea50c3b4674 Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Sun, 21 Aug 2022 19:55:43 +0200 Subject: [PATCH 11/19] one line... --- src/widgets/dialogs/wifi/wifidialog.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 5d2a0e8..be9f2f2 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -306,6 +306,8 @@ void wifiDialog::on_Wificheckbox_stateChanged(int arg1) } else { log("turning wifi off", className); QTimer::singleShot(0, this, SLOT(turnOffWifi())); + // To inform the wifi icon GUI to don't show the connected / failed to connect message + string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped", "true"); ui->stopBtn->setStyleSheet("background-color:grey;"); ui->stopBtn->setEnabled(false); } From 5f9cff5a84ec18a62595eff515b92f5244ad65c5 Mon Sep 17 00:00:00 2001 From: Nicolas Mailloux Date: Mon, 22 Aug 2022 09:42:39 -0400 Subject: [PATCH 12/19] Review --- src/functions.h | 28 ++- src/homeWidget/mainwindow.cpp | 42 ++-- src/homeWidget/mainwindow.h | 4 +- src/main.cpp | 2 - src/widgets/dialogs/wifi/connectiondialog.cpp | 61 +++-- src/widgets/dialogs/wifi/connectiondialog.h | 13 +- src/widgets/dialogs/wifi/connectiondialog.ui | 2 +- src/widgets/dialogs/wifi/network.cpp | 39 ++-- src/widgets/dialogs/wifi/wifidialog.cpp | 209 ++++++++---------- src/widgets/dialogs/wifi/wifidialog.h | 18 +- src/widgets/dialogs/wifi/wifidialog.ui | 2 +- src/widgets/dialogs/wifi/wifilogger.cpp | 32 ++- src/widgets/dialogs/wifi/wifilogger.h | 10 +- 13 files changed, 210 insertions(+), 252 deletions(-) diff --git a/src/functions.h b/src/functions.h index 818507e..192cbcc 100644 --- a/src/functions.h +++ b/src/functions.h @@ -166,13 +166,12 @@ namespace global { inline QString bookPath; } namespace wifi { - // This is the correct way to do this. - enum class WifiState + enum class wifiState { - Configured, - Enabled, - Disabled, - Unknown, // to not confuse lastWifiState + configured, + enabled, + disabled, + unknown, // To not confuse lastWifiState }; inline bool isConnected; class wifiNetworkData { @@ -1069,36 +1068,35 @@ namespace { return 2; } } - global::wifi::WifiState checkWifiState() { + global::wifi::wifiState checkWifiState() { QProcess *wifiStateProcess = new QProcess(); - // Important to remember thats its in chroot... - // What can be run in the chroot, should be run here. ibxd is a bit a mess QString path = "/external_root/usr/local/bin/wifi/wifi_status.sh"; QStringList args; wifiStateProcess->start(path, args); wifiStateProcess->waitForFinished(); wifiStateProcess->deleteLater(); + QString currentWifiState; if(QFile("/run/wifi_status").exists() == true) { currentWifiState = readFile("/run/wifi_status"); } else { - log("/run/wifi_status doesnt exist"); + log("/run/wifi_status doesn't exist", "functions"); } if (currentWifiState.contains("configured") == true) { global::wifi::isConnected = true; - return global::wifi::WifiState::Configured; + return global::wifi::wifiState::configured; } else if (currentWifiState.contains("enabled") == true) { global::wifi::isConnected = false; - return global::wifi::WifiState::Enabled; + return global::wifi::wifiState::enabled; } else if (currentWifiState.contains("disabled") == true) { global::wifi::isConnected = false; - return global::wifi::WifiState::Disabled; + return global::wifi::wifiState::disabled; } else { global::wifi::isConnected = false; - log("Critical error, checkWifiState()", "functions.h"); - return global::wifi::WifiState::Unknown; + QString function = __func__; log(function + ": Critical error", "functions"); + return global::wifi::wifiState::unknown; } } int testPing() { diff --git a/src/homeWidget/mainwindow.cpp b/src/homeWidget/mainwindow.cpp index a4ff543..363055b 100644 --- a/src/homeWidget/mainwindow.cpp +++ b/src/homeWidget/mainwindow.cpp @@ -753,35 +753,35 @@ void MainWindow::setupSearchDialog() { void MainWindow::updateWifiIcon() { /* Usage: - * Mode 0 (looping it) is handled in mainwindow() + * Mode 0 (looping it) is handled in MainWindow */ - global::wifi::WifiState currentWifiState = checkWifiState(); + global::wifi::wifiState currentWifiState = checkWifiState(); - // Its executing only in Enabled mode, which is a mode between connected and disabled so don't worry about performance - if(isConnecting == false and isReconecting == false) { - if(currentWifiState == global::wifi::WifiState::Enabled) { + // It's executing only in enabled mode, which is a mode between connected and disabled, so don't worry about performance + if(isConnecting == false and isReconnecting == false) { + if(currentWifiState == global::wifi::wifiState::enabled) { if(checkProcessName("connection_manager.sh") == true) { isConnecting = true; } else if(checkProcessName("connect_to_network.sh") == true){ isConnecting = true; - isReconecting = true; + isReconnecting = true; } } } - // Ms can make diffrence so: + // ms can make a difference, so: currentWifiState = checkWifiState(); if(lastWifiState != currentWifiState) { - if(currentWifiState == global::wifi::WifiState::Disabled) { + if(currentWifiState == global::wifi::wifiState::disabled) { if(isConnecting == true) { if(checkconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped") == false) { QString wifiName = readFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid").replace("\n", ""); - if(isReconecting == true) { - showToast("Failed to reconnect to " + wifiName); - isReconecting = false; + if(isReconnecting == true) { + showToast("Failed to reconnnect to " + wifiName); + isReconnecting = false; } else { showToast("Failed to connect to " + wifiName); @@ -794,22 +794,22 @@ void MainWindow::updateWifiIcon() { QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped").remove(); } } - lastWifiState = global::wifi::WifiState::Disabled; + lastWifiState = global::wifi::wifiState::disabled; ui->wifiBtn->setIcon(QIcon(":/resources/wifi-off.png")); ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); } - if(currentWifiState == global::wifi::WifiState::Enabled) { - lastWifiState = global::wifi::WifiState::Enabled; + if(currentWifiState == global::wifi::wifiState::enabled) { + lastWifiState = global::wifi::wifiState::enabled; ui->wifiBtn->setIcon(QIcon(":/resources/wifi-standby.png")); ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); } - if(currentWifiState == global::wifi::WifiState::Configured) { + if(currentWifiState == global::wifi::wifiState::configured) { if(isConnecting == true) { setDefaultWorkDir(); QString wifiName = readFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid").replace("\n", ""); - if(isReconecting == true) { + if(isReconnecting == true) { showToast("Reconnected successfully to " + wifiName); - isReconecting = false; + isReconnecting = false; } else { showToast("Connected successfully to " + wifiName); @@ -817,13 +817,11 @@ void MainWindow::updateWifiIcon() { isConnecting = false; QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped").remove(); } - lastWifiState = global::wifi::WifiState::Configured; - ui->wifiBtn->setIcon(QIcon("://resources/wifi-100.png")); + lastWifiState = global::wifi::wifiState::configured; + ui->wifiBtn->setIcon(QIcon(":/resources/wifi-100.png")); ui->wifiBtn->setIconSize(QSize(wifiIconWidth, wifiIconHeight)); } } - - } void MainWindow::updateWifiAble() { @@ -849,7 +847,7 @@ void MainWindow::showToast(QString messageToDisplay) { connect(toastWindow, SIGNAL(closeIndefiniteToast()), SLOT(closeIndefiniteToast())); toastWindow->show(); - // I will soon manage the update thing in a more propper way somewhere else... ~ Szybet + // I will soon manage the update thing in a more proper way somewhere else... ~ Szybet if(messageToDisplay.contains("onnected successfully") == true) { // Give the toast some time to vanish away, then launch OTA updater QTimer::singleShot(5000, this, SLOT(launchOtaUpdater())); diff --git a/src/homeWidget/mainwindow.h b/src/homeWidget/mainwindow.h index 7ddf5ca..539dfdd 100644 --- a/src/homeWidget/mainwindow.h +++ b/src/homeWidget/mainwindow.h @@ -52,9 +52,9 @@ public: bool reboot_after_update = false; bool resetFullWindowException; - global::wifi::WifiState lastWifiState = global::wifi::WifiState::Unknown; + global::wifi::wifiState lastWifiState = global::wifi::wifiState::unknown; bool isConnecting = false; - bool isReconecting = false; + bool isReconnecting = false; int timerTime = 0; QString relative_path; diff --git a/src/main.cpp b/src/main.cpp index a924a69..4bfb82f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -41,8 +41,6 @@ int main(int argc, char *argv[]) global::logger::status = true; } } - // Szybet testing - global::logger::status = true; global::deviceID = readFile("/opt/inkbox_device"); log("Running on device " + global::deviceID, "main", true); diff --git a/src/widgets/dialogs/wifi/connectiondialog.cpp b/src/widgets/dialogs/wifi/connectiondialog.cpp index bbbd53f..2f127eb 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.cpp +++ b/src/widgets/dialogs/wifi/connectiondialog.cpp @@ -18,7 +18,7 @@ connectiondialog::connectiondialog(QWidget *parent) : this->setStyleSheet(stylesheetFile.readAll()); stylesheetFile.close(); - ui->CancelBtn->setStyleSheet("font-size: 9pt"); + ui->cancelBtn->setStyleSheet("font-size: 9pt"); ui->connectBtn->setStyleSheet("font-size: 9pt"); ui->showPasswordBtn->setStyleSheet("font-size: 9pt"); @@ -35,7 +35,7 @@ connectiondialog::~connectiondialog() } void connectiondialog::applyVariables() { - // Here for some devices it will be propably needed to limit the size. the nia is fine + // Here, for some devices it will be propably needed to limit the size ui->nameLabel->setText(connectedNetworkData.name); ui->macLabel->setText(connectedNetworkData.mac); ui->signalLabel->setText(QString::number(connectedNetworkData.signal) + "%"); @@ -62,8 +62,8 @@ void connectiondialog::applyVariables() { } QString password = searchDatabase(connectedNetworkData.name); if(password.isEmpty() == false) { - log("found password: " + password, className); - ui->showPasswordBtn->setIcon(QIcon("://resources/show.png")); + log("Found password: " + password, className); + ui->showPasswordBtn->setIcon(QIcon(":/resources/show.png")); showedPassword = false; savedPassword = password; @@ -89,16 +89,15 @@ QString connectiondialog::searchDatabase(QString key) { for(QJsonValueRef refJsonObject: jsonArray) { QJsonObject jsonMainObject = refJsonObject.toObject(); QString searchedName = jsonMainObject.keys().first().toUtf8(); - log("Found in database: " + searchedName, className); + log("Found in database: '" + searchedName + "'", className); if(searchedName == key) { QString returnedPassword = jsonMainObject.value(key).toString(); - log("Searched name " + searchedName + " matched " + key + " and the password is: " + returnedPassword, className); + log("Searched name '" + searchedName + "' matched '" + key + "' and the password is: '" + returnedPassword + "'", className); return returnedPassword; } else { - log("Searched name " + searchedName + " Doesn't match " + key, className); + log("Searched name '" + searchedName + "' doesn't match " + key + "'", className); } - } return ""; } @@ -122,7 +121,7 @@ void connectiondialog::writeToDatabase(QString name, QString password) { QJsonValue newValue; // https://stackoverflow.com/questions/26804660/how-to-initialize-qjsonobject-from-qstring - // I hoped this will be easier + // I hoped this would be easier QJsonObject newObject = QJsonDocument::fromJson(QString("{\"" + name + "\" : \"" + password + "\" }").toUtf8()).object(); jsonArray.append(newObject); @@ -154,7 +153,7 @@ void connectiondialog::removeFromDatabase(QString name) { for(QJsonValueRef refJsonObject: jsonArray) { QJsonObject jsonMainObject = refJsonObject.toObject(); QString searchedName = jsonMainObject.keys().first().toUtf8(); - log("Found in database: " + searchedName, className); + log("Found in database: '" + searchedName + "'", className); if(searchedName == name) { remove = true; } @@ -175,12 +174,12 @@ void connectiondialog::removeFromDatabase(QString name) { passwordDatabase.close(); } else { - log("ERROR: tryied to remove from database, but couldn't find key", className); + log("ERROR: tried to remove from database, but couldn't find key", className); } } } -void connectiondialog::on_CancelBtn_clicked() +void connectiondialog::on_cancelBtn_clicked() { this->deleteLater(); this->close(); @@ -193,7 +192,7 @@ void connectiondialog::on_passwordTextEdit_selectionChanged() void connectiondialog::on_passwordTextEdit_cursorPositionChanged(int oldpos, int newpos) { - log("Detected click on text edit", className); + log("Detected click on text edit widget", className); if(cursorPositionIgnore == true) { if(newpos != 0) { if(showedPassword == true) { @@ -212,10 +211,10 @@ void connectiondialog::on_passwordTextEdit_cursorPositionChanged(int oldpos, int global::keyboard::keyboardDialog = false; global::keyboard::wifiPassphraseDialog = false; if(global::keyboard::keyboardText.isEmpty() == false) { - // A bit hacky: avoid summoning the keyboard back when the text is changing ( and the cursor too ) showedPassword shouldnt be used for this, but it works and adding another bool would start being messy + // A bit hacky: avoid summoning the keyboard back when the text is changing (and the cursor too) showedPassword shouldn't be used for this, but it works and adding another boolean would start being messy showedPassword = false; ui->passwordTextEdit->setText(global::keyboard::keyboardText); - ui->showPasswordBtn->setIcon(QIcon("://resources/hide.png")); + ui->showPasswordBtn->setIcon(QIcon(":/resources/hide.png")); ui->showPasswordBtn->show(); showedPassword = true; savedPassword = global::keyboard::keyboardText; @@ -224,7 +223,7 @@ void connectiondialog::on_passwordTextEdit_cursorPositionChanged(int oldpos, int global::keyboard::keyboardText = ""; } else { - log("Password is not saved so ignoring text edit call", className); + log("Password is not saved; ignoring text edit call", className); } } } @@ -241,13 +240,13 @@ void connectiondialog::showToastSlot(QString message) { void connectiondialog::on_showPasswordBtn_clicked() { if(showedPassword == false) { - ui->showPasswordBtn->setIcon(QIcon("://resources/hide.png")); + ui->showPasswordBtn->setIcon(QIcon(":/resources/hide.png")); ui->passwordTextEdit->setText(savedPassword); showedPassword = true; } else { showedPassword = false; - ui->showPasswordBtn->setIcon(QIcon("://resources/show.png")); + ui->showPasswordBtn->setIcon(QIcon(":/resources/show.png")); ui->passwordTextEdit->setText("********"); } } @@ -275,26 +274,26 @@ void connectiondialog::on_connectBtn_clicked() } passwordForReconnecting = finalPassword; - ui->CancelBtn->setEnabled(false); - if(checkWifiState() == global::wifi::WifiState::Configured) { + ui->cancelBtn->setEnabled(false); + if(checkWifiState() == global::wifi::wifiState::configured) { string_writeconfig("/opt/ibxd", "stop_wifi_operations\n"); } - string_writeconfig("/run/wifi_network_essid", connectedNetworkData.name.toStdString()); - string_writeconfig("/run/wifi_network_passphrase", finalPassword.toStdString()); + writeFile("/run/wifi_network_essid", connectedNetworkData.name); + writeFile("/run/wifi_network_passphrase", finalPassword); finalConnectWait(); } void connectiondialog::finalConnectWait() { - if(checkIfWifiBussy() == true) { + if(checkIfWifiBusy() == true) { // To be sure if(waitTry == 10) { string_writeconfig("/opt/ibxd", "stop_wifi_operations\n"); } - // Max 10s to wait for everything to shut down + // Wait for everything to shut down; 10 seconds timeout if(waitTry == 20) { string_writeconfig("/opt/ibxd", "stop_wifi_operations\n"); - emit showToastSignal("Failed to stop other wifi processes"); - ui->CancelBtn->setEnabled(true); + emit showToastSignal("Failed to stop other Wi-Fi processes"); + ui->cancelBtn->setEnabled(true); } else { QTimer::singleShot(500, this, SLOT(finalConnectWait())); @@ -304,8 +303,8 @@ void connectiondialog::finalConnectWait() { else { string_writeconfig("/opt/ibxd", "connect_to_wifi_network\n"); - // This will be deleted later in mainwindow icon updater if it failed. Its also deleted in stop wifi script - log("Writing to config dir with connection data", className); + // This will be deleted later in MainWindow's icon updater if it failed. It is also deleted in the Wi-Fi stop script + log("Writing to config directory with connection information data", className); string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid", connectedNetworkData.name.toStdString()); string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/passphrase", passwordForReconnecting.toStdString()); @@ -314,10 +313,8 @@ void connectiondialog::finalConnectWait() { } } -bool connectiondialog::checkIfWifiBussy() { - if(checkProcessName("connect_to_network.sh") == true or - checkProcessName("connection_manager.sh") == true or - checkProcessName("prepare_changing_wifi.sh") == true) { +bool connectiondialog::checkIfWifiBusy() { + if(checkProcessName("connect_to_network.sh") == true or checkProcessName("connection_manager.sh") == true or checkProcessName("prepare_changing_wifi.sh") == true) { return true; } else { diff --git a/src/widgets/dialogs/wifi/connectiondialog.h b/src/widgets/dialogs/wifi/connectiondialog.h index d0d9d46..7dc7799 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.h +++ b/src/widgets/dialogs/wifi/connectiondialog.h @@ -30,25 +30,20 @@ public slots: void refreshScreenSlot(); private slots: - // I know im opening / loading json many times, its maybe not efficient but: - // 1. Its modular + // We are opening/loading the JSON database many times, it might not be efficient, but: + // 1. It's modular // 2. Those operations are rare QString searchDatabase(QString key); void writeToDatabase(QString name, QString password); void removeFromDatabase(QString name); - void finalConnectWait(); - bool checkIfWifiBussy(); - - void on_CancelBtn_clicked(); + bool checkIfWifiBusy(); + void on_cancelBtn_clicked(); void on_passwordTextEdit_selectionChanged(); - void on_passwordTextEdit_cursorPositionChanged(int arg1, int arg2); - void on_showPasswordBtn_clicked(); - void on_connectBtn_clicked(); private: diff --git a/src/widgets/dialogs/wifi/connectiondialog.ui b/src/widgets/dialogs/wifi/connectiondialog.ui index 0e9c693..408f162 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.ui +++ b/src/widgets/dialogs/wifi/connectiondialog.ui @@ -20,7 +20,7 @@ QLayout::SetFixedSize - + Cancel diff --git a/src/widgets/dialogs/wifi/network.cpp b/src/widgets/dialogs/wifi/network.cpp index 35e310d..a9505fe 100644 --- a/src/widgets/dialogs/wifi/network.cpp +++ b/src/widgets/dialogs/wifi/network.cpp @@ -17,10 +17,7 @@ network::network(QWidget *parent) : // Buttons ui->encryptionIcon->setProperty("type", "borderless"); ui->encryptionIcon->setStyleSheet("QPushButton[type='borderless']:pressed { background: white; color: white; border: none; }"); - ui->enterButton->setProperty("type", "borderless"); - - ui->enterButton->setFixedWidth(40); } network::~network() @@ -36,20 +33,19 @@ void network::applyVariables() { } ui->signalStrengthLabel->setText(QString::number(mainData.signal) + percent); - // Limit name size, maybe device specific - QString cuttedSingleData = mainData.name; - if(cuttedSingleData.count() > 27) - { - cuttedSingleData = cuttedSingleData.remove(24, cuttedSingleData.count() - 24); - cuttedSingleData.append("..."); + // Limit name size + QString cutSingleData = mainData.name; + if(cutSingleData.count() > 27) { + cutSingleData = cutSingleData.remove(24, cutSingleData.count() - 24); + cutSingleData.append("..."); } - ui->nameLabel->setText(cuttedSingleData); + ui->nameLabel->setText(cutSingleData); if(mainData.encryption == true) { - ui->encryptionIcon->setIcon(QIcon("://resources/lock.png")); + ui->encryptionIcon->setIcon(QIcon(":/resources/lock.png")); } else { - ui->encryptionIcon->setIcon(QIcon("://resources/public.png")); + ui->encryptionIcon->setIcon(QIcon(":/resources/public.png")); } if(currentlyConnectedNetwork == mainData.name) { @@ -59,25 +55,24 @@ void network::applyVariables() { ui->encryptionIcon->setStyleSheet("background-color:grey;"); ui->enterButton->setStyleSheet("background-color:grey;"); - // Some stylesheet magician could make it work that it cant be clicked ui->encryptionIcon->setStyleSheet("QPushButton {background-color: grey; border: none}; QPushButton[type='borderless']:pressed { background: grey; color: grey; border: none; }"); - ui->enterButton->setStyleSheet("QPushButton {background-color: grey; border: none}; QPushButton[type='borderless']:pressed { background: grey; color: grey; border: none; }"); - } else { + } + else { ui->frame->setStyleSheet(".QFrame{background-color: white; border: 3px solid black; border-radius: 10px;}"); } } void network::on_enterButton_clicked() { - connectiondialog* newConnectionDiallog = new connectiondialog; - newConnectionDiallog->connectedNetworkData = mainData; - newConnectionDiallog->currentlyConnectedNetworkName = currentlyConnectedNetwork; - newConnectionDiallog->applyVariables(); - connect(newConnectionDiallog, &connectiondialog::showToastSignal, this, &network::showToastSlot); - connect(newConnectionDiallog, &connectiondialog::refreshScreenSignal, this, &network::refreshScreenSlot); - newConnectionDiallog->exec(); + connectiondialog* newConnectionDialog = new connectiondialog; + newConnectionDialog->connectedNetworkData = mainData; + newConnectionDialog->currentlyConnectedNetworkName = currentlyConnectedNetwork; + newConnectionDialog->applyVariables(); + connect(newConnectionDialog, &connectiondialog::showToastSignal, this, &network::showToastSlot); + connect(newConnectionDialog, &connectiondialog::refreshScreenSignal, this, &network::refreshScreenSlot); + newConnectionDialog->exec(); } void network::closeWrapper() { diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index be9f2f2..5d378d5 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -28,15 +28,9 @@ wifiDialog::wifiDialog(QWidget *parent) : ui->stopBtn->setIcon(QIcon(":/resources/stop.png")); ui->logBtn->setIcon(QIcon(":/resources/file-text.png")); ui->refreshBtn->setIcon(QIcon(":/resources/refresh.png")); - - ui->Wificheckbox->setStyleSheet("QCheckBox::indicator { width:50px; height: 50px; }"); - + ui->wifiCheckBox->setStyleSheet("QCheckBox::indicator { width:50px; height: 50px; }"); ui->returnBtn->setProperty("type", "borderless"); - // Scroll bar - // Needed for the nia. - ui->scrollArea->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 50px; }"); - // Size QRect screenGeometry = QGuiApplication::screens()[0]->geometry(); this->setFixedWidth(screenGeometry.width()); @@ -58,19 +52,19 @@ wifiDialog::wifiDialog(QWidget *parent) : ui->refreshBtn->setFixedHeight(ui->refreshBtn->height() + heighIncrease); // And set wifi checkbox state. also ignore this first call - global::wifi::WifiState currentWifiState = checkWifiState(); - if(currentWifiState != global::wifi::WifiState::Disabled and currentWifiState != global::wifi::WifiState::Unknown) { - ui->Wificheckbox->setChecked(true); + global::wifi::wifiState currentWifiState = checkWifiState(); + if(currentWifiState != global::wifi::wifiState::disabled and currentWifiState != global::wifi::wifiState::unknown) { + ui->wifiCheckBox->setChecked(true); // To be sure nothing breaks refreshFromWatcher = true; ui->refreshBtn->click(); } else { wifiButtonEnabled = true; - ui->stopBtn->setStyleSheet("background-color:grey;"); + ui->stopBtn->setStyleSheet("background-color: gray;"); ui->stopBtn->setEnabled(false); } - // To avoid confussion with reconnecting + // To avoid confusion with reconnecting QTimer::singleShot(2000, this, SLOT(theWatcher())); } @@ -82,7 +76,7 @@ wifiDialog::~wifiDialog() void wifiDialog::on_refreshBtn_clicked() { log("Clicked refresh button", className); - if(checkWifiState() == global::wifi::WifiState::Disabled) { + if(checkWifiState() == global::wifi::wifiState::disabled) { if(refreshFromWatcher == true) { refreshFromWatcher = false; emit showToast("To scan, turn on wi-fi first"); @@ -99,13 +93,13 @@ void wifiDialog::launchRefresh() { // Order is important if(scanInProgress == false) { scanInProgress = true; - ui->refreshBtn->setStyleSheet("background-color:grey;"); + ui->refreshBtn->setStyleSheet("background-color: gray;"); ui->refreshBtn->setEnabled(false); elapsedSeconds = 0; fullList.remove(); formattedList.remove(); - string_writeconfig("/opt/ibxd", "list_wifi_networks\n"); + writeFile("/opt/ibxd", "list_wifi_networks\n"); QTimer::singleShot(0, this, SLOT(refreshWait())); } else { @@ -116,8 +110,7 @@ void wifiDialog::launchRefresh() { void wifiDialog::refreshWait() { if(fullList.exists() == false and formattedList.exists() == false) { if(elapsedSeconds == 6) { - emit showToast("Failed to get network list"); - log("Failed to get network list", className); + emit showToast("Failed to get networks list"); ui->refreshBtn->setStyleSheet("background-color:white;"); ui->refreshBtn->setEnabled(true); scanInProgress = false; @@ -127,7 +120,7 @@ void wifiDialog::refreshWait() { QTimer::singleShot(1000, this, SLOT(refreshWait())); } } else { - log("Happily got network list", className); + log("Retrieved network list successfully", className); refreshNetworksList(); } } @@ -141,44 +134,46 @@ void wifiDialog::refreshNetworksList() { int count = 1; global::wifi::wifiNetworkData singleNetwork; if(data.count() < 4) { - log("Data lines count is below 4, skipping", className); + log("Data lines count is below 4; skipping", className); continue; } for(QString singleData: data) { if(count == 1) { singleNetwork.mac = singleData; - log("Mac is: " + singleData, className); + log("MAC is: " + singleData, className); } if(count == 2) { - log("wifi name is: " + singleData, className); if(singleData.isEmpty() == true) { - log("Wifi name is empty", className); + log("Network name is empty", className); + } + else { + log("Network name is: " + singleData, className); } singleNetwork.name = singleData; } if(count == 3) { - log("encryption is: " + singleData, className); + log("Encryption type is: " + singleData, className); singleNetwork.encryption = QVariant(singleData).toBool(); } if(count == 4) { - log("signal strength is: " + singleData, className); + log("Signal strength is: " + singleData, className); singleNetwork.signal = QVariant(singleData).toInt(); } if(count >= 5) { - log("Skipping additionall items in wifi", className); + log("Skipping additional items from network information", className); } count = count + 1; } - // Really filter out empty networks + // Filter out remaining empty networks if(singleNetwork.name.isEmpty() == false) { pureNetworkList.append(singleNetwork); } } - log("found valid networks: " + QString::number(pureNetworkList.count()), className); + log("Found " + QString::number(pureNetworkList.count()) + " valid networks", className); if(pureNetworkList.count() == 0) { if(secondScanTry == false) { secondScanTry = true; - if(checkWifiState() != global::wifi::WifiState::Disabled) { + if(checkWifiState() != global::wifi::wifiState::disabled) { scanInProgress = false; QTimer::singleShot(0, this, SLOT(launchRefresh())); log("No networks found. Trying one more time"); @@ -193,21 +188,21 @@ void wifiDialog::refreshNetworksList() { log("No networks found, skipping", className); showToastSlot("No networks found"); ui->refreshBtn->setEnabled(true); - ui->refreshBtn->setStyleSheet("background-color:white;"); + ui->refreshBtn->setStyleSheet("background-color: white;"); scanInProgress = false; return void(); } } QFile currentWifiNameFile = QFile("/external_root/run/current_wifi_name"); currentWifiNameFile.remove(); - string_writeconfig("/opt/ibxd", "get_current_wifi_name\n"); + writeFile("/opt/ibxd", "get_current_wifi_name\n"); usleep(300000); // 0.3s - // Here its looking for the now connected network to put it on top + // Here, it's looking for the currently connected network to put it on top of the list QString currentNetwork = ""; if(currentWifiNameFile.exists() == true) { QString currentWifiNetwork = readFile(currentWifiNameFile.fileName()); currentWifiNetwork = currentWifiNetwork.replace("\n", ""); - log("current network name is: " + currentWifiNetwork, className); + log("Current network name is: " + currentWifiNetwork, className); int countVec = 0; int vectorNetworkLocation = 9999; for(global::wifi::wifiNetworkData wifiNetwork: pureNetworkList) { @@ -220,9 +215,9 @@ void wifiDialog::refreshNetworksList() { // To be really sure that the the info is put there connectedNetwork->currentlyConnectedNetwork = currentNetwork; connectedNetworkDataParent = wifiNetwork; - connectedNetworkDataParentSetted = true; + connectedNetworkDataParentSet = true; - // This doesnt work so a layout is needed + // This doesn't work, so a layout is needed // ui->scrollArea->addScrollBarWidget(connectedNetwork, Qt::AlignTop); connectedNetwork->applyVariables(); connect(this, &wifiDialog::killNetworkWidgets, connectedNetwork, &network::closeWrapper); @@ -235,14 +230,10 @@ void wifiDialog::refreshNetworksList() { } } if(vectorNetworkLocation != 9999) { - log("pureNetworkList size is: " + QString::number(pureNetworkList.count()) + " And i want to remove at: " + QString::number(vectorNetworkLocation), className); + log("pureNetworkList size is: " + QString::number(pureNetworkList.count()) + ", entry at " + QString::number(vectorNetworkLocation) + " slated for removal", className); pureNetworkList.removeAt(vectorNetworkLocation); } } - for(global::wifi::wifiNetworkData wifiNetwork: pureNetworkList) { - log("signal strength without sorting: " + QString::number(wifiNetwork.signal), className); - } - // Sort based on signal strength QVector sortedPureNetworkList; @@ -260,19 +251,18 @@ void wifiDialog::refreshNetworksList() { counter = counter + 1; } } - // This happens if its the smallest value, so insert it at the end + // This happens if it's the smallest value, so insert it at the end if(stopIterating == false) { sortedPureNetworkList.append(wifiNetwork); } } - log("There are " + QString::number(sortedPureNetworkList.count()) + " sorted networks", className); for(global::wifi::wifiNetworkData wifiNetwork: sortedPureNetworkList) { - log("signal strength with sorting: " + QString::number(wifiNetwork.signal), className); + log("Signal strength with sorting: " + QString::number(wifiNetwork.signal), className); } - // And now rest of the networks + // And now, handle the remainder of the networks for(global::wifi::wifiNetworkData wifiNetwork: sortedPureNetworkList) { network* connectedNetwork = new network; connectedNetwork->mainData = wifiNetwork; @@ -291,24 +281,24 @@ void wifiDialog::refreshNetworksList() { } -void wifiDialog::on_Wificheckbox_stateChanged(int arg1) +void wifiDialog::on_wifiCheckBox_stateChanged(int arg1) { - if(ignoreCheckboxCall == false) { - connectedNetworkDataParentSetted = false; + if(ignoreCheckBoxCall == false) { + connectedNetworkDataParentSet = false; log("wifi dialog clicked: " + QString::number(arg1), className); if(wifiButtonEnabled == true) { if(arg1 == 2) { - log("turning wifi on", className); + log("Turning Wi-Fi on", className); // the watcher will scan wifi QTimer::singleShot(0, this, SLOT(turnOnWifi())); - ui->stopBtn->setStyleSheet("background-color:white;"); + ui->stopBtn->setStyleSheet("background-color: white;"); ui->stopBtn->setEnabled(true); } else { - log("turning wifi off", className); + log("Turning Wi-Fi off", className); QTimer::singleShot(0, this, SLOT(turnOffWifi())); - // To inform the wifi icon GUI to don't show the connected / failed to connect message + // To inform the wifi icon GUI to don't show the connected/failed to connect message string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped", "true"); - ui->stopBtn->setStyleSheet("background-color:grey;"); + ui->stopBtn->setStyleSheet("background-color: gray;"); ui->stopBtn->setEnabled(false); } emit killNetworkWidgets(); @@ -318,8 +308,8 @@ void wifiDialog::on_Wificheckbox_stateChanged(int arg1) } } else { - ignoreCheckboxCall = false; - if(checkWifiState() != global::wifi::WifiState::Disabled) { + ignoreCheckBoxCall = false; + if(checkWifiState() != global::wifi::wifiState::disabled) { emit killNetworkWidgets(); forceRefresh = true; } @@ -342,13 +332,13 @@ void wifiDialog::turnOffWifi() { void wifiDialog::on_logBtn_clicked() { - // To avoid half informations - if(scannedAtLeastOnce == false and checkWifiState() == global::wifi::WifiState::Configured) { + // To avoid half of the information + if(scannedAtLeastOnce == false and checkWifiState() == global::wifi::wifiState::configured) { log("Scanning at least once is needed"); emit showToast("Scan at least once"); } else { wifilogger* wifiLoggerDialog = new wifilogger; - if(connectedNetworkDataParentSetted == true) { + if(connectedNetworkDataParentSet == true) { wifiLoggerDialog->connectedNetworkData = connectedNetworkDataParent; wifiLoggerDialog->isThereData = true; } @@ -365,56 +355,54 @@ void wifiDialog::refreshScreenSlot() { } /* -Some documentation used by the watcher -connection_manager.sh - Manages all things, launches other processes -connect_to_network.sh - All in one connection manager. manages everything, used by ipd, should be used for recconections after sleeping / booting -get_dhcp.sh - Gets dhcp addresses -prepare_changing_wifi.sh - Kills everything, prepares to changing network -smarter_time_sync.sh - Synces time -toggle.sh - Turns on / off -list_networks.bin - Well lists networks -check_wifi_password.sh - Checks wifi password -theWatcher() first watches at processes that could kill other ones + Some documentation used by the watcher + * connection_manager.sh - Manages all things, launches other processes + * connect_to_network.sh - All-in-one connection manager. Manages everything, used by IPD, should be used for Wi-Fi reconnections after sleeping/booting + * get_dhcp.sh - Gets dhcp addresses + * prepare_changing_wifi.sh - Kills everything, prepares to changing network + * smarter_time_sync.sh - Syncs time + * toggle.sh - Turns on/off Wi-Fi adapter + * list_networks.bin - Lists networks + * check_wifi_password.sh - Checks Wi-Fi network password + * watcher() first watches at processes that could kill other ones */ -void wifiDialog::theWatcher() { - +void wifiDialog::watcher() { bool killing = checkProcessName("toggle.sh"); bool changing = checkProcessName("prepare_changing_wifi.sh"); if(killing == true) { - setStatusText("Changing wifi state"); - //log("toggle.sh is active", className); + setStatusText("Changing Wi-Fi adapter status"); isToggleRunning = true; - QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } if(changing == true) { - setStatusText("Disconnecting from a network or cleaning"); + setStatusText("Disconnecting from a network or cleaning up"); log("prepare_changing_wifi.sh is active", className); - QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } - bool recconection = checkProcessName("connect_to_network.sh"); - if(recconection == true) { + bool reconnection = checkProcessName("connect_to_network.sh"); + if(reconnection == true) { forceRefresh = true; QFile recName = QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid"); if(recName.exists() == true) { - setStatusText("Recconecting after suspending to " + readFile(recName.fileName()).replace("\n", "")); + setStatusText("Reconnecting after suspending to " + readFile(recName.fileName()).replace("\n", "")); } else { // Shouldn't be possible - setStatusText("Recconecting after sleep"); + setStatusText("Reconnecting after sleep"); } - QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } bool listing = checkProcessName("list_networks.bin"); if(listing == true) { - setStatusText("Scanning networks..."); - QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + setStatusText("Scanning networks ..."); + QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } @@ -422,33 +410,31 @@ void wifiDialog::theWatcher() { if(dhcp == true) { forceRefresh = true; setStatusText("Getting IP address"); - QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } - bool passwordCheck = checkProcessName("check_wifi_password.sh"); if(passwordCheck == true) { forceRefresh = true; - setStatusText("Checking wi-fi password"); - QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + setStatusText("Checking Wi-Fi network password"); + QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } bool time = checkProcessName("smarter_time_sync.sh"); if(time == true) { forceRefresh = true; - setStatusText("Syncing time"); - QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + setStatusText("Syncing"); + QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } - bool connecting = checkProcessName("connection_manager.sh"); if(connecting == true) { forceRefresh = true; - setStatusText("Connecting to wifi..."); - QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + setStatusText("Connecting to Wi-Fi network ..."); + QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } @@ -456,26 +442,26 @@ void wifiDialog::theWatcher() { setStatusText("Idling"); } - if(unlockCheckbox == true) { - ui->Wificheckbox->setEnabled(true); - unlockCheckbox = false; + if(unlockCheckBox == true) { + ui->wifiCheckBox->setEnabled(true); + unlockCheckBox = false; } if(isToggleRunning == true) { isToggleRunning = false; - // To make sure the checkbox is in the right state - if(checkWifiState() == global::wifi::WifiState::Disabled) { + // Make sure the checkbox is in the right state + if(checkWifiState() == global::wifi::wifiState::disabled) { // In this state, ignore forceRefresh to avoid message forceRefresh = false; - if(ui->Wificheckbox->isChecked() == true) { - ignoreCheckboxCall = true; - ui->Wificheckbox->setChecked(false); + if(ui->wifiCheckBox->isChecked() == true) { + ignoreCheckBoxCall = true; + ui->wifiCheckBox->setChecked(false); } } else { - if(ui->Wificheckbox->isChecked() == false) { - ignoreCheckboxCall = true; - ui->Wificheckbox->setChecked(true); + if(ui->wifiCheckBox->isChecked() == false) { + ignoreCheckBoxCall = true; + ui->wifiCheckBox->setChecked(true); } } } @@ -486,7 +472,7 @@ void wifiDialog::theWatcher() { QTimer::singleShot(1500, this, SLOT(waitToScan())); } - QTimer::singleShot(relaunchMs, this, SLOT(theWatcher())); + QTimer::singleShot(relaunchMs, this, SLOT(watcher())); } void wifiDialog::setStatusText(QString message) { @@ -496,23 +482,18 @@ void wifiDialog::setStatusText(QString message) { void wifiDialog::on_stopBtn_clicked() { log("Stop button was clicked", className); - connectedNetworkDataParentSetted = false; - ui->Wificheckbox->setEnabled(false); - unlockCheckbox = true; + connectedNetworkDataParentSet = false; + ui->wifiCheckBox->setEnabled(false); + unlockCheckBox = true; - // To inform the wifi icon GUI to don't show the connected / failed to connect message - string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped", "true"); - - // Maybe limit this, idk - string_writeconfig("/opt/ibxd", "stop_wifi_operations\n"); + // To inform the wifi icon GUI to don't show the connected/failed to connect message + writeFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped", "true"); + writeFile("/opt/ibxd", "stop_wifi_operations\n"); QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid").remove(); QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/passphrase").remove(); - // This variable just avoids showing the toast so i can use it here too... - // Actually refreshing from watcher is smarter so this isin't needed - //refreshFromWatcher = true; - //ui->refreshBtn->click(); + // This variable just avoids showing the toast, so it is usable here too waitToScan(); } @@ -523,7 +504,7 @@ void wifiDialog::on_returnBtn_clicked() } void wifiDialog::waitToScan() { - if(checkWifiState() != global::wifi::WifiState::Disabled) { + if(checkWifiState() != global::wifi::wifiState::disabled) { ui->refreshBtn->click(); } else { diff --git a/src/widgets/dialogs/wifi/wifidialog.h b/src/widgets/dialogs/wifi/wifidialog.h index 04b3c0e..92754c5 100644 --- a/src/widgets/dialogs/wifi/wifidialog.h +++ b/src/widgets/dialogs/wifi/wifidialog.h @@ -20,8 +20,7 @@ public: explicit wifiDialog(QWidget *parent = nullptr); ~wifiDialog(); global::wifi::wifiNetworkData connectedNetworkDataParent; - // well dont touch this until there is something, *** Error in `/tmp/exec': double free or corruption (fasttop): 0x025ed170 *** - bool connectedNetworkDataParentSetted = false; + bool connectedNetworkDataParentSet = false; private: Ui::wifiDialog *ui; @@ -37,11 +36,11 @@ private: bool forceRefresh = false; int relaunchMs = 300; bool refreshFromWatcher = false; - bool unlockCheckbox = false; + bool unlockCheckBox = false; bool scanInProgress = false; bool isToggleRunning = false; - bool ignoreCheckboxCall = false; + bool ignoreCheckBoxCall = false; bool secondScanTry = false; @@ -51,24 +50,25 @@ public slots: void showToastSlot(QString message); void refreshScreenSlot(); - // Shows status of wifi processes, like recconection and others. Also manages refreshing the network list after connection - void theWatcher(); + // Shows status of Wi-Fi processes, like reconnection and others. Also manages refreshing the networks list after connection + void watcher(); signals: void refreshScreen(); void updateWifiIconSig(int mode); void showToast(QString messageToDisplay); - void killNetworkWidgets(); private slots: void on_refreshBtn_clicked(); - void on_Wificheckbox_stateChanged(int arg1); + void on_wifiCheckBox_stateChanged(int arg1); void turnOnWifi(); void turnOffWifi(); void on_logBtn_clicked(); - // This function is a more clever sleep(1), non blocking + + // This function is a more clever sleep(1), non-blocking void refreshWait(); + void setStatusText(QString message); void on_stopBtn_clicked(); void on_returnBtn_clicked(); diff --git a/src/widgets/dialogs/wifi/wifidialog.ui b/src/widgets/dialogs/wifi/wifidialog.ui index 6fdeb0f..e8a2854 100644 --- a/src/widgets/dialogs/wifi/wifidialog.ui +++ b/src/widgets/dialogs/wifi/wifidialog.ui @@ -153,7 +153,7 @@ - + diff --git a/src/widgets/dialogs/wifi/wifilogger.cpp b/src/widgets/dialogs/wifi/wifilogger.cpp index fb62aff..e891c4a 100644 --- a/src/widgets/dialogs/wifi/wifilogger.cpp +++ b/src/widgets/dialogs/wifi/wifilogger.cpp @@ -38,14 +38,14 @@ wifilogger::~wifilogger() } void wifilogger::setWifiInfoPage() { - if(checkWifiState() == global::wifi::WifiState::Configured) { - QTimer::singleShot(0, this, SLOT(getWifiInformations())); + if(checkWifiState() == global::wifi::wifiState::configured) { + QTimer::singleShot(0, this, SLOT(getWifiInformation())); ui->stackedWidget->setCurrentIndex(0); - ui->nameLabel->setText("Network informations"); + ui->nameLabel->setText("Network information"); } else { ui->stackedWidget->setCurrentIndex(1); - ui->nameLabel->setText("No network connected"); + ui->nameLabel->setText("Not currently connected to a network"); } } @@ -97,27 +97,27 @@ void wifilogger::changePage() { } } -void wifilogger::getWifiInformations() { - log("getting wifi informations", className); - QFile wifiInformationsPath = QFile("/external_root/run/wifi_informations"); +void wifilogger::getWifiInformation() { + log("Retrieving Wi-Fi information", className); + QFile wifiInformationPath = QFile("/external_root/run/wifi_information"); if(waitingForFile == false) { - wifiInformationsPath.remove(); + wifiInformationPath.remove(); - log("Launching get_wifi_informations ibxd call", className); - string_writeconfig("/opt/ibxd", "get_wifi_informations\n"); + log("Sending get_wifi_information ibxd call", className); + string_writeconfig("/opt/ibxd", "get_wifi_information\n"); waitingForFile = true; } if(waitingForFile == true) { - if(wifiInformationsPath.exists() == false) { - QTimer::singleShot(1000, this, SLOT(getWifiInformations())); + if(wifiInformationPath.exists() == false) { + QTimer::singleShot(1000, this, SLOT(getWifiInformation())); return void(); } } waitingForFile = false; log("Setting variables", className); - QString wifiInfo = readFile(wifiInformationsPath.fileName()); + QString wifiInfo = readFile(wifiInformationPath.fileName()); QStringList wifiInfoList = wifiInfo.split("\n"); int counter = 0; for(QString infomation: wifiInfoList) { @@ -138,17 +138,13 @@ void wifilogger::getWifiInformations() { if(isThereData == true) { ui->encryptionLabel->setText(QVariant(connectedNetworkData.encryption).toString()); - ui->signalLabel->setText(QString::number(connectedNetworkData.signal) + "%"); - ui->macLabel->setText(connectedNetworkData.mac); } else { - // Shouldn't happen for 99%, but if anyway... its designed to be non blocking, so i cant really wait for this. + // Shouldn't happen for 99%, but if anyway... it's designed to be non-blocking, so I can't really wait for this. ui->encryptionLabel->setText("Rescan needed"); - ui->signalLabel->setText("Rescan needed"); - ui->macLabel->setText("Rescan needed"); } } diff --git a/src/widgets/dialogs/wifi/wifilogger.h b/src/widgets/dialogs/wifi/wifilogger.h index 3781656..4b3b069 100644 --- a/src/widgets/dialogs/wifi/wifilogger.h +++ b/src/widgets/dialogs/wifi/wifilogger.h @@ -17,15 +17,15 @@ public: explicit wifilogger(QWidget *parent = nullptr); ~wifilogger(); global::wifi::wifiNetworkData connectedNetworkData; - // to the above value + // To the above value bool isThereData = false; private: Ui::wifilogger *ui; /* - * 0 is wifi info / no wifi info page - * 1 is fancy logs page - * 2 is all logs + * 0 Is Wi-Fi info/no Wi-Fi info page + * 1 Is fancy logs page + * 2 Is all logs page */ int currentPage = 0; QFile fancyLogs = QFile("/external_root/run/wifi_stats"); @@ -39,7 +39,7 @@ private slots: void on_nextBtn_clicked(); void on_previousBtn_clicked(); void changePage(); - void getWifiInformations(); + void getWifiInformation(); void on_returnBtn_clicked(); void updateLogs(); void on_refreshBtn_clicked(); From c49da9dc90548b0ea43dce89f9c54c2a4c9572e5 Mon Sep 17 00:00:00 2001 From: Nicolas Mailloux Date: Mon, 22 Aug 2022 16:09:18 -0400 Subject: [PATCH 13/19] Wi-Fi graphics redesign WIP --- src/eink.qrc | 3 +- src/functions.h | 3 +- src/homeWidget/mainwindow.cpp | 8 +- src/main.cpp | 1 - src/resources/log.png | Bin 0 -> 2297 bytes src/resources/refresh.png | Bin 8452 -> 7791 bytes src/resources/stop.png | Bin 11604 -> 12436 bytes src/settings/settings.ui | 4 +- src/widgets/dialogs/wifi/connectiondialog.cpp | 3 +- src/widgets/dialogs/wifi/network.cpp | 51 +- src/widgets/dialogs/wifi/network.ui | 33 +- src/widgets/dialogs/wifi/wifidialog.cpp | 54 +- src/widgets/dialogs/wifi/wifidialog.ui | 109 +-- src/widgets/dialogs/wifi/wifilogger.cpp | 40 +- src/widgets/dialogs/wifi/wifilogger.h | 2 +- src/widgets/dialogs/wifi/wifilogger.ui | 789 ++++++++++-------- 16 files changed, 658 insertions(+), 442 deletions(-) create mode 100644 src/resources/log.png diff --git a/src/eink.qrc b/src/eink.qrc index 79fe6e3..91f1794 100644 --- a/src/eink.qrc +++ b/src/eink.qrc @@ -93,9 +93,10 @@ resources/lock.png resources/public.png resources/wifi-0.png - resources/wifi-100.png resources/wifi-25.png resources/wifi-50.png resources/wifi-75.png + resources/wifi-100.png + resources/log.png diff --git a/src/functions.h b/src/functions.h index db88aa8..1060e2a 100644 --- a/src/functions.h +++ b/src/functions.h @@ -166,8 +166,7 @@ namespace global { inline QString bookPath; } namespace wifi { - enum class wifiState - { + enum class wifiState { configured, enabled, disabled, diff --git a/src/homeWidget/mainwindow.cpp b/src/homeWidget/mainwindow.cpp index 363055b..fe9f5c7 100644 --- a/src/homeWidget/mainwindow.cpp +++ b/src/homeWidget/mainwindow.cpp @@ -134,7 +134,7 @@ MainWindow::MainWindow(QWidget *parent) updateWifiAble(); if(global::device::isWifiAble == true) { - // Start wifi updater + // Start Wi-Fi icon updater QTimer *wifiIconTimer = new QTimer(this); wifiIconTimer->setInterval(2500); connect(wifiIconTimer, SIGNAL(timeout()), this, SLOT(updateWifiIcon())); @@ -833,9 +833,9 @@ void MainWindow::updateWifiAble() { void MainWindow::on_wifiBtn_clicked() { - wifiDialog* newWIfiDialog = new wifiDialog(); - QObject::connect(newWIfiDialog, &wifiDialog::showToast, this, &MainWindow::showToast); - newWIfiDialog->exec(); + wifiDialog* newWifiDialog = new wifiDialog(); + QObject::connect(newWifiDialog, &wifiDialog::showToast, this, &MainWindow::showToast); + newWifiDialog->exec(); } void MainWindow::showToast(QString messageToDisplay) { diff --git a/src/main.cpp b/src/main.cpp index 4bfb82f..bd4fea0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -228,7 +228,6 @@ int main(int argc, char *argv[]) const QScreen * screen = qApp->primaryScreen(); w.setGeometry(QRect(QPoint(0,0), screen->geometry().size())); - w.setFixedSize(QSize(screen->geometry().height(), screen->geometry().width())); w.show(); return a.exec(); } diff --git a/src/resources/log.png b/src/resources/log.png new file mode 100644 index 0000000000000000000000000000000000000000..7785a375ac738c8b069639582f35d0076791d8dc GIT binary patch literal 2297 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 I6X?tT0c_v^KL7v# literal 8452 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 R!b6*wEiPJ{mY>JO{XZ*|f4Tqw diff --git a/src/resources/stop.png b/src/resources/stop.png index b813bb05b43a84babbbafddbf7d61084f0601b9a..0b8f02ca8942373c5a7fdb75e770e290332e22d5 100644 GIT binary patch literal 12436 zcmX9^cRZWl_fMksjJ;_jHnnPxmW0G=?X70jXw4d>#HVP)XcN0uDO$8PwZ$l6SBs!3 zN{yD9RZ81me1FO7`Qy3gx#ym9?z!)C@3|-WrnwO_13v=*0ANNT;g$dZaOC2lqoK4s zDq#FXc}eg!Ft~{_Fc1w23B2ta;0*vs;vV93kp0&L-`%o$XDRa^H#m6sW}z$wtM12z zy;<^+;f-dl^KWW1emp0SQExMuJmfLc`_93R*6upnIUqPJ#4-%W{x65qaUe42)02o_ z!V$ZG64%>R^NK95o_UvjQB=%u;p%V&69B*2;BN;^AIj&M5<+8^`iJH^BqtAae{F19 zgosncK=x%nFsDR5ihS^4T4R^vv4e#rW-@t*saop{LY)9ma$9(}-*6tXa)H0R4AmX46UOb=G7k}P3jv~av? zX=j!Jr&eD5jp=cJ9fjo6;;AJb?UJwB6e*~e(Kfy@vr*3 zYUY4{%0cDL=UJKxho}c{$`R@4&v(gR+RKU2gs&_LCuJr{YslDV`ns&0#qZU;3`~H&%+J)$|U#5*cA_9Ly5*|;Ff2K?ejfaU59Psbr z|GevE2Bn2Q22dFQZA4zGX4MUkBXxHhu+40*;L)DyK8pTH^l^csUsQvwS;6CE8y!4eJzTX2GfZocmYA_R?SeJ=GXVW=yyq6kgs zrR(hRJ5M?#F1yZg=Rej!*IKuS198UzlE2pPlBp-PaF~T?OE9 zc$tmn76{iq*3nJebwPh7?k>f<5_ePLy@|WKR5BUM8$kcC5{$kS-unS4A1FZeCm#6y zwCy+oorX@z{3~Efb(pd2Llru5aw@#1S~qZ+(?SxVsn6=hR%at7a4DeZTvry+TTL4p zUr8_}zghd$tXhr(q)-@ASA;?ybbvYlT2%cU;O$#M%VRXICJCV)9vt{MSMN>AC+s4B z(1mEBjN)j(3p8_>S%-a*b-^Sc15G4OR<;{*8spBVcu2Llv`eb*0LxMpCUab z$-m4gBujTsvH_ul(8HeYjr^O(oJu*{c-KieyOU;gnVkLeSR zZo`1U-~wSNAJ$X_rX#oe6AXS^Zu=d^l8XjDe}I+VGzM>(*c;&7H4Zw&|%`tQ(H49fHSS&m(d=KS7A3{E8+8V@t`-t#|%O8b(J41;0*)9 z1g-=vPP17@?f||Or;`%fJc#A)w|zuLLw4|)k)`*-p&i_>FP6}pFdApp=U5bgV(&Q9 zNJBvHYJ$`6r(T`+!;wBDc#0Pmeuhkg+hIg6e6mf-#|nTC$HWO1lWA5AjT%$H`BB$9 z5E8G&z3jpG=>7WCtLd^o6*>dG)bS8wWEn(K4yok3m^Ll2> z5nVV{U;qyx(2<2Xaw=xt4N{4j89?UC^xQLgjWe<;W@c=`>6wudx1l69^?za1f0(xq8TCEOuViW*zt}~l?*&&avA-B zezd^@AthAC=-xO{94{317|F>*Z7vot7|o=1W^ZBqF7;9@<94MCywn@CM@`;s@55S- zyp$+;vX({QZa0AX(SVAnegmGcP3Wg^mA`&mh}Hvid}F}%?X&Osk~Li15mM#194Bb* zfoQ(7;Pe~l-F*Ul$nN?tMe0jA`=&>CTMPPQ*%xzmwWu=(Zj?iX4M#`i0*>EOkGiGw3(u%adC3 zULF^i-w`HrX+x%ke}lUn6CZwJPMj!60FD6S$OVz+Fq2seC&6$@sPgjx`0!l zi|d^q;@jB5Y8lRv*UIdzT)Z_hrCu6)+

8{0d_AbMXd_% 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 literal 11604 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 diff --git a/src/settings/settings.ui b/src/settings/settings.ui index a121f64..a63a5ab 100644 --- a/src/settings/settings.ui +++ b/src/settings/settings.ui @@ -49,7 +49,7 @@ 0 0 457 - 667 + 657 @@ -71,7 +71,7 @@ 0 - 1 + 0 diff --git a/src/widgets/dialogs/wifi/connectiondialog.cpp b/src/widgets/dialogs/wifi/connectiondialog.cpp index 2f127eb..8f6392f 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.cpp +++ b/src/widgets/dialogs/wifi/connectiondialog.cpp @@ -11,6 +11,7 @@ connectiondialog::connectiondialog(QWidget *parent) : ui(new Ui::connectiondialog) { ui->setupUi(this); + this->setFont(QFont("u001")); // Stylesheet, style & misc. QFile stylesheetFile("/mnt/onboard/.adds/inkbox/eink.qss"); @@ -96,7 +97,7 @@ QString connectiondialog::searchDatabase(QString key) { return returnedPassword; } else { - log("Searched name '" + searchedName + "' doesn't match " + key + "'", className); + log("Searched name '" + searchedName + "' doesn't match '" + key + "'", className); } } return ""; diff --git a/src/widgets/dialogs/wifi/network.cpp b/src/widgets/dialogs/wifi/network.cpp index a9505fe..cd53f04 100644 --- a/src/widgets/dialogs/wifi/network.cpp +++ b/src/widgets/dialogs/wifi/network.cpp @@ -2,11 +2,14 @@ #include "ui_network.h" #include "connectiondialog.h" +#include + network::network(QWidget *parent) : QWidget(parent), ui(new Ui::network) { ui->setupUi(this); + this->setFont(QFont("u001")); // Stylesheet, style & misc. QFile stylesheetFile("/mnt/onboard/.adds/inkbox/eink.qss"); @@ -17,6 +20,8 @@ network::network(QWidget *parent) : // Buttons ui->encryptionIcon->setProperty("type", "borderless"); ui->encryptionIcon->setStyleSheet("QPushButton[type='borderless']:pressed { background: white; color: white; border: none; }"); + ui->signalStrengthIcon->setProperty("type", "borderless"); + ui->signalStrengthIcon->setStyleSheet("QPushButton[type='borderless']:pressed { background: white; color: white; border: none; }"); ui->enterButton->setProperty("type", "borderless"); } @@ -27,6 +32,7 @@ network::~network() void network::applyVariables() { log("Applying variables for network", className); + QString percent = "%"; if(mainData.signal < 100) { percent.append(" "); @@ -34,12 +40,13 @@ void network::applyVariables() { ui->signalStrengthLabel->setText(QString::number(mainData.signal) + percent); // Limit name size - QString cutSingleData = mainData.name; - if(cutSingleData.count() > 27) { - cutSingleData = cutSingleData.remove(24, cutSingleData.count() - 24); - cutSingleData.append("..."); + int nameLength = mainData.name.length(); + QString name = mainData.name; + if(nameLength > 20) { + name.chop(nameLength - 20); + name.append("..."); } - ui->nameLabel->setText(cutSingleData); + ui->nameLabel->setText(name); if(mainData.encryption == true) { ui->encryptionIcon->setIcon(QIcon(":/resources/lock.png")); @@ -49,18 +56,34 @@ void network::applyVariables() { } if(currentlyConnectedNetwork == mainData.name) { - ui->frame->setStyleSheet(".QFrame{background-color: grey; border: 3px solid black; border-radius: 10px;}"); - ui->signalStrengthLabel->setStyleSheet("background-color:grey;"); - ui->nameLabel->setStyleSheet("background-color:grey;"); - ui->encryptionIcon->setStyleSheet("background-color:grey;"); - ui->enterButton->setStyleSheet("background-color:grey;"); - - ui->encryptionIcon->setStyleSheet("QPushButton {background-color: grey; border: none}; QPushButton[type='borderless']:pressed { background: grey; color: grey; border: none; }"); - ui->enterButton->setStyleSheet("QPushButton {background-color: grey; border: none}; QPushButton[type='borderless']:pressed { background: grey; color: grey; border: none; }"); + ui->frame->setStyleSheet(".QFrame{background-color: lightGray; border: 2px solid black; border-radius: 10px;}"); + ui->signalStrengthLabel->setStyleSheet("background-color: lightGray;"); + ui->nameLabel->setStyleSheet("background-color: lightGray;"); + ui->encryptionIcon->setStyleSheet("background-color: lightGray;"); + ui->enterButton->setStyleSheet("background-color: lightGray;"); + ui->signalStrengthIcon->setStyleSheet("QPushButton {background-color: lightGray; border: none}; QPushButton[type='borderless']:pressed { background: lightGray; color: lightGray; border: none; }"); + ui->encryptionIcon->setStyleSheet("QPushButton {background-color: lightGray; border: none}; QPushButton[type='borderless']:pressed { background: lightGray; color: lightGray; border: none; }"); + ui->enterButton->setStyleSheet("QPushButton {background-color: lightGray; border: none}; QPushButton[type='borderless']:pressed { background: lightGray; color: lightGray; border: none; }"); } else { - ui->frame->setStyleSheet(".QFrame{background-color: white; border: 3px solid black; border-radius: 10px;}"); + ui->frame->setStyleSheet(".QFrame{background-color: white; border: 2px solid black; border-radius: 10px;}"); + } + + if(mainData.signal >= 0 and mainData.signal <= 25) { + ui->signalStrengthIcon->setIcon(QIcon(":/resources/wifi-0.png")); + } + else if(mainData.signal >= 25 and mainData.signal <= 50) { + ui->signalStrengthIcon->setIcon(QIcon(":/resources/wifi-25.png")); + } + else if(mainData.signal >= 50 and mainData.signal <= 75) { + ui->signalStrengthIcon->setIcon(QIcon(":/resources/wifi-50.png")); + } + else if(mainData.signal >= 75 and mainData.signal <= 100) { + ui->signalStrengthIcon->setIcon(QIcon(":/resources/wifi-75.png")); + } + else if(mainData.signal == 100) { + ui->signalStrengthIcon->setIcon(QIcon(":/resources/wifi-100.png")); } } diff --git a/src/widgets/dialogs/wifi/network.ui b/src/widgets/dialogs/wifi/network.ui index 6487348..0c50b56 100644 --- a/src/widgets/dialogs/wifi/network.ui +++ b/src/widgets/dialogs/wifi/network.ui @@ -21,13 +21,13 @@ - 17 + 0 4 - 17 + 0 4 @@ -47,11 +47,11 @@ QFrame::Plain - 3 + 1 - 3 + 12 3 @@ -63,9 +63,21 @@ 3 - + - SIgnal strenth + + + + + + + + + U001 + + + + Signal strength @@ -75,7 +87,7 @@ QFrame::Plain - 3 + 1 Qt::Vertical @@ -84,8 +96,13 @@ + + + U001 + + - wifi name + Wi-Fi network name diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 5d378d5..70d7b12 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -17,6 +17,7 @@ wifiDialog::wifiDialog(QWidget *parent) : ui(new Ui::wifiDialog) { ui->setupUi(this); + this->setFont(QFont("u001")); // Stylesheet, style & misc. QFile stylesheetFile("/mnt/onboard/.adds/inkbox/eink.qss"); @@ -25,33 +26,44 @@ wifiDialog::wifiDialog(QWidget *parent) : stylesheetFile.close(); this->setModal(true); - ui->stopBtn->setIcon(QIcon(":/resources/stop.png")); - ui->logBtn->setIcon(QIcon(":/resources/file-text.png")); - ui->refreshBtn->setIcon(QIcon(":/resources/refresh.png")); - ui->wifiCheckBox->setStyleSheet("QCheckBox::indicator { width:50px; height: 50px; }"); + ui->wifiCheckBox->setFont(QFont("Inter")); + ui->returnBtn->setFont(QFont("Inter")); + ui->returnBtn->setStyleSheet("font-weight: bold"); + + ui->refreshBtn->setProperty("type", "borderless"); + ui->stopBtn->setProperty("type", "borderless"); + ui->logBtn->setProperty("type", "borderless"); ui->returnBtn->setProperty("type", "borderless"); + ui->refreshBtn->setIcon(QIcon(":/resources/refresh.png")); + ui->stopBtn->setIcon(QIcon(":/resources/stop.png")); + ui->logBtn->setIcon(QIcon(":/resources/log.png")); + // Size QRect screenGeometry = QGuiApplication::screens()[0]->geometry(); - this->setFixedWidth(screenGeometry.width()); + this->setFixedWidth(screenGeometry.width() / 1.1); int halfOfHalfHeight = ((screenGeometry.height() / 2) / 2) / 2; int finalHeight = screenGeometry.height() - halfOfHalfHeight * 2; this->setFixedHeight(finalHeight); - this->move(0, halfOfHalfHeight); + + // Centering dialog + int x = (screenGeometry.width() - this->width()) / 2; + int y = (screenGeometry.height() - this->height()) / 2; + this->move(x, y); // Button sizes - ui->stopBtn->setFixedWidth(screenGeometry.width() / 8); - ui->logBtn->setFixedWidth(screenGeometry.width() / 8); - ui->refreshBtn->setFixedWidth(screenGeometry.width() / 8); + ui->stopBtn->setFixedWidth(screenGeometry.width() / 9); + ui->logBtn->setFixedWidth(screenGeometry.width() / 9); + ui->refreshBtn->setFixedWidth(screenGeometry.width() / 9); - int heighIncrease = 20; - ui->stopBtn->setFixedHeight(ui->stopBtn->height() + heighIncrease); - ui->logBtn->setFixedHeight(ui->logBtn->height() + heighIncrease); - ui->refreshBtn->setFixedHeight(ui->refreshBtn->height() + heighIncrease); + int heightIncrease = 20; + ui->stopBtn->setFixedHeight(ui->stopBtn->height() + heightIncrease); + ui->logBtn->setFixedHeight(ui->logBtn->height() + heightIncrease); + ui->refreshBtn->setFixedHeight(ui->refreshBtn->height() + heightIncrease); - // And set wifi checkbox state. also ignore this first call + // Set Wi-Fi checkbox state. Ignore the first call. global::wifi::wifiState currentWifiState = checkWifiState(); if(currentWifiState != global::wifi::wifiState::disabled and currentWifiState != global::wifi::wifiState::unknown) { ui->wifiCheckBox->setChecked(true); @@ -65,7 +77,7 @@ wifiDialog::wifiDialog(QWidget *parent) : } // To avoid confusion with reconnecting - QTimer::singleShot(2000, this, SLOT(theWatcher())); + QTimer::singleShot(2000, this, SLOT(watcher())); } wifiDialog::~wifiDialog() @@ -362,7 +374,7 @@ void wifiDialog::refreshScreenSlot() { * prepare_changing_wifi.sh - Kills everything, prepares to changing network * smarter_time_sync.sh - Syncs time * toggle.sh - Turns on/off Wi-Fi adapter - * list_networks.bin - Lists networks + * list_networks - Lists networks * check_wifi_password.sh - Checks Wi-Fi network password * watcher() first watches at processes that could kill other ones */ @@ -399,9 +411,9 @@ void wifiDialog::watcher() { return void(); } - bool listing = checkProcessName("list_networks.bin"); + bool listing = checkProcessName("list_networks"); if(listing == true) { - setStatusText("Scanning networks ..."); + setStatusText("Scanning available networks"); QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } @@ -433,13 +445,13 @@ void wifiDialog::watcher() { bool connecting = checkProcessName("connection_manager.sh"); if(connecting == true) { forceRefresh = true; - setStatusText("Connecting to Wi-Fi network ..."); + setStatusText("Connecting to Wi-Fi network"); QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } - if(ui->statusLabel->text() != "Idling") { - setStatusText("Idling"); + if(ui->statusLabel->text() != "Idle") { + setStatusText("Idle"); } if(unlockCheckBox == true) { diff --git a/src/widgets/dialogs/wifi/wifidialog.ui b/src/widgets/dialogs/wifi/wifidialog.ui index e8a2854..d7e7018 100644 --- a/src/widgets/dialogs/wifi/wifidialog.ui +++ b/src/widgets/dialogs/wifi/wifidialog.ui @@ -6,7 +6,7 @@ 0 0 - 783 + 603 679 @@ -35,33 +35,21 @@ 10 - - - - 0 - 0 - - + - + + + QFrame::Plain + - Qt::Horizontal + Qt::Vertical - - QSizePolicy::Fixed - - - - 40 - 20 - - - + @@ -77,23 +65,23 @@ - + + + QFrame::Plain + - Qt::Horizontal + Qt::Vertical - - QSizePolicy::Fixed - - - - 40 - 20 - - - + - + + + + 0 + 0 + + @@ -115,20 +103,7 @@ - - - - - - 9 - - - - Wifi status - - - - + @@ -147,8 +122,14 @@ + + + 75 + true + + - Wifi + Wi-Fi @@ -163,6 +144,18 @@ + + + + + 9 + + + + Wi-Fi status + + + @@ -188,16 +181,22 @@ 0 0 - 765 - 567 + 585 + 557 0 + + 0 + + + 0 + - 9 + 0 0 @@ -238,7 +237,7 @@ QFrame::Plain - 3 + 2 Qt::Horizontal @@ -253,6 +252,12 @@ 0 + + + 75 + true + + Return diff --git a/src/widgets/dialogs/wifi/wifilogger.cpp b/src/widgets/dialogs/wifi/wifilogger.cpp index e891c4a..afcd735 100644 --- a/src/widgets/dialogs/wifi/wifilogger.cpp +++ b/src/widgets/dialogs/wifi/wifilogger.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "wifilogger.h" #include "ui_wifilogger.h" @@ -10,6 +11,17 @@ wifilogger::wifilogger(QWidget *parent) : ui(new Ui::wifilogger) { ui->setupUi(this); + this->setFont(QFont("u001")); + // 'Not currently connected to a network' label + ui->label_8->setFont(QFont("Inter")); + ui->returnBtn->setFont(QFont("Inter")); + ui->nameLabel->setFont(QFont("Inter")); + ui->allLogsText->setFont(QFont("Noto Mono")); + ui->fancyLogsText->setFont(QFont("Noto Mono")); + ui->nameLabel->setStyleSheet("font-weight: bold"); + ui->returnBtn->setStyleSheet("font-weight: bold"); + ui->allLogsText->setStyleSheet("font-size: 7pt"); + ui->fancyLogsText->setStyleSheet("font-size: 7pt"); // Stylesheet, style & misc. QFile stylesheetFile("/mnt/onboard/.adds/inkbox/eink.qss"); @@ -20,16 +32,29 @@ wifilogger::wifilogger(QWidget *parent) : // Scroll bar // Needed for the nia. - ui->allLogsText->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 50px; }"); - ui->fancyLogsText->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 50px; }"); - + // ui->allLogsText->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 50px; }"); + // ui->fancyLogsText->verticalScrollBar()->setStyleSheet("QScrollBar:vertical { width: 50px; }"); log("Entered wifilogger", className); setWifiInfoPage(); + ui->previousBtn->setProperty("type", "borderless"); + ui->nextBtn->setProperty("type", "borderless"); + ui->returnBtn->setProperty("type", "borderless"); ui->refreshBtn->setProperty("type", "borderless"); - ui->nextBtn->setFixedWidth(70); - ui->previousBtn->setFixedWidth(70); + // Size + QRect screenGeometry = QGuiApplication::screens()[0]->geometry(); + this->setFixedWidth(screenGeometry.width() / 1.2); + + int halfOfHalfHeight = ((screenGeometry.height() / 2) / 2) / 2; + int finalHeight = screenGeometry.height() - halfOfHalfHeight * 2.4; + + this->setFixedHeight(finalHeight); + + // Centering dialog + int x = (screenGeometry.width() - this->width()) / 2; + int y = (screenGeometry.height() - this->height()) / 2; + this->move(x, y); } wifilogger::~wifilogger() @@ -92,8 +117,9 @@ void wifilogger::changePage() { } else if(currentPage == 2) { setAllLogsPage(); - } else { - log("This shouldnt happen.", className); + } + else { + log("This shouldn't happen", className); } } diff --git a/src/widgets/dialogs/wifi/wifilogger.h b/src/widgets/dialogs/wifi/wifilogger.h index 4b3b069..c7bcf39 100644 --- a/src/widgets/dialogs/wifi/wifilogger.h +++ b/src/widgets/dialogs/wifi/wifilogger.h @@ -29,7 +29,7 @@ private: */ int currentPage = 0; QFile fancyLogs = QFile("/external_root/run/wifi_stats"); - QFile allLogs = QFile("/external_root/run/wifi_logs"); + QFile allLogs = QFile("/external_root/var/log/wifi.log"); bool waitingForFile = false; private slots: diff --git a/src/widgets/dialogs/wifi/wifilogger.ui b/src/widgets/dialogs/wifi/wifilogger.ui index 6424d22..74c54eb 100644 --- a/src/widgets/dialogs/wifi/wifilogger.ui +++ b/src/widgets/dialogs/wifi/wifilogger.ui @@ -6,327 +6,412 @@ 0 0 - 755 - 613 + 476 + 273 + + + 0 + 0 + + Dialog - - - 0 + + + true - - 3 - - - + + + + 0 + 0 + 442 + 208 + + + + + 9 + + + 9 + + + 9 + + + 9 + - - - - - - 75 - true - - - - Network name: - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 75 - false - true - - - - IP address: - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 75 - true - - - - Mask: - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 75 - true - - - - Gateway: - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 75 - true - - - - Password protected: - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 75 - true - - - - Signal strength: - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 75 - true - - - - MAC address: - - - - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - 75 - true - - + 0 - - No wifi connected - - - Qt::AlignCenter - - - - - - - - - - - Qt::NoTextInteraction - - - - - - - - - - - Qt::NoTextInteraction + + 0 + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + 75 + true + + + + Network name: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + false + true + + + + IP address: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + true + + + + Mask: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + true + + + + Gateway: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + true + + + + Password protected: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + true + + + + Signal strength: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 75 + true + + + + MAC address: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 75 + true + + + + 0 + + + Not currently connected to a network + + + Qt::AlignCenter + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::NoTextInteraction + + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Qt::NoTextInteraction + + + + + @@ -361,28 +446,17 @@ + + + 75 + true + + TextLabel - - - - - 0 - 0 - - - - - - - - :/resources/refresh.png:/resources/refresh.png - - - @@ -409,10 +483,69 @@ + + + + 0 + + + + + + 0 + 0 + + + + + 75 + true + + + + Return + + + + + + + QFrame::Plain + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + + + + + :/resources/refresh.png:/resources/refresh.png + + + + + - - - Return + + + QFrame::Plain + + + 2 + + + Qt::Horizontal From edffb452bd4d030b756959b1913215b42fd45856 Mon Sep 17 00:00:00 2001 From: Nicolas Mailloux Date: Mon, 22 Aug 2022 17:10:09 -0400 Subject: [PATCH 14/19] Wi-Fi: password -> passphrase --- src/widgets/dialogs/generaldialog.cpp | 2 +- src/widgets/dialogs/wifi/connectiondialog.cpp | 146 +++++++++--------- src/widgets/dialogs/wifi/connectiondialog.h | 16 +- src/widgets/dialogs/wifi/connectiondialog.ui | 4 +- src/widgets/dialogs/wifi/wifidialog.cpp | 18 +-- src/widgets/dialogs/wifi/wifidialog.ui | 30 +++- src/widgets/dialogs/wifi/wifilogger.cpp | 2 +- src/widgets/dialogs/wifi/wifilogger.ui | 6 +- 8 files changed, 128 insertions(+), 96 deletions(-) diff --git a/src/widgets/dialogs/generaldialog.cpp b/src/widgets/dialogs/generaldialog.cpp index 2d01897..a3c78eb 100644 --- a/src/widgets/dialogs/generaldialog.cpp +++ b/src/widgets/dialogs/generaldialog.cpp @@ -497,7 +497,7 @@ void generalDialog::on_okBtn_clicked() if(!global::keyboard::keyboardText.isEmpty()) { if(global::keyboard::keyboardText.count() < 8) { global::toast::delay = 3000; - showToast("Minimum password length is 8 characters"); + showToast("Minimum passphrase length is 8 characters"); } else { generalDialog::close(); diff --git a/src/widgets/dialogs/wifi/connectiondialog.cpp b/src/widgets/dialogs/wifi/connectiondialog.cpp index 8f6392f..cc097ab 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.cpp +++ b/src/widgets/dialogs/wifi/connectiondialog.cpp @@ -21,7 +21,7 @@ connectiondialog::connectiondialog(QWidget *parent) : ui->cancelBtn->setStyleSheet("font-size: 9pt"); ui->connectBtn->setStyleSheet("font-size: 9pt"); - ui->showPasswordBtn->setStyleSheet("font-size: 9pt"); + ui->showPassphraseBtn->setStyleSheet("font-size: 9pt"); // Size QRect screenGeometry = QGuiApplication::screens()[0]->geometry(); @@ -42,12 +42,12 @@ void connectiondialog::applyVariables() { ui->signalLabel->setText(QString::number(connectedNetworkData.signal) + "%"); if(connectedNetworkData.encryption == false) { - ui->showPasswordBtn->hide(); - ui->passwordTextEdit->setText("No password required"); - ui->passwordTextEdit->setDisabled(true); + ui->showPassphraseBtn->hide(); + ui->passphraseTextEdit->setText("No passphrase required"); + ui->passphraseTextEdit->setDisabled(true); } else { - if(passwordDatabase.exists() == false) { + if(passphraseDatabase.exists() == false) { log("Creating empty database", className); // https://forum.qt.io/topic/104791/how-i-can-create-json-format-in-qt/5 QJsonObject root; @@ -56,33 +56,33 @@ void connectiondialog::applyVariables() { root["list"] = array; newJsonDocument.setObject(root); - passwordDatabase.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); - passwordDatabase.write(newJsonDocument.toJson()); - passwordDatabase.flush(); - passwordDatabase.close(); + passphraseDatabase.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); + passphraseDatabase.write(newJsonDocument.toJson()); + passphraseDatabase.flush(); + passphraseDatabase.close(); } - QString password = searchDatabase(connectedNetworkData.name); - if(password.isEmpty() == false) { - log("Found password: " + password, className); - ui->showPasswordBtn->setIcon(QIcon(":/resources/show.png")); - showedPassword = false; - savedPassword = password; + QString passphrase = searchDatabase(connectedNetworkData.name); + if(passphrase.isEmpty() == false) { + log("Found passphrase: " + passphrase, className); + ui->showPassphraseBtn->setIcon(QIcon(":/resources/show.png")); + showedPassphrase = false; + savedPassphrase = passphrase; - ui->passwordTextEdit->setText("********"); + ui->passphraseTextEdit->setText("********"); } else { - log("No password found", className); - ui->passwordTextEdit->setText("No password was saved"); - showedPassword = true; - ui->showPasswordBtn->hide(); + log("No passphrase found", className); + ui->passphraseTextEdit->setText("No passphrase was saved"); + showedPassphrase = true; + ui->showPassphraseBtn->hide(); } } } QString connectiondialog::searchDatabase(QString key) { - passwordDatabase.open(QIODevice::ReadOnly | QIODevice::Text); - QString fileRead = passwordDatabase.readAll(); - passwordDatabase.close(); + passphraseDatabase.open(QIODevice::ReadOnly | QIODevice::Text); + QString fileRead = passphraseDatabase.readAll(); + passphraseDatabase.close(); QJsonDocument jsonDocument = QJsonDocument::fromJson(fileRead.toUtf8()); if(jsonDocument["list"].isArray() == true) { @@ -92,9 +92,9 @@ QString connectiondialog::searchDatabase(QString key) { QString searchedName = jsonMainObject.keys().first().toUtf8(); log("Found in database: '" + searchedName + "'", className); if(searchedName == key) { - QString returnedPassword = jsonMainObject.value(key).toString(); - log("Searched name '" + searchedName + "' matched '" + key + "' and the password is: '" + returnedPassword + "'", className); - return returnedPassword; + QString returnedPassphrase = jsonMainObject.value(key).toString(); + log("Searched name '" + searchedName + "' matched '" + key + "' and the passphrase is: '" + returnedPassphrase + "'", className); + return returnedPassphrase; } else { log("Searched name '" + searchedName + "' doesn't match '" + key + "'", className); @@ -107,14 +107,14 @@ QString connectiondialog::searchDatabase(QString key) { } } -void connectiondialog::writeToDatabase(QString name, QString password) { +void connectiondialog::writeToDatabase(QString name, QString passphrase) { if(searchDatabase(name).isEmpty() == false) { removeFromDatabase(name); } - passwordDatabase.open(QIODevice::ReadOnly | QIODevice::Text); - QString fileRead = passwordDatabase.readAll(); - passwordDatabase.close(); + passphraseDatabase.open(QIODevice::ReadOnly | QIODevice::Text); + QString fileRead = passphraseDatabase.readAll(); + passphraseDatabase.close(); QJsonDocument jsonDocument = QJsonDocument::fromJson(fileRead.toUtf8()); if(jsonDocument["list"].isArray() == true) { @@ -123,7 +123,7 @@ void connectiondialog::writeToDatabase(QString name, QString password) { // https://stackoverflow.com/questions/26804660/how-to-initialize-qjsonobject-from-qstring // I hoped this would be easier - QJsonObject newObject = QJsonDocument::fromJson(QString("{\"" + name + "\" : \"" + password + "\" }").toUtf8()).object(); + QJsonObject newObject = QJsonDocument::fromJson(QString("{\"" + name + "\" : \"" + passphrase + "\" }").toUtf8()).object(); jsonArray.append(newObject); QJsonDocument newJsonDocument; @@ -131,10 +131,10 @@ void connectiondialog::writeToDatabase(QString name, QString password) { root["list"] = jsonArray; newJsonDocument.setObject(root); - passwordDatabase.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); - passwordDatabase.write(newJsonDocument.toJson()); - passwordDatabase.flush(); - passwordDatabase.close(); + passphraseDatabase.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); + passphraseDatabase.write(newJsonDocument.toJson()); + passphraseDatabase.flush(); + passphraseDatabase.close(); } else { log("Something went horribly wrong", className); @@ -142,9 +142,9 @@ void connectiondialog::writeToDatabase(QString name, QString password) { } void connectiondialog::removeFromDatabase(QString name) { - passwordDatabase.open(QIODevice::ReadOnly | QIODevice::Text); - QString fileRead = passwordDatabase.readAll(); - passwordDatabase.close(); + passphraseDatabase.open(QIODevice::ReadOnly | QIODevice::Text); + QString fileRead = passphraseDatabase.readAll(); + passphraseDatabase.close(); QJsonDocument jsonDocument = QJsonDocument::fromJson(fileRead.toUtf8()); int counter = 0; @@ -169,10 +169,10 @@ void connectiondialog::removeFromDatabase(QString name) { root["list"] = jsonArray; newJsonDocument.setObject(root); - passwordDatabase.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); - passwordDatabase.write(newJsonDocument.toJson()); - passwordDatabase.flush(); - passwordDatabase.close(); + passphraseDatabase.open(QFile::WriteOnly | QFile::Text | QFile::Truncate); + passphraseDatabase.write(newJsonDocument.toJson()); + passphraseDatabase.flush(); + passphraseDatabase.close(); } else { log("ERROR: tried to remove from database, but couldn't find key", className); @@ -186,18 +186,18 @@ void connectiondialog::on_cancelBtn_clicked() this->close(); } -void connectiondialog::on_passwordTextEdit_selectionChanged() +void connectiondialog::on_passphraseTextEdit_selectionChanged() { - ui->passwordTextEdit->setSelection(0, 0); + ui->passphraseTextEdit->setSelection(0, 0); } -void connectiondialog::on_passwordTextEdit_cursorPositionChanged(int oldpos, int newpos) +void connectiondialog::on_passphraseTextEdit_cursorPositionChanged(int oldpos, int newpos) { log("Detected click on text edit widget", className); if(cursorPositionIgnore == true) { if(newpos != 0) { - if(showedPassword == true) { - ui->passwordTextEdit->setCursorPosition(0); + if(showedPassphrase == true) { + ui->passphraseTextEdit->setCursorPosition(0); global::keyboard::keyboardDialog = true; global::keyboard::wifiPassphraseDialog = true; global::keyboard::keyboardText = ""; @@ -212,19 +212,19 @@ void connectiondialog::on_passwordTextEdit_cursorPositionChanged(int oldpos, int global::keyboard::keyboardDialog = false; global::keyboard::wifiPassphraseDialog = false; if(global::keyboard::keyboardText.isEmpty() == false) { - // A bit hacky: avoid summoning the keyboard back when the text is changing (and the cursor too) showedPassword shouldn't be used for this, but it works and adding another boolean would start being messy - showedPassword = false; - ui->passwordTextEdit->setText(global::keyboard::keyboardText); - ui->showPasswordBtn->setIcon(QIcon(":/resources/hide.png")); - ui->showPasswordBtn->show(); - showedPassword = true; - savedPassword = global::keyboard::keyboardText; - ui->showPasswordBtn->show(); + // A bit hacky: avoid summoning the keyboard back when the text is changing (and the cursor too) showedPassphrase shouldn't be used for this, but it works and adding another boolean would start being messy + showedPassphrase = false; + ui->passphraseTextEdit->setText(global::keyboard::keyboardText); + ui->showPassphraseBtn->setIcon(QIcon(":/resources/hide.png")); + ui->showPassphraseBtn->show(); + showedPassphrase = true; + savedPassphrase = global::keyboard::keyboardText; + ui->showPassphraseBtn->show(); } global::keyboard::keyboardText = ""; } else { - log("Password is not saved; ignoring text edit call", className); + log("Passphrase is not saved; ignoring text edit call", className); } } } @@ -238,17 +238,17 @@ void connectiondialog::showToastSlot(QString message) { emit showToastSignal(message); } -void connectiondialog::on_showPasswordBtn_clicked() +void connectiondialog::on_showPassphraseBtn_clicked() { - if(showedPassword == false) { - ui->showPasswordBtn->setIcon(QIcon(":/resources/hide.png")); - ui->passwordTextEdit->setText(savedPassword); - showedPassword = true; + if(showedPassphrase == false) { + ui->showPassphraseBtn->setIcon(QIcon(":/resources/hide.png")); + ui->passphraseTextEdit->setText(savedPassphrase); + showedPassphrase = true; } else { - showedPassword = false; - ui->showPasswordBtn->setIcon(QIcon(":/resources/show.png")); - ui->passwordTextEdit->setText("********"); + showedPassphrase = false; + ui->showPassphraseBtn->setIcon(QIcon(":/resources/show.png")); + ui->passphraseTextEdit->setText("********"); } } @@ -259,28 +259,28 @@ void connectiondialog::refreshScreenSlot() { void connectiondialog::on_connectBtn_clicked() { - QString finalPassword; + QString finalPassphrase; if(connectedNetworkData.encryption == false) { - finalPassword = "NONE"; + finalPassphrase = "NONE"; } else { - if(savedPassword.isEmpty() == false) { - finalPassword = savedPassword; - writeToDatabase(connectedNetworkData.name, savedPassword); + if(savedPassphrase.isEmpty() == false) { + finalPassphrase = savedPassphrase; + writeToDatabase(connectedNetworkData.name, savedPassphrase); } else { - showToastSlot("Provide a password first"); + showToastSlot("Provide a passphrase first"); return void(); } } - passwordForReconnecting = finalPassword; + passphraseForReconnecting = finalPassphrase; ui->cancelBtn->setEnabled(false); if(checkWifiState() == global::wifi::wifiState::configured) { string_writeconfig("/opt/ibxd", "stop_wifi_operations\n"); } writeFile("/run/wifi_network_essid", connectedNetworkData.name); - writeFile("/run/wifi_network_passphrase", finalPassword); + writeFile("/run/wifi_network_passphrase", finalPassphrase); finalConnectWait(); } @@ -307,7 +307,7 @@ void connectiondialog::finalConnectWait() { // This will be deleted later in MainWindow's icon updater if it failed. It is also deleted in the Wi-Fi stop script log("Writing to config directory with connection information data", className); string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid", connectedNetworkData.name.toStdString()); - string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/passphrase", passwordForReconnecting.toStdString()); + string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/passphrase", passphraseForReconnecting.toStdString()); this->deleteLater(); this->close(); diff --git a/src/widgets/dialogs/wifi/connectiondialog.h b/src/widgets/dialogs/wifi/connectiondialog.h index 7dc7799..ab4e1d0 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.h +++ b/src/widgets/dialogs/wifi/connectiondialog.h @@ -18,7 +18,7 @@ public: ~connectiondialog(); global::wifi::wifiNetworkData connectedNetworkData; QString currentlyConnectedNetworkName; - QFile passwordDatabase = QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/passwords.json"); + QFile passphraseDatabase = QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/passphrases.json"); signals: void showToastSignal(QString message); @@ -34,25 +34,25 @@ private slots: // 1. It's modular // 2. Those operations are rare QString searchDatabase(QString key); - void writeToDatabase(QString name, QString password); + void writeToDatabase(QString name, QString passphrase); void removeFromDatabase(QString name); void finalConnectWait(); bool checkIfWifiBusy(); void on_cancelBtn_clicked(); - void on_passwordTextEdit_selectionChanged(); - void on_passwordTextEdit_cursorPositionChanged(int arg1, int arg2); - void on_showPasswordBtn_clicked(); + void on_passphraseTextEdit_selectionChanged(); + void on_passphraseTextEdit_cursorPositionChanged(int arg1, int arg2); + void on_showPassphraseBtn_clicked(); void on_connectBtn_clicked(); private: Ui::connectiondialog *ui; bool cursorPositionIgnore = false; - bool showedPassword; - QString savedPassword; + bool showedPassphrase; + QString savedPassphrase; int waitTry = 0; - QString passwordForReconnecting; + QString passphraseForReconnecting; }; #endif // CONNECTIONDIALOG_H diff --git a/src/widgets/dialogs/wifi/connectiondialog.ui b/src/widgets/dialogs/wifi/connectiondialog.ui index 408f162..b8ea219 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.ui +++ b/src/widgets/dialogs/wifi/connectiondialog.ui @@ -71,7 +71,7 @@ - + BlankCursor @@ -81,7 +81,7 @@ - + 0 diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 70d7b12..f0b34c6 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -72,7 +72,7 @@ wifiDialog::wifiDialog(QWidget *parent) : ui->refreshBtn->click(); } else { wifiButtonEnabled = true; - ui->stopBtn->setStyleSheet("background-color: gray;"); + ui->stopBtn->setStyleSheet("background-color: lightGray;"); ui->stopBtn->setEnabled(false); } @@ -105,7 +105,7 @@ void wifiDialog::launchRefresh() { // Order is important if(scanInProgress == false) { scanInProgress = true; - ui->refreshBtn->setStyleSheet("background-color: gray;"); + ui->refreshBtn->setStyleSheet("background-color: lightGray;"); ui->refreshBtn->setEnabled(false); elapsedSeconds = 0; @@ -218,7 +218,7 @@ void wifiDialog::refreshNetworksList() { int countVec = 0; int vectorNetworkLocation = 9999; for(global::wifi::wifiNetworkData wifiNetwork: pureNetworkList) { - if(currentWifiNetwork.isEmpty() == false and wifiNetwork.name.contains(currentWifiNetwork) == true) { + if(currentWifiNetwork.isEmpty() == false and wifiNetwork.name == currentWifiNetwork) { log("Found current network in vector", className); vectorNetworkLocation = countVec; currentNetwork = wifiNetwork.name; @@ -308,9 +308,9 @@ void wifiDialog::on_wifiCheckBox_stateChanged(int arg1) } else { log("Turning Wi-Fi off", className); QTimer::singleShot(0, this, SLOT(turnOffWifi())); - // To inform the wifi icon GUI to don't show the connected/failed to connect message + // To inform the Wi-Fi icon updater to not show the connected/failed to connect message string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped", "true"); - ui->stopBtn->setStyleSheet("background-color: gray;"); + ui->stopBtn->setStyleSheet("background-color: lightGray;"); ui->stopBtn->setEnabled(false); } emit killNetworkWidgets(); @@ -375,7 +375,7 @@ void wifiDialog::refreshScreenSlot() { * smarter_time_sync.sh - Syncs time * toggle.sh - Turns on/off Wi-Fi adapter * list_networks - Lists networks - * check_wifi_password.sh - Checks Wi-Fi network password + * check_wifi_passphrase.sh - Checks Wi-Fi network passphrase * watcher() first watches at processes that could kill other ones */ @@ -426,10 +426,10 @@ void wifiDialog::watcher() { return void(); } - bool passwordCheck = checkProcessName("check_wifi_password.sh"); - if(passwordCheck == true) { + bool passphraseCheck = checkProcessName("check_wifi_passphrase.sh"); + if(passphraseCheck == true) { forceRefresh = true; - setStatusText("Checking Wi-Fi network password"); + setStatusText("Checking Wi-Fi network passphrase"); QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } diff --git a/src/widgets/dialogs/wifi/wifidialog.ui b/src/widgets/dialogs/wifi/wifidialog.ui index d7e7018..99832d5 100644 --- a/src/widgets/dialogs/wifi/wifidialog.ui +++ b/src/widgets/dialogs/wifi/wifidialog.ui @@ -124,10 +124,14 @@ + Inter 75 true + + font-family: Inter + Wi-Fi @@ -144,18 +148,42 @@ + + + + QFrame::Plain + + + Qt::Horizontal + + + + u001 9 + + padding-left: 10px; font-family: u001 + Wi-Fi status + + + + QFrame::Plain + + + Qt::Horizontal + + + @@ -182,7 +210,7 @@ 0 0 585 - 557 + 538 diff --git a/src/widgets/dialogs/wifi/wifilogger.cpp b/src/widgets/dialogs/wifi/wifilogger.cpp index afcd735..51682c1 100644 --- a/src/widgets/dialogs/wifi/wifilogger.cpp +++ b/src/widgets/dialogs/wifi/wifilogger.cpp @@ -70,7 +70,7 @@ void wifilogger::setWifiInfoPage() { } else { ui->stackedWidget->setCurrentIndex(1); - ui->nameLabel->setText("Not currently connected to a network"); + ui->nameLabel->setText("Not connected to a network"); } } diff --git a/src/widgets/dialogs/wifi/wifilogger.ui b/src/widgets/dialogs/wifi/wifilogger.ui index 74c54eb..0aedc12 100644 --- a/src/widgets/dialogs/wifi/wifilogger.ui +++ b/src/widgets/dialogs/wifi/wifilogger.ui @@ -229,7 +229,7 @@ - Password protected: + Passphrase-protected: @@ -349,10 +349,14 @@ + Inter 75 true + + font-family: Inter; font-weight: bold + 0 From 3116d7d91809b2f9463003284e736764311b46f5 Mon Sep 17 00:00:00 2001 From: Nicolas Mailloux Date: Mon, 22 Aug 2022 23:52:57 -0400 Subject: [PATCH 15/19] Wi-Fi: Fixes --- src/homeWidget/mainwindow.cpp | 10 ++++------ src/widgets/dialogs/wifi/network.cpp | 6 +++--- src/widgets/dialogs/wifi/network.ui | 6 +++--- src/widgets/dialogs/wifi/wifidialog.cpp | 13 ++++++------- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/homeWidget/mainwindow.cpp b/src/homeWidget/mainwindow.cpp index fe9f5c7..67a0df0 100644 --- a/src/homeWidget/mainwindow.cpp +++ b/src/homeWidget/mainwindow.cpp @@ -778,13 +778,12 @@ void MainWindow::updateWifiIcon() { if(currentWifiState == global::wifi::wifiState::disabled) { if(isConnecting == true) { if(checkconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped") == false) { - QString wifiName = readFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid").replace("\n", ""); if(isReconnecting == true) { - showToast("Failed to reconnnect to " + wifiName); + showToast("Reconnection failed"); isReconnecting = false; } else { - showToast("Failed to connect to " + wifiName); + showToast("Connection failed"); } isConnecting = false; QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid").remove(); @@ -806,13 +805,12 @@ void MainWindow::updateWifiIcon() { if(currentWifiState == global::wifi::wifiState::configured) { if(isConnecting == true) { setDefaultWorkDir(); - QString wifiName = readFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/essid").replace("\n", ""); if(isReconnecting == true) { - showToast("Reconnected successfully to " + wifiName); + showToast("Reconnection successful"); isReconnecting = false; } else { - showToast("Connected successfully to " + wifiName); + showToast("Connection successful"); } isConnecting = false; QFile("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped").remove(); diff --git a/src/widgets/dialogs/wifi/network.cpp b/src/widgets/dialogs/wifi/network.cpp index cd53f04..0864a38 100644 --- a/src/widgets/dialogs/wifi/network.cpp +++ b/src/widgets/dialogs/wifi/network.cpp @@ -73,13 +73,13 @@ void network::applyVariables() { if(mainData.signal >= 0 and mainData.signal <= 25) { ui->signalStrengthIcon->setIcon(QIcon(":/resources/wifi-0.png")); } - else if(mainData.signal >= 25 and mainData.signal <= 50) { + else if(mainData.signal >= 25 and mainData.signal < 50) { ui->signalStrengthIcon->setIcon(QIcon(":/resources/wifi-25.png")); } - else if(mainData.signal >= 50 and mainData.signal <= 75) { + else if(mainData.signal >= 50 and mainData.signal < 75) { ui->signalStrengthIcon->setIcon(QIcon(":/resources/wifi-50.png")); } - else if(mainData.signal >= 75 and mainData.signal <= 100) { + else if(mainData.signal >= 75 and mainData.signal < 100) { ui->signalStrengthIcon->setIcon(QIcon(":/resources/wifi-75.png")); } else if(mainData.signal == 100) { diff --git a/src/widgets/dialogs/wifi/network.ui b/src/widgets/dialogs/wifi/network.ui index 0c50b56..3a44c2f 100644 --- a/src/widgets/dialogs/wifi/network.ui +++ b/src/widgets/dialogs/wifi/network.ui @@ -51,16 +51,16 @@ - 12 + 16 - 3 + 10 3 - 3 + 10 diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index f0b34c6..c697b9d 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -91,8 +91,7 @@ void wifiDialog::on_refreshBtn_clicked() if(checkWifiState() == global::wifi::wifiState::disabled) { if(refreshFromWatcher == true) { refreshFromWatcher = false; - emit showToast("To scan, turn on wi-fi first"); - log("To scan, turn on wi-fi first", className); + emit showToast("To scan, turn Wi-Fi on first"); } } else { @@ -159,7 +158,7 @@ void wifiDialog::refreshNetworksList() { log("Network name is empty", className); } else { - log("Network name is: " + singleData, className); + log("Network name is: '" + singleData + "'", className); } singleNetwork.name = singleData; } @@ -287,7 +286,7 @@ void wifiDialog::refreshNetworksList() { } scannedAtLeastOnce = true; ui->refreshBtn->setEnabled(true); - ui->refreshBtn->setStyleSheet("background-color:white;"); + ui->refreshBtn->setStyleSheet("background-color: white;"); scanInProgress = false; secondScanTry = false; } @@ -297,11 +296,11 @@ void wifiDialog::on_wifiCheckBox_stateChanged(int arg1) { if(ignoreCheckBoxCall == false) { connectedNetworkDataParentSet = false; - log("wifi dialog clicked: " + QString::number(arg1), className); + log("Wi-Fi dialog checkbox clicked: " + QString::number(arg1), className); if(wifiButtonEnabled == true) { if(arg1 == 2) { log("Turning Wi-Fi on", className); - // the watcher will scan wifi + // The watcher will scan Wi-Fi QTimer::singleShot(0, this, SLOT(turnOnWifi())); ui->stopBtn->setStyleSheet("background-color: white;"); ui->stopBtn->setEnabled(true); @@ -373,7 +372,7 @@ void wifiDialog::refreshScreenSlot() { * get_dhcp.sh - Gets dhcp addresses * prepare_changing_wifi.sh - Kills everything, prepares to changing network * smarter_time_sync.sh - Syncs time - * toggle.sh - Turns on/off Wi-Fi adapter + * toggle.sh - Turns Wi-Fi adapter on/off * list_networks - Lists networks * check_wifi_passphrase.sh - Checks Wi-Fi network passphrase * watcher() first watches at processes that could kill other ones From 95fb6af4c2965e135b09c1ddb7ada169a2df3b9c Mon Sep 17 00:00:00 2001 From: Nicolas Mailloux Date: Tue, 23 Aug 2022 11:43:25 -0400 Subject: [PATCH 16/19] Various fixes --- inkbox.pro | 6 +-- src/encfs/encryptionmanager.cpp | 4 +- src/encfs/encryptionmanager.h | 2 +- src/homeWidget/mainwindow.cpp | 24 +++++---- src/homeWidget/mainwindow.h | 4 +- src/reader/reader.cpp | 36 ++++++-------- src/resources/hide.png | Bin 1026 -> 13055 bytes src/resources/show.png | Bin 993 -> 13072 bytes src/settings/koboxsettings.cpp | 2 +- src/settings/koboxsettings.h | 4 +- src/settings/settings.cpp | 2 +- src/settings/settings.h | 4 +- .../{usbms_splash.cpp => usbmsSplash.cpp} | 23 ++++----- src/splash/{usbms_splash.h => usbmsSplash.h} | 12 ++--- .../{usbms_splash.ui => usbmsSplash.ui} | 4 +- src/widgets/dialogs/generaldialog.cpp | 2 +- src/widgets/dialogs/generaldialog.h | 4 +- src/widgets/dialogs/kobox/koboxappsdialog.cpp | 2 +- src/widgets/dialogs/kobox/koboxappsdialog.h | 4 +- src/widgets/dialogs/wifi/connectiondialog.cpp | 46 ++++++++++++++---- src/widgets/dialogs/wifi/connectiondialog.ui | 4 +- 21 files changed, 108 insertions(+), 81 deletions(-) rename src/splash/{usbms_splash.cpp => usbmsSplash.cpp} (94%) rename src/splash/{usbms_splash.h => usbmsSplash.h} (66%) rename src/splash/{usbms_splash.ui => usbmsSplash.ui} (97%) diff --git a/inkbox.pro b/inkbox.pro index a0c19d7..926528e 100644 --- a/inkbox.pro +++ b/inkbox.pro @@ -57,7 +57,7 @@ SOURCES += \ src/settings/settingschooser.cpp \ src/widgets/text/textwidget.cpp \ src/widgets/interfaceWidgets/toast.cpp \ - src/splash/usbms_splash.cpp \ + src/splash/usbmsSplash.cpp \ src/apps/userapps.cpp \ src/widgets/virtualKeyboard/virtualkeyboard.cpp \ src/widgets/virtualKeyboard/virtualkeypad.cpp \ @@ -100,7 +100,7 @@ HEADERS += \ src/settings/settingschooser.h \ src/widgets/text/textwidget.h \ src/widgets/interfaceWidgets/toast.h \ - src/splash/usbms_splash.h \ + src/splash/usbmsSplash.h \ src/apps/userapps.h \ src/widgets/virtualKeyboard/virtualkeyboard.h \ src/widgets/virtualKeyboard/virtualkeypad.h \ @@ -140,7 +140,7 @@ FORMS += \ src/settings/settingschooser.ui \ src/widgets/text/textwidget.ui \ src/widgets/interfaceWidgets/toast.ui \ - src/splash/usbms_splash.ui \ + src/splash/usbmsSplash.ui \ src/apps/userapps.ui \ src/widgets/virtualKeyboard/virtualkeyboard.ui \ src/widgets/virtualKeyboard/virtualkeypad.ui \ diff --git a/src/encfs/encryptionmanager.cpp b/src/encfs/encryptionmanager.cpp index 34a5e46..7493770 100644 --- a/src/encfs/encryptionmanager.cpp +++ b/src/encfs/encryptionmanager.cpp @@ -8,7 +8,7 @@ #include #include #include -#include "usbms_splash.h" +#include "usbmsSplash.h" #include "functions.h" encryptionManager::encryptionManager(QWidget *parent) : @@ -346,7 +346,7 @@ void encryptionManager::on_usbmsBtn_clicked() { log("Showing USBMS splash", className); global::usbms::launchUsbms = true; - usbmsWindow = new usbms_splash(); + usbmsWindow = new usbmsSplash(); usbmsWindow->setAttribute(Qt::WA_DeleteOnClose); usbmsWindow->setGeometry(QRect(QPoint(0,0), screen()->geometry ().size())); usbmsWindow->show(); diff --git a/src/encfs/encryptionmanager.h b/src/encfs/encryptionmanager.h index ac14c91..e90fdb3 100644 --- a/src/encfs/encryptionmanager.h +++ b/src/encfs/encryptionmanager.h @@ -48,7 +48,7 @@ private: toast * toastWindow; hourglassAnimationWidget * hourglassAnimationWidgetWindow; alert * alertWindow; - usbms_splash *usbmsWindow; + usbmsSplash *usbmsWindow; }; #endif // ENCRYPTIONMANAGER_H diff --git a/src/homeWidget/mainwindow.cpp b/src/homeWidget/mainwindow.cpp index 67a0df0..4b3406f 100644 --- a/src/homeWidget/mainwindow.cpp +++ b/src/homeWidget/mainwindow.cpp @@ -634,13 +634,13 @@ void MainWindow::setBatteryIcon() { stdIconHeight = sH / 16; QPixmap chargingPixmap(":/resources/battery_charging.png"); - QPixmap scaledChargingPixmap = chargingPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); + QPixmap scaledChargingPixmap = chargingPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); QPixmap fullPixmap(":/resources/battery_full.png"); - QPixmap scaledFullPixmap = fullPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); + QPixmap scaledFullPixmap = fullPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); QPixmap halfPixmap(":/resources/battery_half.png"); - QPixmap scaledHalfPixmap = halfPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); + QPixmap scaledHalfPixmap = halfPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); QPixmap emptyPixmap(":/resources/battery_empty.png"); - QPixmap scaledEmptyPixmap = emptyPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); + QPixmap scaledEmptyPixmap = emptyPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); // Checking battery level and status, then displaying the relevant icon on batteryIcon if(isUsbPluggedIn() == true) { @@ -664,13 +664,13 @@ void MainWindow::setBatteryIcon() { stdIconWidth = sW / 19; stdIconHeight = sH / 19; QPixmap chargingPixmap(":/resources/battery_charging.png"); - QPixmap scaledChargingPixmap = chargingPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); + QPixmap scaledChargingPixmap = chargingPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); QPixmap fullPixmap(":/resources/battery_full.png"); - QPixmap scaledFullPixmap = fullPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); + QPixmap scaledFullPixmap = fullPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); QPixmap halfPixmap(":/resources/battery_half.png"); - QPixmap scaledHalfPixmap = halfPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); + QPixmap scaledHalfPixmap = halfPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); QPixmap emptyPixmap(":/resources/battery_empty.png"); - QPixmap scaledEmptyPixmap = emptyPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); + QPixmap scaledEmptyPixmap = emptyPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); // Checking battery level and status, then displaying the relevant icon on batteryIcon if(isUsbPluggedIn() == true) { @@ -711,11 +711,12 @@ void MainWindow::setInitialBrightness() { // Coming from OOBE setup; not doing that fancy stuff again ;p QFile::remove("/tmp/oobe-inkbox_completed"); pre_set_brightness(brightness_value); + log("Ignoring cinematic brightness call because it has already been done", className); } else { // Fancy brightness fade-in - if(checkconfig("/tmp/inkbox-cinematic_brightness_auto") == true) { - QFile::remove("/tmp/inkbox-cinematic_brightness_auto"); + if(checkconfig("/tmp/inkbox-cinematicBrightness_auto") == true) { + QFile::remove("/tmp/inkbox-cinematicBrightness_auto"); cinematicBrightness(brightness_value, 2); } else { @@ -723,6 +724,9 @@ void MainWindow::setInitialBrightness() { string_writeconfig("/tmp/inkbox-cinematicBrightness_ran", "true"); cinematicBrightness(brightness_value, 0); } + else { + log("Ignoring cinematic brightness call because it has already been done", className); + } } } } diff --git a/src/homeWidget/mainwindow.h b/src/homeWidget/mainwindow.h index 539dfdd..b793017 100644 --- a/src/homeWidget/mainwindow.h +++ b/src/homeWidget/mainwindow.h @@ -8,7 +8,7 @@ #include "reader.h" #include "quit.h" #include "alert.h" -#include "usbms_splash.h" +#include "usbmsSplash.h" #include "brightnessdialog.h" #include "generaldialog.h" #include "koboxsettings.h" @@ -106,7 +106,7 @@ private: reader * readerWindow; quit * quitWindow; alert * alertWindow; - usbms_splash * usbmsWindow; + usbmsSplash * usbmsWindow; brightnessDialog * brightnessDialogWindow; generalDialog * generalDialogWindow; koboxSettings * koboxSettingsWindow; diff --git a/src/reader/reader.cpp b/src/reader/reader.cpp index 5893852..2c95bff 100644 --- a/src/reader/reader.cpp +++ b/src/reader/reader.cpp @@ -366,30 +366,24 @@ reader::reader(QWidget *parent) : float sH = QGuiApplication::screens()[0]->size().height(); // Defining what the icons' size will be if(checkconfig("/opt/inkbox_genuine") == true) { + float stdIconWidth; + float stdIconHeight; if(global::deviceID == "n705\n" or global::deviceID == "n905\n" or global::deviceID == "n613\n" or global::deviceID == "n236\n" or global::deviceID == "n437\n" or global::deviceID == "n306\n" or global::deviceID == "kt\n" or global::deviceID == "emu\n") { - float stdIconWidth = sW / 16; - float stdIconHeight = sW / 16; - QPixmap chargingPixmap(":/resources/battery_charging.png"); - scaledChargingPixmap = chargingPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); - QPixmap fullPixmap(":/resources/battery_full.png"); - scaledFullPixmap = fullPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); - QPixmap halfPixmap(":/resources/battery_half.png"); - scaledHalfPixmap = halfPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); - QPixmap emptyPixmap(":/resources/battery_empty.png"); - scaledEmptyPixmap = emptyPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); + stdIconWidth = sW / 16; + stdIconHeight = sW / 16; } else { - float stdIconWidth = sW / 19; - float stdIconHeight = sH / 19; - QPixmap chargingPixmap(":/resources/battery_charging.png"); - scaledChargingPixmap = chargingPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); - QPixmap fullPixmap(":/resources/battery_full.png"); - scaledFullPixmap = fullPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); - QPixmap halfPixmap(":/resources/battery_half.png"); - scaledHalfPixmap = halfPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); - QPixmap emptyPixmap(":/resources/battery_empty.png"); - scaledEmptyPixmap = emptyPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio); + stdIconWidth = sW / 19; + stdIconHeight = sH / 19; } + QPixmap chargingPixmap(":/resources/battery_charging.png"); + scaledChargingPixmap = chargingPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); + QPixmap fullPixmap(":/resources/battery_full.png"); + scaledFullPixmap = fullPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); + QPixmap halfPixmap(":/resources/battery_half.png"); + scaledHalfPixmap = halfPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); + QPixmap emptyPixmap(":/resources/battery_empty.png"); + scaledEmptyPixmap = emptyPixmap.scaled(stdIconWidth, stdIconHeight, Qt::KeepAspectRatio, Qt::SmoothTransformation); } else { float stdIconWidth = sW / 19; @@ -1282,7 +1276,7 @@ void reader::on_homeBtn_clicked() // Remount tmpfs string_writeconfig("/inkbox/remount", "true"); // Specify cinematic brightness mode - string_writeconfig("/tmp/inkbox-cinematic_brightness_auto", "true"); + string_writeconfig("/tmp/inkbox-cinematicBrightness_auto", "true"); // Relaunching process quit_restart(); diff --git a/src/resources/hide.png b/src/resources/hide.png index 5b643fd51b9569b5168578465098ab842f5613f8..3d2533ae71734c9850335fa58b43729c60012d6f 100644 GIT binary patch literal 13055 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 XfW~u&<2~uk2tZfM@J9J{)Z_mFxG4Ao literal 1026 zcmV+d1pWJoP)Px&yh%hsRA@u(n1QiPK@5iTDxd>YfC^9nDnJFO02QDDRDcRl0V+TTRKR>@b0#l# zlkB-?=AJuaXYRav-`$hVpZxigy=QXb>+Hn+m;V5coxxrPE{e#{V>?zo-vhw;4^R)9CM!qpw3@w4!u4F5IzGqea}R6_aJ&Tum%L#yCEWEj~AbBI%<7vpP?u3zlzBB zL+Lk?(FzEhye%U4JI+@90?Z2$dB0XTqCSv;AkswgLe<+~AF9WB&t`#Sjcf+Qr>0(j z!Xcuoa(r1tcv*V!-h*fVQxSPt4N3+8I~fQZW6kmz3PQg}B67(&4ES4>Y*YXcsn70! ztl5#qI`s~uK5!_an-_;L6C(gV^2i*~QMHIbWa?BYRBR9krPL6_XqY4NI#Q5&-;}b# z=2?o9NOL%!?>N9nhAHT{R+c-4}Kb0FC8gdkEU#d~Z6)SlGm& zh)#gudzD+{mB1{^1F*dR)trx1U={=i+h>R{N)s(I_ttD+zm6sU+{lnirB0S&Y!cOP z?(~Yp5>@4Qri7TsVN^}uFQDzi7U_@XToRnWh3#ceqa58QEKScvbZ{Vnf(c5cm0Mwe!U0n+KV&M>sXX|&ip(&583ES+h6b3cAv0g2F{a(W%ltA$pEn5&*uD(Ly*Ox;UM(c0H{IJ zK6B8OQvD#U^aW21jN{Oo$_3njs({eDM5t7i3|Irb%eQ_{HUPwn!x;$etWOY7He?ri zVau+pu)9EJ0bm42r~_UV#mTh(AP{Q+SXxnFM6#kfJs_GT`}|ZU4gp{t(jRjvKpn~b zFK_CsDw5I-J6TN(v$z$28Jdjtt^%wHvrQh_6T4K#9jgPKykN^Mx07*qoM6N<$g8e|wQ2+n{ diff --git a/src/resources/show.png b/src/resources/show.png index 0c0be28daacb9c7d185fe3ef7cbc47560b4a4605..0694e9ca122f444bc2543c6873731045945a3f84 100644 GIT binary patch literal 13072 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

Yh+XWl-eC*2`QJUrYlY7hh;>YG=csrF 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 literal 993 zcmV<710MW|P)Px&n@L1LRA@u(nSqfFK@f)fA|L}qfCvx)B0vO)01+SpWN;!t1c(3`5CQd7_5Z40 zznSUTw|8}}YNtxw+MDj_zyE)Fdgo5;l8=*19=~k>E}FrOfsKKc8Q3J`3A}1%cg*aT zncekwJoBFM+swZC^Jjnl;_p{+u$F;GX7)G)y)+oWyf?ECOAR&uSO71~>{-b0vFpnY zhTfRjtEG;X0ze+`%?i5_T;llUnL`E& zc4}cy!UJdWS~9{PK*})#fb4zp49X#azjXbUi%d))G5Cu>*!1_R#8d#Fo8VPVh=mP@ z{;Q0uDq%w~NNhA%gMC0@&|nQfsDd5Xj{u_%sRa&06Tg2Bs5bY{yPZ~P-J1ILSUm!4CwBO8Fa-a{t-_2nN3V7 zWgjs1ipyD)(FmH&`LNgoODo-?GRoRf*E3S0bW-M276C!O(>loLlXOnZRJ!t9>d_ao zT6TnuRsx$=D-rvosxi!+aPwRmHFE@@!-IfWaMaAf9CXKir==z`&)iX0OEX7rCBWbP z%sDtDt9Cj{L-HDRk;sX_TAz#BfCM+{t>|j$L^Xydd{qH*M~G7bJ4iZtF zwq%>E$IsTX6RrRdFpi^~ct-}2%hA^%Nn3n{;V)hmbY&B5X8>qEnU9})0s`IiK_gkT z_5#7um9ii5EeDCo7YNPjyaa$wUV!9V1Ra9$T7?Y8YZVHDu2+y(tJCGOfWRxc?Z7Mr zAVcUTb5+HeY3!JT)?sqC8C(rO4#*b&dR3setAttribute(Qt::WA_DeleteOnClose); usbmsWindow->setGeometry(QRect(QPoint(0,0), screen()->geometry ().size())); usbmsWindow->show(); diff --git a/src/settings/koboxsettings.h b/src/settings/koboxsettings.h index 43b254a..fbced89 100644 --- a/src/settings/koboxsettings.h +++ b/src/settings/koboxsettings.h @@ -4,7 +4,7 @@ #include #include "generaldialog.h" -#include "usbms_splash.h" +#include "usbmsSplash.h" namespace Ui { class koboxSettings; @@ -33,7 +33,7 @@ private slots: private: Ui::koboxSettings *ui; generalDialog *generalDialogWindow; - usbms_splash *usbmsWindow; + usbmsSplash *usbmsWindow; }; #endif // KOBOXSETTINGS_H diff --git a/src/settings/settings.cpp b/src/settings/settings.cpp index d48f141..3133a81 100644 --- a/src/settings/settings.cpp +++ b/src/settings/settings.cpp @@ -901,7 +901,7 @@ void settings::usbms_launch() log("Showing USBMS splash", className); global::usbms::launchUsbms = true; - usbmsWindow = new usbms_splash(); + usbmsWindow = new usbmsSplash(); usbmsWindow->setAttribute(Qt::WA_DeleteOnClose); usbmsWindow->setGeometry(QRect(QPoint(0,0), screen()->geometry ().size())); usbmsWindow->show(); diff --git a/src/settings/settings.h b/src/settings/settings.h index 4ad0205..0089283 100644 --- a/src/settings/settings.h +++ b/src/settings/settings.h @@ -3,7 +3,7 @@ #include -#include +#include #include "generaldialog.h" #include "otamanager.h" #include "toast.h" @@ -79,7 +79,7 @@ signals: private: Ui::settings *ui; - usbms_splash *usbmsWindow; + usbmsSplash *usbmsWindow; generalDialog *generalDialogWindow; otaManager *otaManagerWindow; toast *toastWindow; diff --git a/src/splash/usbms_splash.cpp b/src/splash/usbmsSplash.cpp similarity index 94% rename from src/splash/usbms_splash.cpp rename to src/splash/usbmsSplash.cpp index 774b9bd..b99fa90 100644 --- a/src/splash/usbms_splash.cpp +++ b/src/splash/usbmsSplash.cpp @@ -1,5 +1,5 @@ -#include "usbms_splash.h" -#include "ui_usbms_splash.h" +#include "usbmsSplash.h" +#include "ui_usbmsSplash.h" #include #include @@ -7,12 +7,12 @@ #include "functions.h" -usbms_splash::usbms_splash(QWidget *parent) : +usbmsSplash::usbmsSplash(QWidget *parent) : QWidget(parent), - ui(new Ui::usbms_splash) + ui(new Ui::usbmsSplash) { ui->setupUi(this); - usbms_splash::setFont(QFont("u001")); + usbmsSplash::setFont(QFont("u001")); ui->label->setFont(QFont("Inter")); // Getting the screen's size @@ -60,11 +60,11 @@ usbms_splash::usbms_splash(QWidget *parent) : if(global::usbms::launchUsbms == true) { global::usbms::launchUsbms = false; - usbms_launch(); + usbmsLaunch(); } } -void usbms_splash::usbms_launch() +void usbmsSplash::usbmsLaunch() { log("Entering USBMS session", className); string_writeconfig("/tmp/in_usbms", "true"); @@ -169,16 +169,17 @@ void usbms_splash::usbms_launch() usbms_t->start(); } -usbms_splash::~usbms_splash() +usbmsSplash::~usbmsSplash() { delete ui; } -void usbms_splash::brightnessDown() { +void usbmsSplash::brightnessDown() { cinematicBrightness(0, 1); + writeFile("/tmp/inkbox-cinematicBrightness_ran", "false"); } -void usbms_splash::quit_restart() { +void usbmsSplash::quit_restart() { // If existing, cleaning bookconfig_mount mountpoint string_writeconfig("/opt/ibxd", "bookconfig_unmount\n"); @@ -188,7 +189,7 @@ void usbms_splash::quit_restart() { qApp->quit(); } -void usbms_splash::restartServices() { +void usbmsSplash::restartServices() { // Restarting USBNet // NOTE: USBNet is only started if required conditions are met (see https://github.com/Kobo-InkBox/rootfs/blob/master/etc/init.d/usbnet) string_writeconfig("/opt/ibxd", "usbnet_start\n"); diff --git a/src/splash/usbms_splash.h b/src/splash/usbmsSplash.h similarity index 66% rename from src/splash/usbms_splash.h rename to src/splash/usbmsSplash.h index 3d8d8af..cce0038 100644 --- a/src/splash/usbms_splash.h +++ b/src/splash/usbmsSplash.h @@ -4,22 +4,22 @@ #include namespace Ui { -class usbms_splash; +class usbmsSplash; } -class usbms_splash : public QWidget +class usbmsSplash : public QWidget { Q_OBJECT public: QString className = this->metaObject()->className(); - explicit usbms_splash(QWidget *parent = nullptr); - ~usbms_splash(); + explicit usbmsSplash(QWidget *parent = nullptr); + ~usbmsSplash(); float sW; float sH; QString massStorageModule; - void usbms_launch(); + void usbmsLaunch(); private slots: void brightnessDown(); @@ -27,7 +27,7 @@ private slots: void restartServices(); private: - Ui::usbms_splash *ui; + Ui::usbmsSplash *ui; }; #endif // USBMS_SPLASH_H diff --git a/src/splash/usbms_splash.ui b/src/splash/usbmsSplash.ui similarity index 97% rename from src/splash/usbms_splash.ui rename to src/splash/usbmsSplash.ui index 5b4fde8..57b7cda 100644 --- a/src/splash/usbms_splash.ui +++ b/src/splash/usbmsSplash.ui @@ -1,7 +1,7 @@ - usbms_splash - + usbmsSplash + 0 diff --git a/src/widgets/dialogs/generaldialog.cpp b/src/widgets/dialogs/generaldialog.cpp index a3c78eb..c3d0db0 100644 --- a/src/widgets/dialogs/generaldialog.cpp +++ b/src/widgets/dialogs/generaldialog.cpp @@ -337,7 +337,7 @@ void generalDialog::on_okBtn_clicked() global::usbms::usbmsDialog = false; global::usbms::launchUsbms = true; - usbmsWindow = new usbms_splash(); + usbmsWindow = new usbmsSplash(); usbmsWindow->setAttribute(Qt::WA_DeleteOnClose); usbmsWindow->setGeometry(QRect(QPoint(0,0), screen()->geometry ().size())); usbmsWindow->show(); diff --git a/src/widgets/dialogs/generaldialog.h b/src/widgets/dialogs/generaldialog.h index a1e742c..9f91738 100644 --- a/src/widgets/dialogs/generaldialog.h +++ b/src/widgets/dialogs/generaldialog.h @@ -3,7 +3,7 @@ #include -#include "usbms_splash.h" +#include "usbmsSplash.h" #include "textwidget.h" #include "virtualkeyboard.h" #include "virtualkeypad.h" @@ -73,7 +73,7 @@ private slots: private: Ui::generalDialog *ui; - usbms_splash *usbmsWindow; + usbmsSplash *usbmsWindow; textwidget *textwidgetWindow; virtualkeyboard *keyboardWidget; virtualkeypad *keypadWidget; diff --git a/src/widgets/dialogs/kobox/koboxappsdialog.cpp b/src/widgets/dialogs/kobox/koboxappsdialog.cpp index 2a8dd8f..2ad0c50 100644 --- a/src/widgets/dialogs/kobox/koboxappsdialog.cpp +++ b/src/widgets/dialogs/kobox/koboxappsdialog.cpp @@ -166,7 +166,7 @@ void koboxAppsDialog::on_launchBtn_clicked() // Re-use USBMS splash window for KoBox splash, since it's pretty much the same layout log("Showing KoBox splash", className); - usbmsSplashWindow = new usbms_splash(); + usbmsSplashWindow = new usbmsSplash(); usbmsSplashWindow->setAttribute(Qt::WA_DeleteOnClose); usbmsSplashWindow->setGeometry(QRect(QPoint(0,0), screen()->geometry().size())); usbmsSplashWindow->show(); diff --git a/src/widgets/dialogs/kobox/koboxappsdialog.h b/src/widgets/dialogs/kobox/koboxappsdialog.h index f3861f3..fa95967 100644 --- a/src/widgets/dialogs/kobox/koboxappsdialog.h +++ b/src/widgets/dialogs/kobox/koboxappsdialog.h @@ -4,7 +4,7 @@ #include #include -#include "usbms_splash.h" +#include "usbmsSplash.h" namespace Ui { class koboxAppsDialog; @@ -36,7 +36,7 @@ signals: private: Ui::koboxAppsDialog *ui; - usbms_splash *usbmsSplashWindow; + usbmsSplash *usbmsSplashWindow; }; #endif // KOBOXAPPSDIALOG_H diff --git a/src/widgets/dialogs/wifi/connectiondialog.cpp b/src/widgets/dialogs/wifi/connectiondialog.cpp index cc097ab..eaf01d0 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.cpp +++ b/src/widgets/dialogs/wifi/connectiondialog.cpp @@ -12,6 +12,9 @@ connectiondialog::connectiondialog(QWidget *parent) : { ui->setupUi(this); this->setFont(QFont("u001")); + ui->passphraseTextEdit->setFont(QFont("Noto Mono")); + ui->label->setFont(QFont("Inter")); + ui->label_2->setFont(QFont("Inter")); // Stylesheet, style & misc. QFile stylesheetFile("/mnt/onboard/.adds/inkbox/eink.qss"); @@ -19,15 +22,29 @@ connectiondialog::connectiondialog(QWidget *parent) : this->setStyleSheet(stylesheetFile.readAll()); stylesheetFile.close(); - ui->cancelBtn->setStyleSheet("font-size: 9pt"); - ui->connectBtn->setStyleSheet("font-size: 9pt"); - ui->showPassphraseBtn->setStyleSheet("font-size: 9pt"); + ui->cancelBtn->setProperty("type", "borderless"); + ui->connectBtn->setProperty("type", "borderless"); + ui->showPassphraseBtn->setProperty("type", "borderless"); + + ui->label->setStyleSheet("font-weight: bold"); + ui->label_2->setStyleSheet("font-weight: bold"); + + ui->cancelBtn->setIcon(QIcon(":/resources/close.png")); + ui->connectBtn->setIcon(QIcon(":/resources/arrow-right.png")); // Size QRect screenGeometry = QGuiApplication::screens()[0]->geometry(); - this->setFixedWidth(screenGeometry.width()); + this->setFixedWidth(screenGeometry.width() / 1.5); + int halfOfHalfHeight = ((screenGeometry.height() / 2) / 2) / 2; + int finalHeight = screenGeometry.height() - halfOfHalfHeight * 6.3; + this->setFixedHeight(finalHeight); + + // Centering dialog + int x = (screenGeometry.width() - this->width()) / 2; + int y = (screenGeometry.height() - this->height()) / 2; + this->move(x, y); } connectiondialog::~connectiondialog() @@ -63,12 +80,17 @@ void connectiondialog::applyVariables() { } QString passphrase = searchDatabase(connectedNetworkData.name); if(passphrase.isEmpty() == false) { - log("Found passphrase: " + passphrase, className); + log("Found passphrase: '" + passphrase + "'", className); ui->showPassphraseBtn->setIcon(QIcon(":/resources/show.png")); showedPassphrase = false; savedPassphrase = passphrase; - ui->passphraseTextEdit->setText("********"); + int passphraseLength = passphrase.length(); + QString hiddenPassphrase; + for(int i = 0; i < passphraseLength; i++) { + hiddenPassphrase.append("•"); + } + ui->passphraseTextEdit->setText(hiddenPassphrase); } else { log("No passphrase found", className); @@ -224,12 +246,12 @@ void connectiondialog::on_passphraseTextEdit_cursorPositionChanged(int oldpos, i global::keyboard::keyboardText = ""; } else { - log("Passphrase is not saved; ignoring text edit call", className); + log("Passphrase is not saved; ignoring text edit widget call", className); } } } else { - log("Ignoring click on text edit", className); + log("Ignoring click on text edit widget", className); cursorPositionIgnore = true; } } @@ -248,7 +270,13 @@ void connectiondialog::on_showPassphraseBtn_clicked() else { showedPassphrase = false; ui->showPassphraseBtn->setIcon(QIcon(":/resources/show.png")); - ui->passphraseTextEdit->setText("********"); + + int passphraseLength = searchDatabase(connectedNetworkData.name).length(); + QString hiddenPassphrase; + for(int i = 0; i < passphraseLength; i++) { + hiddenPassphrase.append("•"); + } + ui->passphraseTextEdit->setText(hiddenPassphrase); } } diff --git a/src/widgets/dialogs/wifi/connectiondialog.ui b/src/widgets/dialogs/wifi/connectiondialog.ui index b8ea219..7c97ade 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.ui +++ b/src/widgets/dialogs/wifi/connectiondialog.ui @@ -22,7 +22,7 @@ - Cancel + @@ -62,7 +62,7 @@ - Connect + From 4bb87485e0a50ed856931ae1a1d754552da7a3b2 Mon Sep 17 00:00:00 2001 From: Nicolas Mailloux Date: Sun, 28 Aug 2022 01:03:45 -0400 Subject: [PATCH 17/19] Wi-Fi fixes --- src/widgets/dialogs/wifi/connectiondialog.cpp | 51 ++++++++++++++++--- src/widgets/dialogs/wifi/network.cpp | 11 +++- src/widgets/dialogs/wifi/wifidialog.cpp | 34 +++++++------ src/widgets/dialogs/wifi/wifidialog.ui | 6 +-- src/widgets/dialogs/wifi/wifilogger.ui | 9 ++-- 5 files changed, 79 insertions(+), 32 deletions(-) diff --git a/src/widgets/dialogs/wifi/connectiondialog.cpp b/src/widgets/dialogs/wifi/connectiondialog.cpp index eaf01d0..e783dc2 100644 --- a/src/widgets/dialogs/wifi/connectiondialog.cpp +++ b/src/widgets/dialogs/wifi/connectiondialog.cpp @@ -34,10 +34,21 @@ connectiondialog::connectiondialog(QWidget *parent) : // Size QRect screenGeometry = QGuiApplication::screens()[0]->geometry(); - this->setFixedWidth(screenGeometry.width() / 1.5); + if(global::deviceID == "n705\n") { + this->setFixedWidth(screenGeometry.width() / 1.2); + } + else { + this->setFixedWidth(screenGeometry.width() / 1.5); + } int halfOfHalfHeight = ((screenGeometry.height() / 2) / 2) / 2; - int finalHeight = screenGeometry.height() - halfOfHalfHeight * 6.3; + int finalHeight; + if(global::deviceID == "n705\n") { + finalHeight = screenGeometry.height() - halfOfHalfHeight * 5.9; + } + else { + finalHeight = screenGeometry.height() - halfOfHalfHeight * 6.3; + } this->setFixedHeight(finalHeight); @@ -53,8 +64,21 @@ connectiondialog::~connectiondialog() } void connectiondialog::applyVariables() { - // Here, for some devices it will be propably needed to limit the size - ui->nameLabel->setText(connectedNetworkData.name); + // Limit name size + int truncateThreshold; + if(global::deviceID == "n705\n") { + truncateThreshold = 20; + } + else { + truncateThreshold = 30; + } + int nameLength = connectedNetworkData.name.length(); + QString name = connectedNetworkData.name; + if(nameLength > truncateThreshold) { + name.chop(nameLength - truncateThreshold); + name.append("..."); + } + ui->nameLabel->setText(name); ui->macLabel->setText(connectedNetworkData.mac); ui->signalLabel->setText(QString::number(connectedNetworkData.signal) + "%"); @@ -272,11 +296,22 @@ void connectiondialog::on_showPassphraseBtn_clicked() ui->showPassphraseBtn->setIcon(QIcon(":/resources/show.png")); int passphraseLength = searchDatabase(connectedNetworkData.name).length(); - QString hiddenPassphrase; - for(int i = 0; i < passphraseLength; i++) { - hiddenPassphrase.append("•"); + if(passphraseLength != 0) { + QString hiddenPassphrase; + for(int i = 0; i < passphraseLength; i++) { + hiddenPassphrase.append("•"); + } + ui->passphraseTextEdit->setText(hiddenPassphrase); + } + else { + // This is executed if the user asks to hide the passphrase but it isn't saved yet (upon first connection to a network) + QString hiddenPassphrase; + int passphraseLength = ui->passphraseTextEdit->text().length(); + for(int i = 0; i < passphraseLength; i++) { + hiddenPassphrase.append("•"); + } + ui->passphraseTextEdit->setText(hiddenPassphrase); } - ui->passphraseTextEdit->setText(hiddenPassphrase); } } diff --git a/src/widgets/dialogs/wifi/network.cpp b/src/widgets/dialogs/wifi/network.cpp index 0864a38..cc50f43 100644 --- a/src/widgets/dialogs/wifi/network.cpp +++ b/src/widgets/dialogs/wifi/network.cpp @@ -40,10 +40,17 @@ void network::applyVariables() { ui->signalStrengthLabel->setText(QString::number(mainData.signal) + percent); // Limit name size + int truncateThreshold; + if(global::deviceID == "n705\n") { + truncateThreshold = 12; + } + else { + truncateThreshold = 20; + } int nameLength = mainData.name.length(); QString name = mainData.name; - if(nameLength > 20) { - name.chop(nameLength - 20); + if(nameLength > truncateThreshold) { + name.chop(nameLength - truncateThreshold); name.append("..."); } ui->nameLabel->setText(name); diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index c697b9d..df25b1a 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -54,14 +54,16 @@ wifiDialog::wifiDialog(QWidget *parent) : this->move(x, y); // Button sizes - ui->stopBtn->setFixedWidth(screenGeometry.width() / 9); - ui->logBtn->setFixedWidth(screenGeometry.width() / 9); - ui->refreshBtn->setFixedWidth(screenGeometry.width() / 9); - - int heightIncrease = 20; - ui->stopBtn->setFixedHeight(ui->stopBtn->height() + heightIncrease); - ui->logBtn->setFixedHeight(ui->logBtn->height() + heightIncrease); - ui->refreshBtn->setFixedHeight(ui->refreshBtn->height() + heightIncrease); + if(global::deviceID == "n705\n") { + ui->refreshBtn->setStyleSheet("padding: 20px;"); + ui->stopBtn->setStyleSheet("padding: 20px;"); + ui->logBtn->setStyleSheet("padding: 20px;"); + } + else { + ui->refreshBtn->setStyleSheet("padding: 25px;"); + ui->stopBtn->setStyleSheet("padding: 25px;"); + ui->logBtn->setStyleSheet("padding: 25px;"); + } // Set Wi-Fi checkbox state. Ignore the first call. global::wifi::wifiState currentWifiState = checkWifiState(); @@ -72,12 +74,12 @@ wifiDialog::wifiDialog(QWidget *parent) : ui->refreshBtn->click(); } else { wifiButtonEnabled = true; - ui->stopBtn->setStyleSheet("background-color: lightGray;"); + ui->stopBtn->setStyleSheet(ui->stopBtn->styleSheet() + "background-color: lightGray;"); ui->stopBtn->setEnabled(false); } // To avoid confusion with reconnecting - QTimer::singleShot(2000, this, SLOT(watcher())); + QTimer::singleShot(0, this, SLOT(watcher())); } wifiDialog::~wifiDialog() @@ -104,7 +106,7 @@ void wifiDialog::launchRefresh() { // Order is important if(scanInProgress == false) { scanInProgress = true; - ui->refreshBtn->setStyleSheet("background-color: lightGray;"); + ui->refreshBtn->setStyleSheet(ui->refreshBtn->styleSheet() + "background-color: lightGray;"); ui->refreshBtn->setEnabled(false); elapsedSeconds = 0; @@ -122,7 +124,7 @@ void wifiDialog::refreshWait() { if(fullList.exists() == false and formattedList.exists() == false) { if(elapsedSeconds == 6) { emit showToast("Failed to get networks list"); - ui->refreshBtn->setStyleSheet("background-color:white;"); + ui->refreshBtn->setStyleSheet(ui->refreshBtn->styleSheet() + "background-color: white;"); ui->refreshBtn->setEnabled(true); scanInProgress = false; } @@ -199,7 +201,7 @@ void wifiDialog::refreshNetworksList() { log("No networks found, skipping", className); showToastSlot("No networks found"); ui->refreshBtn->setEnabled(true); - ui->refreshBtn->setStyleSheet("background-color: white;"); + ui->refreshBtn->setStyleSheet(ui->refreshBtn->styleSheet() + "background-color: white;"); scanInProgress = false; return void(); } @@ -286,7 +288,7 @@ void wifiDialog::refreshNetworksList() { } scannedAtLeastOnce = true; ui->refreshBtn->setEnabled(true); - ui->refreshBtn->setStyleSheet("background-color: white;"); + ui->refreshBtn->setStyleSheet(ui->refreshBtn->styleSheet() + "background-color: white;"); scanInProgress = false; secondScanTry = false; } @@ -302,14 +304,14 @@ void wifiDialog::on_wifiCheckBox_stateChanged(int arg1) log("Turning Wi-Fi on", className); // The watcher will scan Wi-Fi QTimer::singleShot(0, this, SLOT(turnOnWifi())); - ui->stopBtn->setStyleSheet("background-color: white;"); + ui->stopBtn->setStyleSheet(ui->stopBtn->styleSheet() + "background-color: white;"); ui->stopBtn->setEnabled(true); } else { log("Turning Wi-Fi off", className); QTimer::singleShot(0, this, SLOT(turnOffWifi())); // To inform the Wi-Fi icon updater to not show the connected/failed to connect message string_writeconfig("/mnt/onboard/.adds/inkbox/.config/17-wifi_connection_information/stopped", "true"); - ui->stopBtn->setStyleSheet("background-color: lightGray;"); + ui->stopBtn->setStyleSheet(ui->stopBtn->styleSheet() + "background-color: lightGray;"); ui->stopBtn->setEnabled(false); } emit killNetworkWidgets(); diff --git a/src/widgets/dialogs/wifi/wifidialog.ui b/src/widgets/dialogs/wifi/wifidialog.ui index 99832d5..cc46fe0 100644 --- a/src/widgets/dialogs/wifi/wifidialog.ui +++ b/src/widgets/dialogs/wifi/wifidialog.ui @@ -170,7 +170,7 @@ padding-left: 10px; font-family: u001 - Wi-Fi status + @@ -209,8 +209,8 @@ 0 0 - 585 - 538 + 591 + 526 diff --git a/src/widgets/dialogs/wifi/wifilogger.ui b/src/widgets/dialogs/wifi/wifilogger.ui index 0aedc12..2c4a561 100644 --- a/src/widgets/dialogs/wifi/wifilogger.ui +++ b/src/widgets/dialogs/wifi/wifilogger.ui @@ -7,7 +7,7 @@ 0 0 476 - 273 + 317 @@ -30,8 +30,8 @@ 0 0 - 442 - 208 + 460 + 210 @@ -366,6 +366,9 @@ Qt::AlignCenter + + true + From f21857fad90c990f16830b920298b4b7ee3afe30 Mon Sep 17 00:00:00 2001 From: Szybet <53944559+Szybet@users.noreply.github.com> Date: Sun, 28 Aug 2022 17:58:22 +0200 Subject: [PATCH 18/19] fix for only one network scanned and for closing wifi logger --- src/widgets/dialogs/wifi/wifidialog.cpp | 32 ++++++++++++++----------- src/widgets/dialogs/wifi/wifilogger.cpp | 6 ++--- src/widgets/dialogs/wifi/wifilogger.h | 1 + 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index df25b1a..8fdc5b8 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -252,21 +252,24 @@ void wifiDialog::refreshNetworksList() { QVector sortedPureNetworkList; sortedPureNetworkList.append(pureNetworkList.first()); pureNetworkList.removeFirst(); - for(global::wifi::wifiNetworkData wifiNetwork: pureNetworkList) { - bool stopIterating = false; - int counter = 0; - for(global::wifi::wifiNetworkData wifiNetworkToSort: sortedPureNetworkList) { - if(stopIterating == false) { - if(wifiNetwork.signal >= wifiNetworkToSort.signal) { - sortedPureNetworkList.insert(counter, wifiNetwork); - stopIterating = true; + // Possible fix for a segment fault + if(pureNetworkList.isEmpty() == false) { + for(global::wifi::wifiNetworkData wifiNetwork: pureNetworkList) { + bool stopIterating = false; + int counter = 0; + for(global::wifi::wifiNetworkData wifiNetworkToSort: sortedPureNetworkList) { + if(stopIterating == false) { + if(wifiNetwork.signal >= wifiNetworkToSort.signal) { + sortedPureNetworkList.insert(counter, wifiNetwork); + stopIterating = true; + } + counter = counter + 1; } - counter = counter + 1; } - } - // This happens if it's the smallest value, so insert it at the end - if(stopIterating == false) { - sortedPureNetworkList.append(wifiNetwork); + // This happens if it's the smallest value, so insert it at the end + if(stopIterating == false) { + sortedPureNetworkList.append(wifiNetwork); + } } } log("There are " + QString::number(sortedPureNetworkList.count()) + " sorted networks", className); @@ -438,7 +441,8 @@ void wifiDialog::watcher() { bool time = checkProcessName("smarter_time_sync.sh"); if(time == true) { forceRefresh = true; - setStatusText("Syncing"); + // Please leave it as "Syncting time" because many people will complain about innacurate time. This info will answer them + setStatusText("Syncing time"); QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); } diff --git a/src/widgets/dialogs/wifi/wifilogger.cpp b/src/widgets/dialogs/wifi/wifilogger.cpp index 51682c1..1b59149 100644 --- a/src/widgets/dialogs/wifi/wifilogger.cpp +++ b/src/widgets/dialogs/wifi/wifilogger.cpp @@ -64,7 +64,7 @@ wifilogger::~wifilogger() void wifilogger::setWifiInfoPage() { if(checkWifiState() == global::wifi::wifiState::configured) { - QTimer::singleShot(0, this, SLOT(getWifiInformation())); + getWifiInformationTimer.singleShot(0, this, SLOT(getWifiInformation())); ui->stackedWidget->setCurrentIndex(0); ui->nameLabel->setText("Network information"); } @@ -128,7 +128,6 @@ void wifilogger::getWifiInformation() { QFile wifiInformationPath = QFile("/external_root/run/wifi_information"); if(waitingForFile == false) { wifiInformationPath.remove(); - log("Sending get_wifi_information ibxd call", className); string_writeconfig("/opt/ibxd", "get_wifi_information\n"); waitingForFile = true; @@ -136,7 +135,7 @@ void wifilogger::getWifiInformation() { if(waitingForFile == true) { if(wifiInformationPath.exists() == false) { - QTimer::singleShot(1000, this, SLOT(getWifiInformation())); + getWifiInformationTimer.singleShot(1000, this, SLOT(getWifiInformation())); return void(); } } @@ -179,6 +178,7 @@ void wifilogger::getWifiInformation() { void wifilogger::on_returnBtn_clicked() { log("Exiting wifilogger", className); + getWifiInformationTimer.stop(); this->deleteLater(); this->close(); } diff --git a/src/widgets/dialogs/wifi/wifilogger.h b/src/widgets/dialogs/wifi/wifilogger.h index c7bcf39..e10bd92 100644 --- a/src/widgets/dialogs/wifi/wifilogger.h +++ b/src/widgets/dialogs/wifi/wifilogger.h @@ -31,6 +31,7 @@ private: QFile fancyLogs = QFile("/external_root/run/wifi_stats"); QFile allLogs = QFile("/external_root/var/log/wifi.log"); bool waitingForFile = false; + QTimer getWifiInformationTimer; private slots: void setWifiInfoPage(); From cb884392d245464dc8e9438b32de85958fdd4d09 Mon Sep 17 00:00:00 2001 From: Nicolas Mailloux Date: Sun, 28 Aug 2022 17:44:59 -0400 Subject: [PATCH 19/19] Wi-Fi: Fixes for Glo HD --- src/widgets/dialogs/wifi/wifidialog.cpp | 7 +++---- src/widgets/dialogs/wifi/wifidialog.ui | 19 ++++--------------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/src/widgets/dialogs/wifi/wifidialog.cpp b/src/widgets/dialogs/wifi/wifidialog.cpp index 8fdc5b8..971987f 100644 --- a/src/widgets/dialogs/wifi/wifidialog.cpp +++ b/src/widgets/dialogs/wifi/wifidialog.cpp @@ -252,7 +252,7 @@ void wifiDialog::refreshNetworksList() { QVector sortedPureNetworkList; sortedPureNetworkList.append(pureNetworkList.first()); pureNetworkList.removeFirst(); - // Possible fix for a segment fault + // Possible fix for a segmentation fault if(pureNetworkList.isEmpty() == false) { for(global::wifi::wifiNetworkData wifiNetwork: pureNetworkList) { bool stopIterating = false; @@ -376,7 +376,7 @@ void wifiDialog::refreshScreenSlot() { * connect_to_network.sh - All-in-one connection manager. Manages everything, used by IPD, should be used for Wi-Fi reconnections after sleeping/booting * get_dhcp.sh - Gets dhcp addresses * prepare_changing_wifi.sh - Kills everything, prepares to changing network - * smarter_time_sync.sh - Syncs time + * timesync.sh - Syncs time * toggle.sh - Turns Wi-Fi adapter on/off * list_networks - Lists networks * check_wifi_passphrase.sh - Checks Wi-Fi network passphrase @@ -438,10 +438,9 @@ void wifiDialog::watcher() { return void(); } - bool time = checkProcessName("smarter_time_sync.sh"); + bool time = checkProcessName("timesync.sh"); if(time == true) { forceRefresh = true; - // Please leave it as "Syncting time" because many people will complain about innacurate time. This info will answer them setStatusText("Syncing time"); QTimer::singleShot(relaunchMs, this, SLOT(watcher())); return void(); diff --git a/src/widgets/dialogs/wifi/wifidialog.ui b/src/widgets/dialogs/wifi/wifidialog.ui index cc46fe0..361f044 100644 --- a/src/widgets/dialogs/wifi/wifidialog.ui +++ b/src/widgets/dialogs/wifi/wifidialog.ui @@ -121,29 +121,18 @@ - - - - Inter - 75 - true - + + + Qt::RightToLeft - font-family: Inter + font-family: Inter; font-weight: bold Wi-Fi - - - - - - -