From 9ea334d08f42f3c362e86499dc3c0ed658bb428c Mon Sep 17 00:00:00 2001 From: keshavbhatt Date: Mon, 5 Apr 2021 02:11:25 +0530 Subject: src init --- src/mainwindow.h | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 src/mainwindow.h (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.h b/src/mainwindow.h new file mode 100644 index 0000000..367d18a --- /dev/null +++ b/src/mainwindow.h @@ -0,0 +1,107 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "notificationpopup.h" +#include "requestinterceptor.h" +#include "settingswidget.h" +#include "webenginepage.h" + +#include "downloadmanagerwidget.h" + + +class MainWindow : public QMainWindow +{ + Q_OBJECT +public: + explicit MainWindow(QWidget *parent = nullptr); +public slots: + void updateWindowTheme(); + void updatePageTheme(); +protected: + void closeEvent(QCloseEvent *event) override; + +private: + QPalette lightPalette; + void createActions(); + void createStatusBar(); + void createTrayIcon(); + void createWebEngine(); + + QSettings settings; + + QRegExp notificationsTitleRegExp; + QIcon trayIconRead; + QIcon trayIconUnread; + + QAction *reloadAction; + QAction *minimizeAction; + QAction *restoreAction; + QAction *aboutAction; + QAction *settingsAction; + QAction *quitAction; + + QMenu *trayIconMenu; + QSystemTrayIcon *trayIcon; + + QWebEngineView *webEngine; + QStatusBar *statusBar; + + + SettingsWidget * settingsWidget = nullptr; + + //void reload(); + + DownloadManagerWidget m_downloadManagerWidget; + QScopedPointer m_otrProfile; + + +private slots: + + void readSettings(); + void handleWebViewTitleChanged(QString title); + void handleLoadStarted(); + void handleLoadProgress(int progress); + void handleDownloadRequested(QWebEngineDownloadItem *download); + void iconActivated(QSystemTrayIcon::ActivationReason reason); + void messageClicked(); + void doReload(); + void showAbout(); + void notify(QString title, QString message); + void showSettings(); + void handleCookieAdded(const QNetworkCookie &cookie); + void handleLoadFinished(bool loaded); + + QString getPageTheme(); + void toggleMute(const bool checked); + void doAppReload(); + void askToReloadPage(); + void updateSettingsUserAgentWidget(); + void fullScreenRequested(QWebEngineFullScreenRequest request); + + void createWebPage(bool offTheRecord =false); + void init_settingWidget(); + void init_globalWebProfile(); +}; + +#endif // MAINWINDOW_H -- cgit v1.2.3 From b36d68f0f3e066226c30ac51127e80e07bcc158a Mon Sep 17 00:00:00 2001 From: keshavbhatt Date: Mon, 5 Apr 2021 09:52:28 +0530 Subject: fixed dark style bg color, update system tray menu according to window state, restore window geometry after minimizing to tray. --- src/mainwindow.cpp | 23 +++++++++++++++++++++-- src/mainwindow.h | 1 + 2 files changed, 22 insertions(+), 2 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 38ecbe6..d27ae79 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -58,7 +58,9 @@ void MainWindow::updateWindowTheme() palette.setColor(QPalette::Window,QColor("#131C21")); //whatsapp dark color palette.setColor(QPalette::WindowText,Qt::white); palette.setColor(QPalette::Disabled,QPalette::WindowText,QColor(127,127,127)); - palette.setColor(QPalette::Base,QColor(42,42,42)); + //palette.setColor(QPalette::Base,QColor(42,42,42)); + palette.setColor(QPalette::Base,QColor(84,84,84)); + palette.setColor(QPalette::AlternateBase,QColor(66,66,66)); palette.setColor(QPalette::ToolTipBase,Qt::white); palette.setColor(QPalette::ToolTipText,QColor(53,53,53)); @@ -245,7 +247,7 @@ void MainWindow::createActions() addAction(minimizeAction); restoreAction = new QAction(tr("&Restore"), this); - connect(restoreAction, &QAction::triggered, this, &QWidget::showNormal); + connect(restoreAction, &QAction::triggered, this, &QWidget::show); addAction(restoreAction); reloadAction = new QAction(tr("Re&load"), this); @@ -277,6 +279,7 @@ void MainWindow::createStatusBar() void MainWindow::createTrayIcon() { trayIconMenu = new QMenu(this); + trayIconMenu->setObjectName("trayIconMenu"); trayIconMenu->addAction(minimizeAction); trayIconMenu->addAction(restoreAction); trayIconMenu->addSeparator(); @@ -288,6 +291,7 @@ void MainWindow::createTrayIcon() trayIcon = new QSystemTrayIcon(trayIconRead, this); trayIcon->setContextMenu(trayIconMenu); + connect(trayIconMenu,SIGNAL(aboutToShow()),this,SLOT(check_window_state())); trayIcon->show(); @@ -297,6 +301,21 @@ void MainWindow::createTrayIcon() this, &MainWindow::iconActivated); } +//check window state and set tray menus +void MainWindow::check_window_state() +{ + QObject *tray_icon_menu = this->findChild("trayIconMenu"); + if(tray_icon_menu != nullptr){ + if(this->isVisible()){ + ((QMenu*)(tray_icon_menu))->actions().at(0)->setDisabled(false); + ((QMenu*)(tray_icon_menu))->actions().at(1)->setDisabled(true); + }else{ + ((QMenu*)(tray_icon_menu))->actions().at(0)->setDisabled(true); + ((QMenu*)(tray_icon_menu))->actions().at(1)->setDisabled(false); + } + } +} + void MainWindow::init_globalWebProfile() { diff --git a/src/mainwindow.h b/src/mainwindow.h index 367d18a..fb68e11 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -102,6 +102,7 @@ private slots: void createWebPage(bool offTheRecord =false); void init_settingWidget(); void init_globalWebProfile(); + void check_window_state(); }; #endif // MAINWINDOW_H -- cgit v1.2.3 From 247580131f26881b6d47966ba97f4a53ebe73583 Mon Sep 17 00:00:00 2001 From: keshavbhatt Date: Mon, 5 Apr 2021 11:13:06 +0530 Subject: lock screen init --- src/WhatsApp.pro | 3 ++ src/mainwindow.cpp | 38 +++++++++++++++++++- src/mainwindow.h | 4 +++ src/settingswidget.ui | 98 ++++++++++++++++++++++++++++++++------------------- 4 files changed, 105 insertions(+), 38 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/WhatsApp.pro b/src/WhatsApp.pro index 5dee6e0..b8ee249 100644 --- a/src/WhatsApp.pro +++ b/src/WhatsApp.pro @@ -38,6 +38,7 @@ SOURCES += \ downloadmanagerwidget.cpp \ downloadwidget.cpp \ elidedlabel.cpp \ + lock.cpp \ main.cpp \ mainwindow.cpp \ settingswidget.cpp \ @@ -53,6 +54,7 @@ HEADERS += \ downloadmanagerwidget.h \ downloadwidget.h \ elidedlabel.h \ + lock.h \ mainwindow.h \ notificationpopup.h \ requestinterceptor.h \ @@ -84,6 +86,7 @@ FORMS += \ certificateerrordialog.ui \ downloadmanagerwidget.ui \ downloadwidget.ui \ + lock.ui \ passworddialog.ui \ settingswidget.ui diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d27ae79..e30f393 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -301,6 +301,42 @@ void MainWindow::createTrayIcon() this, &MainWindow::iconActivated); } + +void MainWindow::init_lock() +{ +// if(lockWidget==nullptr){ +// lockWidget = new Lock(this); +// lockWidget->setObjectName("lockWidget"); +// } +// lockWidget->setWindowFlags(Qt::Widget); +// lockWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); +// lockWidget->setGeometry(this->rect()); + +// connect(lockWidget,&Lock::passwordNotSet,[=](){ +// settings.setValue("lockscreen",false); +// ui->applock_checkbox->setChecked(false); +// }); + +// connect(lockWidget,&Lock::unLocked,[=]() +// { +// //unlock event +// }); + +// connect(lockWidget,&Lock::passwordSet,[=](){ +// //enable disable lock screen +// if(settings.value("asdfg").isValid()){ +// ui->current_password->setText("Current Password: "+QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())+""); +// }else{ +// ui->current_password->setText("Current Password: Require setup"); +// } +// ui->applock_checkbox->setChecked(settings.value("lockscreen",false).toBool()); +// }); +// lockWidget->show(); +// if(settings.value("asdfg").isValid() && settings.value("lockscreen").toBool()==true){ +// lockWidget->lock_app(); +// } +} + //check window state and set tray menus void MainWindow::check_window_state() { @@ -428,7 +464,7 @@ void MainWindow::createWebPage(bool offTheRecord) QWebEnginePage *page = new WebEnginePage(profile,webEngine); if(settings.value("windowTheme","light").toString() == "dark"){ - page->setBackgroundColor(QColor("#F0F0F0")); //whatsapp bg color + page->setBackgroundColor(QColor("#131C21")); //whatsapp bg color } webEngine->setPage(page); //page should be set parent of profile to prevent diff --git a/src/mainwindow.h b/src/mainwindow.h index fb68e11..67a783b 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -26,6 +26,7 @@ #include "requestinterceptor.h" #include "settingswidget.h" #include "webenginepage.h" +#include "lock.h" #include "downloadmanagerwidget.h" @@ -75,6 +76,8 @@ private: DownloadManagerWidget m_downloadManagerWidget; QScopedPointer m_otrProfile; + Lock *lockWidget = nullptr; + private slots: @@ -103,6 +106,7 @@ private slots: void init_settingWidget(); void init_globalWebProfile(); void check_window_state(); + void init_lock(); }; #endif // MAINWINDOW_H diff --git a/src/settingswidget.ui b/src/settingswidget.ui index 7318e5c..9a1c92c 100644 --- a/src/settingswidget.ui +++ b/src/settingswidget.ui @@ -6,8 +6,8 @@ 0 0 - 539 - 447 + 553 + 478 @@ -104,32 +104,39 @@ background:transparent; General settings - - - - + + + + - Default close button action + Disable Notifications PopUp - - - - - Minimize to tray - - - - - Quit Application - - + + + + Mute Audio + + + + + + + Disable Auto Playback of Media + + + + + + + Disable loading videos + - + @@ -154,7 +161,7 @@ background:transparent; - + @@ -190,33 +197,50 @@ background:transparent; - - - - + + + + - Disable Notifications PopUp + Default close button action - - - - Mute Audio - + + + + + Minimize to tray + + + + + Quit Application + + - - + + + + + + 0 + + + + + <html><head/><body><p>Enable application lock screen.</p></body></html> + - Disable Auto Playback of Media + Enable App Lock on Start - - + + - Disable loading videos + Current Password: -- cgit v1.2.3 From e0ac0208e700cf108f6295f66e2bb003fe53607b Mon Sep 17 00:00:00 2001 From: keshavbhatt Date: Mon, 5 Apr 2021 23:53:46 +0530 Subject: implemented new about dialog, app lock feature --- snap_launcher/bin/whatsie | Bin 1152976 -> 1186040 bytes src/mainwindow.cpp | 220 ++++++++++++++++++++++++++++------------------ src/mainwindow.h | 10 ++- src/settingswidget.cpp | 25 ++++++ src/settingswidget.h | 6 +- src/settingswidget.ui | 23 +++-- 6 files changed, 191 insertions(+), 93 deletions(-) (limited to 'src/mainwindow.h') diff --git a/snap_launcher/bin/whatsie b/snap_launcher/bin/whatsie index bb29d16..372c1ef 100755 Binary files a/snap_launcher/bin/whatsie and b/snap_launcher/bin/whatsie differ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e30f393..69f792e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,5 +1,6 @@ #include "mainwindow.h" +#include extern QString defaultUserAgentStr; @@ -9,17 +10,39 @@ MainWindow::MainWindow(QWidget *parent) trayIconRead(":/icons/app/whatsapp.svg"), trayIconUnread(":/icons/app/whatsapp-message.svg") { + qApp->setQuitOnLastWindowClosed(false); + setWindowTitle(QApplication::applicationName()); setWindowIcon(QIcon(":/icons/app/icon-256.png")); setMinimumWidth(800); setMinimumHeight(600); - readSettings(); + + + restoreGeometry(settings.value("geometry").toByteArray()); + restoreState(settings.value("windowState").toByteArray()); createActions(); createStatusBar(); createTrayIcon(); createWebEngine(); + + if(settings.value("lockscreen",false).toBool()) + { + init_lock(); + } + QTimer *timer = new QTimer(this); + timer->setInterval(1000); + connect(timer,&QTimer::timeout,[=](){ + if(settings.value("asdfg").isValid()){ + if(lockWidget && lockWidget->isLocked==false){ + timer->stop(); + //init_accountWidget(); + } + } + }); + timer->start(); + init_settingWidget(); lightPalette = qApp->palette(); @@ -27,8 +50,6 @@ MainWindow::MainWindow(QWidget *parent) // quit application if the download manager window is the only remaining window m_downloadManagerWidget.setAttribute(Qt::WA_QuitOnClose, false); - - } void MainWindow::updatePageTheme() @@ -48,11 +69,18 @@ void MainWindow::updatePageTheme() } } +void MainWindow::resizeEvent(QResizeEvent *event) +{ + if(lockWidget != nullptr){ + lockWidget->resize(event->size()); + } +} + void MainWindow::updateWindowTheme() { if(settings.value("windowTheme","light").toString() == "dark") { - //TODO make dark palette match whatsapp dark theme + qApp->setStyle(QStyleFactory::create("fusion")); QPalette palette; palette.setColor(QPalette::Window,QColor("#131C21")); //whatsapp dark color @@ -84,6 +112,13 @@ void MainWindow::updateWindowTheme() qApp->setPalette(lightPalette); this->update(); } + + if(lockWidget!=nullptr){ + lockWidget->setStyleSheet("QWidget#login{background-color:palette(window)};" + "QWidget#signup{background-color:palette(window)};" + ); + lockWidget->applyThemeQuirks(); + } } void MainWindow::handleCookieAdded(const QNetworkCookie &cookie) @@ -91,11 +126,6 @@ void MainWindow::handleCookieAdded(const QNetworkCookie &cookie) qDebug() << cookie.toRawForm() << "\n\n\n"; } -void MainWindow::readSettings() -{ - restoreGeometry(settings.value("geometry").toByteArray()); - restoreState(settings.value("windowState").toByteArray()); -} void MainWindow::init_settingWidget() { @@ -106,6 +136,7 @@ void MainWindow::init_settingWidget() settingsWidget->setWindowTitle(QApplication::applicationName()+" | Settings"); settingsWidget->setWindowFlags(Qt::Dialog); + connect(settingsWidget,SIGNAL(init_lock()),this,SLOT(init_lock())); connect(settingsWidget,SIGNAL(updateWindowTheme()),this,SLOT(updateWindowTheme())); connect(settingsWidget,SIGNAL(updatePageTheme()),this,SLOT(updatePageTheme())); connect(settingsWidget,&SettingsWidget::muteToggled,[=](const bool checked) @@ -131,11 +162,49 @@ void MainWindow::init_settingWidget() QWebEngineSettings::PlaybackRequiresUserGesture, checked); }); + + settingsWidget->appLockSetChecked(settings.value("lockscreen",false).toBool()); + settingsWidget->resize(settingsWidget->sizeHint().width(),settingsWidget->minimumSizeHint().height()); + } +} + +void MainWindow::lockApp() +{ + if(settings.value("asdfg").isValid() && settings.value("lockscreen").toBool()==false){ + QMessageBox::critical(this,QApplication::applicationName()+"| Error", + "Unable to lock App, Enable AppLock in settings First."); + this->show(); + return; + } + + if(settings.value("asdfg").isValid()){ + init_lock(); + }else{ + if(settings.value("asdfg").isValid() ==false){ + QMessageBox msgBox; + msgBox.setText("App lock is not configured."); + msgBox.setIconPixmap(QPixmap(":/icons/information-line.png").scaled(42,42,Qt::KeepAspectRatio,Qt::SmoothTransformation)); + msgBox.setInformativeText("Do you want to setup App lock now ?"); + msgBox.setStandardButtons(QMessageBox::Cancel ); + QPushButton *setAppLock = new QPushButton("Yes",nullptr); + msgBox.addButton(setAppLock,QMessageBox::NoRole); + connect(setAppLock,&QPushButton::clicked,[=](){ + init_lock(); + }); + msgBox.exec(); + } } } void MainWindow::showSettings() { + if(lockWidget && lockWidget->isLocked){ + QMessageBox::critical(this,QApplication::applicationName()+"| Error", + "UnLock Application to access Settings."); + this->show(); + return; + } + if(webEngine == nullptr){ QMessageBox::critical(this,QApplication::applicationName()+"| Error", "Unable to initialize settings module.\nIs webengine initialized?"); @@ -166,44 +235,12 @@ void MainWindow::askToReloadPage() void MainWindow::showAbout() { - QDialog *aboutDialog = new QDialog(this,Qt::Dialog); - aboutDialog->setWindowModality(Qt::WindowModal); - QVBoxLayout *layout = new QVBoxLayout; - QLabel *message = new QLabel(aboutDialog); - layout->addWidget(message); - connect(message,&QLabel::linkActivated,[=](const QString linkStr){ - if(linkStr.contains("about_qt")){ - qApp->aboutQt(); - }else{ - QDesktopServices::openUrl(QUrl(linkStr)); - } - }); - aboutDialog->setLayout(layout); - aboutDialog->setAttribute(Qt::WA_DeleteOnClose,true); - aboutDialog->show(); - - QString mes = - "

" - "


" - "

Designed and Developed

" - "

by Keshav Bhatt <keshavnrj@gmail.com>

" - "

Website: https://ktechpit.com

" - "

Runtime: Qt Toolkit

" - "

Version: "+QApplication::applicationVersion()+"

" - "


" - "

More Apps

" - "


"; - - QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this); - message->setGraphicsEffect(eff); - QPropertyAnimation *a = new QPropertyAnimation(eff,"opacity"); - a->setDuration(1000); - a->setStartValue(0); - a->setEndValue(1); - a->setEasingCurve(QEasingCurve::InCurve); - a->start(QPropertyAnimation::DeleteWhenStopped); - message->setText(mes); - message->show(); + About *about = new About(this); + about->setWindowFlag(Qt::Dialog); + about->adjustSize(); + about->setFixedSize(about->sizeHint()); + about->setAttribute(Qt::WA_DeleteOnClose); + about->show(); } void MainWindow::closeEvent(QCloseEvent *event) @@ -255,6 +292,11 @@ void MainWindow::createActions() connect(reloadAction, &QAction::triggered, this, &MainWindow::doReload); addAction(reloadAction); + lockAction = new QAction(tr("Lock"), this); + lockAction->setShortcut(QKeySequence(Qt::Key_Control,Qt::Key_L)); + connect(lockAction, &QAction::triggered, this, &MainWindow::lockApp); + addAction(lockAction); + settingsAction = new QAction(tr("Settings"), this); connect(settingsAction, &QAction::triggered, this, &MainWindow::showSettings); @@ -284,6 +326,7 @@ void MainWindow::createTrayIcon() trayIconMenu->addAction(restoreAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(reloadAction); + trayIconMenu->addAction(lockAction); trayIconMenu->addAction(settingsAction); trayIconMenu->addAction(aboutAction); trayIconMenu->addSeparator(); @@ -304,37 +347,42 @@ void MainWindow::createTrayIcon() void MainWindow::init_lock() { -// if(lockWidget==nullptr){ -// lockWidget = new Lock(this); -// lockWidget->setObjectName("lockWidget"); -// } -// lockWidget->setWindowFlags(Qt::Widget); -// lockWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); -// lockWidget->setGeometry(this->rect()); - -// connect(lockWidget,&Lock::passwordNotSet,[=](){ -// settings.setValue("lockscreen",false); -// ui->applock_checkbox->setChecked(false); -// }); - -// connect(lockWidget,&Lock::unLocked,[=]() -// { -// //unlock event -// }); - -// connect(lockWidget,&Lock::passwordSet,[=](){ -// //enable disable lock screen -// if(settings.value("asdfg").isValid()){ -// ui->current_password->setText("Current Password: "+QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())+""); -// }else{ -// ui->current_password->setText("Current Password: Require setup"); -// } -// ui->applock_checkbox->setChecked(settings.value("lockscreen",false).toBool()); -// }); -// lockWidget->show(); -// if(settings.value("asdfg").isValid() && settings.value("lockscreen").toBool()==true){ -// lockWidget->lock_app(); -// } + if(lockWidget==nullptr){ + lockWidget = new Lock(this); + lockWidget->setObjectName("lockWidget"); + } + lockWidget->setWindowFlags(Qt::Widget); + lockWidget->setStyleSheet("QWidget#login{background-color:palette(window)};" + "QWidget#signup{background-color:palette(window)}"); + lockWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + lockWidget->setGeometry(this->rect()); + + connect(lockWidget,&Lock::passwordNotSet,[=]() + { + settings.setValue("lockscreen",false); + settingsWidget->appLockSetChecked(false); + }); + + connect(lockWidget,&Lock::unLocked,[=]() + { + //unlock event + }); + + connect(lockWidget,&Lock::passwordSet,[=](){ + //enable disable lock screen + if(settings.value("asdfg").isValid()){ + settingsWidget->setCurrentPasswordText("Current Password: " + +QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())+""); + }else{ + settingsWidget->setCurrentPasswordText("Current Password: Require setup"); + } + settingsWidget->appLockSetChecked(settings.value("lockscreen",false).toBool()); + }); + lockWidget->applyThemeQuirks(); + lockWidget->show(); + if(settings.value("asdfg").isValid() && settings.value("lockscreen").toBool()==true){ + lockWidget->lock_app(); + } } //check window state and set tray menus @@ -349,6 +397,11 @@ void MainWindow::check_window_state() ((QMenu*)(tray_icon_menu))->actions().at(0)->setDisabled(true); ((QMenu*)(tray_icon_menu))->actions().at(1)->setDisabled(false); } + if(lockWidget && lockWidget->isLocked){ + ((QMenu*)(tray_icon_menu))->actions().at(4)->setDisabled(true); + }else{ + ((QMenu*)(tray_icon_menu))->actions().at(4)->setDisabled(false); + } } } @@ -464,12 +517,13 @@ void MainWindow::createWebPage(bool offTheRecord) QWebEnginePage *page = new WebEnginePage(profile,webEngine); if(settings.value("windowTheme","light").toString() == "dark"){ - page->setBackgroundColor(QColor("#131C21")); //whatsapp bg color + page->setBackgroundColor(QColor("#131C21")); //whatsapp dark bg color } webEngine->setPage(page); //page should be set parent of profile to prevent //Release of profile requested but WebEnginePage still not deleted. Expect troubles ! profile->setParent(page); + profile->setSpellCheckEnabled(true); //RequestInterceptor *interceptor = new RequestInterceptor(profile); //profile->setUrlRequestInterceptor(interceptor); page->setUrl(QUrl("https://web.whatsapp.com/")); @@ -518,6 +572,7 @@ void MainWindow::handleLoadStarted() void MainWindow::handleLoadFinished(bool loaded) { + statusBar->hide(); if(loaded){ updatePageTheme(); } @@ -525,14 +580,11 @@ void MainWindow::handleLoadFinished(bool loaded) void MainWindow::handleLoadProgress(int progress) { - if (progress >= 100) + statusBar->showMessage("Loading "+QString::number(progress)+"%"); + if (progress >= 50) { statusBar->hide(); } - else - { - statusBar->showMessage("Loading "+QString::number(progress)+"%"); - } } //unused direct method to download file without having entry in download manager diff --git a/src/mainwindow.h b/src/mainwindow.h index 67a783b..7614c5f 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -29,6 +29,7 @@ #include "lock.h" #include "downloadmanagerwidget.h" +#include "about.h" class MainWindow : public QMainWindow @@ -39,9 +40,11 @@ public: public slots: void updateWindowTheme(); void updatePageTheme(); -protected: - void closeEvent(QCloseEvent *event) override; + +protected slots: + void closeEvent(QCloseEvent *event) override; + void resizeEvent(QResizeEvent *event); private: QPalette lightPalette; void createActions(); @@ -61,6 +64,7 @@ private: QAction *aboutAction; QAction *settingsAction; QAction *quitAction; + QAction *lockAction; QMenu *trayIconMenu; QSystemTrayIcon *trayIcon; @@ -81,7 +85,6 @@ private: private slots: - void readSettings(); void handleWebViewTitleChanged(QString title); void handleLoadStarted(); void handleLoadProgress(int progress); @@ -107,6 +110,7 @@ private slots: void init_globalWebProfile(); void check_window_state(); void init_lock(); + void lockApp(); }; #endif // MAINWINDOW_H diff --git a/src/settingswidget.cpp b/src/settingswidget.cpp index 7f9a257..4a735b8 100644 --- a/src/settingswidget.cpp +++ b/src/settingswidget.cpp @@ -23,6 +23,9 @@ SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, QString ui->themeComboBox->setCurrentText(utils::toCamelCase(settings.value("windowTheme","light").toString())); ui->userAgentLineEdit->setText(settings.value("useragent",defaultUserAgentStr).toString()); + this->setCurrentPasswordText("Current Password: " + +QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())+""); + applyThemeQuirks(); ui->setUserAgent->setEnabled(false); @@ -187,3 +190,25 @@ void SettingsWidget::on_closeButtonActionComboBox_currentIndexChanged(int index) { settings.setValue("closeButtonActionCombo",index); } + +void SettingsWidget::appLockSetChecked(bool checked) +{ + ui->applock_checkbox->setChecked(checked); +} + +void SettingsWidget::setCurrentPasswordText(QString str) +{ + ui->current_password->setText(str); +} + +void SettingsWidget::on_applock_checkbox_toggled(bool checked) +{ + if(settings.value("asdfg").isValid()){ + settings.setValue("lockscreen",checked); + }else{ + settings.setValue("lockscreen",false); + } + if(checked){ + emit init_lock(); + } +} diff --git a/src/settingswidget.h b/src/settingswidget.h index a21a410..640f294 100644 --- a/src/settingswidget.h +++ b/src/settingswidget.h @@ -21,7 +21,7 @@ signals: void muteToggled(const bool checked); void autoPlayMediaToggled(const bool checked); void userAgentChanged(QString userAgentStr); - + void init_lock(); public: explicit SettingsWidget(QWidget *parent = nullptr,QString engineCachePath = "", QString enginePersistentStoragePath = ""); @@ -30,6 +30,8 @@ public: public slots: void refresh(); void updateDefaultUAButton(const QString engineUA); + void appLockSetChecked(bool checked); + void setCurrentPasswordText(QString str); private slots: QString cachePath(); QString persistentStoragePath(); @@ -57,6 +59,8 @@ private slots: void on_closeButtonActionComboBox_currentIndexChanged(int index); + void on_applock_checkbox_toggled(bool checked); + private: Ui::SettingsWidget *ui; QString engineCachePath,enginePersistentStoragePath; diff --git a/src/settingswidget.ui b/src/settingswidget.ui index 9a1c92c..1e8b647 100644 --- a/src/settingswidget.ui +++ b/src/settingswidget.ui @@ -6,8 +6,8 @@ 0 0 - 553 - 478 + 554 + 565 @@ -83,7 +83,7 @@ background:transparent;
- + @@ -98,7 +98,7 @@ background:transparent; 9 - + General settings @@ -249,7 +249,7 @@ background:transparent; - + Application Storage and Other Settings @@ -369,6 +369,19 @@ background:transparent;
+ + + + Qt::Vertical + + + + 20 + 40 + + + +
-- cgit v1.2.3 From 85e3f22fa8f3215e28bffdf6453898d4b1e5b1bd Mon Sep 17 00:00:00 2001 From: keshavbhatt Date: Tue, 6 Apr 2021 02:38:48 +0530 Subject: bypass browser upgrade page. --- snap_launcher/bin/whatsie | Bin 1185888 -> 1186016 bytes src/mainwindow.cpp | 45 ++++++++++++++++++++++++++++++++++++++++++--- src/mainwindow.h | 4 ++++ 3 files changed, 46 insertions(+), 3 deletions(-) (limited to 'src/mainwindow.h') diff --git a/snap_launcher/bin/whatsie b/snap_launcher/bin/whatsie index efd189a..9601baf 100755 Binary files a/snap_launcher/bin/whatsie and b/snap_launcher/bin/whatsie differ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 69f792e..3408e8f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,6 +1,7 @@ #include "mainwindow.h" #include +#include extern QString defaultUserAgentStr; @@ -383,6 +384,7 @@ void MainWindow::init_lock() if(settings.value("asdfg").isValid() && settings.value("lockscreen").toBool()==true){ lockWidget->lock_app(); } + updateWindowTheme(); } //check window state and set tray menus @@ -409,6 +411,8 @@ void MainWindow::init_globalWebProfile() { QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); + profile->setHttpUserAgent(settings.value("useragent",defaultUserAgentStr).toString()); + auto* webSettings = profile->settings(); webSettings->setAttribute(QWebEngineSettings::AutoLoadImages, true); webSettings->setAttribute(QWebEngineSettings::JavascriptEnabled, true); @@ -443,6 +447,8 @@ void MainWindow::createWebEngine() widgetSize.setHorizontalStretch(1); widgetSize.setVerticalStretch(1); + QtWebEngine::initialize(); + QWebEngineView *webEngine = new QWebEngineView(this); setCentralWidget(webEngine); webEngine->setSizePolicy(widgetSize); @@ -523,10 +529,13 @@ void MainWindow::createWebPage(bool offTheRecord) //page should be set parent of profile to prevent //Release of profile requested but WebEnginePage still not deleted. Expect troubles ! profile->setParent(page); + profile->setSpellCheckEnabled(true); - //RequestInterceptor *interceptor = new RequestInterceptor(profile); - //profile->setUrlRequestInterceptor(interceptor); - page->setUrl(QUrl("https://web.whatsapp.com/")); +// RequestInterceptor *interceptor = new RequestInterceptor(profile); +// profile->setUrlRequestInterceptor(interceptor); + qsrand(time(NULL)); + auto randomValue = qrand() % 300; + page->setUrl(QUrl("https://web.whatsapp.com?v="+QString::number(randomValue))); connect(profile, &QWebEngineProfile::downloadRequested, &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested); @@ -574,10 +583,39 @@ void MainWindow::handleLoadFinished(bool loaded) { statusBar->hide(); if(loaded){ + //check if page has loaded correctly + checkLoadedCorrectly(); updatePageTheme(); } } +void MainWindow::checkLoadedCorrectly() +{ + if(webEngine && webEngine->page()) + { + webEngine->page()->runJavaScript( + "document.getElementsByClassName('landing-title')[0].innerText", + [this](const QVariant &result){ + qDebug()<<"Loaded correctly value:"< -1){ + doReload(); + correctlyLoaderRetries--; + }else{ + utils::delete_cache(webEngine->page()->profile()->cachePath()); + utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); + QMessageBox::information(this,QApplication::applicationName()+"| Page load error", + "Application restart required.\nPlease restart application."); + quitAction->trigger(); + } + //webEngine->page()->runJavaScript("this.window.location.replace('https://web.whatsapp.com?v=' + Math.floor((Math.random() * 1000) + 1).toString(), {});"); + } + } + ); + } +} + void MainWindow::handleLoadProgress(int progress) { statusBar->showMessage("Loading "+QString::number(progress)+"%"); @@ -625,6 +663,7 @@ void MainWindow::messageClicked() void MainWindow::doAppReload() { + if(this->webEngine->page()){ this->webEngine->page()->disconnect(); } diff --git a/src/mainwindow.h b/src/mainwindow.h index 7614c5f..89c3e3f 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -82,6 +82,7 @@ private: Lock *lockWidget = nullptr; + int correctlyLoaderRetries = 4; private slots: @@ -111,6 +112,9 @@ private slots: void check_window_state(); void init_lock(); void lockApp(); + + + void checkLoadedCorrectly(); }; #endif // MAINWINDOW_H -- cgit v1.2.3 From 03ffbdfce826d85198e804e04475b3db3d870ec1 Mon Sep 17 00:00:00 2001 From: keshavbhatt Date: Fri, 9 Apr 2021 10:26:02 +0530 Subject: new global app shortcuts, other improvements --- src/mainwindow.cpp | 90 +++++++++++++++++++++++++++++++++++++++++++++--------- src/mainwindow.h | 8 +++++ 2 files changed, 83 insertions(+), 15 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index c291f8d..e139855 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,7 +1,8 @@ #include "mainwindow.h" -#include -#include +#include + + extern QString defaultUserAgentStr; @@ -110,6 +111,8 @@ void MainWindow::updateWindowTheme() this->webEngine->setStyleSheet("QWebEngineView{background:#131C21;}"); //whatsapp dark color } else{ + this->webEngine->setStyleSheet("QWebEngineView{background:#f8f9fa;}"); //whatsapp light color + lightPalette.setColor(QPalette::Window,QColor("#f8f9fa")); qApp->setPalette(lightPalette); this->update(); } @@ -164,7 +167,26 @@ void MainWindow::init_settingWidget() checked); }); + connect(settingsWidget,&SettingsWidget::dictChanged,[=](QString dictName) + { + if(webEngine && webEngine->page()) + { + webEngine->page()->profile()->setSpellCheckLanguages(QStringList()<page()) + { + webEngine->page()->profile()->setSpellCheckEnabled(checked); + } + }); + settingsWidget->appLockSetChecked(settings.value("lockscreen",false).toBool()); + + //spell checker + settingsWidget->loadDictionaries(m_dictionaries); + settingsWidget->resize(settingsWidget->sizeHint().width(),settingsWidget->minimumSizeHint().height()); } } @@ -244,6 +266,7 @@ void MainWindow::showAbout() about->show(); } + void MainWindow::closeEvent(QCloseEvent *event) { settings.setValue("geometry", saveGeometry()); @@ -279,10 +302,19 @@ void MainWindow::notify(QString title,QString message) void MainWindow::createActions() { + fullscreenAction = new QAction(tr("Fullscreen"),this); + fullscreenAction->setShortcut(Qt::Key_F11); + connect(fullscreenAction, &QAction::triggered,[=](){ + setWindowState(windowState() ^ Qt::WindowFullScreen); + }); + this->addAction(fullscreenAction); + minimizeAction = new QAction(tr("Mi&nimize to tray"), this); + minimizeAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_H)); connect(minimizeAction, &QAction::triggered, this, &QWidget::hide); addAction(minimizeAction); + this->addAction(minimizeAction); restoreAction = new QAction(tr("&Restore"), this); connect(restoreAction, &QAction::triggered, this, &QWidget::show); @@ -293,22 +325,24 @@ void MainWindow::createActions() connect(reloadAction, &QAction::triggered, this, &MainWindow::doReload); addAction(reloadAction); - lockAction = new QAction(tr("Lock"), this); - lockAction->setShortcut(QKeySequence(Qt::Key_Control,Qt::Key_L)); + lockAction = new QAction(tr("Loc&k"), this); + lockAction->setShortcut(QKeySequence(Qt::Modifier::CTRL+Qt::Key_L)); connect(lockAction, &QAction::triggered, this, &MainWindow::lockApp); addAction(lockAction); + this->addAction(lockAction); - settingsAction = new QAction(tr("Settings"), this); + settingsAction = new QAction(tr("&Settings"), this); connect(settingsAction, &QAction::triggered, this, &MainWindow::showSettings); - aboutAction = new QAction(tr("About"), this); + aboutAction = new QAction(tr("&About"), this); connect(aboutAction, &QAction::triggered, this, &MainWindow::showAbout); quitAction = new QAction(tr("&Quit"), this); quitAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_Q)); connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit); addAction(quitAction); + this->addAction(quitAction); } void MainWindow::createStatusBar() @@ -328,6 +362,7 @@ void MainWindow::createTrayIcon() trayIconMenu->addSeparator(); trayIconMenu->addAction(reloadAction); trayIconMenu->addAction(lockAction); + trayIconMenu->addSeparator(); trayIconMenu->addAction(settingsAction); trayIconMenu->addAction(aboutAction); trayIconMenu->addSeparator(); @@ -343,6 +378,14 @@ void MainWindow::createTrayIcon() this, &MainWindow::messageClicked); connect(trayIcon, &QSystemTrayIcon::activated, this, &MainWindow::iconActivated); + + //enable show shortcuts in menu + if(qApp->styleHints()->showShortcutsInContextMenus()) + { + foreach(QAction *action, trayIconMenu->actions()){ + action->setShortcutVisibleInContextMenu(true); + } + } } @@ -412,7 +455,12 @@ void MainWindow::init_globalWebProfile() QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); profile->setHttpUserAgent(settings.value("useragent",defaultUserAgentStr).toString()); - profile->setSpellCheckEnabled(true); + + QStringList dict_names; + dict_names.append(settings.value("sc_dict","en-US").toString()); + + profile->setSpellCheckEnabled(settings.value("sc_enabled",true).toBool()); + profile->setSpellCheckLanguages(dict_names); auto* webSettings = profile->settings(); webSettings->setAttribute(QWebEngineSettings::AutoLoadImages, true); @@ -449,13 +497,17 @@ void MainWindow::createWebEngine() widgetSize.setHorizontalStretch(1); widgetSize.setVerticalStretch(1); - QWebEngineView *webEngine = new QWebEngineView(this); + m_dictionaries = Dictionaries::GetDictionaries(); + + WebView *webEngine = new WebView(this,m_dictionaries); setCentralWidget(webEngine); webEngine->setSizePolicy(widgetSize); webEngine->show(); this->webEngine = webEngine; - + webEngine->addAction(minimizeAction); + webEngine->addAction(lockAction); + webEngine->addAction(quitAction); connect(webEngine, &QWebEngineView::titleChanged, this, &MainWindow::handleWebViewTitleChanged); @@ -483,8 +535,7 @@ void MainWindow::createWebEngine() break; } QMessageBox::StandardButton btn = QMessageBox::question(window(), status, - tr("Render process exited with code: %1\n" - "Do you want to reload the page ?").arg(statusCode)); + tr("Render process exited with code: %1\n" "Do you want to reload the page ?").arg(statusCode)); if (btn == QMessageBox::Yes) QTimer::singleShot(0, [this] { this->webEngine->reload(); }); }); @@ -497,12 +548,19 @@ void MainWindow::createWebEngine() void MainWindow::createWebPage(bool offTheRecord) { - if (offTheRecord && !m_otrProfile) { + if (offTheRecord && !m_otrProfile) + { m_otrProfile.reset(new QWebEngineProfile); - } + } auto profile = offTheRecord ? m_otrProfile.get() : QWebEngineProfile::defaultProfile(); - profile->setSpellCheckEnabled(true); + + QStringList dict_names; + dict_names.append(settings.value("sc_dict","en-US").toString()); + + profile->setSpellCheckEnabled(settings.value("sc_enabled",true).toBool()); + profile->setSpellCheckLanguages(dict_names); + profile->setHttpUserAgent(settings.value("useragent",defaultUserAgentStr).toString()); auto popup = new NotificationPopup(webEngine); @@ -524,6 +582,8 @@ void MainWindow::createWebPage(bool offTheRecord) QWebEnginePage *page = new WebEnginePage(profile,webEngine); if(settings.value("windowTheme","light").toString() == "dark"){ page->setBackgroundColor(QColor("#131C21")); //whatsapp dark bg color + }else{ + page->setBackgroundColor(QColor("#f8f9fa")); //whatsapp light bg color } webEngine->setPage(page); //page should be set parent of profile to prevent @@ -535,7 +595,7 @@ void MainWindow::createWebPage(bool offTheRecord) qsrand(time(NULL)); auto randomValue = qrand() % 300; page->setUrl(QUrl("https://web.whatsapp.com?v="+QString::number(randomValue))); - + //page->setUrl(QUrl("http://ktechpit.com/USS/text.html")); connect(profile, &QWebEngineProfile::downloadRequested, &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested); diff --git a/src/mainwindow.h b/src/mainwindow.h index 89c3e3f..07b7408 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -22,6 +22,9 @@ #include #include +#include +#include + #include "notificationpopup.h" #include "requestinterceptor.h" #include "settingswidget.h" @@ -30,6 +33,8 @@ #include "downloadmanagerwidget.h" #include "about.h" +#include "dictionaries.h" +#include "webview.h" class MainWindow : public QMainWindow @@ -65,6 +70,7 @@ private: QAction *settingsAction; QAction *quitAction; QAction *lockAction; + QAction *fullscreenAction; QMenu *trayIconMenu; QSystemTrayIcon *trayIcon; @@ -84,6 +90,8 @@ private: int correctlyLoaderRetries = 4; + QStringList m_dictionaries; + private slots: void handleWebViewTitleChanged(QString title); -- cgit v1.2.3 From 324a115e028907fe3544dff9517a0d48e77d7cd5 Mon Sep 17 00:00:00 2001 From: keshavbhatt Date: Fri, 9 Apr 2021 18:32:44 +0530 Subject: wrote new test case to check loaded correctly. --- src/mainwindow.cpp | 88 ++++++++++++++++++++++++++++++++---------------------- src/mainwindow.h | 1 + 2 files changed, 54 insertions(+), 35 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e139855..7fc19e6 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -85,17 +85,17 @@ void MainWindow::updateWindowTheme() qApp->setStyle(QStyleFactory::create("fusion")); QPalette palette; - palette.setColor(QPalette::Window,QColor("#131C21")); //whatsapp dark color + palette.setColor(QPalette::Window,QColor("#262D31")); //whatsapp dark color + palette.setColor(QPalette::Disabled,QPalette::Window,QColor("#3f4143")); //whatsapp dark color + palette.setColor(QPalette::WindowText,Qt::white); palette.setColor(QPalette::Disabled,QPalette::WindowText,QColor(127,127,127)); - //palette.setColor(QPalette::Base,QColor(42,42,42)); - palette.setColor(QPalette::Base,QColor(84,84,84)); - - palette.setColor(QPalette::AlternateBase,QColor(66,66,66)); + palette.setColor(QPalette::Base,QColor("#323739")); + palette.setColor(QPalette::AlternateBase,QColor("#5f6c73")); palette.setColor(QPalette::ToolTipBase,Qt::white); palette.setColor(QPalette::ToolTipText,QColor(53,53,53)); palette.setColor(QPalette::Text,Qt::white); - palette.setColor(QPalette::Disabled,QPalette::Text,QColor(127,127,127)); + palette.setColor(QPalette::Disabled,QPalette::Text,QColor("#646464")); palette.setColor(QPalette::Dark,QColor(35,35,35)); palette.setColor(QPalette::Shadow,QColor(20,20,20)); palette.setColor(QPalette::Button,QColor(53,53,53)); @@ -652,36 +652,54 @@ void MainWindow::checkLoadedCorrectly() { if(webEngine && webEngine->page()) { - webEngine->page()->runJavaScript( - "document.getElementsByClassName('landing-title')[0].innerText", - [this](const QVariant &result){ - qWarning()<<"Loaded correctly value:"< -1){ - qWarning()<<"doReload()"<page()->profile()->cachePath()); - utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); - settings.setValue("useragent",defaultUserAgentStr); - utils * util = new utils(this); - util->DisplayExceptionErrorDialog("checkLoadedCorrectly() reload retries 0, Resetting UA, Quiting!\nUA: "+settings.value("useragent","DefaultUA").toString()); - - quitAction->trigger(); - } - }else if(webEngine->title().contains("Error",Qt::CaseInsensitive)){ - utils::delete_cache(webEngine->page()->profile()->cachePath()); - utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); - settings.setValue("useragent",defaultUserAgentStr); - utils * util = new utils(this); - util->DisplayExceptionErrorDialog("handleWebViewTitleChanged(title) title: Error, Resetting UA, Quiting!\nUA: "+settings.value("useragent","DefaultUA").toString()); - - quitAction->trigger(); - } + //test 1 based on the class name of body of the page + webEngine->page()->runJavaScript("document.querySelector('body').className",[this](const QVariant &result) + { + if(result.toString().contains("page-version",Qt::CaseInsensitive)) + { + qWarning()<<"Test 1 found"<page()->runJavaScript( +// "document.getElementsByClassName('landing-title')[0].innerText", +// [this](const QVariant &result){ +// qWarning()<<"Test #1 Loaded correctly value:"<title().contains("Error",Qt::CaseInsensitive)){ +// utils::delete_cache(webEngine->page()->profile()->cachePath()); +// utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); +// settings.setValue("useragent",defaultUserAgentStr); +// utils * util = new utils(this); +// util->DisplayExceptionErrorDialog("handleWebViewTitleChanged(title) title: Error, Resetting UA, Quiting!\nUA: "+settings.value("useragent","DefaultUA").toString()); + +// quitAction->trigger(); +// } +// } +// ); + } +} + +void MainWindow::loadingQuirk(QString test) +{ + //contains ug message apply quirk + if(correctlyLoaderRetries > -1){ + qWarning()<page()->profile()->cachePath()); + utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); + settings.setValue("useragent",defaultUserAgentStr); + utils * util = new utils(this); + util->DisplayExceptionErrorDialog(test+" checkLoadedCorrectly()/loadingQuirk() reload retries 0, Resetting UA, Quiting!\nUA: "+settings.value("useragent","DefaultUA").toString()); + + quitAction->trigger(); } } diff --git a/src/mainwindow.h b/src/mainwindow.h index 07b7408..db8e958 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -123,6 +123,7 @@ private slots: void checkLoadedCorrectly(); + void loadingQuirk(QString test); }; #endif // MAINWINDOW_H -- cgit v1.2.3 From 9f096f17f19dfdae57d51d81343cb4fecb5beb34 Mon Sep 17 00:00:00 2001 From: keshavbhatt Date: Sun, 11 Apr 2021 02:03:36 +0530 Subject: code clean up and theme switching issue fix, notification pop-up theme fix. --- src/mainwindow.cpp | 98 +++++++++++++++++++++--------------------------------- src/mainwindow.h | 11 +++--- 2 files changed, 44 insertions(+), 65 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 678cd2d..41b6429 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -13,14 +13,17 @@ MainWindow::MainWindow(QWidget *parent) trayIconRead(":/icons/app/whatsapp.svg"), trayIconUnread(":/icons/app/whatsapp-message.svg") { + this->setObjectName("MainWindow"); + qApp->setQuitOnLastWindowClosed(false); + lightPalette = qApp->palette(); + setWindowTitle(QApplication::applicationName()); setWindowIcon(QIcon(":/icons/app/icon-256.png")); setMinimumWidth(800); setMinimumHeight(600); - restoreGeometry(settings.value("geometry").toByteArray()); restoreState(settings.value("windowState").toByteArray()); @@ -29,7 +32,6 @@ MainWindow::MainWindow(QWidget *parent) createTrayIcon(); createWebEngine(); - if(settings.value("lockscreen",false).toBool()) { init_lock(); @@ -51,7 +53,6 @@ MainWindow::MainWindow(QWidget *parent) // quit application if the download manager window is the only remaining window m_downloadManagerWidget.setAttribute(Qt::WA_QuitOnClose, false); - lightPalette = qApp->palette(); updateWindowTheme(); } @@ -83,7 +84,6 @@ void MainWindow::updateWindowTheme() { if(settings.value("windowTheme","light").toString() == "dark") { - qApp->setStyle(QStyleFactory::create("fusion")); QPalette palette; palette.setColor(QPalette::Window,QColor("#262D31")); //whatsapp dark color @@ -117,11 +117,12 @@ void MainWindow::updateWindowTheme() qApp->setPalette(lightPalette); } + setNotificationPresenter(webEngine->page()->profile()); + if(lockWidget!=nullptr) { lockWidget->setStyleSheet("QWidget#login{background-color:palette(window)};" - "QWidget#signup{background-color:palette(window)};" - ); + "QWidget#signup{background-color:palette(window)};"); lockWidget->applyThemeQuirks(); } this->update(); @@ -301,7 +302,6 @@ void MainWindow::notify(QString title,QString message) popup->style()->polish(qApp); popup->setMinimumWidth(300); popup->adjustSize(); - popup->update(); popup->present(title,message,QPixmap(":/icons/app/icon-64.png")); } @@ -503,47 +503,16 @@ void MainWindow::createWebEngine() webEngine->show(); this->webEngine = webEngine; - //webEngine->setContextMenuPolicy(Qt::CustomContextMenu); webEngine->addAction(minimizeAction); webEngine->addAction(lockAction); webEngine->addAction(quitAction); - connect(webEngine, &QWebEngineView::titleChanged, - this, &MainWindow::handleWebViewTitleChanged); - connect(webEngine, &QWebEngineView::loadStarted, - this, &MainWindow::handleLoadStarted); - connect(webEngine, &QWebEngineView::loadProgress, - this, &MainWindow::handleLoadProgress); - connect(webEngine, &QWebEngineView::loadFinished, - this, &MainWindow::handleLoadFinished); - connect(webEngine, &QWebEngineView::renderProcessTerminated, - [this](QWebEnginePage::RenderProcessTerminationStatus termStatus, int statusCode) { - QString status; - switch (termStatus) { - case QWebEnginePage::NormalTerminationStatus: - status = tr("Render process normal exit"); - break; - case QWebEnginePage::AbnormalTerminationStatus: - status = tr("Render process abnormal exit"); - break; - case QWebEnginePage::CrashedTerminationStatus: - status = tr("Render process crashed"); - break; - case QWebEnginePage::KilledTerminationStatus: - status = tr("Render process killed"); - break; - } - QMessageBox::StandardButton btn = QMessageBox::question(window(), status, - tr("Render process exited with code: %1\n" "Do you want to reload the page ?").arg(statusCode)); - if (btn == QMessageBox::Yes) - QTimer::singleShot(0, [this] { this->webEngine->reload(); }); - }); + createWebPage(false); - QWebEngineCookieStore *browser_cookie_store = webEngine->page()->profile()->cookieStore(); + QWebEngineCookieStore *browser_cookie_store = this->webEngine->page()->profile()->cookieStore(); connect( browser_cookie_store, &QWebEngineCookieStore::cookieAdded, this, &MainWindow::handleCookieAdded ); - createWebPage(false); } void MainWindow::createWebPage(bool offTheRecord) @@ -552,7 +521,6 @@ void MainWindow::createWebPage(bool offTheRecord) { m_otrProfile.reset(new QWebEngineProfile); } - auto profile = offTheRecord ? m_otrProfile.get() : QWebEngineProfile::defaultProfile(); QStringList dict_names; @@ -560,26 +528,9 @@ void MainWindow::createWebPage(bool offTheRecord) profile->setSpellCheckEnabled(settings.value("sc_enabled",true).toBool()); profile->setSpellCheckLanguages(dict_names); - profile->setHttpUserAgent(settings.value("useragent",defaultUserAgentStr).toString()); - auto popup = new NotificationPopup(webEngine); - connect(popup,&NotificationPopup::notification_clicked,[=](){ - if(windowState()==Qt::WindowMinimized || windowState()!=Qt::WindowActive){ - activateWindow(); - raise(); - showNormal(); - } - }); - profile->setNotificationPresenter([=] (std::unique_ptr notification) - { - if(settings.value("disableNotificationPopups",false).toBool() == true){ - return; - } - popup->setMinimumWidth(300); - popup->update(); - popup->present(notification); - }); + setNotificationPresenter(profile); QWebEnginePage *page = new WebEnginePage(profile,webEngine); if(settings.value("windowTheme","light").toString() == "dark"){ @@ -597,7 +548,6 @@ void MainWindow::createWebPage(bool offTheRecord) qsrand(time(NULL)); auto randomValue = qrand() % 300; page->setUrl(QUrl("https://web.whatsapp.com?v="+QString::number(randomValue))); - //page->setUrl(QUrl("http://ktechpit.com/USS/text.html")); connect(profile, &QWebEngineProfile::downloadRequested, &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested); @@ -605,6 +555,34 @@ void MainWindow::createWebPage(bool offTheRecord) this, SLOT(fullScreenRequested(QWebEngineFullScreenRequest))); } +void MainWindow::setNotificationPresenter(QWebEngineProfile* profile) +{ + auto *op = webEngine->findChild("engineNotifier"); + if( op != nullptr){ + op->close(); + op->deleteLater(); + } + + auto popup = new NotificationPopup(webEngine); + popup->setObjectName("engineNotifier"); + connect(popup,&NotificationPopup::notification_clicked,[=](){ + if(windowState()==Qt::WindowMinimized || windowState()!=Qt::WindowActive){ + activateWindow(); + raise(); + showNormal(); + } + }); + + profile->setNotificationPresenter([=] (std::unique_ptr notification) + { + if(settings.value("disableNotificationPopups",false).toBool() == true){ + return; + } + popup->setMinimumWidth(300); + popup->present(notification); + }); +} + void MainWindow::fullScreenRequested(QWebEngineFullScreenRequest request) { if (request.toggleOn()) diff --git a/src/mainwindow.h b/src/mainwindow.h index db8e958..75948e9 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -46,6 +46,11 @@ public slots: void updateWindowTheme(); void updatePageTheme(); + void handleWebViewTitleChanged(QString title); + void handleLoadStarted(); + void handleLoadProgress(int progress); + void handleLoadFinished(bool loaded); + void handleDownloadRequested(QWebEngineDownloadItem *download); protected slots: void closeEvent(QCloseEvent *event) override; @@ -94,10 +99,6 @@ private: private slots: - void handleWebViewTitleChanged(QString title); - void handleLoadStarted(); - void handleLoadProgress(int progress); - void handleDownloadRequested(QWebEngineDownloadItem *download); void iconActivated(QSystemTrayIcon::ActivationReason reason); void messageClicked(); void doReload(); @@ -105,7 +106,6 @@ private slots: void notify(QString title, QString message); void showSettings(); void handleCookieAdded(const QNetworkCookie &cookie); - void handleLoadFinished(bool loaded); QString getPageTheme(); void toggleMute(const bool checked); @@ -124,6 +124,7 @@ private slots: void checkLoadedCorrectly(); void loadingQuirk(QString test); + void setNotificationPresenter(QWebEngineProfile *profile); }; #endif // MAINWINDOW_H -- cgit v1.2.3 From ee87efdc6a4edabd9e1fc4f303bd094a912831c7 Mon Sep 17 00:00:00 2001 From: keshavbhatt Date: Wed, 5 May 2021 02:49:24 +0530 Subject: removed status bar widget, added RateApp dialog. --- src/mainwindow.cpp | 50 +++++++++++++++++++++----------------------------- src/mainwindow.h | 6 ++---- 2 files changed, 23 insertions(+), 33 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ac90ffe..42047ea 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -29,7 +29,6 @@ MainWindow::MainWindow(QWidget *parent) restoreState(settings.value("windowState").toByteArray()); createActions(); - createStatusBar(); createTrayIcon(); createWebEngine(); @@ -55,6 +54,22 @@ MainWindow::MainWindow(QWidget *parent) m_downloadManagerWidget.setAttribute(Qt::WA_QuitOnClose, false); updateWindowTheme(); + + RateApp *rateApp = new RateApp(this, "snap://whatsie", 3, 5, 1000 * 30); + rateApp->setWindowTitle(QApplication::applicationName()+" | "+tr("Rate Application")); + rateApp->setVisible(false); + rateApp->setWindowFlags(Qt::Dialog); + rateApp->setAttribute(Qt::WA_DeleteOnClose,true); + QPoint centerPos = this->geometry().center()-rateApp->geometry().center(); + connect(rateApp,&RateApp::showRateDialog,[=]() + { + if(this->windowState() != Qt::WindowMinimized && this->isVisible() && isActiveWindow()){ + rateApp->move(centerPos); + rateApp->show(); + }else{ + rateApp->delayShowEvent(); + } + }); } void MainWindow::updatePageTheme() @@ -324,7 +339,7 @@ void MainWindow::notify(QString title,QString message) else{ auto popup = new NotificationPopup(webEngine); connect(popup,&NotificationPopup::notification_clicked,[=](){ - if(windowState()==Qt::WindowMinimized || windowState()!=Qt::WindowActive){ + if(windowState() == Qt::WindowMinimized || windowState() != Qt::WindowActive){ activateWindow(); raise(); showNormal(); @@ -382,14 +397,6 @@ void MainWindow::createActions() this->addAction(quitAction); } -void MainWindow::createStatusBar() -{ - QStatusBar *statusBar = new QStatusBar(this); - setStatusBar(statusBar); - statusBar->hide(); - this->statusBar = statusBar; -} - void MainWindow::createTrayIcon() { trayIconMenu = new QMenu(this); @@ -543,8 +550,8 @@ void MainWindow::createWebEngine() createWebPage(false); - QWebEngineCookieStore *browser_cookie_store = this->webEngine->page()->profile()->cookieStore(); - connect( browser_cookie_store, &QWebEngineCookieStore::cookieAdded, this, &MainWindow::handleCookieAdded ); +// QWebEngineCookieStore *browser_cookie_store = this->webEngine->page()->profile()->cookieStore(); +// connect( browser_cookie_store, &QWebEngineCookieStore::cookieAdded, this, &MainWindow::handleCookieAdded ); } @@ -617,7 +624,7 @@ void MainWindow::setNotificationPresenter(QWebEngineProfile* profile) trayIcon->showMessage(notification->title(),notification->message(),icon,settings.value("notificationTimeOut",9000).toInt()); trayIcon->disconnect(trayIcon,SIGNAL(messageClicked())); connect(trayIcon,&QSystemTrayIcon::messageClicked,[=](){ - if(windowState()==Qt::WindowMinimized || windowState()!=Qt::WindowActive){ + if(windowState() == Qt::WindowMinimized || windowState() != Qt::WindowActive){ activateWindow(); raise(); showNormal(); @@ -673,14 +680,8 @@ void MainWindow::handleWebViewTitleChanged(QString title) } } -void MainWindow::handleLoadStarted() -{ - statusBar->show(); -} - void MainWindow::handleLoadFinished(bool loaded) { - statusBar->hide(); if(loaded){ //check if page has loaded correctly checkLoadedCorrectly(); @@ -698,6 +699,7 @@ void MainWindow::checkLoadedCorrectly() if(result.toString().contains("page-version",Qt::CaseInsensitive)) { qWarning()<<"Test 1 found"<page()->runJavaScript("document.getElementsByTagName('body')[0].innerText = ''"); loadingQuirk("test1"); }else if(webEngine->title().contains("Error",Qt::CaseInsensitive)) { @@ -752,16 +754,6 @@ void MainWindow::loadingQuirk(QString test) } } - -void MainWindow::handleLoadProgress(int progress) -{ - statusBar->showMessage("Loading "+QString::number(progress)+"%"); - if (progress >= 50) - { - statusBar->hide(); - } -} - //unused direct method to download file without having entry in download manager void MainWindow::handleDownloadRequested(QWebEngineDownloadItem *download) { diff --git a/src/mainwindow.h b/src/mainwindow.h index 75948e9..98af994 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -35,6 +35,7 @@ #include "about.h" #include "dictionaries.h" #include "webview.h" +#include "rateapp.h" class MainWindow : public QMainWindow @@ -47,8 +48,6 @@ public slots: void updatePageTheme(); void handleWebViewTitleChanged(QString title); - void handleLoadStarted(); - void handleLoadProgress(int progress); void handleLoadFinished(bool loaded); void handleDownloadRequested(QWebEngineDownloadItem *download); @@ -58,7 +57,6 @@ protected slots: private: QPalette lightPalette; void createActions(); - void createStatusBar(); void createTrayIcon(); void createWebEngine(); @@ -81,7 +79,7 @@ private: QSystemTrayIcon *trayIcon; QWebEngineView *webEngine; - QStatusBar *statusBar; + //QStatusBar *statusBar; SettingsWidget * settingsWidget = nullptr; -- cgit v1.2.3 From 6045235c1d9a2dfd91d593a9d62b2f5fa09b8c8c Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Sun, 30 May 2021 20:46:40 +0530 Subject: fixed theme switch issue --- snap_launcher/bin/whatsie | Bin 1713920 -> 1718656 bytes src/mainwindow.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++--- src/mainwindow.h | 4 ++++ 3 files changed, 51 insertions(+), 3 deletions(-) (limited to 'src/mainwindow.h') diff --git a/snap_launcher/bin/whatsie b/snap_launcher/bin/whatsie index 3096854..e4ee637 100755 Binary files a/snap_launcher/bin/whatsie and b/snap_launcher/bin/whatsie differ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index de208ef..d63b1d4 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,5 +1,6 @@ #include "mainwindow.h" +#include #include #include #include @@ -314,7 +315,11 @@ void MainWindow::closeEvent(QCloseEvent *event) { settings.setValue("geometry", saveGeometry()); settings.setValue("windowState", saveState()); - settings.setValue("windowTheme",getPageTheme()); + +// getPageTheme(); +// QTimer::singleShot(500,[=](){ +// qWarning()<<"THEME"<hide(); @@ -366,6 +371,12 @@ void MainWindow::notify(QString title,QString message) void MainWindow::createActions() { + + openUrlAction = new QAction("New Chat",this); + this->addAction(openUrlAction); + openUrlAction->setShortcut(QKeySequence(Qt::Modifier::CTRL+Qt::Key_N)); + connect(openUrlAction,&QAction::triggered,this,&MainWindow::newChat); + fullscreenAction = new QAction(tr("Fullscreen"),this); fullscreenAction->setShortcut(Qt::Key_F11); connect(fullscreenAction, &QAction::triggered,[=](){ @@ -404,11 +415,20 @@ void MainWindow::createActions() quitAction = new QAction(tr("&Quit"), this); quitAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_Q)); - connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit); + connect(quitAction, &QAction::triggered,this,&MainWindow::quitApp); addAction(quitAction); this->addAction(quitAction); } +void MainWindow::quitApp() +{ + getPageTheme(); + QTimer::singleShot(800,[=](){ + qWarning()<<"THEME"<quit(); + }); +} + void MainWindow::createTrayIcon() { trayIconMenu = new QMenu(this); @@ -819,6 +839,28 @@ void MainWindow::doAppReload() createWebPage(false); } +void MainWindow::newChat() +{ + bool ok; + QString text = QInputDialog::getText(this, tr("New Chat"), + tr("Enter a valid WhatsApp number you want to chat with."), QLineEdit::Normal, + "",&ok); + if (ok && isPhoneNumber(text)){ + qWarning()<<"Opening new Chat with"<webEngine->page()->load(QUrl("https://web.whatsapp.com/send?phone="+text)); + }else{ + QMessageBox::information(this,QApplication::applicationName()+"| Error", + "Invalid Phone Number"); + } +} + +bool MainWindow::isPhoneNumber(const QString phoneNumber) +{ + const QString phone = "^((\\+?(\\d{2}))\\s?)?((\\d{2})|(\\((\\d{2})\\))\\s?)?(\\d{3,15})(\\-(\\d{3,15}))?$"; + QRegularExpression reg(phone); + return reg.match(phoneNumber).hasMatch(); +} + void MainWindow::doReload() { this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, false); @@ -837,8 +879,10 @@ QString MainWindow::getPageTheme() { webEngine->page()->runJavaScript( "document.querySelector('body').className;", - [](const QVariant &result){ + [this](const QVariant &result){ theme = result.toString(); + theme.contains("dark") ? theme = "dark" : theme = "light"; + settings.setValue("windowTheme",theme); } ); } diff --git a/src/mainwindow.h b/src/mainwindow.h index 98af994..a78bea0 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -74,6 +74,7 @@ private: QAction *quitAction; QAction *lockAction; QAction *fullscreenAction; + QAction *openUrlAction; QMenu *trayIconMenu; QSystemTrayIcon *trayIcon; @@ -123,6 +124,9 @@ private slots: void checkLoadedCorrectly(); void loadingQuirk(QString test); void setNotificationPresenter(QWebEngineProfile *profile); + void newChat(); + bool isPhoneNumber(const QString phoneNumber); + void quitApp(); }; #endif // MAINWINDOW_H -- cgit v1.2.3 From 84f120f133ba1b2ca7db2cf99010245ed1d94234 Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Sun, 30 May 2021 22:04:28 +0530 Subject: allow passing app arguments --- snap_launcher/bin/whatsie | Bin 1718656 -> 1723208 bytes snap_launcher/whatsie.desktop | 9 +++++---- src/main.cpp | 10 +++++++++- src/mainwindow.cpp | 34 ++++++++++++++++++++-------------- src/mainwindow.h | 2 ++ src/settingswidget.cpp | 3 +++ 6 files changed, 39 insertions(+), 19 deletions(-) (limited to 'src/mainwindow.h') diff --git a/snap_launcher/bin/whatsie b/snap_launcher/bin/whatsie index e4ee637..259c5da 100755 Binary files a/snap_launcher/bin/whatsie and b/snap_launcher/bin/whatsie differ diff --git a/snap_launcher/whatsie.desktop b/snap_launcher/whatsie.desktop index 2eeac11..e5c9560 100644 --- a/snap_launcher/whatsie.desktop +++ b/snap_launcher/whatsie.desktop @@ -2,12 +2,13 @@ Version=1.0 GenericName=WhatSie Name[en_US]=WhatSie -Comment=Qt WhatsApp Client +Comment=Qt WhatsApp Web Client Name=WhatSie Type=Application Icon=${SNAP}/meta/gui/icon.png Keywords=WhatSie;WhatsApp -Exec=whatsie %F -Categories=Network;Qt; +Exec=whatsie %u +Categories=Chat;Network;InstantMessaging;Qt; +MimeType=x-scheme-handler/web.whatsapp.com;x-scheme-handler/http;x-scheme-handler/https; Terminal=false -StartupNotify=false +X-GNOME-UsesNotifications=true diff --git a/src/main.cpp b/src/main.cpp index 0a93f8e..ebb0623 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,7 +16,6 @@ int main(int argc, char *argv[]) { QApplication app(argc, argv); app.setWindowIcon(QIcon(":/icons/app/icon-256.png")); - //argv[argc++] = "--single-process"; QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); static const char ENV_VAR_QT_DEVICE_PIXEL_RATIO[] = "QT_DEVICE_PIXEL_RATIO"; @@ -48,6 +47,15 @@ int main(int argc, char *argv[]) QWebEngineSettings::defaultSettings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); MainWindow window; + + QStringList argsList = app.arguments(); + qWarning()<<"Launching with argument"<webEngine->page()->load(QUrl(arg)); +} + void MainWindow::updatePageTheme() { QString webPageTheme = "web"; //implies light @@ -315,11 +321,10 @@ void MainWindow::closeEvent(QCloseEvent *event) { settings.setValue("geometry", saveGeometry()); settings.setValue("windowState", saveState()); - -// getPageTheme(); -// QTimer::singleShot(500,[=](){ -// qWarning()<<"THEME"<refresh(); + }); if(QSystemTrayIcon::isSystemTrayAvailable() && settings.value("closeButtonActionCombo",0).toInt() == 0){ this->hide(); @@ -423,7 +428,7 @@ void MainWindow::createActions() void MainWindow::quitApp() { getPageTheme(); - QTimer::singleShot(800,[=](){ + QTimer::singleShot(500,[=](){ qWarning()<<"THEME"<quit(); }); @@ -439,6 +444,7 @@ void MainWindow::createTrayIcon() trayIconMenu->addAction(reloadAction); trayIconMenu->addAction(lockAction); trayIconMenu->addSeparator(); + trayIconMenu->addAction(openUrlAction); trayIconMenu->addAction(settingsAction); trayIconMenu->addAction(aboutAction); trayIconMenu->addSeparator(); @@ -843,20 +849,20 @@ void MainWindow::newChat() { bool ok; QString text = QInputDialog::getText(this, tr("New Chat"), - tr("Enter a valid WhatsApp number you want to chat with."), QLineEdit::Normal, + tr("Enter a valid WhatsApp number with country code (ex- +91XXXXXXXXXX)"), QLineEdit::Normal, "",&ok); - if (ok && isPhoneNumber(text)){ - qWarning()<<"Opening new Chat with"<webEngine->page()->load(QUrl("https://web.whatsapp.com/send?phone="+text)); - }else{ - QMessageBox::information(this,QApplication::applicationName()+"| Error", + if (ok){ + if(isPhoneNumber(text)) + this->webEngine->page()->load(QUrl("https://web.whatsapp.com/send?phone="+text)); + else + QMessageBox::information(this,QApplication::applicationName()+"| Error", "Invalid Phone Number"); } } bool MainWindow::isPhoneNumber(const QString phoneNumber) { - const QString phone = "^((\\+?(\\d{2}))\\s?)?((\\d{2})|(\\((\\d{2})\\))\\s?)?(\\d{3,15})(\\-(\\d{3,15}))?$"; + const QString phone = "^\\+(((\\d{2}))\\s?)?((\\d{2})|(\\((\\d{2})\\))\\s?)?(\\d{3,15})(\\-(\\d{3,15}))?$"; QRegularExpression reg(phone); return reg.match(phoneNumber).hasMatch(); } diff --git a/src/mainwindow.h b/src/mainwindow.h index a78bea0..f5c51b2 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -50,6 +50,8 @@ public slots: void handleWebViewTitleChanged(QString title); void handleLoadFinished(bool loaded); void handleDownloadRequested(QWebEngineDownloadItem *download); + void loadAppWithArgument(const QString arg); + protected slots: void closeEvent(QCloseEvent *event) override; diff --git a/src/settingswidget.cpp b/src/settingswidget.cpp index 9d4904a..2750e4d 100644 --- a/src/settingswidget.cpp +++ b/src/settingswidget.cpp @@ -147,6 +147,8 @@ void SettingsWidget::loadDictionaries(QStringList dictionaries) void SettingsWidget::refresh() { + ui->themeComboBox->setCurrentText(utils::toCamelCase(settings.value("windowTheme","light").toString())); + ui->cacheSize->setText(utils::refreshCacheSize(cachePath())); ui->cookieSize->setText(utils::refreshCacheSize(persistentStoragePath())); @@ -165,6 +167,7 @@ void SettingsWidget::refresh() //enable disable spell check ui->enableSpellCheck->setChecked(settings.value("sc_enabled",true).toBool()); + } void SettingsWidget::updateDefaultUAButton(const QString engineUA) -- cgit v1.2.3 From 4deed2488131ffd8d2646c57eea8ab5b8c3bc334 Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Mon, 7 Jun 2021 12:24:32 +0530 Subject: code refactoring --- src/mainwindow.cpp | 8 ++++---- src/mainwindow.h | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 93ba706..45a2262 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -74,7 +74,7 @@ MainWindow::MainWindow(QWidget *parent) }); } -void MainWindow::loadAppWithArgument(const QString arg) +void MainWindow::loadAppWithArgument(const QString &arg) { //https://faq.whatsapp.com/iphone/how-to-link-to-whatsapp-from-a-different-app/?lang=en @@ -367,7 +367,7 @@ void MainWindow::closeEvent(QCloseEvent *event) QMainWindow::closeEvent(event); } -void MainWindow::notify(QString title,QString message) +void MainWindow::notify(QString title, QString message) { if(settings.value("disableNotificationPopups",false).toBool() == true){ @@ -890,7 +890,7 @@ void MainWindow::newChat() } } -bool MainWindow::isPhoneNumber(const QString phoneNumber) +bool MainWindow::isPhoneNumber(const QString &phoneNumber) { const QString phone = "^\\+(((\\d{2}))\\s?)?((\\d{2})|(\\((\\d{2})\\))\\s?)?(\\d{3,15})(\\-(\\d{3,15}))?$"; QRegularExpression reg(phone); @@ -902,7 +902,7 @@ void MainWindow::doReload() this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, false); } -void MainWindow::toggleMute(const bool checked) +void MainWindow::toggleMute(const bool &checked) { this->webEngine->page()->setAudioMuted(checked); } diff --git a/src/mainwindow.h b/src/mainwindow.h index f5c51b2..98da302 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -50,7 +50,7 @@ public slots: void handleWebViewTitleChanged(QString title); void handleLoadFinished(bool loaded); void handleDownloadRequested(QWebEngineDownloadItem *download); - void loadAppWithArgument(const QString arg); + void loadAppWithArgument(const QString &arg); protected slots: @@ -109,7 +109,7 @@ private slots: void handleCookieAdded(const QNetworkCookie &cookie); QString getPageTheme(); - void toggleMute(const bool checked); + void toggleMute(const bool &checked); void doAppReload(); void askToReloadPage(); void updateSettingsUserAgentWidget(); @@ -127,7 +127,7 @@ private slots: void loadingQuirk(QString test); void setNotificationPresenter(QWebEngineProfile *profile); void newChat(); - bool isPhoneNumber(const QString phoneNumber); + bool isPhoneNumber(const QString &phoneNumber); void quitApp(); }; -- cgit v1.2.3 From 9867a6b6279229d53fe59854a511c9eea9888427 Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Mon, 28 Feb 2022 18:08:28 +0530 Subject: build: migrate to qt 5.15 --- src/SunClock.cpp | 133 ++- src/about.cpp | 172 ++-- src/automatictheme.cpp | 171 ++-- src/dictionaries.cpp | 97 +- src/downloadmanagerwidget.cpp | 72 +- src/downloadwidget.cpp | 171 ++-- src/downloadwidget.h | 3 +- src/elidedlabel.cpp | 53 +- src/lock.cpp | 350 ++++--- src/main.cpp | 96 +- src/mainwindow.cpp | 1743 ++++++++++++++++----------------- src/mainwindow.h | 147 ++- src/permissiondialog.cpp | 114 ++- src/rateapp.cpp | 204 ++-- src/rungaurd.cpp | 104 +- src/settingswidget.cpp | 785 ++++++++------- src/utils.cpp | 417 ++++---- src/webenginepage.cpp | 479 ++++----- src/webview.cpp | 152 +-- src/widgets/scrolltext/scrolltext.cpp | 263 +++-- 20 files changed, 2818 insertions(+), 2908 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/SunClock.cpp b/src/SunClock.cpp index ead4d54..132c0a6 100644 --- a/src/SunClock.cpp +++ b/src/SunClock.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include inline double rad(double degrees) { @@ -12,7 +12,8 @@ inline double deg(double radians) { return radians * radToDeg; } -Sunclock::Sunclock(double const &latitude_, double const &longitude_, double const &tz_offset_) +Sunclock::Sunclock(double const &latitude_, double const &longitude_, + double const &tz_offset_) : latitude(latitude_), longitude(longitude_), tz_offset(tz_offset_) {} double Sunclock::irradiance() { return irradiance(time(0)); } @@ -32,7 +33,8 @@ double Sunclock::irradiance(time_t when) { double _sun_app_long = sun_app_long(_sun_true_long, _julian_century); double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); double _var_y = var_y(_obliq_corr); - double _eq_of_time = eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); + double _eq_of_time = + eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); double _declination = declination(_obliq_corr, _sun_app_long); double _true_solar_time = true_solar_time(_time_of_day, _eq_of_time); double _hour_angle = hour_angle(_true_solar_time); @@ -57,13 +59,16 @@ time_t Sunclock::sunrise(time_t date) { double _sun_app_long = sun_app_long(_sun_true_long, _julian_century); double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); double _var_y = var_y(_obliq_corr); - double _eq_of_time = eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); + double _eq_of_time = + eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); double _declination = declination(_obliq_corr, _sun_app_long); double _hour_angle_sunrise = hour_angle_sunrise(_declination); - double noon_decimal_day = (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; + double noon_decimal_day = + (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; double decimal_day = noon_decimal_day - _hour_angle_sunrise * 4 / 1440; - return time_from_decimal_day(date, decimal_day) - (time_t)(tz_offset * 60 * 60); + return time_from_decimal_day(date, decimal_day) - + (time_t)(tz_offset * 60 * 60); } time_t Sunclock::solar_noon() { return solar_noon(time(0)); } @@ -80,10 +85,13 @@ time_t Sunclock::solar_noon(time_t date) { double _obliq_corr = obliq_corr(_mean_obliq_ecliptic, _julian_century); double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); double _var_y = var_y(_obliq_corr); - double _eq_of_time = eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); + double _eq_of_time = + eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); - double decimal_day = (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; - return time_from_decimal_day(date, decimal_day) - (time_t)(tz_offset * 60 * 60); + double decimal_day = + (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; + return time_from_decimal_day(date, decimal_day) - + (time_t)(tz_offset * 60 * 60); } time_t Sunclock::sunset() { return sunset(time(0)); } @@ -103,13 +111,16 @@ time_t Sunclock::sunset(time_t date) { double _sun_app_long = sun_app_long(_sun_true_long, _julian_century); double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); double _var_y = var_y(_obliq_corr); - double _eq_of_time = eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); + double _eq_of_time = + eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); double _declination = declination(_obliq_corr, _sun_app_long); double _hour_angle_sunrise = hour_angle_sunrise(_declination); - double noon_decimal_day = (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; + double noon_decimal_day = + (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; double decimal_day = noon_decimal_day + _hour_angle_sunrise * 4 / 1440; - return time_from_decimal_day(date, decimal_day) - (time_t)(tz_offset * 60 * 60); + return time_from_decimal_day(date, decimal_day) - + (time_t)(tz_offset * 60 * 60); } double Sunclock::time_of_day(time_t date) { @@ -142,7 +153,8 @@ time_t Sunclock::time_from_decimal_day(time_t date, double decimal_day) { int Sunclock::days_since_1900(struct tm *t) { int year = t->tm_year; if (year < 0 || year > 199) { - throw std::invalid_argument("days_since_1900 - Date must be between 1900 and 2099"); + throw std::invalid_argument( + "days_since_1900 - Date must be between 1900 and 2099"); } int month = t->tm_mon + 1; int days = t->tm_mday; @@ -157,33 +169,44 @@ int Sunclock::days_since_1900(struct tm *t) { return (yearDays + monthDays + days - 63); } -double Sunclock::julian_day(struct tm *t, double const &time_of_day, double const &tz_offset) { +double Sunclock::julian_day(struct tm *t, double const &time_of_day, + double const &tz_offset) { return days_since_1900(t) + 2415018.5 + time_of_day - tz_offset / 24; } -double Sunclock::julian_century(double _julian_day) { return (_julian_day - 2451545.0) / 36525.0; } +double Sunclock::julian_century(double _julian_day) { + return (_julian_day - 2451545.0) / 36525.0; +} double Sunclock::mean_long_sun(double _julian_century) { - return (280.46646 + fmod(_julian_century * (36000.76983 + _julian_century * 0.0003032), 360)); + return ( + 280.46646 + + fmod(_julian_century * (36000.76983 + _julian_century * 0.0003032), 360)); } double Sunclock::mean_anom_sun(double _julian_century) { - return 357.52911 + _julian_century * (35999.05029 - 0.0001537 * _julian_century); + return 357.52911 + + _julian_century * (35999.05029 - 0.0001537 * _julian_century); } -double Sunclock::sun_eq_of_centre(double _mean_anom_sun, double _julian_century) { - return sin(rad(_mean_anom_sun)) - * (1.914602 - _julian_century * (0.004817 + 0.000014 * _julian_century)) - + sin(rad(2 * _mean_anom_sun)) * (0.019993 - 0.000101 * _julian_century) - + sin(rad(3 * _mean_anom_sun)) * 0.000289; +double Sunclock::sun_eq_of_centre(double _mean_anom_sun, + double _julian_century) { + return sin(rad(_mean_anom_sun)) * + (1.914602 - + _julian_century * (0.004817 + 0.000014 * _julian_century)) + + sin(rad(2 * _mean_anom_sun)) * + (0.019993 - 0.000101 * _julian_century) + + sin(rad(3 * _mean_anom_sun)) * 0.000289; } -double Sunclock::sun_true_long(double _mean_long_sun, double _sun_eq_of_centre) { +double Sunclock::sun_true_long(double _mean_long_sun, + double _sun_eq_of_centre) { return _mean_long_sun + _sun_eq_of_centre; } double Sunclock::eccent_earth_orbit(double _julian_century) { - return 0.016708634 - _julian_century * (0.000042037 + 0.0001537 * _julian_century); + return 0.016708634 - + _julian_century * (0.000042037 + 0.0001537 * _julian_century); } double Sunclock::var_y(double _obliq_corr) { @@ -191,55 +214,63 @@ double Sunclock::var_y(double _obliq_corr) { } double Sunclock::mean_obliq_ecliptic(double _julian_century) { - return (23 - + (26 - + ((21.448 - - _julian_century - * (46.815 + _julian_century * (0.00059 - _julian_century * 0.001813)))) - / 60) - / 60); + return (23 + (26 + ((21.448 - _julian_century * + (46.815 + _julian_century * + (0.00059 - _julian_century * + 0.001813)))) / + 60) / + 60); } -double Sunclock::obliq_corr(double _mean_obliq_ecliptic, double _julian_century) { - return _mean_obliq_ecliptic + 0.00256 * cos(deg(125.04 - 1934.136 * _julian_century)); +double Sunclock::obliq_corr(double _mean_obliq_ecliptic, + double _julian_century) { + return _mean_obliq_ecliptic + + 0.00256 * cos(deg(125.04 - 1934.136 * _julian_century)); } double Sunclock::sun_app_long(double _sun_true_long, double _julian_century) { - return (_sun_true_long - 0.00569 - 0.00478 * sin(deg(125.04 - 1934.136 * _julian_century))); + return (_sun_true_long - 0.00569 - + 0.00478 * sin(deg(125.04 - 1934.136 * _julian_century))); } double Sunclock::declination(double _obliq_corr, double _sun_app_long) { return deg(asin(sin(rad(_obliq_corr)) * sin(rad(_sun_app_long)))); } -double Sunclock::eq_of_time(double _var_y, double _mean_long_sun, double _eccent_earth_orbit, - double _mean_anom_sun) { - return 4 - * deg(_var_y * sin(2 * rad(_mean_long_sun)) - - 2 * _eccent_earth_orbit * sin(rad(_mean_anom_sun)) - + 4 * _eccent_earth_orbit * _var_y * sin(rad(_mean_anom_sun)) - * cos(2 * rad(_mean_long_sun)) - - 0.5 * _var_y * _var_y * sin(4 * rad(_mean_long_sun)) - - 1.25 * _eccent_earth_orbit * _eccent_earth_orbit * sin(2 * rad(_mean_anom_sun))); +double Sunclock::eq_of_time(double _var_y, double _mean_long_sun, + double _eccent_earth_orbit, double _mean_anom_sun) { + return 4 * deg(_var_y * sin(2 * rad(_mean_long_sun)) - + 2 * _eccent_earth_orbit * sin(rad(_mean_anom_sun)) + + 4 * _eccent_earth_orbit * _var_y * sin(rad(_mean_anom_sun)) * + cos(2 * rad(_mean_long_sun)) - + 0.5 * _var_y * _var_y * sin(4 * rad(_mean_long_sun)) - + 1.25 * _eccent_earth_orbit * _eccent_earth_orbit * + sin(2 * rad(_mean_anom_sun))); } double Sunclock::true_solar_time(double _time_of_day, double _eq_of_time) { - return fmod((_time_of_day * 1440 + _eq_of_time + 4 * longitude - 60 * tz_offset), 1440); + return fmod( + (_time_of_day * 1440 + _eq_of_time + 4 * longitude - 60 * tz_offset), + 1440); } double Sunclock::hour_angle(double _true_solar_time) { - return (_true_solar_time / 4 < 0 ? _true_solar_time / 4 + 180 : _true_solar_time / 4 - 180); + return (_true_solar_time / 4 < 0 ? _true_solar_time / 4 + 180 + : _true_solar_time / 4 - 180); } double Sunclock::hour_angle_sunrise(double _declination) { - return deg(acos(cos(rad(90.833)) / (cos(rad(latitude)) * cos(rad(_declination))) - - tan(rad(latitude)) * tan(rad(_declination)))); + return deg( + acos(cos(rad(90.833)) / (cos(rad(latitude)) * cos(rad(_declination))) - + tan(rad(latitude)) * tan(rad(_declination)))); } double Sunclock::solar_zenith(double _declination, double _hour_angle) { - return deg(acos(sin(rad(latitude)) * sin(rad(_declination)) - + cos(rad(latitude)) * cos(rad(_declination)) * cos(rad(_hour_angle)))); + return deg(acos(sin(rad(latitude)) * sin(rad(_declination)) + + cos(rad(latitude)) * cos(rad(_declination)) * + cos(rad(_hour_angle)))); } -double Sunclock::solar_elevation(double _solar_zenith) { return 90 - _solar_zenith; } - +double Sunclock::solar_elevation(double _solar_zenith) { + return 90 - _solar_zenith; +} diff --git a/src/about.cpp b/src/about.cpp index 2212700..9038f20 100644 --- a/src/about.cpp +++ b/src/about.cpp @@ -6,102 +6,92 @@ #include #include -About::About(QWidget *parent) : - QWidget(parent), - ui(new Ui::About) -{ - ui->setupUi(this); - - //init - appName = QApplication::applicationName(); - appDescription = "WhatsApp Web clinet for Linux Desktop"; - isOpenSource = true; - appAuthorName = "Keshav Bhatt"; - appAuthorEmail = "keshavnrj@gmail.com"; - appAuthorLink = "http://ktechpit.com"; - donateLink = "https://paypal.me/keshavnrj/5"; - moreAppsLink = "https://snapcraft.io/search?q=keshavnrj"; - - appSourceCodeLink = "https://github.com/keshavbhatt/whatsie"; - appRateLink = "snap://whatsie"; - - - ui->appNameDesc->setText(QString("

" - "%1

" - "

" - "%2

").arg(appName,appDescription)); - - ui->desc2->setText(QString("

Designed & Developed by:" - " %1

" - "Developer Email address: %2

" - "

Developer Website:" - " %3

").arg(appAuthorName,appAuthorEmail,appAuthorLink)); - - - ui->version->setText("Version: "+QApplication::applicationVersion()); +About::About(QWidget *parent) : QWidget(parent), ui(new Ui::About) { + ui->setupUi(this); + + // init + appName = QApplication::applicationName(); + appDescription = "WhatsApp Web clinet for Linux Desktop"; + isOpenSource = true; + appAuthorName = "Keshav Bhatt"; + appAuthorEmail = "keshavnrj@gmail.com"; + appAuthorLink = "http://ktechpit.com"; + donateLink = "https://paypal.me/keshavnrj/5"; + moreAppsLink = "https://snapcraft.io/search?q=keshavnrj"; + + appSourceCodeLink = "https://github.com/keshavbhatt/whatsie"; + appRateLink = "snap://whatsie"; + + ui->appNameDesc->setText( + QString("

" + "%1

" + "

" + "%2

") + .arg(appName, appDescription)); + + ui->desc2->setText( + QString("

Designed & Developed " + "by:" + " %1

" + "Developer Email address: %2

" + "

Developer Website:" + " %3

") + .arg(appAuthorName, appAuthorEmail, appAuthorLink)); + + ui->version->setText("Version: " + QApplication::applicationVersion()); + + ui->debugInfoText->setHtml(utils::appDebugInfo()); + + ui->debugInfoText->hide(); + + ui->debugInfoButton->setText(QObject::tr("Show Debug Info")); + + if (isOpenSource == false) { + ui->source_code->hide(); + } + + connect(ui->donate, &QPushButton::clicked, + [=]() { QDesktopServices::openUrl(QUrl(donateLink)); }); + + connect(ui->rate, &QPushButton::clicked, + [=]() { QDesktopServices::openUrl(QUrl(appRateLink)); }); + connect(ui->more_apps, &QPushButton::clicked, + [=]() { QDesktopServices::openUrl(QUrl(moreAppsLink)); }); + connect(ui->source_code, &QPushButton::clicked, + [=]() { QDesktopServices::openUrl(QUrl(appSourceCodeLink)); }); + + setWindowTitle(QApplication::applicationName() + " | About"); + + ui->centerWidget->hide(); + + QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this); + ui->centerWidget->setGraphicsEffect(eff); + QPropertyAnimation *a = new QPropertyAnimation(eff, "opacity"); + a->setDuration(1000); + a->setStartValue(0); + a->setEndValue(1); + a->setEasingCurve(QEasingCurve::InCurve); + a->start(QPropertyAnimation::DeleteWhenStopped); + ui->centerWidget->show(); +} - ui->debugInfoText->setHtml(utils::appDebugInfo()); +About::~About() { delete ui; } +void About::on_debugInfoButton_clicked() { + if (ui->debugInfoText->isVisible()) { ui->debugInfoText->hide(); - ui->debugInfoButton->setText(QObject::tr("Show Debug Info")); - if(isOpenSource == false){ - ui->source_code->hide(); - } - - connect(ui->donate,&QPushButton::clicked,[=](){ - QDesktopServices::openUrl(QUrl(donateLink)); - }); - - connect(ui->rate,&QPushButton::clicked,[=](){ - QDesktopServices::openUrl(QUrl(appRateLink)); - }); - connect(ui->more_apps,&QPushButton::clicked,[=](){ - QDesktopServices::openUrl(QUrl(moreAppsLink)); - }); - connect(ui->source_code,&QPushButton::clicked,[=](){ - QDesktopServices::openUrl(QUrl(appSourceCodeLink)); - }); - - setWindowTitle(QApplication::applicationName() +" | About"); - - ui->centerWidget->hide(); - - QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this); - ui->centerWidget->setGraphicsEffect(eff); - QPropertyAnimation *a = new QPropertyAnimation(eff,"opacity"); - a->setDuration(1000); - a->setStartValue(0); - a->setEndValue(1); - a->setEasingCurve(QEasingCurve::InCurve); - a->start(QPropertyAnimation::DeleteWhenStopped); - ui->centerWidget->show(); -} - -About::~About() -{ - delete ui; -} - -void About::on_debugInfoButton_clicked() -{ - if(ui->debugInfoText->isVisible()){ - ui->debugInfoText->hide(); - ui->debugInfoButton->setText(QObject::tr("Show Debug Info")); - - this->resize(this->width(),this->minimumHeight()); - }else{ - ui->debugInfoText->show(); - ui->debugInfoButton->setText(QObject::tr("Hide Debug Info")); - this->adjustSize(); - } - + this->resize(this->width(), this->minimumHeight()); + } else { + ui->debugInfoText->show(); + ui->debugInfoButton->setText(QObject::tr("Hide Debug Info")); + this->adjustSize(); + } } -void About::on_donate_2_clicked() -{ - QDesktopServices::openUrl(QUrl("https://opencollective.com/whatsie")); +void About::on_donate_2_clicked() { + QDesktopServices::openUrl(QUrl("https://opencollective.com/whatsie")); } diff --git a/src/automatictheme.cpp b/src/automatictheme.cpp index b538244..6e14623 100644 --- a/src/automatictheme.cpp +++ b/src/automatictheme.cpp @@ -4,113 +4,114 @@ #include "SunClock.hpp" #include -AutomaticTheme::AutomaticTheme(QWidget *parent) : - QWidget(parent), - ui(new Ui::AutomaticTheme) -{ - ui->setupUi(this); - ui->refresh->setEnabled(false); +AutomaticTheme::AutomaticTheme(QWidget *parent) + : QWidget(parent), ui(new Ui::AutomaticTheme) { + ui->setupUi(this); + ui->refresh->setEnabled(false); - sunrise.setSecsSinceEpoch(settings.value("sunrise").toLongLong()); - sunset.setSecsSinceEpoch(settings.value("sunset").toLongLong()); + sunrise.setSecsSinceEpoch(settings.value("sunrise").toLongLong()); + sunset.setSecsSinceEpoch(settings.value("sunset").toLongLong()); - ui->sunrise->setTime(sunrise.time()); - ui->sunset->setTime(sunset.time()); + ui->sunrise->setTime(sunrise.time()); + ui->sunset->setTime(sunset.time()); - QTimeZone zone = QTimeZone::systemTimeZone(); - QDateTime dt = QDateTime::currentDateTime(); + QTimeZone zone = QTimeZone::systemTimeZone(); + QDateTime dt = QDateTime::currentDateTime(); - if(zone.isValid()){ - hour_offset = (double)zone.standardTimeOffset(dt)/(double)3600; - }else{ - settings.setValue("automaticTheme",false); - QMessageBox::critical(this,"Error","Unable to get system TimeZone information.\n\nAutomatic theme switcher will not work."); - return; - } + if (zone.isValid()) { + hour_offset = (double)zone.standardTimeOffset(dt) / (double)3600; + } else { + settings.setValue("automaticTheme", false); + QMessageBox::critical( + this, "Error", + "Unable to get system TimeZone information.\n\nAutomatic theme " + "switcher will not work."); + return; + } - gPosInfoSrc = QGeoPositionInfoSource::createDefaultSource(this); + gPosInfoSrc = QGeoPositionInfoSource::createDefaultSource(this); - if (gPosInfoSrc) // sudo apt install geoclue-2.0 - { - ui->refresh->setEnabled(true); - connect(gPosInfoSrc,&QGeoPositionInfoSource::positionUpdated,[=](const QGeoPositionInfo &update){ - QGeoCoordinate cor = update.coordinate(); - if(cor.isValid()) - { + if (gPosInfoSrc) // sudo apt install geoclue-2.0 + { + ui->refresh->setEnabled(true); + connect(gPosInfoSrc, &QGeoPositionInfoSource::positionUpdated, + [=](const QGeoPositionInfo &update) { + QGeoCoordinate cor = update.coordinate(); + if (cor.isValid()) { this->lon = cor.longitude(); this->lat = cor.latitude(); ui->refresh->setEnabled(true); gPosInfoSrc->stopUpdates(); - }else{ + } else { ui->refresh->setEnabled(false); - } - }); - connect(gPosInfoSrc,&QGeoPositionInfoSource::updateTimeout,[=](){ - if(!settings.value("sunrise").isValid() || !settings.value("sunset").isValid()) - { - if(ui->refresh->isEnabled()) - ui->refresh->click(); - } - }); - gPosInfoSrc->startUpdates(); - }else{ - ui->refresh->setEnabled(false); - settings.setValue("automaticTheme",false); - QMessageBox::critical(this,"Error","Unable to initialize QGeoPositionInfoSource.\n\nAutomatic theme switcher will not work." - "\n\nPlease fill the sunset and sunrise time manually."); - } + } + }); + connect(gPosInfoSrc, &QGeoPositionInfoSource::updateTimeout, [=]() { + if (!settings.value("sunrise").isValid() || + !settings.value("sunset").isValid()) { + if (ui->refresh->isEnabled()) + ui->refresh->click(); + } + }); + gPosInfoSrc->startUpdates(); + } else { + ui->refresh->setEnabled(false); + settings.setValue("automaticTheme", false); + QMessageBox::critical( + this, "Error", + "Unable to initialize QGeoPositionInfoSource.\n\nAutomatic theme " + "switcher will not work." + "\n\nPlease fill the sunset and sunrise time manually."); + } } -AutomaticTheme::~AutomaticTheme() -{ - gPosInfoSrc->disconnect(); - gPosInfoSrc->deleteLater(); - delete ui; +AutomaticTheme::~AutomaticTheme() { + gPosInfoSrc->disconnect(); + gPosInfoSrc->deleteLater(); + delete ui; } -void AutomaticTheme::on_refresh_clicked() -{ - QGeoCoordinate geoCor = QGeoCoordinate(this->lat,this->lon); - if(geoCor.isValid()) - { - Sunclock sun(this->lat, this->lon, this->hour_offset); - sunrise.setSecsSinceEpoch(sun.sunrise(QDateTime::currentDateTime().toTime_t())); - sunset.setSecsSinceEpoch(sun.sunset(QDateTime::currentDateTime().toTime_t())); +void AutomaticTheme::on_refresh_clicked() { + QGeoCoordinate geoCor = QGeoCoordinate(this->lat, this->lon); + if (geoCor.isValid()) { + Sunclock sun(this->lat, this->lon, this->hour_offset); + sunrise.setSecsSinceEpoch( + sun.sunrise(QDateTime::currentDateTime().toTime_t())); + sunset.setSecsSinceEpoch( + sun.sunset(QDateTime::currentDateTime().toTime_t())); - ui->sunrise->setTime(sunrise.time()); - ui->sunset->setTime(sunset.time()); - }else{ - settings.setValue("automaticTheme",false); - QMessageBox::critical(this,"Error","Invalid Geo-Coordinates.\n\nPlease try again."); - } + ui->sunrise->setTime(sunrise.time()); + ui->sunset->setTime(sunset.time()); + } else { + settings.setValue("automaticTheme", false); + QMessageBox::critical(this, "Error", + "Invalid Geo-Coordinates.\n\nPlease try again."); + } } -void AutomaticTheme::on_save_clicked() -{ - if( sunrise.toSecsSinceEpoch() == sunset.toSecsSinceEpoch() ){ - settings.setValue("automaticTheme",false); - QMessageBox::critical(this,"Error","Invalid settings.\n\nSunrise and Sunset time cannot have similar values.\n\nPlease try again."); - //this->close(); - }else{ - settings.setValue("sunrise",sunrise.toSecsSinceEpoch()); - settings.setValue("sunset",sunset.toSecsSinceEpoch()); - settings.setValue("automaticTheme",true); - this->close(); - } +void AutomaticTheme::on_save_clicked() { + if (sunrise.toSecsSinceEpoch() == sunset.toSecsSinceEpoch()) { + settings.setValue("automaticTheme", false); + QMessageBox::critical(this, "Error", + "Invalid settings.\n\nSunrise and Sunset time cannot " + "have similar values.\n\nPlease try again."); + } else { + settings.setValue("sunrise", sunrise.toSecsSinceEpoch()); + settings.setValue("sunset", sunset.toSecsSinceEpoch()); + settings.setValue("automaticTheme", true); + this->close(); + } } -void AutomaticTheme::on_cancel_clicked() -{ - settings.setValue("automaticTheme",false); - this->close(); +void AutomaticTheme::on_cancel_clicked() { + settings.setValue("automaticTheme", false); + this->close(); } -void AutomaticTheme::on_sunrise_timeChanged(const QTime &time) -{ - sunrise.setTime(QTime(time.hour(),time.minute(),0)); +void AutomaticTheme::on_sunrise_timeChanged(const QTime &time) { + sunrise.setTime(QTime(time.hour(), time.minute(), 0)); } -void AutomaticTheme::on_sunset_timeChanged(const QTime &time) -{ - sunset.setTime(QTime(time.hour(),time.minute(),0)); +void AutomaticTheme::on_sunset_timeChanged(const QTime &time) { + sunset.setTime(QTime(time.hour(), time.minute(), 0)); } diff --git a/src/dictionaries.cpp b/src/dictionaries.cpp index 5ae6cc3..9538582 100644 --- a/src/dictionaries.cpp +++ b/src/dictionaries.cpp @@ -1,73 +1,66 @@ #include "dictionaries.h" -#include +#include "utils.h" #include +#include #include #include #include -#include "utils.h" -static QString DICTIONARY_FILE_SUFFIX = ".bdic"; -Dictionaries::Dictionaries(QObject *parent) : QObject(parent) -{ - setParent(parent); -} +QString DICTIONARY_FILE_SUFFIX = ".bdic"; -Dictionaries::~Dictionaries() -{ - this->deleteLater(); +Dictionaries::Dictionaries(QObject *parent) : QObject(parent) { + setParent(parent); } +Dictionaries::~Dictionaries() { this->deleteLater(); } -QString Dictionaries::GetDictionaryPath() -{ - QString dict_path; - - // the environment variable takes precedence on all platforms - if (qEnvironmentVariableIsSet("QTWEBENGINE_DICTIONARIES_PATH")) { - dict_path = utils::GetEnvironmentVar("QTWEBENGINE_DICTIONARIES_PATH"); - return dict_path; - } - - // next look relative to the executable - dict_path = QCoreApplication::applicationDirPath() + "/qtwebengine_dictionaries"; +QString Dictionaries::GetDictionaryPath() { + QString dict_path; + // the environment variable takes precedence on all platforms + if (qEnvironmentVariableIsSet("QTWEBENGINE_DICTIONARIES_PATH")) { + dict_path = utils::GetEnvironmentVar("QTWEBENGINE_DICTIONARIES_PATH"); + return dict_path; + } - if (QDir(dict_path).exists()) { - return dict_path; - } + // next look relative to the executable + dict_path = + QCoreApplication::applicationDirPath() + "/qtwebengine_dictionaries"; - //inside the installed Qt directories - dict_path = QLibraryInfo::location(QLibraryInfo::DataPath) + "/qtwebengine_dictionaries"; + if (QDir(dict_path).exists()) { + return dict_path; + } + // inside the installed Qt directories + dict_path = QLibraryInfo::location(QLibraryInfo::DataPath) + + "/qtwebengine_dictionaries"; - if (QDir(dict_path).exists()) { - return dict_path; - } + if (QDir(dict_path).exists()) { + return dict_path; + } - return QString(); + return QString(); } - -QStringList Dictionaries::GetDictionaries() -{ - QStringList dictionaries; - QString dict_path = GetDictionaryPath(); - if (dict_path.isEmpty()) { - return dictionaries; - } - QDir dictDir(dict_path); - if (dictDir.exists()) { - QStringList filters; - // Look for all *.bdic files. - filters << "*" + DICTIONARY_FILE_SUFFIX; - dictDir.setNameFilters(filters); - QStringList dictionary_files = dictDir.entryList(); - foreach(QString file, dictionary_files) { - QFileInfo fileInfo(file); - QString dname = fileInfo.baseName(); - dictionaries.append(dname); - } - } +QStringList Dictionaries::GetDictionaries() { + QStringList dictionaries; + QString dict_path = GetDictionaryPath(); + if (dict_path.isEmpty()) { return dictionaries; + } + QDir dictDir(dict_path); + if (dictDir.exists()) { + QStringList filters; + // Look for all *.bdic files. + filters << "*" + DICTIONARY_FILE_SUFFIX; + dictDir.setNameFilters(filters); + QStringList dictionary_files = dictDir.entryList(); + foreach (QString file, dictionary_files) { + QFileInfo fileInfo(file); + QString dname = fileInfo.baseName(); + dictionaries.append(dname); + } + } + return dictionaries; } diff --git a/src/downloadmanagerwidget.cpp b/src/downloadmanagerwidget.cpp index d013b1c..ac44efe 100644 --- a/src/downloadmanagerwidget.cpp +++ b/src/downloadmanagerwidget.cpp @@ -6,45 +6,47 @@ #include DownloadManagerWidget::DownloadManagerWidget(QWidget *parent) - : QWidget(parent) - , m_numDownloads(0) -{ - setupUi(this); + : QWidget(parent), m_numDownloads(0) { + setupUi(this); } -void DownloadManagerWidget::downloadRequested(QWebEngineDownloadItem *download) -{ - Q_ASSERT(download && download->state() == QWebEngineDownloadItem::DownloadRequested); - QString path; - - bool usenativeFileDialog = settings.value("useNativeFileDialog",false).toBool(); - if(usenativeFileDialog == false){ - path = QFileDialog::getSaveFileName(this, tr("Save as"), download->path(),tr("Any file (*)"),nullptr,QFileDialog::DontUseNativeDialog); - }else{ - path = QFileDialog::getSaveFileName(this, tr("Save as"), download->path(),tr("Any file (*)"),nullptr); - } - - if (path.isEmpty()) - return; - - download->setPath(path); - download->accept(); - add(new DownloadWidget(download)); - show(); +void DownloadManagerWidget::downloadRequested( + QWebEngineDownloadItem *download) { + Q_ASSERT(download && + download->state() == QWebEngineDownloadItem::DownloadRequested); + QString path; + + bool usenativeFileDialog = + settings.value("useNativeFileDialog", false).toBool(); + if (usenativeFileDialog == false) { + path = QFileDialog::getSaveFileName(this, tr("Save as"), download->downloadDirectory(), + tr("Any file (*)"), nullptr, + QFileDialog::DontUseNativeDialog); + } else { + path = QFileDialog::getSaveFileName(this, tr("Save as"), download->downloadDirectory(), + tr("Any file (*)"), nullptr); + } + + if (path.isEmpty()) + return; + + download->setDownloadDirectory(path); + download->accept(); + add(new DownloadWidget(download)); + show(); } -void DownloadManagerWidget::add(DownloadWidget *downloadWidget) -{ - connect(downloadWidget, &DownloadWidget::removeClicked, this, &DownloadManagerWidget::remove); - m_itemsLayout->insertWidget(0, downloadWidget, 0, Qt::AlignTop); - if (m_numDownloads++ == 0) - m_zeroItemsLabel->hide(); +void DownloadManagerWidget::add(DownloadWidget *downloadWidget) { + connect(downloadWidget, &DownloadWidget::removeClicked, this, + &DownloadManagerWidget::remove); + m_itemsLayout->insertWidget(0, downloadWidget, 0, Qt::AlignTop); + if (m_numDownloads++ == 0) + m_zeroItemsLabel->hide(); } -void DownloadManagerWidget::remove(DownloadWidget *downloadWidget) -{ - m_itemsLayout->removeWidget(downloadWidget); - downloadWidget->deleteLater(); - if (--m_numDownloads == 0) - m_zeroItemsLabel->show(); +void DownloadManagerWidget::remove(DownloadWidget *downloadWidget) { + m_itemsLayout->removeWidget(downloadWidget); + downloadWidget->deleteLater(); + if (--m_numDownloads == 0) + m_zeroItemsLabel->show(); } diff --git a/src/downloadwidget.cpp b/src/downloadwidget.cpp index 005ea1e..acfe732 100644 --- a/src/downloadwidget.cpp +++ b/src/downloadwidget.cpp @@ -4,105 +4,96 @@ #include #include -DownloadWidget::DownloadWidget(QWebEngineDownloadItem *download, QWidget *parent) - : QFrame(parent) - , m_download(download) - , m_timeAdded(QTime::currentTime()) -{ - setupUi(this); - m_dstName->setText(QFileInfo(m_download->path()).fileName()); - m_srcUrl->setText(m_download->url().toDisplayString()); +DownloadWidget::DownloadWidget(QWebEngineDownloadItem *download, + QWidget *parent) + : QFrame(parent), m_download(download) { + setupUi(this); + //m_timeAdded(QTime::currentTime()); + m_dstName->setText(QFileInfo(m_download->downloadDirectory()).fileName()); + m_srcUrl->setText(m_download->url().toDisplayString()); - connect(m_cancelButton, &QPushButton::clicked, - [this](bool) { - if (m_download->state() == QWebEngineDownloadItem::DownloadInProgress) - m_download->cancel(); - else - emit removeClicked(this); - }); + connect(m_cancelButton, &QPushButton::clicked, [this](bool) { + if (m_download->state() == QWebEngineDownloadItem::DownloadInProgress) + m_download->cancel(); + else + emit removeClicked(this); + }); - connect(m_download, &QWebEngineDownloadItem::downloadProgress, - this, &DownloadWidget::updateWidget); + connect(m_download, &QWebEngineDownloadItem::downloadProgress, this, + &DownloadWidget::updateWidget); - connect(m_download, &QWebEngineDownloadItem::stateChanged, - this, &DownloadWidget::updateWidget); + connect(m_download, &QWebEngineDownloadItem::stateChanged, this, + &DownloadWidget::updateWidget); - updateWidget(); + updateWidget(); } -inline QString DownloadWidget::withUnit(qreal bytes) -{ - if (bytes < (1 << 10)) - return tr("%L1 B").arg(bytes); - else if (bytes < (1 << 20)) - return tr("%L1 KiB").arg(bytes / (1 << 10), 0, 'f', 2); - else if (bytes < (1 << 30)) - return tr("%L1 MiB").arg(bytes / (1 << 20), 0, 'f', 2); - else - return tr("%L1 GiB").arg(bytes / (1 << 30), 0, 'f', 2); +inline QString DownloadWidget::withUnit(qreal bytes) { + if (bytes < (1 << 10)) + return tr("%L1 B").arg(bytes); + else if (bytes < (1 << 20)) + return tr("%L1 KiB").arg(bytes / (1 << 10), 0, 'f', 2); + else if (bytes < (1 << 30)) + return tr("%L1 MiB").arg(bytes / (1 << 20), 0, 'f', 2); + else + return tr("%L1 GiB").arg(bytes / (1 << 30), 0, 'f', 2); } -void DownloadWidget::updateWidget() -{ - qreal totalBytes = m_download->totalBytes(); - qreal receivedBytes = m_download->receivedBytes(); - qreal bytesPerSecond = receivedBytes / m_timeAdded.elapsed() * 1000; +void DownloadWidget::updateWidget() { + qreal totalBytes = m_download->totalBytes(); + qreal receivedBytes = m_download->receivedBytes(); + qreal bytesPerSecond = receivedBytes / m_timeAdded.elapsed() * 1000; - auto state = m_download->state(); - switch (state) { - case QWebEngineDownloadItem::DownloadRequested: - Q_UNREACHABLE(); - break; - case QWebEngineDownloadItem::DownloadInProgress: - if (totalBytes >= 0) { - m_progressBar->setValue(qRound(100 * receivedBytes / totalBytes)); - m_progressBar->setDisabled(false); - m_progressBar->setFormat( - tr("%p% - %1 of %2 downloaded - %3/s") - .arg(withUnit(receivedBytes)) - .arg(withUnit(totalBytes)) - .arg(withUnit(bytesPerSecond))); - } else { - m_progressBar->setValue(0); - m_progressBar->setDisabled(false); - m_progressBar->setFormat( - tr("unknown size - %1 downloaded - %2/s") - .arg(withUnit(receivedBytes)) - .arg(withUnit(bytesPerSecond))); - } - break; - case QWebEngineDownloadItem::DownloadCompleted: - m_progressBar->setValue(100); - m_progressBar->setDisabled(true); - m_progressBar->setFormat( - tr("completed - %1 downloaded - %2/s") - .arg(withUnit(receivedBytes)) - .arg(withUnit(bytesPerSecond))); - break; - case QWebEngineDownloadItem::DownloadCancelled: - m_progressBar->setValue(0); - m_progressBar->setDisabled(true); - m_progressBar->setFormat( - tr("cancelled - %1 downloaded - %2/s") - .arg(withUnit(receivedBytes)) - .arg(withUnit(bytesPerSecond))); - break; - case QWebEngineDownloadItem::DownloadInterrupted: - m_progressBar->setValue(0); - m_progressBar->setDisabled(true); - m_progressBar->setFormat( - tr("interrupted: %1") - .arg(m_download->interruptReasonString())); - break; - } - - if (state == QWebEngineDownloadItem::DownloadInProgress) { - static QIcon cancelIcon(QStringLiteral(":/icons/stop-line.png")); - m_cancelButton->setIcon(cancelIcon); - m_cancelButton->setToolTip(tr("Stop downloading")); + auto state = m_download->state(); + switch (state) { + case QWebEngineDownloadItem::DownloadRequested: + Q_UNREACHABLE(); + break; + case QWebEngineDownloadItem::DownloadInProgress: + if (totalBytes >= 0) { + m_progressBar->setValue(qRound(100 * receivedBytes / totalBytes)); + m_progressBar->setDisabled(false); + m_progressBar->setFormat(tr("%p% - %1 of %2 downloaded - %3/s") + .arg(withUnit(receivedBytes)) + .arg(withUnit(totalBytes)) + .arg(withUnit(bytesPerSecond))); } else { - static QIcon removeIcon(QStringLiteral(":/icons/close-fill.png")); - m_cancelButton->setIcon(removeIcon); - m_cancelButton->setToolTip(tr("Remove from list")); + m_progressBar->setValue(0); + m_progressBar->setDisabled(false); + m_progressBar->setFormat(tr("unknown size - %1 downloaded - %2/s") + .arg(withUnit(receivedBytes)) + .arg(withUnit(bytesPerSecond))); } + break; + case QWebEngineDownloadItem::DownloadCompleted: + m_progressBar->setValue(100); + m_progressBar->setDisabled(true); + m_progressBar->setFormat(tr("completed - %1 downloaded - %2/s") + .arg(withUnit(receivedBytes)) + .arg(withUnit(bytesPerSecond))); + break; + case QWebEngineDownloadItem::DownloadCancelled: + m_progressBar->setValue(0); + m_progressBar->setDisabled(true); + m_progressBar->setFormat(tr("cancelled - %1 downloaded - %2/s") + .arg(withUnit(receivedBytes)) + .arg(withUnit(bytesPerSecond))); + break; + case QWebEngineDownloadItem::DownloadInterrupted: + m_progressBar->setValue(0); + m_progressBar->setDisabled(true); + m_progressBar->setFormat( + tr("interrupted: %1").arg(m_download->interruptReasonString())); + break; + } + + if (state == QWebEngineDownloadItem::DownloadInProgress) { + static QIcon cancelIcon(QStringLiteral(":/icons/stop-line.png")); + m_cancelButton->setIcon(cancelIcon); + m_cancelButton->setToolTip(tr("Stop downloading")); + } else { + static QIcon removeIcon(QStringLiteral(":/icons/close-fill.png")); + m_cancelButton->setIcon(removeIcon); + m_cancelButton->setToolTip(tr("Remove from list")); + } } diff --git a/src/downloadwidget.h b/src/downloadwidget.h index 521d996..ff9e488 100644 --- a/src/downloadwidget.h +++ b/src/downloadwidget.h @@ -57,6 +57,7 @@ #include #include +#include QT_BEGIN_NAMESPACE class QWebEngineDownloadItem; @@ -82,7 +83,7 @@ private: QString withUnit(qreal bytes); QWebEngineDownloadItem *m_download; - QTime m_timeAdded; + QElapsedTimer m_timeAdded; }; #endif // DOWNLOADWIDGET_H diff --git a/src/elidedlabel.cpp b/src/elidedlabel.cpp index 6c14af4..b88ed4f 100644 --- a/src/elidedlabel.cpp +++ b/src/elidedlabel.cpp @@ -5,45 +5,48 @@ #include #include -ElidedLabel::ElidedLabel(QWidget* parent, Qt::WindowFlags f) +ElidedLabel::ElidedLabel(QWidget *parent, Qt::WindowFlags f) : QLabel(parent, f), m_elide_mode(Qt::ElideRight) { - setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); + setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); } -ElidedLabel::ElidedLabel(const QString& txt, QWidget* parent, Qt::WindowFlags f) +ElidedLabel::ElidedLabel(const QString &txt, QWidget *parent, Qt::WindowFlags f) : QLabel(txt, parent, f), m_elide_mode(Qt::ElideRight) { - setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); + setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); } -ElidedLabel::ElidedLabel(const QString& txt, Qt::TextElideMode elideMode, QWidget* parent, Qt::WindowFlags f) +ElidedLabel::ElidedLabel(const QString &txt, Qt::TextElideMode elideMode, + QWidget *parent, Qt::WindowFlags f) : QLabel(txt, parent, f), m_elide_mode(elideMode) { - setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); - + setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); } -void ElidedLabel::setText(const QString& txt) { - QLabel::setText(txt); - cacheElidedText(geometry().width()); - setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); +void ElidedLabel::setText(const QString &txt) { + QLabel::setText(txt); + cacheElidedText(geometry().width()); + setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); } - void ElidedLabel::cacheElidedText(int w) { - m_cached_elided_text = fontMetrics().elidedText(text(), m_elide_mode, w, (buddy() == nullptr)? 0 : Qt::TextShowMnemonic); + m_cached_elided_text = fontMetrics().elidedText( + text(), m_elide_mode, w, (buddy() == nullptr) ? 0 : Qt::TextShowMnemonic); } -void ElidedLabel::resizeEvent(QResizeEvent* e) { - QLabel::resizeEvent(e); - cacheElidedText(e->size().width()); +void ElidedLabel::resizeEvent(QResizeEvent *e) { + QLabel::resizeEvent(e); + cacheElidedText(e->size().width()); } -void ElidedLabel::paintEvent(QPaintEvent* e) { - if(m_elide_mode == Qt::ElideNone) { - QLabel::paintEvent(e); - } else { - QPainter p(this); - p.drawText(0, 0, geometry().width(), geometry().height(), - QStyle::visualAlignment(text().isRightToLeft()? Qt::RightToLeft : Qt::LeftToRight, alignment()) | ((buddy() == nullptr)? 0 : Qt::TextShowMnemonic), - m_cached_elided_text); - } +void ElidedLabel::paintEvent(QPaintEvent *e) { + if (m_elide_mode == Qt::ElideNone) { + QLabel::paintEvent(e); + } else { + QPainter p(this); + p.drawText(0, 0, geometry().width(), geometry().height(), + QStyle::visualAlignment(text().isRightToLeft() ? Qt::RightToLeft + : Qt::LeftToRight, + alignment()) | + ((buddy() == nullptr) ? 0 : Qt::TextShowMnemonic), + m_cached_elided_text); + } } diff --git a/src/lock.cpp b/src/lock.cpp index e5c65d1..4eb65d1 100644 --- a/src/lock.cpp +++ b/src/lock.cpp @@ -5,214 +5,196 @@ #ifdef Q_OS_WIN32 #include #else -#include // sudo apt install libx11-dev +#include // apt install libx11-dev #include #include #endif -Lock::Lock(QWidget *parent) : - QWidget(parent), - ui(new Ui::Lock) -{ - ui->setupUi(this); - ui->unlock->setEnabled(false); - ui->setPass->setEnabled(false); - ui->wrong->hide(); +Lock::Lock(QWidget *parent) : QWidget(parent), ui(new Ui::Lock) { + ui->setupUi(this); + ui->unlock->setEnabled(false); + ui->setPass->setEnabled(false); + ui->wrong->hide(); - QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this); - ui->centerWidget->setGraphicsEffect(eff); + QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this); + ui->centerWidget->setGraphicsEffect(eff); - animate(); + animate(); - if(settings.value("asdfg").isValid() == false) - { - isLocked = false; - ui->signup->show(); - ui->login->hide(); - animate(); - ui->passcode1->setFocus(); - }else - { - lock_app(); - } + if (settings.value("asdfg").isValid() == false) { + isLocked = false; + ui->signup->show(); + ui->login->hide(); + animate(); + ui->passcode1->setFocus(); + } else { + lock_app(); + } + checkCaps(); + QString capsStyle = QString("background-color: palette(window);" + "padding:4px;" + "border:0px solid palette(highlight);" + "border-radius: 2px;" + "color:palette(window-text);"); + ui->caps1->setStyleSheet(capsStyle); + ui->caps2->setStyleSheet(capsStyle); + ui->signup_warning->setStyleSheet(capsStyle); + ui->wrong->setStyleSheet(capsStyle); +} + +void Lock::animate() { + ui->centerWidget->hide(); + QPropertyAnimation *a = + new QPropertyAnimation(ui->centerWidget->graphicsEffect(), "opacity"); + a->setDuration(400); + a->setStartValue(0); + a->setEndValue(1); + a->setEasingCurve(QEasingCurve::InCurve); + a->start(QPropertyAnimation::DeleteWhenStopped); + ui->centerWidget->show(); +} + +void Lock::applyThemeQuirks() { + // little quirks + + ui->label_4->setStyleSheet( + "color:#c2c5d1;padding: 0px 8px 0px 8px;background:transparent;"); + ui->label_3->setStyleSheet( + "color:#c2c5d1;padding: 0px 8px 0px 8px;background:transparent;"); + + ui->login->setStyleSheet("QWidget#login{background-color:palette(window);" + "background-image:url(:/icons/wa_bg.png)};"); + ui->signup->setStyleSheet("QWidget#signup{background-color:palette(window);" + "background-image:url(:/icons/wa_bg.png)};"); + + ui->widget_2->setStyleSheet( + "QWidget#widget_2{\nborder-radius: " + "5px;\nbackground-image:url(:/icons/" + "texture.png);\nbackground-color:palette(shadow);\n}"); + ui->widget->setStyleSheet( + "QWidget#widget{\nborder-radius: " + "5px;\nbackground-image:url(:/icons/" + "texture.png);\nbackground-color:palette(shadow);\n}"); + + ui->centerWidget->setStyleSheet( + "QWidget#centerWidget{background-image:url(:/icons/wa_bg.png)}"); + if (settings.value("windowTheme", "light").toString() == "dark") { + + } else { + } +} + +Lock::~Lock() { delete ui; } + +void Lock::checkCaps() { + if (getCapsLockOn()) { + ui->caps1->show(); + ui->caps2->show(); + } else { + ui->caps1->hide(); + ui->caps2->hide(); + } +} + +void Lock::keyReleaseEvent(QKeyEvent *event) { + if (event->key() == Qt::Key_CapsLock) { checkCaps(); - QString capsStyle = QString("background-color: palette(window);" - "padding:4px;" - "border:0px solid palette(highlight);" - "border-radius: 2px;" - "color:palette(window-text);"); - ui->caps1->setStyleSheet(capsStyle); - ui->caps2->setStyleSheet(capsStyle); - ui->signup_warning->setStyleSheet(capsStyle); - ui->wrong->setStyleSheet(capsStyle); - -} - -void Lock::animate() -{ - ui->centerWidget->hide(); - QPropertyAnimation *a = new QPropertyAnimation(ui->centerWidget->graphicsEffect(),"opacity"); - a->setDuration(400); - a->setStartValue(0); - a->setEndValue(1); - a->setEasingCurve(QEasingCurve::InCurve); - a->start(QPropertyAnimation::DeleteWhenStopped); - ui->centerWidget->show(); -} - -void Lock::applyThemeQuirks(){ - //little quirks - - ui->label_4->setStyleSheet("color:#c2c5d1;padding: 0px 8px 0px 8px;background:transparent;"); - ui->label_3->setStyleSheet("color:#c2c5d1;padding: 0px 8px 0px 8px;background:transparent;"); - - ui->login->setStyleSheet("QWidget#login{background-color:palette(window);background-image:url(:/icons/wa_bg.png)};"); - ui->signup->setStyleSheet("QWidget#signup{background-color:palette(window);background-image:url(:/icons/wa_bg.png)};"); - - ui->widget_2->setStyleSheet("QWidget#widget_2{\nborder-radius: 5px;\nbackground-image:url(:/icons/texture.png);\nbackground-color:palette(shadow);\n}"); - ui->widget->setStyleSheet("QWidget#widget{\nborder-radius: 5px;\nbackground-image:url(:/icons/texture.png);\nbackground-color:palette(shadow);\n}"); - - ui->centerWidget->setStyleSheet("QWidget#centerWidget{background-image:url(:/icons/wa_bg.png)}"); - if(settings.value("windowTheme","light").toString() == "dark") - { - - }else{ - - } -} - -Lock::~Lock() -{ - delete ui; -} - -void Lock::checkCaps() -{ - if(getCapsLockOn()){ - ui->caps1->show(); - ui->caps2->show(); - }else{ - ui->caps1->hide(); - ui->caps2->hide(); - } -} - -void Lock::keyReleaseEvent(QKeyEvent *event){ - if(event->key() == Qt::Key_CapsLock){ - checkCaps(); + } +} + +bool Lock::event(QEvent *e) { return QWidget::event(e); } + +void Lock::on_passcode1_textChanged(const QString &arg1) { + if (arg1.contains(" ")) { + ui->passcode1->setText(arg1.simplified()); + } + ui->setPass->setEnabled(arg1.length() > 4 && arg1 == ui->passcode2->text()); +} + +void Lock::on_passcode2_textChanged(const QString &arg1) { + if (arg1.contains(" ")) { + ui->passcode2->setText(arg1.simplified()); + } + ui->setPass->setEnabled(arg1.length() > 4 && arg1 == ui->passcode1->text()); +} + +void Lock::on_setPass_clicked() { + QString pass1, pass2; + pass1 = ui->passcode1->text().trimmed(); + pass2 = ui->passcode2->text().trimmed(); + if (pass1 == pass2) { + settings.setValue("asdfg", QByteArray(pass1.toUtf8()).toBase64()); + settings.setValue("lockscreen", true); + ui->passcode1->clear(); + ui->passcode2->clear(); + emit passwordSet(); + if (check_password_set()) { + ui->signup->hide(); + ui->login->show(); + ui->passcodeLogin->setFocus(); } + } else { + return; + } } -bool Lock::event(QEvent* e) -{ - return QWidget::event(e); -} +bool Lock::check_password_set() { return settings.value("asdfg").isValid(); } -void Lock::on_passcode1_textChanged(const QString &arg1) -{ - if(arg1.contains(" ")){ - ui->passcode1->setText(arg1.simplified()); - } - ui->setPass->setEnabled(arg1.length()>4 && arg1== ui->passcode2->text()); -} - -void Lock::on_passcode2_textChanged(const QString &arg1) -{ - if(arg1.contains(" ")){ - ui->passcode2->setText(arg1.simplified()); - } - ui->setPass->setEnabled(arg1.length()>4 && arg1== ui->passcode1->text()); -} - -void Lock::on_setPass_clicked() -{ - QString pass1,pass2; - pass1 = ui->passcode1->text().trimmed(); - pass2 = ui->passcode2->text().trimmed(); - if(pass1==pass2) - { - settings.setValue("asdfg",QByteArray(pass1.toUtf8()).toBase64()); - settings.setValue("lockscreen",true); - ui->passcode1->clear(); - ui->passcode2->clear(); - emit passwordSet(); - if(check_password_set()){ - ui->signup->hide(); - ui->login->show(); - ui->passcodeLogin->setFocus(); - } - }else { - return; - } -} - -bool Lock::check_password_set(){ - return settings.value("asdfg").isValid(); -} - -void Lock::on_unlock_clicked() -{ - QString password = QByteArray::fromBase64(settings.value("asdfg").toByteArray()); - if(ui->passcodeLogin->text() == password && check_password_set()) - { - ui->login->hide(); - ui->signup->hide(); - ui->passcodeLogin->clear(); - isLocked = false; - this->hide(); - emit unLocked(); - }else{ - ui->wrong->show(); - } +void Lock::on_unlock_clicked() { + QString password = + QByteArray::fromBase64(settings.value("asdfg").toByteArray()); + if (ui->passcodeLogin->text() == password && check_password_set()) { + ui->login->hide(); + ui->signup->hide(); + ui->passcodeLogin->clear(); + isLocked = false; + this->hide(); + emit unLocked(); + } else { + ui->wrong->show(); + } } -void Lock::on_passcodeLogin_textChanged(const QString &arg1) -{ - if(arg1.contains(" ")){ - ui->passcodeLogin->setText(arg1.simplified()); - } - ui->wrong->hide(); - ui->unlock->setEnabled(arg1.length()>4); +void Lock::on_passcodeLogin_textChanged(const QString &arg1) { + if (arg1.contains(" ")) { + ui->passcodeLogin->setText(arg1.simplified()); + } + ui->wrong->hide(); + ui->unlock->setEnabled(arg1.length() > 4); } -void Lock::lock_app() -{ - checkCaps(); - ui->wrong->hide(); - ui->signup->hide(); - ui->login->show(); - isLocked = true; - this->show(); - animate(); - ui->passcodeLogin->setFocus(); +void Lock::lock_app() { + checkCaps(); + ui->wrong->hide(); + ui->signup->hide(); + ui->login->show(); + isLocked = true; + this->show(); + animate(); + ui->passcodeLogin->setFocus(); } -void Lock::on_passcodeLogin_returnPressed() -{ - on_unlock_clicked(); -} +void Lock::on_passcodeLogin_returnPressed() { on_unlock_clicked(); } -bool Lock::getCapsLockOn() -{ +bool Lock::getCapsLockOn() { // platform dependent method of determining if CAPS LOCK is on #ifdef Q_OS_WIN32 // MS Windows version - return GetKeyState(VK_CAPITAL) == 1; + return GetKeyState(VK_CAPITAL) == 1; #else // X11 version (Linux/Unix/Mac OS X/etc...) - Display* d = XOpenDisplay((char*)0); - bool caps_state = false; - if (d) { - unsigned n; - XkbGetIndicatorState(d, XkbUseCoreKbd, &n); - caps_state = (n & 0x01) == 1; - } - return caps_state; + Display *d = XOpenDisplay((char *)0); + bool caps_state = false; + if (d) { + unsigned n; + XkbGetIndicatorState(d, XkbUseCoreKbd, &n); + caps_state = (n & 0x01) == 1; + } + return caps_state; #endif } -void Lock::on_cancelSetting_clicked() -{ - isLocked = false; - emit passwordNotSet(); - this->hide(); +void Lock::on_cancelSetting_clicked() { + isLocked = false; + emit passwordNotSet(); + this->hide(); } diff --git a/src/main.cpp b/src/main.cpp index 1b3881e..7f94a3d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,67 +1,71 @@ #include -#include -#include +#include +#include #include #include -#include -#include +#include +#include #include "mainwindow.h" -#include "rungaurd.h" #include "common.h" +#include "rungaurd.h" +int main(int argc, char *argv[]) { + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + static const char ENV_VAR_QT_DEVICE_PIXEL_RATIO[] = "QT_DEVICE_PIXEL_RATIO"; + if (!qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO) && + !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR") && + !qEnvironmentVariableIsSet("QT_SCALE_FACTOR") && + !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) { + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + } -int main(int argc, char *argv[]) -{ - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - static const char ENV_VAR_QT_DEVICE_PIXEL_RATIO[] = "QT_DEVICE_PIXEL_RATIO"; - if (!qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO) - && !qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR") - && !qEnvironmentVariableIsSet("QT_SCALE_FACTOR") - && !qEnvironmentVariableIsSet("QT_SCREEN_SCALE_FACTORS")) { - QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); - } - - QApplication app(argc, argv); - app.setWindowIcon(QIcon(":/icons/app/icon-256.png")); + QApplication app(argc, argv); + app.setWindowIcon(QIcon(":/icons/app/icon-256.png")); - QApplication::setApplicationName("WhatSie"); - QApplication::setOrganizationName("org.keshavnrj.ubuntu"); - QApplication::setApplicationVersion(VERSIONSTR); + QApplication::setApplicationName("WhatSie"); + QApplication::setOrganizationName("org.keshavnrj.ubuntu"); + QApplication::setApplicationVersion(VERSIONSTR); - QString appname = QApplication::applicationName(); + QString appname = QApplication::applicationName(); - //allow multiple instances in debug builds - #ifndef QT_DEBUG - RunGuard guard("org.keshavnrj.ubuntu."+appname); - if ( !guard.tryToRun() ){ - QMessageBox::critical(0, appname,"An instance of "+appname+" is already running."); - return 0; - } - #endif +// allow multiple instances in debug builds +#ifndef QT_DEBUG + RunGuard guard("org.keshavnrj.ubuntu." + appname); + if (!guard.tryToRun()) { + QMessageBox::critical(0, appname, + "An instance of " + appname + " is already running."); + return 0; + } +#endif - qputenv("QTWEBENGINE_CHROMIUM_FLAGS","--single-process"); + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--single-process"); #ifdef QT_DEBUG - qputenv("QTWEBENGINE_CHROMIUM_FLAGS","--remote-debugging-port=9421"); + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--remote-debugging-port=9421"); #endif - qputenv("QTWEBENGINE_CHROMIUM_FLAGS","--disable-logging"); + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-logging"); - QWebEngineSettings::defaultSettings()->setAttribute(QWebEngineSettings::PluginsEnabled, true); - QWebEngineSettings::defaultSettings()->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, true); - QWebEngineSettings::defaultSettings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); + QWebEngineSettings::defaultSettings()->setAttribute( + QWebEngineSettings::PluginsEnabled, true); + QWebEngineSettings::defaultSettings()->setAttribute( + QWebEngineSettings::DnsPrefetchEnabled, true); + QWebEngineSettings::defaultSettings()->setAttribute( + QWebEngineSettings::FullScreenSupportEnabled, true); + QWebEngineSettings::defaultSettings()->setAttribute( + QWebEngineSettings::JavascriptCanAccessClipboard, true); - MainWindow window; + MainWindow window; - QStringList argsList = app.arguments(); - qWarning()<<"Launching with argument"< #include #include +#include extern QString defaultUserAgentStr; MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent), - notificationsTitleRegExp("^\\([1-9]\\d*\\).*"), + : QMainWindow(parent), notificationsTitleRegExp("^\\([1-9]\\d*\\).*"), trayIconRead(":/icons/app/whatsapp.svg"), - trayIconUnread(":/icons/app/whatsapp-message.svg") -{ - this->setObjectName("MainWindow"); - - qApp->setQuitOnLastWindowClosed(false); - - lightPalette = qApp->palette(); - lightPalette.setColor(QPalette::Window,QColor("#F0F0F0"));//whatsapp light palette - - - setWindowTitle(QApplication::applicationName()); - setWindowIcon(QIcon(":/icons/app/icon-256.png")); - setMinimumWidth(500); - setMinimumHeight(520); - - restoreGeometry(settings.value("geometry").toByteArray()); - restoreState(settings.value("windowState").toByteArray()); - - createActions(); - createTrayIcon(); - createWebEngine(); - - if(settings.value("lockscreen",false).toBool()) - { - init_lock(); - } - QTimer *timer = new QTimer(this); - timer->setInterval(1000); - connect(timer,&QTimer::timeout,[=](){ - if(settings.value("asdfg").isValid()){ - if(lockWidget && lockWidget->isLocked==false){ - timer->stop(); - //init_accountWidget(); - } - } - }); - timer->start(); - - init_settingWidget(); - - // quit application if the download manager window is the only remaining window - m_downloadManagerWidget.setAttribute(Qt::WA_QuitOnClose, false); - - updateWindowTheme(); - - RateApp *rateApp = new RateApp(this, "snap://whatsie", 5, 5, 1000 * 30); - rateApp->setWindowTitle(QApplication::applicationName()+" | "+tr("Rate Application")); - rateApp->setVisible(false); - rateApp->setWindowFlags(Qt::Dialog); - rateApp->setAttribute(Qt::WA_DeleteOnClose,true); - QPoint centerPos = this->geometry().center()-rateApp->geometry().center(); - connect(rateApp,&RateApp::showRateDialog,[=]() - { - if(this->windowState() != Qt::WindowMinimized && this->isVisible() && isActiveWindow()){ - rateApp->move(centerPos); - rateApp->show(); - }else{ - rateApp->delayShowEvent(); - } - }); -} - -void MainWindow::loadAppWithArgument(const QString &arg) -{ - //https://faq.whatsapp.com/iphone/how-to-link-to-whatsapp-from-a-different-app/?lang=en - - //The WhatsApp Messenger application - if(arg.contains("://app")){ - qWarning()<<"WhatsApp Messenger application"; - this->show(); //restore app - return; - } - //PASSED SCHEME whatsapp://send?text=Hello%2C%20World!&phone=919568388397" - //CONVERTED URI https://web.whatsapp.com/send?phone=919568388397&text=Hello%2C%20World - //New chat composer - if(arg.contains("send?") || arg.contains("send/?")) - { - QString newArg = arg; - qWarning()<<"New chat composer"; - newArg = newArg.replace("?","&"); - QUrlQuery query(newArg); - qWarning()<webEngine->page()->load(QUrl(urlStr)); - return; - } -} - -void MainWindow::updatePageTheme() -{ - QString webPageTheme = "web"; //implies light - QString windowTheme = settings.value("windowTheme","light").toString(); - if(windowTheme == "dark"){ - webPageTheme = "web dark"; - } - if(webEngine && webEngine->page()){ - webEngine->page()->runJavaScript( - "document.querySelector('body').className='"+webPageTheme+"';", - [](const QVariant &result){ - qDebug() << "Value is: " << result.toString() << endl; - } - ); - } -} - -void MainWindow::resizeEvent(QResizeEvent *event) -{ - if(lockWidget != nullptr){ - lockWidget->resize(event->size()); - } -} - -void MainWindow::updateWindowTheme() -{ - if(settings.value("windowTheme","light").toString() == "dark") - { - qApp->setStyle(QStyleFactory::create("fusion")); - QPalette palette; - palette.setColor(QPalette::Window, QColor("#262D31")); - palette.setColor(QPalette::Text, Qt::white); - palette.setColor(QPalette::WindowText, Qt::white); - palette.setColor(QPalette::Base, QColor("#323739")); - palette.setColor(QPalette::AlternateBase, QColor("#5f6c73")); - palette.setColor(QPalette::ToolTipBase, QColor(66, 66, 66)); - palette.setColor(QPalette::Disabled, QPalette::Window,QColor("#3f4143")); - palette.setColor(QPalette::ToolTipText, QColor("silver")); - palette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127)); - palette.setColor(QPalette::Dark, QColor(35, 35, 35)); - palette.setColor(QPalette::Shadow, QColor(20, 20, 20)); - palette.setColor(QPalette::Button, QColor("#262D31")); - palette.setColor(QPalette::ButtonText, Qt::white); - palette.setColor(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127)); - palette.setColor(QPalette::BrightText, Qt::red); - palette.setColor(QPalette::Link, QColor(42, 130, 218)); - palette.setColor(QPalette::Highlight, QColor(38, 140, 196)); - palette.setColor(QPalette::Disabled, QPalette::Highlight, QColor(80, 80, 80)); - palette.setColor(QPalette::HighlightedText, Qt::white); - palette.setColor(QPalette::Disabled, QPalette::HighlightedText,QColor(127, 127, 127)); - qApp->setPalette(palette); - this->webEngine->setStyleSheet("QWebEngineView{background:#131C21;}"); //whatsapp dark color - //this->webEngine->page()->setBackgroundColor(QColor("#131C21;")); //whatsapp dark color - } - else{ - qApp->setPalette(lightPalette); - this->webEngine->setStyleSheet("QWebEngineView{background:#F0F0F0;}"); //whatsapp light color - //this->webEngine->page()->setBackgroundColor(QColor("#F0F0F0;")); //whatsapp light color - } - - QList widgets = this->findChildren(); - - foreach (QWidget* w, widgets) - { - w->setPalette(qApp->palette()); - } - - setNotificationPresenter(webEngine->page()->profile()); - - if(lockWidget!=nullptr) - { - lockWidget->setStyleSheet("QWidget#login{background-color:palette(window)};" - "QWidget#signup{background-color:palette(window)};"); - lockWidget->applyThemeQuirks(); - } - this->update(); -} - -void MainWindow::handleCookieAdded(const QNetworkCookie &cookie) -{ + trayIconUnread(":/icons/app/whatsapp-message.svg") { + this->setObjectName("MainWindow"); + + qApp->setQuitOnLastWindowClosed(false); + + lightPalette = qApp->palette(); + lightPalette.setColor(QPalette::Window, + QColor(240, 240, 240)); // whatsapp light palette + + setWindowTitle(QApplication::applicationName()); + setWindowIcon(QIcon(":/icons/app/icon-256.png")); + setMinimumWidth(750); + setMinimumHeight(640); + + restoreGeometry(settings.value("geometry").toByteArray()); + restoreState(settings.value("windowState").toByteArray()); + + createActions(); + createTrayIcon(); + createWebEngine(); + + if (settings.value("lockscreen", false).toBool()) { + init_lock(); + } + QTimer *timer = new QTimer(this); + timer->setInterval(1000); + connect(timer, &QTimer::timeout, lockWidget, [=]() { + if (settings.value("asdfg").isValid()) { + if (lockWidget && lockWidget->isLocked == false) { + timer->stop(); + } + } + }); + timer->start(); + + init_settingWidget(); + + // quit application if the download manager window is the only remaining + // window + m_downloadManagerWidget.setAttribute(Qt::WA_QuitOnClose, false); + + updateWindowTheme(); + + RateApp *rateApp = new RateApp(this, "snap://whatsie", 5, 5, 1000 * 30); + rateApp->setWindowTitle(QApplication::applicationName() + " | " + + tr("Rate Application")); + rateApp->setVisible(false); + rateApp->setWindowFlags(Qt::Dialog); + rateApp->setAttribute(Qt::WA_DeleteOnClose, true); + QPoint centerPos = this->geometry().center() - rateApp->geometry().center(); + connect(rateApp, &RateApp::showRateDialog, rateApp, [=]() { + if (this->windowState() != Qt::WindowMinimized && this->isVisible() && + isActiveWindow()) { + rateApp->move(centerPos); + rateApp->show(); + } else { + rateApp->delayShowEvent(); + } + }); +} + +void MainWindow::loadAppWithArgument(const QString &arg) { + // https://faq.whatsapp.com/iphone/how-to-link-to-whatsapp-from-a-different-app/?lang=en + + // The WhatsApp Messenger application + if (arg.contains("://app")) { + qWarning() << "WhatsApp Messenger application"; + this->show(); // restore app + return; + } + // PASSED SCHEME whatsapp://send?text=Hello%2C%20World!&phone=919568388397" + // CONVERTED URI + // https://web.whatsapp.com/send?phone=919568388397&text=Hello%2C%20World New + // chat composer + if (arg.contains("send?") || arg.contains("send/?")) { + QString newArg = arg; + qWarning() << "New chat composer"; + newArg = newArg.replace("?", "&"); + QUrlQuery query(newArg); + qWarning() << query.hasQueryItem("phone"); + QString phone, phoneStr, text, textStr, urlStr; + // create send url equivalent + phone = query.queryItemValue("phone"); + text = query.queryItemValue("text"); + + phoneStr = phone.isEmpty() ? "" : "phone=" + phone; + textStr = text.isEmpty() ? "" : "text=" + text; + + urlStr = "https://web.whatsapp.com/send?" + phoneStr + "&" + textStr; + qWarning() << "Loading" << urlStr; + this->webEngine->page()->load(QUrl(urlStr)); + return; + } +} + +void MainWindow::updatePageTheme() { + QString webPageTheme = "web"; // implies light + QString windowTheme = settings.value("windowTheme", "light").toString(); + if (windowTheme == "dark") { + webPageTheme = "web dark"; + } + if (webEngine && webEngine->page()) { + webEngine->page()->runJavaScript( + "document.querySelector('body').className='" + webPageTheme + "';", + [](const QVariant &result) { + qDebug() << "Value is: " << result.toString() << Qt::endl; + }); + } +} + +void MainWindow::resizeEvent(QResizeEvent *event) { + if (lockWidget != nullptr) { + lockWidget->resize(event->size()); + } +} + +void MainWindow::updateWindowTheme() { + if (settings.value("windowTheme", "light").toString() == "dark") { + qApp->setStyle(QStyleFactory::create("fusion")); + QPalette palette; + palette.setColor(QPalette::Window, QColor(38, 45, 49)); + palette.setColor(QPalette::Text, Qt::white); + palette.setColor(QPalette::WindowText, Qt::white); + palette.setColor(QPalette::Base, QColor(50, 55, 57)); + palette.setColor(QPalette::AlternateBase, QColor(95, 108, 115)); + palette.setColor(QPalette::ToolTipBase, QColor(66, 66, 66)); + palette.setColor(QPalette::Disabled, QPalette::Window, QColor(65, 65, 67)); + palette.setColor(QPalette::ToolTipText, QColor("silver")); + palette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127)); + palette.setColor(QPalette::Dark, QColor(35, 35, 35)); + palette.setColor(QPalette::Shadow, QColor(20, 20, 20)); + palette.setColor(QPalette::Button, QColor(38, 45, 49)); + palette.setColor(QPalette::ButtonText, Qt::white); + palette.setColor(QPalette::Disabled, QPalette::ButtonText, + QColor(127, 127, 127)); + palette.setColor(QPalette::BrightText, Qt::red); + palette.setColor(QPalette::Link, QColor(42, 130, 218)); + palette.setColor(QPalette::Highlight, QColor(38, 140, 196)); + palette.setColor(QPalette::Disabled, QPalette::Highlight, + QColor(80, 80, 80)); + palette.setColor(QPalette::HighlightedText, Qt::white); + palette.setColor(QPalette::Disabled, QPalette::HighlightedText, + QColor(127, 127, 127)); + qApp->setPalette(palette); + this->webEngine->setStyleSheet( + "QWebEngineView{background:#131C21;}"); // whatsapp dark color + } else { + qApp->setPalette(lightPalette); + this->webEngine->setStyleSheet( + "QWebEngineView{background:#F0F0F0;}"); // whatsapp light color + } + + QList widgets = this->findChildren(); + + foreach (QWidget *w, widgets) { w->setPalette(qApp->palette()); } + + setNotificationPresenter(webEngine->page()->profile()); + + if (lockWidget != nullptr) { + lockWidget->setStyleSheet( + "QWidget#login{background-color:palette(window)};" + "QWidget#signup{background-color:palette(window)};"); + lockWidget->applyThemeQuirks(); + } + this->update(); +} + +void MainWindow::handleCookieAdded(const QNetworkCookie &cookie) { qDebug() << cookie.toRawForm() << "\n\n\n"; } - -void MainWindow::init_settingWidget() -{ - if(settingsWidget == nullptr) - { - settingsWidget = new SettingsWidget(this,webEngine->page()->profile()->cachePath() - ,webEngine->page()->profile()->persistentStoragePath()); - settingsWidget->setWindowTitle(QApplication::applicationName()+" | Settings"); - settingsWidget->setWindowFlags(Qt::Dialog); - - connect(settingsWidget,SIGNAL(init_lock()),this,SLOT(init_lock())); - connect(settingsWidget,SIGNAL(updateWindowTheme()),this,SLOT(updateWindowTheme())); - connect(settingsWidget,SIGNAL(updatePageTheme()),this,SLOT(updatePageTheme())); - - connect(settingsWidget,&SettingsWidget::muteToggled,[=](const bool checked) - { - this->toggleMute(checked); - }); - connect(settingsWidget,&SettingsWidget::userAgentChanged,[=](QString userAgentStr) - { - if(webEngine->page()->profile()->httpUserAgent() != userAgentStr) - { - settings.setValue("useragent",userAgentStr); +void MainWindow::init_settingWidget() { + if (settingsWidget == nullptr) { + settingsWidget = new SettingsWidget( + this, webEngine->page()->profile()->cachePath(), + webEngine->page()->profile()->persistentStoragePath()); + settingsWidget->setWindowTitle(QApplication::applicationName() + + " | Settings"); + settingsWidget->setWindowFlags(Qt::Dialog); + + connect(settingsWidget, SIGNAL(init_lock()), this, SLOT(init_lock())); + connect(settingsWidget, SIGNAL(updateWindowTheme()), this, + SLOT(updateWindowTheme())); + connect(settingsWidget, SIGNAL(updatePageTheme()), this, + SLOT(updatePageTheme())); + + connect(settingsWidget, &SettingsWidget::muteToggled,settingsWidget, + [=](const bool checked) { this->toggleMute(checked); }); + connect(settingsWidget, &SettingsWidget::userAgentChanged, settingsWidget, + [=](QString userAgentStr) { + if (webEngine->page()->profile()->httpUserAgent() != + userAgentStr) { + settings.setValue("useragent", userAgentStr); this->updateSettingsUserAgentWidget(); this->askToReloadPage(); - } - }); - connect(settingsWidget,&SettingsWidget::autoPlayMediaToggled,[=](bool checked) - { - QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); - auto* webSettings = profile->settings(); - webSettings->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture,checked); - - this->webEngine->page()->profile()->settings()->setAttribute( - QWebEngineSettings::PlaybackRequiresUserGesture, - checked); - }); + } + }); + connect(settingsWidget, &SettingsWidget::autoPlayMediaToggled,settingsWidget, + [=](bool checked) { + QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); + auto *webSettings = profile->settings(); + webSettings->setAttribute( + QWebEngineSettings::PlaybackRequiresUserGesture, checked); + + this->webEngine->page()->profile()->settings()->setAttribute( + QWebEngineSettings::PlaybackRequiresUserGesture, checked); + }); - connect(settingsWidget,&SettingsWidget::dictChanged,[=](QString dictName) - { - if(webEngine && webEngine->page()) - { - webEngine->page()->profile()->setSpellCheckLanguages(QStringList()<page()) { + webEngine->page()->profile()->setSpellCheckLanguages( + QStringList() << dictName); + } + }); - connect(settingsWidget,&SettingsWidget::spellCheckChanged,[=](bool checked){ - if(webEngine && webEngine->page()) - { + connect(settingsWidget, &SettingsWidget::spellCheckChanged,settingsWidget, + [=](bool checked) { + if (webEngine && webEngine->page()) { webEngine->page()->profile()->setSpellCheckEnabled(checked); - } - }); - - connect(settingsWidget,&SettingsWidget::zoomChanged,[=]() - { - double currentFactor = settings.value("zoomFactor",1.0).toDouble(); - webEngine->page()->setZoomFactor(currentFactor); - }); + } + }); - connect(settingsWidget,&SettingsWidget::notificationPopupTimeOutChanged,[=](){ - setNotificationPresenter(this->webEngine->page()->profile()); - }); + connect(settingsWidget, &SettingsWidget::zoomChanged,settingsWidget, [=]() { + double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); + webEngine->page()->setZoomFactor(currentFactor); + }); - connect(settingsWidget,&SettingsWidget::notify,[=](QString message) - { - notify("",message); - }); + connect(settingsWidget, &SettingsWidget::notificationPopupTimeOutChanged,settingsWidget, + [=]() { + setNotificationPresenter(this->webEngine->page()->profile()); + }); - settingsWidget->appLockSetChecked(settings.value("lockscreen",false).toBool()); + connect(settingsWidget, &SettingsWidget::notify,settingsWidget, + [=](QString message) { notify("", message); }); - //spell checker - settingsWidget->loadDictionaries(m_dictionaries); + settingsWidget->appLockSetChecked( + settings.value("lockscreen", false).toBool()); - settingsWidget->resize(settingsWidget->sizeHint().width(),settingsWidget->minimumSizeHint().height()); - } -} + // spell checker + settingsWidget->loadDictionaries(m_dictionaries); -void MainWindow::lockApp() -{ - if(lockWidget != nullptr && lockWidget->isLocked) - return; - -// if(settings.value("asdfg").isValid() && settings.value("lockscreen").toBool()==false){ -// QMessageBox::critical(this,QApplication::applicationName()+"| Error", -// "Unable to lock App, Enable AppLock in settings First."); -// this->show(); -// return; -// } - - if(settings.value("asdfg").isValid()){ - init_lock(); - lockWidget->lock_app(); - }else{ - QMessageBox msgBox; - msgBox.setText("App lock is not configured."); - msgBox.setIconPixmap(QPixmap(":/icons/information-line.png").scaled(42,42,Qt::KeepAspectRatio,Qt::SmoothTransformation)); - msgBox.setInformativeText("Do you want to setup App lock now ?"); - msgBox.setStandardButtons(QMessageBox::Cancel ); - QPushButton *setAppLock = new QPushButton("Yes",nullptr); - msgBox.addButton(setAppLock,QMessageBox::NoRole); - connect(setAppLock,&QPushButton::clicked,[=](){ - init_lock(); - }); - msgBox.exec(); - } + settingsWidget->resize(settingsWidget->sizeHint().width(), + settingsWidget->minimumSizeHint().height()); + } } -void MainWindow::showSettings() -{ - if(lockWidget && lockWidget->isLocked){ - QMessageBox::critical(this,QApplication::applicationName()+"| Error", - "UnLock Application to access Settings."); - this->show(); - return; - } +void MainWindow::lockApp() { + if (lockWidget != nullptr && lockWidget->isLocked) + return; - if(webEngine == nullptr){ - QMessageBox::critical(this,QApplication::applicationName()+"| Error", - "Unable to initialize settings module.\nIs webengine initialized?"); - return; - } - if(!settingsWidget->isVisible()) - { - this->updateSettingsUserAgentWidget(); - settingsWidget->refresh(); - settingsWidget->showNormal(); - } -} - -void MainWindow::updateSettingsUserAgentWidget() -{ - settingsWidget->updateDefaultUAButton(this->webEngine->page()->profile()->httpUserAgent()); -} - -void MainWindow::askToReloadPage() -{ + if (settings.value("asdfg").isValid()) { + init_lock(); + lockWidget->lock_app(); + } else { QMessageBox msgBox; - msgBox.setWindowTitle(QApplication::applicationName()+" | Action required"); - msgBox.setInformativeText("Page needs to be reloaded to continue."); - msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setText("App lock is not configured."); + msgBox.setIconPixmap( + QPixmap(":/icons/information-line.png") + .scaled(42, 42, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + msgBox.setInformativeText("Do you want to setup App lock now ?"); + msgBox.setStandardButtons(QMessageBox::Cancel); + QPushButton *setAppLock = new QPushButton("Yes", nullptr); + msgBox.addButton(setAppLock, QMessageBox::NoRole); + connect(setAppLock, &QPushButton::clicked,setAppLock, [=]() { init_lock(); }); msgBox.exec(); - this->doAppReload(); -} - -void MainWindow::showAbout() -{ - About *about = new About(this); - about->setWindowFlag(Qt::Dialog); - about->setMinimumSize(about->sizeHint()); - about->adjustSize(); - about->setAttribute(Qt::WA_DeleteOnClose); - about->show(); -} - - -void MainWindow::closeEvent(QCloseEvent *event) -{ - settings.setValue("geometry", saveGeometry()); - settings.setValue("windowState", saveState()); - getPageTheme(); - QTimer::singleShot(500,[=](){ - settingsWidget->refresh(); - }); - - if(QSystemTrayIcon::isSystemTrayAvailable() && settings.value("closeButtonActionCombo",0).toInt() == 0){ - this->hide(); - event->ignore(); - if(settings.value("firstrun_tray",true).toBool()){ - notify(QApplication::applicationName(),"Application is minimized to system tray."); - settings.setValue("firstrun_tray", false); - } - return; - } - event->accept(); - qApp->quit(); - settings.setValue("firstrun_tray", true); - QMainWindow::closeEvent(event); -} - -void MainWindow::notify(QString title, QString message) -{ - - if(settings.value("disableNotificationPopups",false).toBool() == true){ - return; - } - - if(title.isEmpty()) title = QApplication::applicationName(); - - if(settings.value("notificationCombo",1).toInt() == 0 && trayIcon != nullptr) - { - trayIcon->showMessage(title,message,QIcon(":/icons/app/icon-64.png"),settings.value("notificationTimeOut",9000).toInt()); - trayIcon->disconnect(trayIcon,SIGNAL(messageClicked())); - connect(trayIcon,&QSystemTrayIcon::messageClicked,[=](){ - if(windowState()==Qt::WindowMinimized || windowState()!=Qt::WindowActive){ - activateWindow(); - raise(); - showNormal(); - } - }); - } - else{ - auto popup = new NotificationPopup(webEngine); - connect(popup,&NotificationPopup::notification_clicked,[=](){ - if(windowState() == Qt::WindowMinimized || windowState() != Qt::WindowActive){ - activateWindow(); - raise(); - showNormal(); - } - }); - popup->style()->polish(qApp); - popup->setMinimumWidth(300); - popup->adjustSize(); - popup->present(title,message,QPixmap(":/icons/app/icon-64.png")); - } -} - -void MainWindow::createActions() -{ - - openUrlAction = new QAction("New Chat",this); - this->addAction(openUrlAction); - openUrlAction->setShortcut(QKeySequence(Qt::Modifier::CTRL+Qt::Key_N)); - connect(openUrlAction,&QAction::triggered,this,&MainWindow::newChat); - - fullscreenAction = new QAction(tr("Fullscreen"),this); - fullscreenAction->setShortcut(Qt::Key_F11); - connect(fullscreenAction, &QAction::triggered,[=](){ - setWindowState(windowState() ^ Qt::WindowFullScreen); - }); - this->addAction(fullscreenAction); - - - minimizeAction = new QAction(tr("Mi&nimize to tray"), this); - minimizeAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_H)); - connect(minimizeAction, &QAction::triggered, this, &QWidget::hide); - addAction(minimizeAction); - this->addAction(minimizeAction); - - restoreAction = new QAction(tr("&Restore"), this); - connect(restoreAction, &QAction::triggered, this, &QWidget::show); - addAction(restoreAction); - - reloadAction = new QAction(tr("Re&load"), this); - reloadAction->setShortcut(Qt::Key_F5); - connect(reloadAction, &QAction::triggered, this, &MainWindow::doReload); - addAction(reloadAction); - - lockAction = new QAction(tr("Loc&k"), this); - lockAction->setShortcut(QKeySequence(Qt::Modifier::CTRL+Qt::Key_L)); - connect(lockAction, &QAction::triggered, this, &MainWindow::lockApp); - addAction(lockAction); - this->addAction(lockAction); - - settingsAction = new QAction(tr("&Settings"), this); - connect(settingsAction, &QAction::triggered, this, &MainWindow::showSettings); - - - aboutAction = new QAction(tr("&About"), this); - connect(aboutAction, &QAction::triggered, this, &MainWindow::showAbout); - - quitAction = new QAction(tr("&Quit"), this); - quitAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_Q)); - connect(quitAction, &QAction::triggered,this,&MainWindow::quitApp); - addAction(quitAction); - this->addAction(quitAction); -} - -void MainWindow::quitApp() -{ - getPageTheme(); - QTimer::singleShot(500,[=](){ - qWarning()<<"THEME"<quit(); + } +} + +void MainWindow::showSettings() { + if (lockWidget && lockWidget->isLocked) { + QMessageBox::critical(this, QApplication::applicationName() + "| Error", + "UnLock Application to access Settings."); + this->show(); + return; + } + + if (webEngine == nullptr) { + QMessageBox::critical( + this, QApplication::applicationName() + "| Error", + "Unable to initialize settings module.\nIs webengine initialized?"); + return; + } + if (!settingsWidget->isVisible()) { + this->updateSettingsUserAgentWidget(); + settingsWidget->refresh(); + settingsWidget->showNormal(); + } +} + +void MainWindow::updateSettingsUserAgentWidget() { + settingsWidget->updateDefaultUAButton( + this->webEngine->page()->profile()->httpUserAgent()); +} + +void MainWindow::askToReloadPage() { + QMessageBox msgBox; + msgBox.setWindowTitle(QApplication::applicationName() + " | Action required"); + msgBox.setInformativeText("Page needs to be reloaded to continue."); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.exec(); + this->doAppReload(); +} + +void MainWindow::showAbout() { + About *about = new About(this); + about->setWindowFlag(Qt::Dialog); + about->setMinimumSize(about->sizeHint()); + about->adjustSize(); + about->setAttribute(Qt::WA_DeleteOnClose); + about->show(); +} + +void MainWindow::closeEvent(QCloseEvent *event) { + settings.setValue("geometry", saveGeometry()); + settings.setValue("windowState", saveState()); + getPageTheme(); + QTimer::singleShot(500,settingsWidget, [=]() { settingsWidget->refresh(); }); + + if (QSystemTrayIcon::isSystemTrayAvailable() && + settings.value("closeButtonActionCombo", 0).toInt() == 0) { + this->hide(); + event->ignore(); + if (settings.value("firstrun_tray", true).toBool()) { + notify(QApplication::applicationName(), + "Application is minimized to system tray."); + settings.setValue("firstrun_tray", false); + } + return; + } + event->accept(); + qApp->quit(); + settings.setValue("firstrun_tray", true); + QMainWindow::closeEvent(event); +} + +void MainWindow::notify(QString title, QString message) { + + if (settings.value("disableNotificationPopups", false).toBool() == true) { + return; + } + + if (title.isEmpty()) + title = QApplication::applicationName(); + + if (settings.value("notificationCombo", 1).toInt() == 0 && + trayIcon != nullptr) { + trayIcon->showMessage(title, message, QIcon(":/icons/app/icon-64.png"), + settings.value("notificationTimeOut", 9000).toInt()); + trayIcon->disconnect(trayIcon, SIGNAL(messageClicked())); + connect(trayIcon, &QSystemTrayIcon::messageClicked,trayIcon, [=]() { + if (windowState() == Qt::WindowMinimized || + windowState() != Qt::WindowActive) { + activateWindow(); + raise(); + showNormal(); + } }); -} - -void MainWindow::createTrayIcon() -{ - trayIconMenu = new QMenu(this); - trayIconMenu->setObjectName("trayIconMenu"); - trayIconMenu->addAction(minimizeAction); - trayIconMenu->addAction(restoreAction); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(reloadAction); - trayIconMenu->addAction(lockAction); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(openUrlAction); - trayIconMenu->addAction(settingsAction); - trayIconMenu->addAction(aboutAction); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(quitAction); - - trayIcon = new QSystemTrayIcon(trayIconRead, this); - trayIcon->setContextMenu(trayIconMenu); - connect(trayIconMenu,SIGNAL(aboutToShow()),this,SLOT(check_window_state())); - - trayIcon->show(); - - connect(trayIcon, &QSystemTrayIcon::messageClicked, - this, &MainWindow::messageClicked); - connect(trayIcon, &QSystemTrayIcon::activated, - this, &MainWindow::iconActivated); - - - //enable show shortcuts in menu - if(qApp->styleHints()->showShortcutsInContextMenus()) - { - foreach(QAction *action, trayIconMenu->actions()){ - action->setShortcutVisibleInContextMenu(true); - } - } -} - - -void MainWindow::init_lock() -{ - if(lockWidget==nullptr){ - lockWidget = new Lock(this); - lockWidget->setObjectName("lockWidget"); - } - lockWidget->setWindowFlags(Qt::Widget); - lockWidget->setStyleSheet("QWidget#login{background-color:palette(window)};" - "QWidget#signup{background-color:palette(window)}"); - lockWidget->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); - lockWidget->setGeometry(this->rect()); - - connect(lockWidget,&Lock::passwordNotSet,[=]() - { - settings.setValue("lockscreen",false); - settingsWidget->appLockSetChecked(false); - }); - - connect(lockWidget,&Lock::unLocked,[=]() - { - //unlock event - }); - - connect(lockWidget,&Lock::passwordSet,[=](){ - //enable disable lock screen - if(settings.value("asdfg").isValid()){ - settingsWidget->setCurrentPasswordText("Current Password: " - +QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())+""); - }else{ - settingsWidget->setCurrentPasswordText("Current Password: Require setup"); - } - settingsWidget->appLockSetChecked(settings.value("lockscreen",false).toBool()); - }); - lockWidget->applyThemeQuirks(); - lockWidget->show(); - if(settings.value("asdfg").isValid() && settings.value("lockscreen").toBool()==true){ - lockWidget->lock_app(); - } - updateWindowTheme(); -} - -//check window state and set tray menus -void MainWindow::check_window_state() -{ - QObject *tray_icon_menu = this->findChild("trayIconMenu"); - if(tray_icon_menu != nullptr){ - if(this->isVisible()){ - ((QMenu*)(tray_icon_menu))->actions().at(0)->setDisabled(false); - ((QMenu*)(tray_icon_menu))->actions().at(1)->setDisabled(true); - }else{ - ((QMenu*)(tray_icon_menu))->actions().at(0)->setDisabled(true); - ((QMenu*)(tray_icon_menu))->actions().at(1)->setDisabled(false); - } - if(lockWidget && lockWidget->isLocked){ - ((QMenu*)(tray_icon_menu))->actions().at(4)->setDisabled(true); - }else{ - ((QMenu*)(tray_icon_menu))->actions().at(4)->setDisabled(false); - } - } -} - -void MainWindow::init_globalWebProfile() -{ - - QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); - profile->setHttpUserAgent(settings.value("useragent",defaultUserAgentStr).toString()); - - QStringList dict_names; - dict_names.append(settings.value("sc_dict","en-US").toString()); - - profile->setSpellCheckEnabled(settings.value("sc_enabled",true).toBool()); - profile->setSpellCheckLanguages(dict_names); - - auto* webSettings = profile->settings(); - webSettings->setAttribute(QWebEngineSettings::AutoLoadImages, true); - webSettings->setAttribute(QWebEngineSettings::JavascriptEnabled, true); - webSettings->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true); - webSettings->setAttribute(QWebEngineSettings::LocalStorageEnabled, true); - webSettings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, true); - webSettings->setAttribute(QWebEngineSettings::XSSAuditingEnabled, true); - webSettings->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, true); - webSettings->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled, false); - webSettings->setAttribute(QWebEngineSettings::DnsPrefetchEnabled,true); - webSettings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled ,true); - webSettings->setAttribute(QWebEngineSettings::LinksIncludedInFocusChain, false); - webSettings->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, false); - webSettings->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, - settings.value("autoPlayMedia",false).toBool()); - -} - -void MainWindow::createWebEngine() -{ - init_globalWebProfile(); - - QSizePolicy widgetSize; - widgetSize.setHorizontalPolicy(QSizePolicy::Expanding); - widgetSize.setVerticalPolicy(QSizePolicy::Expanding); - widgetSize.setHorizontalStretch(1); - widgetSize.setVerticalStretch(1); - - m_dictionaries = Dictionaries::GetDictionaries(); - - WebView *webEngine = new WebView(this,m_dictionaries); - setCentralWidget(webEngine); - webEngine->setSizePolicy(widgetSize); - webEngine->show(); - - this->webEngine = webEngine; - - webEngine->addAction(minimizeAction); - webEngine->addAction(lockAction); - webEngine->addAction(quitAction); - - createWebPage(false); - -// QWebEngineCookieStore *browser_cookie_store = this->webEngine->page()->profile()->cookieStore(); -// connect( browser_cookie_store, &QWebEngineCookieStore::cookieAdded, this, &MainWindow::handleCookieAdded ); - -} - -void MainWindow::createWebPage(bool offTheRecord) -{ - if (offTheRecord && !m_otrProfile) - { - m_otrProfile.reset(new QWebEngineProfile); - } - auto profile = offTheRecord ? m_otrProfile.get() : QWebEngineProfile::defaultProfile(); - - QStringList dict_names; - dict_names.append(settings.value("sc_dict","en-US").toString()); - - profile->setSpellCheckEnabled(settings.value("sc_enabled",true).toBool()); - profile->setSpellCheckLanguages(dict_names); - profile->setHttpUserAgent(settings.value("useragent",defaultUserAgentStr).toString()); - - setNotificationPresenter(profile); - - QWebEnginePage *page = new WebEnginePage(profile,webEngine); - if(settings.value("windowTheme","light").toString() == "dark"){ - page->setBackgroundColor(QColor("#131C21")); //whatsapp dark bg color - }else{ - page->setBackgroundColor(QColor("#F0F0F0")); //whatsapp light bg color - } - webEngine->setPage(page); - //page should be set parent of profile to prevent - //Release of profile requested but WebEnginePage still not deleted. Expect troubles ! - profile->setParent(page); - -// RequestInterceptor *interceptor = new RequestInterceptor(profile); -// profile->setUrlRequestInterceptor(interceptor); - qsrand(time(NULL)); - auto randomValue = qrand() % 300; - page->setUrl(QUrl("https://web.whatsapp.com?v="+QString::number(randomValue))); - connect(profile, &QWebEngineProfile::downloadRequested, - &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested); - - connect(webEngine->page(), SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)), - this, SLOT(fullScreenRequested(QWebEngineFullScreenRequest))); - - double currentFactor = settings.value("zoomFactor",1.0).toDouble(); - webEngine->page()->setZoomFactor(currentFactor); -} - -void MainWindow::setNotificationPresenter(QWebEngineProfile* profile) -{ - auto *op = webEngine->findChild("engineNotifier"); - if( op != nullptr){ - op->close(); - op->deleteLater(); - } - + } else { auto popup = new NotificationPopup(webEngine); - popup->setObjectName("engineNotifier"); - connect(popup,&NotificationPopup::notification_clicked,[=](){ - if(windowState()==Qt::WindowMinimized || windowState()!=Qt::WindowActive){ - activateWindow(); - raise(); - showNormal(); - } - }); - - profile->setNotificationPresenter([=] (std::unique_ptr notification) - { - if(settings.value("disableNotificationPopups",false).toBool() == true){ - return; - } - if(settings.value("notificationCombo",1).toInt() == 0 && trayIcon != nullptr) - { - QIcon icon(QPixmap::fromImage(notification->icon())); - trayIcon->showMessage(notification->title(),notification->message(),icon,settings.value("notificationTimeOut",9000).toInt()); - trayIcon->disconnect(trayIcon,SIGNAL(messageClicked())); - connect(trayIcon,&QSystemTrayIcon::messageClicked,[=](){ - if(windowState() == Qt::WindowMinimized || windowState() != Qt::WindowActive){ - activateWindow(); - raise(); - showNormal(); - } - }); - - }else{ - popup->setMinimumWidth(300); - popup->present(notification); - } - + connect(popup, &NotificationPopup::notification_clicked, popup,[=]() { + if (windowState() == Qt::WindowMinimized || + windowState() != Qt::WindowActive) { + activateWindow(); + raise(); + showNormal(); + } }); -} - -void MainWindow::fullScreenRequested(QWebEngineFullScreenRequest request) -{ - if (request.toggleOn()) - { - webEngine->showFullScreen(); - this->showFullScreen(); - request.accept(); + popup->style()->polish(qApp); + popup->setMinimumWidth(300); + popup->adjustSize(); + popup->present(title, message, QPixmap(":/icons/app/icon-64.png")); + } +} + +void MainWindow::createActions() { + + openUrlAction = new QAction("New Chat", this); + this->addAction(openUrlAction); + openUrlAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_N)); + connect(openUrlAction, &QAction::triggered, this, &MainWindow::newChat); + + fullscreenAction = new QAction(tr("Fullscreen"), this); + fullscreenAction->setShortcut(Qt::Key_F11); + connect(fullscreenAction, &QAction::triggered,fullscreenAction, + [=]() { setWindowState(windowState() ^ Qt::WindowFullScreen); }); + this->addAction(fullscreenAction); + + minimizeAction = new QAction(tr("Mi&nimize to tray"), this); + minimizeAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_H)); + connect(minimizeAction, &QAction::triggered, this, &QWidget::hide); + addAction(minimizeAction); + this->addAction(minimizeAction); + + restoreAction = new QAction(tr("&Restore"), this); + connect(restoreAction, &QAction::triggered, this, &QWidget::show); + addAction(restoreAction); + + reloadAction = new QAction(tr("Re&load"), this); + reloadAction->setShortcut(Qt::Key_F5); + connect(reloadAction, &QAction::triggered, this, &MainWindow::doReload); + addAction(reloadAction); + + lockAction = new QAction(tr("Loc&k"), this); + lockAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_L)); + connect(lockAction, &QAction::triggered, this, &MainWindow::lockApp); + addAction(lockAction); + this->addAction(lockAction); + + settingsAction = new QAction(tr("&Settings"), this); + connect(settingsAction, &QAction::triggered, this, &MainWindow::showSettings); + + aboutAction = new QAction(tr("&About"), this); + connect(aboutAction, &QAction::triggered, this, &MainWindow::showAbout); + + quitAction = new QAction(tr("&Quit"), this); + quitAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_Q)); + connect(quitAction, &QAction::triggered, this, &MainWindow::quitApp); + addAction(quitAction); + this->addAction(quitAction); +} + +void MainWindow::quitApp() { + getPageTheme(); + QTimer::singleShot(500, &settings,[=]() { + qWarning() << "THEME" << settings.value("windowTheme").toString(); + settings.setValue("firstrun_tray", true); + qApp->quit(); + }); +} + +void MainWindow::createTrayIcon() { + trayIconMenu = new QMenu(this); + trayIconMenu->setObjectName("trayIconMenu"); + trayIconMenu->addAction(minimizeAction); + trayIconMenu->addAction(restoreAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(reloadAction); + trayIconMenu->addAction(lockAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(openUrlAction); + trayIconMenu->addAction(settingsAction); + trayIconMenu->addAction(aboutAction); + trayIconMenu->addSeparator(); + trayIconMenu->addAction(quitAction); + + trayIcon = new QSystemTrayIcon(trayIconRead, this); + trayIcon->setContextMenu(trayIconMenu); + connect(trayIconMenu, SIGNAL(aboutToShow()), this, + SLOT(check_window_state())); + + trayIcon->show(); + + connect(trayIcon, &QSystemTrayIcon::messageClicked, this, + &MainWindow::messageClicked); + connect(trayIcon, &QSystemTrayIcon::activated, this, + &MainWindow::iconActivated); + + // enable show shortcuts in menu + if (qApp->styleHints()->showShortcutsInContextMenus()) { + foreach (QAction *action, trayIconMenu->actions()) { + action->setShortcutVisibleInContextMenu(true); + } + } +} + +void MainWindow::init_lock() { + if (lockWidget == nullptr) { + lockWidget = new Lock(this); + lockWidget->setObjectName("lockWidget"); + } + lockWidget->setWindowFlags(Qt::Widget); + lockWidget->setStyleSheet("QWidget#login{background-color:palette(window)};" + "QWidget#signup{background-color:palette(window)}"); + lockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + lockWidget->setGeometry(this->rect()); + + connect(lockWidget, &Lock::passwordNotSet,settingsWidget, [=]() { + settings.setValue("lockscreen", false); + settingsWidget->appLockSetChecked(false); + }); + + connect(lockWidget, &Lock::unLocked, [=]() { + // unlock event + }); + + connect(lockWidget, &Lock::passwordSet,settingsWidget, [=]() { + // enable disable lock screen + if (settings.value("asdfg").isValid()) { + settingsWidget->setCurrentPasswordText( + "Current Password: " + + QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8()) + + ""); } else { - webEngine->showNormal(); - this->showNormal(); - request.accept(); - } -} - -void MainWindow::handleWebViewTitleChanged(QString title) -{ - setWindowTitle(title); - - if (notificationsTitleRegExp.exactMatch(title)) - { - if(notificationsTitleRegExp.isEmpty() == false){ - QString capturedTitle = notificationsTitleRegExp.capturedTexts().first(); - QRegExp rgex("\\([^\\d]*(\\d+)[^\\d]*\\)"); - rgex.setMinimal(true); - if(rgex.indexIn(capturedTitle) != -1){ - qDebug()< 1 ? tr("messages"): tr("message"); - restoreAction->setText(tr("Restore")+" | "+unreadMessageCount+" "+suffix); - } - } - trayIcon->setIcon(trayIconUnread); - setWindowIcon(trayIconUnread); - } - else - { - trayIcon->setIcon(trayIconRead); - setWindowIcon(trayIconRead); - } -} - -void MainWindow::handleLoadFinished(bool loaded) -{ - if(loaded){ - //check if page has loaded correctly - checkLoadedCorrectly(); - updatePageTheme(); - } -} - -void MainWindow::checkLoadedCorrectly() -{ - if(webEngine && webEngine->page()) - { - //test 1 based on the class name of body of the page - webEngine->page()->runJavaScript("document.querySelector('body').className",[this](const QVariant &result) - { - if(result.toString().contains("page-version",Qt::CaseInsensitive)) - { - qWarning()<<"Test 1 found"<page()->runJavaScript("document.getElementsByTagName('body')[0].innerText = ''"); - loadingQuirk("test1"); - }else if(webEngine->title().contains("Error",Qt::CaseInsensitive)) - { - utils::delete_cache(webEngine->page()->profile()->cachePath()); - utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); - settings.setValue("useragent",defaultUserAgentStr); - utils * util = new utils(this); - util->DisplayExceptionErrorDialog("test1 handleWebViewTitleChanged(title) title: Error, Resetting UA, Quiting!\nUA: "+settings.value("useragent","DefaultUA").toString()); - - quitAction->trigger(); - }else{ - qWarning()<<"Test 1 Loaded correctly value:"<page()->runJavaScript( -// "document.getElementsByClassName('landing-title')[0].innerText", -// [this](const QVariant &result){ -// qWarning()<<"Test #1 Loaded correctly value:"<title().contains("Error",Qt::CaseInsensitive)){ -// utils::delete_cache(webEngine->page()->profile()->cachePath()); -// utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); -// settings.setValue("useragent",defaultUserAgentStr); -// utils * util = new utils(this); -// util->DisplayExceptionErrorDialog("handleWebViewTitleChanged(title) title: Error, Resetting UA, Quiting!\nUA: "+settings.value("useragent","DefaultUA").toString()); - -// quitAction->trigger(); -// } -// } -// ); - } -} - -void MainWindow::loadingQuirk(QString test) -{ - //contains ug message apply quirk - if(correctlyLoaderRetries > -1){ - qWarning()<page()->profile()->cachePath()); - utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); - settings.setValue("useragent",defaultUserAgentStr); - utils * util = new utils(this); - util->DisplayExceptionErrorDialog(test+" checkLoadedCorrectly()/loadingQuirk() reload retries 0, Resetting UA, Quiting!\nUA: "+settings.value("useragent","DefaultUA").toString()); - - quitAction->trigger(); - } -} - -//unused direct method to download file without having entry in download manager -void MainWindow::handleDownloadRequested(QWebEngineDownloadItem *download) -{ - QFileDialog dialog(this); - bool usenativeFileDialog = settings.value("useNativeFileDialog",false).toBool(); - - if(usenativeFileDialog == false){ - dialog.setOption(QFileDialog::DontUseNativeDialog,true); - } - - dialog.setAcceptMode(QFileDialog::AcceptMode::AcceptSave); - dialog.setFileMode(QFileDialog::FileMode::AnyFile); - QString suggestedFileName = QUrl(download->path()).fileName(); - dialog.selectFile(suggestedFileName); - - if (dialog.exec() && dialog.selectedFiles().size() > 0) - { - download->setPath(dialog.selectedFiles().at(0)); - download->accept(); - } -} - -void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) -{ - Q_UNUSED(reason); - if (isVisible()) { - hide(); + settingsWidget->setCurrentPasswordText( + "Current Password: Require setup"); + } + settingsWidget->appLockSetChecked( + settings.value("lockscreen", false).toBool()); + }); + lockWidget->applyThemeQuirks(); + lockWidget->show(); + if (settings.value("asdfg").isValid() && + settings.value("lockscreen").toBool() == true) { + lockWidget->lock_app(); + } + updateWindowTheme(); +} + +// check window state and set tray menus +void MainWindow::check_window_state() { + QObject *tray_icon_menu = this->findChild("trayIconMenu"); + if (tray_icon_menu != nullptr) { + if (this->isVisible()) { + ((QMenu *)(tray_icon_menu))->actions().at(0)->setDisabled(false); + ((QMenu *)(tray_icon_menu))->actions().at(1)->setDisabled(true); } else { - showNormal(); + ((QMenu *)(tray_icon_menu))->actions().at(0)->setDisabled(true); + ((QMenu *)(tray_icon_menu))->actions().at(1)->setDisabled(false); } -} - -void MainWindow::messageClicked() -{ - if (isVisible()) { - hide(); + if (lockWidget && lockWidget->isLocked) { + ((QMenu *)(tray_icon_menu))->actions().at(4)->setDisabled(true); } else { - showNormal(); - } -} + ((QMenu *)(tray_icon_menu))->actions().at(4)->setDisabled(false); + } + } +} + +void MainWindow::init_globalWebProfile() { + + QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); + profile->setHttpUserAgent( + settings.value("useragent", defaultUserAgentStr).toString()); + + QStringList dict_names; + dict_names.append(settings.value("sc_dict", "en-US").toString()); + + profile->setSpellCheckEnabled(settings.value("sc_enabled", true).toBool()); + profile->setSpellCheckLanguages(dict_names); + + auto *webSettings = profile->settings(); + webSettings->setAttribute(QWebEngineSettings::AutoLoadImages, true); + webSettings->setAttribute(QWebEngineSettings::JavascriptEnabled, true); + webSettings->setAttribute(QWebEngineSettings::JavascriptCanOpenWindows, true); + webSettings->setAttribute(QWebEngineSettings::LocalStorageEnabled, true); + webSettings->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, + true); + webSettings->setAttribute(QWebEngineSettings::XSSAuditingEnabled, true); + webSettings->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, + true); + webSettings->setAttribute(QWebEngineSettings::ScrollAnimatorEnabled, false); + webSettings->setAttribute(QWebEngineSettings::DnsPrefetchEnabled, true); + webSettings->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); + webSettings->setAttribute(QWebEngineSettings::LinksIncludedInFocusChain, + false); + webSettings->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, + false); + webSettings->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, + settings.value("autoPlayMedia", false).toBool()); +} + +void MainWindow::createWebEngine() { + init_globalWebProfile(); + + QSizePolicy widgetSize; + widgetSize.setHorizontalPolicy(QSizePolicy::Expanding); + widgetSize.setVerticalPolicy(QSizePolicy::Expanding); + widgetSize.setHorizontalStretch(1); + widgetSize.setVerticalStretch(1); + + m_dictionaries = Dictionaries::GetDictionaries(); + + WebView *webEngine = new WebView(this, m_dictionaries); + setCentralWidget(webEngine); + webEngine->setSizePolicy(widgetSize); + webEngine->show(); + + this->webEngine = webEngine; + + webEngine->addAction(minimizeAction); + webEngine->addAction(lockAction); + webEngine->addAction(quitAction); + + createWebPage(false); + + // QWebEngineCookieStore *browser_cookie_store = + // this->webEngine->page()->profile()->cookieStore(); connect( + // browser_cookie_store, &QWebEngineCookieStore::cookieAdded, this, + // &MainWindow::handleCookieAdded ); +} + +void MainWindow::createWebPage(bool offTheRecord) { + if (offTheRecord && !m_otrProfile) { + m_otrProfile.reset(new QWebEngineProfile); + } + auto profile = + offTheRecord ? m_otrProfile.get() : QWebEngineProfile::defaultProfile(); + + QStringList dict_names; + dict_names.append(settings.value("sc_dict", "en-US").toString()); + + profile->setSpellCheckEnabled(settings.value("sc_enabled", true).toBool()); + profile->setSpellCheckLanguages(dict_names); + profile->setHttpUserAgent( + settings.value("useragent", defaultUserAgentStr).toString()); + + setNotificationPresenter(profile); + + QWebEnginePage *page = new WebEnginePage(profile, webEngine); + if (settings.value("windowTheme", "light").toString() == "dark") { + page->setBackgroundColor(QColor(19, 28, 33)); // whatsapp dark bg color + } else { + page->setBackgroundColor(QColor(240, 240, 240)); // whatsapp light bg color + } + webEngine->setPage(page); + // page should be set parent of profile to prevent + // Release of profile requested but WebEnginePage still not deleted. Expect + // troubles ! + profile->setParent(page); + // RequestInterceptor *interceptor = new RequestInterceptor(profile); + // profile->setUrlRequestInterceptor(interceptor); + auto randomValue = QRandomGenerator::global()->generateDouble() * 300; + page->setUrl( + QUrl("https://web.whatsapp.com?v=" + QString::number(randomValue))); + connect(profile, &QWebEngineProfile::downloadRequested, + &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested); + + connect(webEngine->page(), + SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)), this, + SLOT(fullScreenRequested(QWebEngineFullScreenRequest))); + + double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); + webEngine->page()->setZoomFactor(currentFactor); +} + +void MainWindow::setNotificationPresenter(QWebEngineProfile *profile) { + auto *op = webEngine->findChild("engineNotifier"); + if (op != nullptr) { + op->close(); + op->deleteLater(); + } + + auto popup = new NotificationPopup(webEngine); + popup->setObjectName("engineNotifier"); + connect(popup, &NotificationPopup::notification_clicked,popup,[=]() { + if (windowState() == Qt::WindowMinimized || + windowState() != Qt::WindowActive) { + activateWindow(); + raise(); + showNormal(); + } + }); + + profile->setNotificationPresenter( + [=](std::unique_ptr notification) { + if (settings.value("disableNotificationPopups", false).toBool() == + true) { + return; + } + if (settings.value("notificationCombo", 1).toInt() == 0 && + trayIcon != nullptr) { + QIcon icon(QPixmap::fromImage(notification->icon())); + trayIcon->showMessage( + notification->title(), notification->message(), icon, + settings.value("notificationTimeOut", 9000).toInt()); + trayIcon->disconnect(trayIcon, SIGNAL(messageClicked())); + connect(trayIcon, &QSystemTrayIcon::messageClicked,trayIcon, [=]() { + if (windowState() == Qt::WindowMinimized || + windowState() != Qt::WindowActive) { + activateWindow(); + raise(); + showNormal(); + } + }); -void MainWindow::doAppReload() -{ + } else { + popup->setMinimumWidth(300); + popup->present(notification); + } + }); +} + +void MainWindow::fullScreenRequested(QWebEngineFullScreenRequest request) { + if (request.toggleOn()) { + webEngine->showFullScreen(); + this->showFullScreen(); + request.accept(); + } else { + webEngine->showNormal(); + this->showNormal(); + request.accept(); + } +} + +void MainWindow::handleWebViewTitleChanged(QString title) { + setWindowTitle(title); + + if (notificationsTitleRegExp.exactMatch(title)) { + if (notificationsTitleRegExp.isEmpty() == false) { + QString capturedTitle = notificationsTitleRegExp.capturedTexts().first(); + QRegExp rgex("\\([^\\d]*(\\d+)[^\\d]*\\)"); + rgex.setMinimal(true); + if (rgex.indexIn(capturedTitle) != -1) { + qDebug() << rgex.capturedTexts(); + QString unreadMessageCount = rgex.capturedTexts().last(); + QString suffix = + unreadMessageCount.toInt() > 1 ? tr("messages") : tr("message"); + restoreAction->setText(tr("Restore") + " | " + unreadMessageCount + + " " + suffix); + } + } + trayIcon->setIcon(trayIconUnread); + setWindowIcon(trayIconUnread); + } else { + trayIcon->setIcon(trayIconRead); + setWindowIcon(trayIconRead); + } +} + +void MainWindow::handleLoadFinished(bool loaded) { + if (loaded) { + // check if page has loaded correctly + checkLoadedCorrectly(); + updatePageTheme(); + } +} + +void MainWindow::checkLoadedCorrectly() { + if (webEngine && webEngine->page()) { + // test 1 based on the class name of body of the page + webEngine->page()->runJavaScript( + "document.querySelector('body').className", + [this](const QVariant &result) { + if (result.toString().contains("page-version", Qt::CaseInsensitive)) { + qWarning() << "Test 1 found" << result.toString(); + webEngine->page()->runJavaScript( + "document.getElementsByTagName('body')[0].innerText = ''"); + loadingQuirk("test1"); + } else if (webEngine->title().contains("Error", + Qt::CaseInsensitive)) { + utils::delete_cache(webEngine->page()->profile()->cachePath()); + utils::delete_cache( + webEngine->page()->profile()->persistentStoragePath()); + settings.setValue("useragent", defaultUserAgentStr); + utils *util = new utils(this); + util->DisplayExceptionErrorDialog( + "test1 handleWebViewTitleChanged(title) title: Error, " + "Resetting UA, Quiting!\nUA: " + + settings.value("useragent", "DefaultUA").toString()); + + quitAction->trigger(); + } else { + qWarning() << "Test 1 Loaded correctly value:" << result.toString(); + } + }); - if(this->webEngine->page()){ - this->webEngine->page()->disconnect(); - } - createWebPage(false); -} - -void MainWindow::newChat() -{ - bool ok; - QString text = QInputDialog::getText(this, tr("New Chat"), - tr("Enter a valid WhatsApp number with country code (ex- +91XXXXXXXXXX)"), QLineEdit::Normal, - "",&ok); - if (ok){ - if(isPhoneNumber(text)) - this->webEngine->page()->load(QUrl("https://web.whatsapp.com/send?phone="+text)); - else - QMessageBox::information(this,QApplication::applicationName()+"| Error", - "Invalid Phone Number"); - } + // //test #2 based on the content of landing-title class of page + // webEngine->page()->runJavaScript( + // "document.getElementsByClassName('landing-title')[0].innerText", + // [this](const QVariant &result){ + // qWarning()<<"Test #1 Loaded correctly + // value:"<title().contains("Error",Qt::CaseInsensitive)){ + // utils::delete_cache(webEngine->page()->profile()->cachePath()); + // utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); + // settings.setValue("useragent",defaultUserAgentStr); + // utils * util = new utils(this); + // util->DisplayExceptionErrorDialog("handleWebViewTitleChanged(title) + // title: Error, Resetting UA, Quiting!\nUA: + // "+settings.value("useragent","DefaultUA").toString()); + + // quitAction->trigger(); + // } + // } + // ); + } +} + +void MainWindow::loadingQuirk(QString test) { + // contains ug message apply quirk + if (correctlyLoaderRetries > -1) { + qWarning() << test << "checkLoadedCorrectly()/loadingQuirk()/doReload()" + << correctlyLoaderRetries; + doReload(); + correctlyLoaderRetries--; + } else { + utils::delete_cache(webEngine->page()->profile()->cachePath()); + utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); + settings.setValue("useragent", defaultUserAgentStr); + utils *util = new utils(this); + util->DisplayExceptionErrorDialog( + test + + " checkLoadedCorrectly()/loadingQuirk() reload retries 0, Resetting " + "UA, Quiting!\nUA: " + + settings.value("useragent", "DefaultUA").toString()); + + quitAction->trigger(); + } +} + +// unused direct method to download file without having entry in download +// manager +void MainWindow::handleDownloadRequested(QWebEngineDownloadItem *download) { + QFileDialog dialog(this); + bool usenativeFileDialog = + settings.value("useNativeFileDialog", false).toBool(); + + if (usenativeFileDialog == false) { + dialog.setOption(QFileDialog::DontUseNativeDialog, true); + } + + dialog.setAcceptMode(QFileDialog::AcceptMode::AcceptSave); + dialog.setFileMode(QFileDialog::FileMode::AnyFile); + QString suggestedFileName = QUrl(download->downloadDirectory()).fileName(); + dialog.selectFile(suggestedFileName); + + if (dialog.exec() && dialog.selectedFiles().size() > 0) { + download->setDownloadDirectory(dialog.selectedFiles().at(0)); + download->accept(); + } +} + +void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) { + Q_UNUSED(reason); + if (isVisible()) { + hide(); + } else { + showNormal(); + } +} + +void MainWindow::messageClicked() { + if (isVisible()) { + hide(); + } else { + showNormal(); + } +} + +void MainWindow::doAppReload() { + + if (this->webEngine->page()) { + this->webEngine->page()->disconnect(); + } + createWebPage(false); +} + +void MainWindow::newChat() { + bool ok; + QString text = QInputDialog::getText( + this, tr("New Chat"), + tr("Enter a valid WhatsApp number with country code (ex- +91XXXXXXXXXX)"), + QLineEdit::Normal, "", &ok); + if (ok) { + if (isPhoneNumber(text)) + this->webEngine->page()->load( + QUrl("https://web.whatsapp.com/send?phone=" + text)); + else + QMessageBox::information(this, + QApplication::applicationName() + "| Error", + "Invalid Phone Number"); + } } -bool MainWindow::isPhoneNumber(const QString &phoneNumber) -{ - const QString phone = "^\\+(((\\d{2}))\\s?)?((\\d{2})|(\\((\\d{2})\\))\\s?)?(\\d{3,15})(\\-(\\d{3,15}))?$"; - QRegularExpression reg(phone); - return reg.match(phoneNumber).hasMatch(); +bool MainWindow::isPhoneNumber(const QString &phoneNumber) { + const QString phone = "^\\+(((\\d{2}))\\s?)?((\\d{2})|(\\((\\d{2})\\))\\s?)?(" + "\\d{3,15})(\\-(\\d{3,15}))?$"; + static QRegularExpression reg(phone); + return reg.match(phoneNumber).hasMatch(); } -void MainWindow::doReload() -{ - this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, false); +void MainWindow::doReload() { + this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, + false); } -void MainWindow::toggleMute(const bool &checked) -{ - this->webEngine->page()->setAudioMuted(checked); +void MainWindow::toggleMute(const bool &checked) { + this->webEngine->page()->setAudioMuted(checked); } // get value of page theme when page is loaded -QString MainWindow::getPageTheme() -{ - static QString theme = "web"; //implies light - if(webEngine && webEngine->page()) - { - webEngine->page()->runJavaScript( - "document.querySelector('body').className;", - [this](const QVariant &result){ - theme = result.toString(); - theme.contains("dark") ? theme = "dark" : theme = "light"; - settings.setValue("windowTheme",theme); - } - ); - } - return theme; +QString MainWindow::getPageTheme() { + static QString theme = "web"; // implies light + if (webEngine && webEngine->page()) { + webEngine->page()->runJavaScript( + "document.querySelector('body').className;", + [this](const QVariant &result) { + theme = result.toString(); + theme.contains("dark") ? theme = "dark" : theme = "light"; + settings.setValue("windowTheme", theme); + }); + } + return theme; } diff --git a/src/mainwindow.h b/src/mainwindow.h index 98da302..dbc59e7 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -19,116 +19,109 @@ #include #include #include -#include #include +#include #include #include +#include "lock.h" #include "notificationpopup.h" #include "requestinterceptor.h" #include "settingswidget.h" #include "webenginepage.h" -#include "lock.h" -#include "downloadmanagerwidget.h" #include "about.h" #include "dictionaries.h" -#include "webview.h" +#include "downloadmanagerwidget.h" #include "rateapp.h" +#include "webview.h" - -class MainWindow : public QMainWindow -{ - Q_OBJECT +class MainWindow : public QMainWindow { + Q_OBJECT public: - explicit MainWindow(QWidget *parent = nullptr); + explicit MainWindow(QWidget *parent = nullptr); public slots: - void updateWindowTheme(); - void updatePageTheme(); - - void handleWebViewTitleChanged(QString title); - void handleLoadFinished(bool loaded); - void handleDownloadRequested(QWebEngineDownloadItem *download); - void loadAppWithArgument(const QString &arg); + void updateWindowTheme(); + void updatePageTheme(); + void handleWebViewTitleChanged(QString title); + void handleLoadFinished(bool loaded); + void handleDownloadRequested(QWebEngineDownloadItem *download); + void loadAppWithArgument(const QString &arg); protected slots: - void closeEvent(QCloseEvent *event) override; - void resizeEvent(QResizeEvent *event); -private: - QPalette lightPalette; - void createActions(); - void createTrayIcon(); - void createWebEngine(); - - QSettings settings; + void closeEvent(QCloseEvent *event) override; + void resizeEvent(QResizeEvent *event) override; - QRegExp notificationsTitleRegExp; - QIcon trayIconRead; - QIcon trayIconUnread; +private: + QPalette lightPalette; + void createActions(); + void createTrayIcon(); + void createWebEngine(); - QAction *reloadAction; - QAction *minimizeAction; - QAction *restoreAction; - QAction *aboutAction; - QAction *settingsAction; - QAction *quitAction; - QAction *lockAction; - QAction *fullscreenAction; - QAction *openUrlAction; + QSettings settings; - QMenu *trayIconMenu; - QSystemTrayIcon *trayIcon; + QRegExp notificationsTitleRegExp; + QIcon trayIconRead; + QIcon trayIconUnread; - QWebEngineView *webEngine; - //QStatusBar *statusBar; + QAction *reloadAction; + QAction *minimizeAction; + QAction *restoreAction; + QAction *aboutAction; + QAction *settingsAction; + QAction *quitAction; + QAction *lockAction; + QAction *fullscreenAction; + QAction *openUrlAction; + QMenu *trayIconMenu; + QSystemTrayIcon *trayIcon; - SettingsWidget * settingsWidget = nullptr; + QWebEngineView *webEngine; - //void reload(); + SettingsWidget *settingsWidget = nullptr; - DownloadManagerWidget m_downloadManagerWidget; - QScopedPointer m_otrProfile; + DownloadManagerWidget m_downloadManagerWidget; + QScopedPointer m_otrProfile; - Lock *lockWidget = nullptr; + Lock *lockWidget = nullptr; - int correctlyLoaderRetries = 4; + int correctlyLoaderRetries = 4; - QStringList m_dictionaries; + QStringList m_dictionaries; private slots: - void iconActivated(QSystemTrayIcon::ActivationReason reason); - void messageClicked(); - void doReload(); - void showAbout(); - void notify(QString title, QString message); - void showSettings(); - void handleCookieAdded(const QNetworkCookie &cookie); - - QString getPageTheme(); - void toggleMute(const bool &checked); - void doAppReload(); - void askToReloadPage(); - void updateSettingsUserAgentWidget(); - void fullScreenRequested(QWebEngineFullScreenRequest request); - - void createWebPage(bool offTheRecord =false); - void init_settingWidget(); - void init_globalWebProfile(); - void check_window_state(); - void init_lock(); - void lockApp(); - - - void checkLoadedCorrectly(); - void loadingQuirk(QString test); - void setNotificationPresenter(QWebEngineProfile *profile); - void newChat(); - bool isPhoneNumber(const QString &phoneNumber); - void quitApp(); + void iconActivated(QSystemTrayIcon::ActivationReason reason); + void messageClicked(); + void doReload(); + void showAbout(); + void notify(QString title, QString message); + void showSettings(); + void handleCookieAdded(const QNetworkCookie &cookie); + + QString getPageTheme(); + void toggleMute(const bool &checked); + void doAppReload(); + void askToReloadPage(); + void updateSettingsUserAgentWidget(); + void fullScreenRequested(QWebEngineFullScreenRequest request); + + void createWebPage(bool offTheRecord = false); + void init_settingWidget(); + void init_globalWebProfile(); + void check_window_state(); + void init_lock(); + void lockApp(); + + void checkLoadedCorrectly(); + void loadingQuirk(QString test); + void setNotificationPresenter(QWebEngineProfile *profile); + void newChat(); + bool isPhoneNumber(const QString &phoneNumber); + void quitApp(); }; #endif // MAINWINDOW_H diff --git a/src/permissiondialog.cpp b/src/permissiondialog.cpp index 4cd77c8..2f181b6 100644 --- a/src/permissiondialog.cpp +++ b/src/permissiondialog.cpp @@ -5,72 +5,68 @@ #include #include +PermissionDialog::PermissionDialog(QWidget *parent) + : QWidget(parent), ui(new Ui::PermissionDialog) { + ui->setupUi(this); -PermissionDialog::PermissionDialog(QWidget *parent) : - QWidget(parent), - ui(new Ui::PermissionDialog) -{ - ui->setupUi(this); + ui->featuresTableWidget->horizontalHeader()->setSectionResizeMode( + QHeaderView::Stretch); + ui->featuresTableWidget->verticalHeader()->setVisible(true); + ui->featuresTableWidget->horizontalHeader()->setVisible(true); + ui->featuresTableWidget->setSelectionMode(QAbstractItemView::NoSelection); + ui->featuresTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); + ui->featuresTableWidget->setFocusPolicy(Qt::NoFocus); - ui->featuresTableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - ui->featuresTableWidget->verticalHeader()->setVisible(true); - ui->featuresTableWidget->horizontalHeader()->setVisible(true); - ui->featuresTableWidget->setSelectionMode(QAbstractItemView::NoSelection); - ui->featuresTableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers); - ui->featuresTableWidget->setFocusPolicy(Qt::NoFocus); - - QMetaEnum en = QMetaEnum::fromType(); - for (int i = 0; i < en.keyCount(); i++ ) { - QWebEnginePage::Feature feature = (QWebEnginePage::Feature) en.value(i); - QString featureName = QVariant::fromValue(feature).toString(); - addToFeaturesTable(feature,featureName); - } + QMetaEnum en = QMetaEnum::fromType(); + for (int i = 0; i < en.keyCount(); i++) { + QWebEnginePage::Feature feature = (QWebEnginePage::Feature)en.value(i); + QString featureName = QVariant::fromValue(feature).toString(); + addToFeaturesTable(feature, featureName); + } } -void PermissionDialog::addToFeaturesTable(QWebEnginePage::Feature feature, QString & featureName) -{ - if(featureName.isEmpty()== false){ - int nextRow; - int row = ui->featuresTableWidget->rowCount(); - if(row==0){ - nextRow = 0; - }else{ - nextRow = row++; - } +void PermissionDialog::addToFeaturesTable(QWebEnginePage::Feature feature, + QString &featureName) { + if (featureName.isEmpty() == false) { + int nextRow; + int row = ui->featuresTableWidget->rowCount(); + if (row == 0) { + nextRow = 0; + } else { + nextRow = row++; + } - QStringList columnData; - columnData<featuresTableWidget->insertRow(nextRow); - settings.beginGroup("permissions"); - //add column - for (int i = 0; i < columnData.count(); i++) { + // insertRow + ui->featuresTableWidget->insertRow(nextRow); + settings.beginGroup("permissions"); + // add column + for (int i = 0; i < columnData.count(); i++) { - if(columnData.at(i)=="status"){ - QCheckBox *featureCheckBox = new QCheckBox(0); - featureCheckBox->setStyleSheet("border:0px;margin-left:50%; margin-right:50%;"); - featureCheckBox->setChecked(settings.value(featureName,false).toBool()); - connect(featureCheckBox,&QCheckBox::toggled,[=](bool checked){ - //save permission - settings.setValue("permissions/"+featureName,checked); - emit webPageFeatureChanged(feature); - }); - ui->featuresTableWidget->setCellWidget(nextRow,i,featureCheckBox); - }else{ - QTableWidgetItem *item = new QTableWidgetItem(); - item->setText(columnData.at(i)); - item->setFlags(item->flags() & ~Qt::ItemIsSelectable); - ui->featuresTableWidget->setItem(nextRow, i,item); - } - this->update(); - } - settings.endGroup(); + if (columnData.at(i) == "status") { + QCheckBox *featureCheckBox = new QCheckBox(0); + featureCheckBox->setStyleSheet( + "border:0px;margin-left:50%; margin-right:50%;"); + featureCheckBox->setChecked( + settings.value(featureName, false).toBool()); + connect(featureCheckBox, &QCheckBox::toggled, [=](bool checked) { + // save permission + settings.setValue("permissions/" + featureName, checked); + emit webPageFeatureChanged(feature); + }); + ui->featuresTableWidget->setCellWidget(nextRow, i, featureCheckBox); + } else { + QTableWidgetItem *item = new QTableWidgetItem(); + item->setText(columnData.at(i)); + item->setFlags(item->flags() & ~Qt::ItemIsSelectable); + ui->featuresTableWidget->setItem(nextRow, i, item); + } + this->update(); } + settings.endGroup(); + } } - -PermissionDialog::~PermissionDialog() -{ - delete ui; -} +PermissionDialog::~PermissionDialog() { delete ui; } diff --git a/src/rateapp.cpp b/src/rateapp.cpp index 47382f5..f69080e 100644 --- a/src/rateapp.cpp +++ b/src/rateapp.cpp @@ -3,137 +3,131 @@ #include #include -RateApp::RateApp(QWidget *parent, QString app_rating_url, int app_launch_count, int app_install_days, int present_delay) : - QWidget(parent), - ui(new Ui::RateApp) -{ - ui->setupUi(this); - - this->app_rating_url= app_rating_url; // Url to open when rating button clicked - this->app_launch_count = app_launch_count; // How many time the app must be launched by user to show this dialog - this->app_install_days = app_install_days; // How many days the app must be installed by user to show this dialog - this->present_delay = present_delay; // Delay after which this dialog should be shown to use if all conditions matched - - showTimer = new QTimer(this); - showTimer->setInterval(this->present_delay); - connect(showTimer,&QTimer::timeout,[=](){ - qDebug()<<"Rate timer timeout"; - emit showRateDialog(); - if(this->isVisible()) - showTimer->stop(); - }); - - //increase the app_launched_count by one - int app_launched = settings.value("app_launched_count",0).toInt(); - settings.setValue("app_launched_count",app_launched + 1); - - //check if app install time is set in settings - if(settings.value("app_install_time").isNull()) - { - settings.setValue("app_install_time",QDateTime::currentSecsSinceEpoch()); - - }else if (settings.value("app_install_time").isValid()) - { - qDebug()<<"RATEAPP should show:"<start(); - }else { - //if shouldshow is false, delete this obj to free resources - this->deleteLater(); - } +RateApp::RateApp(QWidget *parent, QString app_rating_url, int app_launch_count, + int app_install_days, int present_delay) + : QWidget(parent), ui(new Ui::RateApp) { + ui->setupUi(this); + + this->app_rating_url = + app_rating_url; // Url to open when rating button clicked + this->app_launch_count = + app_launch_count; // How many time the app must be launched by user to + // show this dialog + this->app_install_days = + app_install_days; // How many days the app must be installed by user to + // show this dialog + this->present_delay = + present_delay; // Delay after which this dialog should be shown to use if + // all conditions matched + + showTimer = new QTimer(this); + showTimer->setInterval(this->present_delay); + connect(showTimer, &QTimer::timeout, [=]() { + qDebug() << "Rate timer timeout"; + emit showRateDialog(); + if (this->isVisible()) + showTimer->stop(); + }); + + // increase the app_launched_count by one + int app_launched = settings.value("app_launched_count", 0).toInt(); + settings.setValue("app_launched_count", app_launched + 1); + + // check if app install time is set in settings + if (settings.value("app_install_time").isNull()) { + settings.setValue("app_install_time", QDateTime::currentSecsSinceEpoch()); + + } else if (settings.value("app_install_time").isValid()) { + qDebug() << "RATEAPP should show:" << shouldShow(); + if (shouldShow()) { + showTimer->start(); + } else { + // if shouldshow is false, delete this obj to free resources + this->deleteLater(); } + } - //if already reated delete this obj to free resources - if(settings.value("rated_already",false).toBool()) - { - this->deleteLater(); - } + // if already reated delete this obj to free resources + if (settings.value("rated_already", false).toBool()) { + this->deleteLater(); + } } -void RateApp::delayShowEvent() -{ - showTimer->start(); +void RateApp::delayShowEvent() { + showTimer->start(); - qDebug()<<"Timer running"<isActive()<interval()<< - showTimer->isSingleShot(); - qDebug()<<"App was minimized and was not visible, " + qDebug() << "Timer running" << showTimer->isActive() << showTimer->interval() + << showTimer->isSingleShot(); + qDebug() << "App was minimized and was not visible, " "hence delaying the showevent of RateApp dialog by " - <showTimer->interval()/1000<<"seconds"; + << this->showTimer->interval() / 1000 << "seconds"; } /** * @brief RateApp::shouldShow * @return true, if the dialog should be shown to user */ -bool RateApp::shouldShow() -{ - bool shouldShow = false; - int app_launched_count = settings.value("app_launched_count",0).toInt(); - qint64 currentDateTime = QDateTime::currentSecsSinceEpoch(); - qint64 installed_date_time = settings.value("app_install_time").toLongLong(); - bool ratedAlready = settings.value("rated_already",false).toBool(); - - if(ratedAlready) //return false if already reated; - return false; - - shouldShow = (((currentDateTime - installed_date_time > app_install_days * 86400) || - app_launched_count >= this->app_launch_count) - && ratedAlready == false); - - return shouldShow; +bool RateApp::shouldShow() { + bool shouldShow = false; + int app_launched_count = settings.value("app_launched_count", 0).toInt(); + qint64 currentDateTime = QDateTime::currentSecsSinceEpoch(); + qint64 installed_date_time = settings.value("app_install_time").toLongLong(); + bool ratedAlready = settings.value("rated_already", false).toBool(); + + if (ratedAlready) // return false if already reated; + return false; + + shouldShow = + (((currentDateTime - installed_date_time > app_install_days * 86400) || + app_launched_count >= this->app_launch_count) && + ratedAlready == false); + + return shouldShow; } -RateApp::~RateApp() -{ - qDebug()<<"RateApp Obj deleted"; - showTimer->disconnect(); - showTimer->deleteLater(); - delete ui; +RateApp::~RateApp() { + qDebug() << "RateApp Obj deleted"; + showTimer->disconnect(); + showTimer->deleteLater(); + delete ui; } -void RateApp::on_rateNowBtn_clicked() -{ - QDesktopServices::openUrl(QUrl(app_rating_url)); - this->reset(); - this->close(); +void RateApp::on_rateNowBtn_clicked() { + QDesktopServices::openUrl(QUrl(app_rating_url)); + this->reset(); + this->close(); } -void RateApp::on_alreadyDoneBtn_clicked() -{ - settings.setValue("rated_already",true); - this->close(); +void RateApp::on_alreadyDoneBtn_clicked() { + settings.setValue("rated_already", true); + this->close(); } -void RateApp::on_laterBtn_clicked() -{ - this->reset(); - this->close(); +void RateApp::on_laterBtn_clicked() { + this->reset(); + this->close(); } -void RateApp::reset() -{ - settings.setValue("rated_already",false); - settings.setValue("app_launched_count",0); - settings.setValue("app_install_time",QDateTime::currentSecsSinceEpoch()); +void RateApp::reset() { + settings.setValue("rated_already", false); + settings.setValue("app_launched_count", 0); + settings.setValue("app_install_time", QDateTime::currentSecsSinceEpoch()); } -void RateApp::on_rateOnGithub_clicked() -{ - QDesktopServices::openUrl(QUrl("https://github.com/keshavbhatt/whatsie")); - this->reset(); - this->close(); +void RateApp::on_rateOnGithub_clicked() { + QDesktopServices::openUrl(QUrl("https://github.com/keshavbhatt/whatsie")); + this->reset(); + this->close(); } -void RateApp::on_donate_clicked() -{ - QDesktopServices::openUrl(QUrl("https://paypal.me/keshavnrj/5.00")); - this->reset(); - this->close(); +void RateApp::on_donate_clicked() { + QDesktopServices::openUrl(QUrl("https://paypal.me/keshavnrj/5.00")); + this->reset(); + this->close(); } -void RateApp::on_donate_2_clicked() -{ - QDesktopServices::openUrl(QUrl("https://opencollective.com/whatsie")); - this->reset(); - this->close(); +void RateApp::on_donate_2_clicked() { + QDesktopServices::openUrl(QUrl("https://opencollective.com/whatsie")); + this->reset(); + this->close(); } diff --git a/src/rungaurd.cpp b/src/rungaurd.cpp index 7136e7b..887eaf0 100644 --- a/src/rungaurd.cpp +++ b/src/rungaurd.cpp @@ -2,78 +2,66 @@ #include -namespace -{ +namespace { - QString generateKeyHash( const QString& key, const QString& salt ) - { - QByteArray data; +QString generateKeyHash(const QString &key, const QString &salt) { + QByteArray data; - data.append( key.toUtf8() ); - data.append( salt.toUtf8() ); - data = QCryptographicHash::hash( data, QCryptographicHash::Sha1 ).toHex(); - - return data; - } + data.append(key.toUtf8()); + data.append(salt.toUtf8()); + data = QCryptographicHash::hash(data, QCryptographicHash::Sha1).toHex(); + return data; } - -RunGuard::RunGuard( const QString& key ) - : key( key ) - , memLockKey( generateKeyHash( key, "_memLockKey" ) ) - , sharedmemKey( generateKeyHash( key, "_sharedmemKey" ) ) - , sharedMem( sharedmemKey ) - , memLock( memLockKey, 1 ) -{ - memLock.acquire(); - { - QSharedMemory fix( sharedmemKey ); // Fix for *nix: http://habrahabr.ru/post/173281/ - fix.attach(); - } - memLock.release(); +} // namespace + +RunGuard::RunGuard(const QString &key) + : key(key), memLockKey(generateKeyHash(key, "_memLockKey")), + sharedmemKey(generateKeyHash(key, "_sharedmemKey")), + sharedMem(sharedmemKey), memLock(memLockKey, 1) { + memLock.acquire(); + { + QSharedMemory fix( + sharedmemKey); // Fix for *nix: http://habrahabr.ru/post/173281/ + fix.attach(); + } + memLock.release(); } -RunGuard::~RunGuard() -{ - release(); -} +RunGuard::~RunGuard() { release(); } -bool RunGuard::isAnotherRunning() -{ - if ( sharedMem.isAttached() ) - return false; +bool RunGuard::isAnotherRunning() { + if (sharedMem.isAttached()) + return false; - memLock.acquire(); - const bool isRunning = sharedMem.attach(); - if ( isRunning ) - sharedMem.detach(); - memLock.release(); + memLock.acquire(); + const bool isRunning = sharedMem.attach(); + if (isRunning) + sharedMem.detach(); + memLock.release(); - return isRunning; + return isRunning; } -bool RunGuard::tryToRun() -{ - if ( isAnotherRunning() ) // Extra check - return false; +bool RunGuard::tryToRun() { + if (isAnotherRunning()) // Extra check + return false; - memLock.acquire(); - const bool result = sharedMem.create( sizeof( quint64 ) ); - memLock.release(); - if ( !result ) - { - release(); - return false; - } + memLock.acquire(); + const bool result = sharedMem.create(sizeof(quint64)); + memLock.release(); + if (!result) { + release(); + return false; + } - return true; + return true; } -void RunGuard::release() -{ - memLock.acquire(); - if ( sharedMem.isAttached() ) - sharedMem.detach(); - memLock.release(); +void RunGuard::release() { + memLock.acquire(); + if (sharedMem.isAttached()) + sharedMem.detach(); + memLock.release(); } diff --git a/src/settingswidget.cpp b/src/settingswidget.cpp index 2750e4d..5903491 100644 --- a/src/settingswidget.cpp +++ b/src/settingswidget.cpp @@ -1,460 +1,443 @@ #include "settingswidget.h" #include "ui_settingswidget.h" +#include "mainwindow.h" #include #include -#include "mainwindow.h" #include "automatictheme.h" - extern QString defaultUserAgentStr; -SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, QString enginePersistentStoragePath) : - QWidget(parent), - ui(new Ui::SettingsWidget) -{ - ui->setupUi(this); - - this->engineCachePath = engineCachePath; - this->enginePersistentStoragePath = enginePersistentStoragePath; - - ui->zoomFactorSpinBox->setRange(0.25,5.0); - ui->zoomFactorSpinBox->setValue(settings.value("zoomFactor",1.0).toDouble()); - //emit zoomChanged(); - - ui->closeButtonActionComboBox->setCurrentIndex(settings.value("closeButtonActionCombo",0).toInt()); - ui->notificationCheckBox->setChecked(settings.value("disableNotificationPopups",false).toBool()); - ui->muteAudioCheckBox->setChecked(settings.value("muteAudio",false).toBool()); - ui->autoPlayMediaCheckBox->setChecked(settings.value("autoPlayMedia",false).toBool()); - ui->themeComboBox->setCurrentText(utils::toCamelCase(settings.value("windowTheme","light").toString())); - ui->userAgentLineEdit->setText(settings.value("useragent",defaultUserAgentStr).toString()); - ui->enableSpellCheck->setChecked(settings.value("sc_enabled",true).toBool()); - ui->notificationTimeOutspinBox->setValue(settings.value("notificationTimeOut",9000).toInt()/1000); - ui->notificationCombo->setCurrentIndex(settings.value("notificationCombo",1).toInt()); - ui->useNativeFileDialog->setChecked(settings.value("useNativeFileDialog",false).toBool()); - - ui->automaticThemeCheckBox->blockSignals(true); - bool automaticThemeSwitching = settings.value("automaticTheme",false).toBool(); - ui->automaticThemeCheckBox->setChecked(automaticThemeSwitching); - ui->automaticThemeCheckBox->blockSignals(false); - - themeSwitchTimer = new QTimer(this); - themeSwitchTimer->setInterval(60000); // 1 min - connect(themeSwitchTimer,&QTimer::timeout,[=](){ - themeSwitchTimerTimeout(); - }); - - //instantly call the timeout slot if automatic theme switching enabled - if(automaticThemeSwitching) - themeSwitchTimerTimeout(); - //start regular timer to update theme - updateAutomaticTheme(); - - this->setCurrentPasswordText("Current Password: " - +QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())+""); - - applyThemeQuirks(); - - ui->setUserAgent->setEnabled(false); -} - -inline bool inRange(unsigned low, unsigned high, unsigned x) -{ - return ((x-low) <= (high-low)); -} - -void SettingsWidget::themeSwitchTimerTimeout() -{ - if(settings.value("automaticTheme",false).toBool()) - { - //start time - QDateTime sunrise; sunrise.setSecsSinceEpoch(settings.value("sunrise").toLongLong()); - //end time - QDateTime sunset; sunset.setSecsSinceEpoch(settings.value("sunset").toLongLong()); - QDateTime currentTime = QDateTime::currentDateTime(); - - int sunsetSeconds = QTime(0,0).secsTo(sunset.time()); - int sunriseSeconds = QTime(0,0).secsTo(sunrise.time()); - int currentSeconds = QTime(0,0).secsTo(currentTime.time()); - - if(inRange(sunsetSeconds,sunriseSeconds,currentSeconds)) - { - qDebug()<<"is night: "; - ui->themeComboBox->setCurrentText("Dark"); - }else{ - qDebug()<<"is morn: "; - ui->themeComboBox->setCurrentText("Light"); - } +SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, + QString enginePersistentStoragePath) + : QWidget(parent), ui(new Ui::SettingsWidget) { + ui->setupUi(this); + + this->engineCachePath = engineCachePath; + this->enginePersistentStoragePath = enginePersistentStoragePath; + + ui->zoomFactorSpinBox->setRange(0.25, 5.0); + ui->zoomFactorSpinBox->setValue(settings.value("zoomFactor", 1.0).toDouble()); + // emit zoomChanged(); + + ui->closeButtonActionComboBox->setCurrentIndex( + settings.value("closeButtonActionCombo", 0).toInt()); + ui->notificationCheckBox->setChecked( + settings.value("disableNotificationPopups", false).toBool()); + ui->muteAudioCheckBox->setChecked( + settings.value("muteAudio", false).toBool()); + ui->autoPlayMediaCheckBox->setChecked( + settings.value("autoPlayMedia", false).toBool()); + ui->themeComboBox->setCurrentText( + utils::toCamelCase(settings.value("windowTheme", "light").toString())); + ui->userAgentLineEdit->setText( + settings.value("useragent", defaultUserAgentStr).toString()); + ui->enableSpellCheck->setChecked(settings.value("sc_enabled", true).toBool()); + ui->notificationTimeOutspinBox->setValue( + settings.value("notificationTimeOut", 9000).toInt() / 1000); + ui->notificationCombo->setCurrentIndex( + settings.value("notificationCombo", 1).toInt()); + ui->useNativeFileDialog->setChecked( + settings.value("useNativeFileDialog", false).toBool()); + + ui->automaticThemeCheckBox->blockSignals(true); + bool automaticThemeSwitching = + settings.value("automaticTheme", false).toBool(); + ui->automaticThemeCheckBox->setChecked(automaticThemeSwitching); + ui->automaticThemeCheckBox->blockSignals(false); + + themeSwitchTimer = new QTimer(this); + themeSwitchTimer->setInterval(60000); // 1 min + connect(themeSwitchTimer, &QTimer::timeout, + [=]() { themeSwitchTimerTimeout(); }); + + // instantly call the timeout slot if automatic theme switching enabled + if (automaticThemeSwitching) + themeSwitchTimerTimeout(); + // start regular timer to update theme + updateAutomaticTheme(); + + this->setCurrentPasswordText( + "Current Password: " + + QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8()) + + ""); + + applyThemeQuirks(); + + ui->setUserAgent->setEnabled(false); +} + +inline bool inRange(unsigned low, unsigned high, unsigned x) { + return ((x - low) <= (high - low)); +} + +void SettingsWidget::themeSwitchTimerTimeout() { + if (settings.value("automaticTheme", false).toBool()) { + // start time + QDateTime sunrise; + sunrise.setSecsSinceEpoch(settings.value("sunrise").toLongLong()); + // end time + QDateTime sunset; + sunset.setSecsSinceEpoch(settings.value("sunset").toLongLong()); + QDateTime currentTime = QDateTime::currentDateTime(); + + int sunsetSeconds = QTime(0, 0).secsTo(sunset.time()); + int sunriseSeconds = QTime(0, 0).secsTo(sunrise.time()); + int currentSeconds = QTime(0, 0).secsTo(currentTime.time()); + + if (inRange(sunsetSeconds, sunriseSeconds, currentSeconds)) { + qDebug() << "is night: "; + ui->themeComboBox->setCurrentText("Dark"); + } else { + qDebug() << "is morn: "; + ui->themeComboBox->setCurrentText("Light"); } -} - - - -void SettingsWidget::updateAutomaticTheme() -{ - bool automaticThemeSwitching = settings.value("automaticTheme",false).toBool(); - if(automaticThemeSwitching && !themeSwitchTimer->isActive()){ - themeSwitchTimer->start(); - }else if(!automaticThemeSwitching){ - themeSwitchTimer->stop(); - } -} - -SettingsWidget::~SettingsWidget() -{ - delete ui; -} - -void SettingsWidget::loadDictionaries(QStringList dictionaries) -{ - // set up supported spellcheck dictionaries - QStringList ui_dictionary_names; - foreach(QString dictionary_name, dictionaries) { - ui_dictionary_names.append(dictionary_name); - } - - ui_dictionary_names.removeDuplicates(); - ui_dictionary_names.sort(); - - //add to ui - ui->dictComboBox->blockSignals(true); - foreach(const QString dict_name, ui_dictionary_names) - { - QString short_name = QString(dict_name).split("_").last(); - short_name = (short_name.isEmpty() || short_name.contains("-")) ? QString(dict_name).split("-").last() : short_name; - short_name = short_name.isEmpty() ? "XX" : short_name; - short_name = short_name.length() > 2 ? short_name.left(2) : short_name; - QIcon icon(QString(":/icons/flags/%1.png").arg(short_name.toLower())); - if(icon.isNull() == false) - ui->dictComboBox->addItem(icon,dict_name); - else - ui->dictComboBox->addItem(QIcon(":/icons/flags/xx.png"),dict_name); - } - ui->dictComboBox->blockSignals(false); - - // load settings for spellcheck dictionary - QString dictionary_name = settings.value("sc_dict","en-US").toString(); - int pos = ui->dictComboBox->findText(dictionary_name); - if (pos == -1) { - pos = ui->dictComboBox->findText("en-US"); - if (pos == -1) { - pos = 0; - } - } - ui->dictComboBox->setCurrentIndex(pos); -} - -void SettingsWidget::refresh() -{ - ui->themeComboBox->setCurrentText(utils::toCamelCase(settings.value("windowTheme","light").toString())); - - ui->cacheSize->setText(utils::refreshCacheSize(cachePath())); - ui->cookieSize->setText(utils::refreshCacheSize(persistentStoragePath())); - - //update dict settings at runtime - // load settings for spellcheck dictionary - QString dictionary_name = settings.value("sc_dict","en-US").toString(); - int pos = ui->dictComboBox->findText(dictionary_name); + } +} + +void SettingsWidget::updateAutomaticTheme() { + bool automaticThemeSwitching = + settings.value("automaticTheme", false).toBool(); + if (automaticThemeSwitching && !themeSwitchTimer->isActive()) { + themeSwitchTimer->start(); + } else if (!automaticThemeSwitching) { + themeSwitchTimer->stop(); + } +} + +SettingsWidget::~SettingsWidget() { delete ui; } + +void SettingsWidget::loadDictionaries(QStringList dictionaries) { + // set up supported spellcheck dictionaries + QStringList ui_dictionary_names; + foreach (QString dictionary_name, dictionaries) { + ui_dictionary_names.append(dictionary_name); + } + + ui_dictionary_names.removeDuplicates(); + ui_dictionary_names.sort(); + + // add to ui + ui->dictComboBox->blockSignals(true); + foreach (const QString dict_name, ui_dictionary_names) { + QString short_name = QString(dict_name).split("_").last(); + short_name = (short_name.isEmpty() || short_name.contains("-")) + ? QString(dict_name).split("-").last() + : short_name; + short_name = short_name.isEmpty() ? "XX" : short_name; + short_name = short_name.length() > 2 ? short_name.left(2) : short_name; + QIcon icon(QString(":/icons/flags/%1.png").arg(short_name.toLower())); + if (icon.isNull() == false) + ui->dictComboBox->addItem(icon, dict_name); + else + ui->dictComboBox->addItem(QIcon(":/icons/flags/xx.png"), dict_name); + } + ui->dictComboBox->blockSignals(false); + + // load settings for spellcheck dictionary + QString dictionary_name = settings.value("sc_dict", "en-US").toString(); + int pos = ui->dictComboBox->findText(dictionary_name); + if (pos == -1) { + pos = ui->dictComboBox->findText("en-US"); if (pos == -1) { - pos = ui->dictComboBox->findText("en-US"); - if (pos == -1) { - pos = 0; - } - } - ui->dictComboBox->setCurrentIndex(pos); - - //enable disable spell check - ui->enableSpellCheck->setChecked(settings.value("sc_enabled",true).toBool()); - - -} - -void SettingsWidget::updateDefaultUAButton(const QString engineUA) -{ - bool isDefault = QString::compare(engineUA,defaultUserAgentStr,Qt::CaseInsensitive) == 0; - ui->defaultUserAgentButton->setEnabled(!isDefault); - - if(ui->userAgentLineEdit->text().trimmed().isEmpty()){ - ui->userAgentLineEdit->setText(engineUA); + pos = 0; } + } + ui->dictComboBox->setCurrentIndex(pos); } +void SettingsWidget::refresh() { + ui->themeComboBox->setCurrentText( + utils::toCamelCase(settings.value("windowTheme", "light").toString())); -QString SettingsWidget::cachePath() -{ - return engineCachePath; -} + ui->cacheSize->setText(utils::refreshCacheSize(cachePath())); + ui->cookieSize->setText(utils::refreshCacheSize(persistentStoragePath())); -QString SettingsWidget::persistentStoragePath() -{ - return enginePersistentStoragePath; -} - -void SettingsWidget::on_deleteCache_clicked() -{ - QMessageBox msgBox; - msgBox.setText("This will delete app cache! Application cache makes application load faster."); - msgBox.setIconPixmap(QPixmap(":/icons/information-line.png").scaled(42,42,Qt::KeepAspectRatio,Qt::SmoothTransformation)); - - msgBox.setInformativeText("Delete Application cache ?"); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - int ret = msgBox.exec(); - switch (ret) { - case QMessageBox::Yes:{ - utils::delete_cache(this->cachePath()); - refresh(); - break; - } - case QMessageBox::No: - break; + // update dict settings at runtime + // load settings for spellcheck dictionary + QString dictionary_name = settings.value("sc_dict", "en-US").toString(); + int pos = ui->dictComboBox->findText(dictionary_name); + if (pos == -1) { + pos = ui->dictComboBox->findText("en-US"); + if (pos == -1) { + pos = 0; } + } + ui->dictComboBox->setCurrentIndex(pos); + + // enable disable spell check + ui->enableSpellCheck->setChecked(settings.value("sc_enabled", true).toBool()); +} + +void SettingsWidget::updateDefaultUAButton(const QString engineUA) { + bool isDefault = + QString::compare(engineUA, defaultUserAgentStr, Qt::CaseInsensitive) == 0; + ui->defaultUserAgentButton->setEnabled(!isDefault); + + if (ui->userAgentLineEdit->text().trimmed().isEmpty()) { + ui->userAgentLineEdit->setText(engineUA); + } +} + +QString SettingsWidget::cachePath() { return engineCachePath; } + +QString SettingsWidget::persistentStoragePath() { + return enginePersistentStoragePath; +} + +void SettingsWidget::on_deleteCache_clicked() { + QMessageBox msgBox; + msgBox.setText("This will delete app cache! Application cache makes " + "application load faster."); + msgBox.setIconPixmap( + QPixmap(":/icons/information-line.png") + .scaled(42, 42, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + + msgBox.setInformativeText("Delete Application cache ?"); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + int ret = msgBox.exec(); + switch (ret) { + case QMessageBox::Yes: { + utils::delete_cache(this->cachePath()); + refresh(); + break; + } + case QMessageBox::No: + break; + } +} + +void SettingsWidget::on_deletePersistentData_clicked() { + QMessageBox msgBox; + msgBox.setText( + "This will delete app Persistent Data ! Persistent data includes " + "persistent cookies, HTML5 local storage, and visited links."); + msgBox.setIconPixmap( + QPixmap(":/icons/information-line.png") + .scaled(42, 42, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + msgBox.setInformativeText("Delete Application Cookies ?"); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + int ret = msgBox.exec(); + switch (ret) { + case QMessageBox::Yes: { + utils::delete_cache(this->persistentStoragePath()); + refresh(); + break; + } + case QMessageBox::No: + break; + } +} + +void SettingsWidget::on_notificationCheckBox_toggled(bool checked) { + settings.setValue("disableNotificationPopups", checked); +} + +void SettingsWidget::on_themeComboBox_currentTextChanged(const QString &arg1) { + applyThemeQuirks(); + settings.setValue("windowTheme", QString(arg1).toLower()); + emit updateWindowTheme(); + emit updatePageTheme(); +} + +void SettingsWidget::applyThemeQuirks() { + // little quirks + if (QString::compare(ui->themeComboBox->currentText(), "dark", + Qt::CaseInsensitive) == 0) { + ui->bottomLine->setStyleSheet("background-color: rgb(5, 97, 98);"); + ui->label_7->setStyleSheet( + "color:#c2c5d1;padding: 0px 8px 0px 8px;background:transparent;"); + } else { + ui->bottomLine->setStyleSheet("background-color: rgb(74, 223, 131);"); + ui->label_7->setStyleSheet( + "color:#1e1f21;padding: 0px 8px 0px 8px;background:transparent;"); + } +} + +void SettingsWidget::on_muteAudioCheckBox_toggled(bool checked) { + settings.setValue("muteAudio", checked); + emit muteToggled(checked); +} + +void SettingsWidget::on_autoPlayMediaCheckBox_toggled(bool checked) { + settings.setValue("autoPlayMedia", checked); + emit autoPlayMediaToggled(checked); +} + +void SettingsWidget::on_defaultUserAgentButton_clicked() { + ui->userAgentLineEdit->setText(defaultUserAgentStr); + emit userAgentChanged(ui->userAgentLineEdit->text()); +} + +void SettingsWidget::on_userAgentLineEdit_textChanged(const QString &arg1) { + bool isDefault = QString::compare(arg1.trimmed(), defaultUserAgentStr, + Qt::CaseInsensitive) == 0; + bool isPrevious = + QString::compare( + arg1.trimmed(), + settings.value("useragent", defaultUserAgentStr).toString(), + Qt::CaseInsensitive) == 0; + + if (isDefault == false && arg1.trimmed().isEmpty() == false) { + ui->defaultUserAgentButton->setEnabled(false); + ui->setUserAgent->setEnabled(false); + } + if (isPrevious == false && arg1.trimmed().isEmpty() == false) { + ui->setUserAgent->setEnabled(true); + ui->defaultUserAgentButton->setEnabled(true); + } + if (isPrevious) { + ui->defaultUserAgentButton->setEnabled(true); + ui->setUserAgent->setEnabled(false); + } } -void SettingsWidget::on_deletePersistentData_clicked() -{ - QMessageBox msgBox; - msgBox.setText("This will delete app Persistent Data ! Persistent data includes persistent cookies, HTML5 local storage, and visited links."); - msgBox.setIconPixmap(QPixmap(":/icons/information-line.png").scaled(42,42,Qt::KeepAspectRatio,Qt::SmoothTransformation)); - msgBox.setInformativeText("Delete Application Cookies ?"); - msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - msgBox.setDefaultButton(QMessageBox::No); - int ret = msgBox.exec(); - switch (ret) { - case QMessageBox::Yes:{ - utils::delete_cache(this->persistentStoragePath()); - refresh(); - break; - } - case QMessageBox::No: - break; - } +void SettingsWidget::on_setUserAgent_clicked() { + if (ui->userAgentLineEdit->text().trimmed().isEmpty()) { + QMessageBox::information(this, QApplication::applicationName() + "| Error", + "Cannot set an empty UserAgent String."); + return; + } + emit userAgentChanged(ui->userAgentLineEdit->text()); } -void SettingsWidget::on_notificationCheckBox_toggled(bool checked) -{ - settings.setValue("disableNotificationPopups",checked); +void SettingsWidget::on_closeButtonActionComboBox_currentIndexChanged( + int index) { + settings.setValue("closeButtonActionCombo", index); } -void SettingsWidget::on_themeComboBox_currentTextChanged(const QString &arg1) -{ - applyThemeQuirks(); - settings.setValue("windowTheme",QString(arg1).toLower()); - emit updateWindowTheme(); - emit updatePageTheme(); +void SettingsWidget::appLockSetChecked(bool checked) { + ui->applock_checkbox->setChecked(checked); } - -void SettingsWidget::applyThemeQuirks() -{ - //little quirks - if(QString::compare(ui->themeComboBox->currentText(),"dark",Qt::CaseInsensitive)==0) - { - ui->bottomLine->setStyleSheet("background-color: rgb(5, 97, 98);"); - ui->label_7->setStyleSheet("color:#c2c5d1;padding: 0px 8px 0px 8px;background:transparent;"); - }else{ - ui->bottomLine->setStyleSheet("background-color: rgb(74, 223, 131);"); - ui->label_7->setStyleSheet("color:#1e1f21;padding: 0px 8px 0px 8px;background:transparent;"); - } +void SettingsWidget::setCurrentPasswordText(QString str) { + ui->current_password->setText(str); } - -void SettingsWidget::on_muteAudioCheckBox_toggled(bool checked) -{ - settings.setValue("muteAudio",checked); - emit muteToggled(checked); +void SettingsWidget::on_applock_checkbox_toggled(bool checked) { + if (settings.value("asdfg").isValid()) { + settings.setValue("lockscreen", checked); + } else { + settings.setValue("lockscreen", false); + } + if (checked) { + emit init_lock(); + } } -void SettingsWidget::on_autoPlayMediaCheckBox_toggled(bool checked) -{ - settings.setValue("autoPlayMedia",checked); - emit autoPlayMediaToggled(checked); +void SettingsWidget::on_dictComboBox_currentIndexChanged(const QString &arg1) { + settings.setValue("sc_dict", arg1); + emit dictChanged(arg1); } -void SettingsWidget::on_defaultUserAgentButton_clicked() -{ - ui->userAgentLineEdit->setText(defaultUserAgentStr); - emit userAgentChanged(ui->userAgentLineEdit->text()); +void SettingsWidget::on_enableSpellCheck_toggled(bool checked) { + settings.setValue("sc_enabled", checked); + emit spellCheckChanged(checked); } -void SettingsWidget::on_userAgentLineEdit_textChanged(const QString &arg1) -{ - bool isDefault = QString::compare(arg1.trimmed(),defaultUserAgentStr,Qt::CaseInsensitive) == 0; - bool isPrevious= QString::compare(arg1.trimmed(),settings.value("useragent",defaultUserAgentStr).toString(),Qt::CaseInsensitive) == 0; +void SettingsWidget::on_showShortcutsButton_clicked() { + QWidget *sheet = new QWidget(this); + sheet->setWindowTitle(QApplication::applicationName() + + " | Global shortcuts"); - if(isDefault == false && arg1.trimmed().isEmpty()==false) - { - ui->defaultUserAgentButton->setEnabled(false); - ui->setUserAgent->setEnabled(false); - } - if(isPrevious == false && arg1.trimmed().isEmpty() == false) - { - ui->setUserAgent->setEnabled(true); - ui->defaultUserAgentButton->setEnabled(true); - } - if(isPrevious){ - ui->defaultUserAgentButton->setEnabled(true); - ui->setUserAgent->setEnabled(false); - } -} + sheet->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint); + sheet->move(this->geometry().center() - sheet->geometry().center()); -void SettingsWidget::on_setUserAgent_clicked() -{ - if(ui->userAgentLineEdit->text().trimmed().isEmpty()){ - QMessageBox::information(this,QApplication::applicationName()+"| Error", - "Cannot set an empty UserAgent String."); - return; + QVBoxLayout *layout = new QVBoxLayout(sheet); + sheet->setLayout(layout); + auto *w = qobject_cast(parent()); + if (w != 0) { + foreach (QAction *action, w->actions()) { + QString shortcutStr = action->shortcut().toString(); + if (shortcutStr.isEmpty() == false) { + QLabel *label = new QLabel( + action->text().remove("&") + " | " + shortcutStr, sheet); + label->setAlignment(Qt::AlignHCenter); + layout->addWidget(label); + } } - emit userAgentChanged(ui->userAgentLineEdit->text()); + } + sheet->setAttribute(Qt::WA_DeleteOnClose); + sheet->show(); } - -void SettingsWidget::on_closeButtonActionComboBox_currentIndexChanged(int index) -{ - settings.setValue("closeButtonActionCombo",index); -} - -void SettingsWidget::appLockSetChecked(bool checked) -{ - ui->applock_checkbox->setChecked(checked); +void SettingsWidget::on_showPermissionsButton_clicked() { + PermissionDialog *permissionDialog = new PermissionDialog(this); + permissionDialog->setWindowTitle(QApplication::applicationName() + " | " + + tr("Feature permissions")); + permissionDialog->setWindowFlag(Qt::Dialog); + permissionDialog->setAttribute(Qt::WA_DeleteOnClose, true); + permissionDialog->move(this->geometry().center() - + permissionDialog->geometry().center()); + permissionDialog->setMinimumSize(485, 310); + permissionDialog->adjustSize(); + permissionDialog->show(); } -void SettingsWidget::setCurrentPasswordText(QString str) -{ - ui->current_password->setText(str); -} - -void SettingsWidget::on_applock_checkbox_toggled(bool checked) -{ - if(settings.value("asdfg").isValid()){ - settings.setValue("lockscreen",checked); - }else{ - settings.setValue("lockscreen",false); - } - if(checked){ - emit init_lock(); - } +void SettingsWidget::on_notificationTimeOutspinBox_valueChanged(int arg1) { + settings.setValue("notificationTimeOut", arg1 * 1000); + emit notificationPopupTimeOutChanged(); } -void SettingsWidget::on_dictComboBox_currentIndexChanged(const QString &arg1) -{ - settings.setValue("sc_dict",arg1); - emit dictChanged(arg1); +void SettingsWidget::on_notificationCombo_currentIndexChanged(int index) { + settings.setValue("notificationCombo", index); } -void SettingsWidget::on_enableSpellCheck_toggled(bool checked) -{ - settings.setValue("sc_enabled",checked); - emit spellCheckChanged(checked); +void SettingsWidget::on_tryNotification_clicked() { + emit notify("Test Notification"); } -void SettingsWidget::on_showShortcutsButton_clicked() -{ - QWidget *sheet = new QWidget(this); - sheet->setWindowTitle(QApplication::applicationName()+" | Global shortcuts"); - - sheet->setWindowFlags(Qt::Popup |Qt::FramelessWindowHint); - sheet->move(this->geometry().center()-sheet->geometry().center()); - - QVBoxLayout *layout = new QVBoxLayout(sheet); - sheet->setLayout(layout); - auto *w = qobject_cast(parent()); - if(w != 0){ - foreach (QAction *action, w->actions()) { - QString shortcutStr = action->shortcut().toString(); - if(shortcutStr.isEmpty()==false){ - QLabel *label = new QLabel(action->text().remove("&")+" | "+shortcutStr,sheet); - label->setAlignment(Qt::AlignHCenter); - layout->addWidget(label); - } - } - } - sheet->setAttribute(Qt::WA_DeleteOnClose); - sheet->show(); -} - -void SettingsWidget::on_showPermissionsButton_clicked() -{ - PermissionDialog *permissionDialog = new PermissionDialog(this); - permissionDialog->setWindowTitle(QApplication::applicationName()+" | "+tr("Feature permissions")); - permissionDialog->setWindowFlag(Qt::Dialog); - permissionDialog->setAttribute(Qt::WA_DeleteOnClose,true); - permissionDialog->move(this->geometry().center()-permissionDialog->geometry().center()); - permissionDialog->setMinimumSize(485,310); - permissionDialog->adjustSize(); - permissionDialog->show(); -} - - -void SettingsWidget::on_notificationTimeOutspinBox_valueChanged(int arg1) -{ - settings.setValue("notificationTimeOut",arg1*1000); - emit notificationPopupTimeOutChanged(); -} - -void SettingsWidget::on_notificationCombo_currentIndexChanged(int index) -{ - settings.setValue("notificationCombo",index); -} - -void SettingsWidget::on_tryNotification_clicked() -{ - emit notify("Test Notification"); -} - -void SettingsWidget::on_automaticThemeCheckBox_toggled(bool checked) -{ - if(checked) - { - AutomaticTheme *automaticTheme = new AutomaticTheme(this); - automaticTheme->setWindowTitle(QApplication::applicationName()+" | Automatic theme switcher setup"); - automaticTheme->setWindowFlag(Qt::Dialog); - automaticTheme->setAttribute(Qt::WA_DeleteOnClose,true); - connect(automaticTheme,&AutomaticTheme::destroyed,[=](){ - bool automaticThemeSwitching = settings.value("automaticTheme",false).toBool(); - ui->automaticThemeCheckBox->setChecked(automaticThemeSwitching); - if(automaticThemeSwitching) - themeSwitchTimerTimeout(); - updateAutomaticTheme(); - }); - automaticTheme->show(); - }else{ - settings.setValue("automaticTheme",false); - updateAutomaticTheme(); - } +void SettingsWidget::on_automaticThemeCheckBox_toggled(bool checked) { + if (checked) { + AutomaticTheme *automaticTheme = new AutomaticTheme(this); + automaticTheme->setWindowTitle(QApplication::applicationName() + + " | Automatic theme switcher setup"); + automaticTheme->setWindowFlag(Qt::Dialog); + automaticTheme->setAttribute(Qt::WA_DeleteOnClose, true); + connect(automaticTheme, &AutomaticTheme::destroyed, [=]() { + bool automaticThemeSwitching = + settings.value("automaticTheme", false).toBool(); + ui->automaticThemeCheckBox->setChecked(automaticThemeSwitching); + if (automaticThemeSwitching) + themeSwitchTimerTimeout(); + updateAutomaticTheme(); + }); + automaticTheme->show(); + } else { + settings.setValue("automaticTheme", false); + updateAutomaticTheme(); + } } -void SettingsWidget::on_useNativeFileDialog_toggled(bool checked) -{ - settings.setValue("useNativeFileDialog",checked); +void SettingsWidget::on_useNativeFileDialog_toggled(bool checked) { + settings.setValue("useNativeFileDialog", checked); } -void SettingsWidget::on_zoomPlus_clicked() -{ - double currentFactor = settings.value("zoomFactor",1.0).toDouble(); - double newFactor = currentFactor + 0.25; - ui->zoomFactorSpinBox->setValue(newFactor); +void SettingsWidget::on_zoomPlus_clicked() { + double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); + double newFactor = currentFactor + 0.25; + ui->zoomFactorSpinBox->setValue(newFactor); - settings.setValue("zoomFactor",ui->zoomFactorSpinBox->value()); - emit zoomChanged(); + settings.setValue("zoomFactor", ui->zoomFactorSpinBox->value()); + emit zoomChanged(); } -void SettingsWidget::on_zoomMinus_clicked() -{ - double currentFactor = settings.value("zoomFactor",1.0).toDouble(); - double newFactor = currentFactor - 0.25; - ui->zoomFactorSpinBox->setValue(newFactor); +void SettingsWidget::on_zoomMinus_clicked() { + double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); + double newFactor = currentFactor - 0.25; + ui->zoomFactorSpinBox->setValue(newFactor); - settings.setValue("zoomFactor",ui->zoomFactorSpinBox->value()); - emit zoomChanged(); + settings.setValue("zoomFactor", ui->zoomFactorSpinBox->value()); + emit zoomChanged(); } -void SettingsWidget::on_zoomReset_clicked() -{ - double newFactor = 1.0; - ui->zoomFactorSpinBox->setValue(newFactor); +void SettingsWidget::on_zoomReset_clicked() { + double newFactor = 1.0; + ui->zoomFactorSpinBox->setValue(newFactor); - settings.setValue("zoomFactor",ui->zoomFactorSpinBox->value()); - emit zoomChanged(); + settings.setValue("zoomFactor", ui->zoomFactorSpinBox->value()); + emit zoomChanged(); } diff --git a/src/utils.cpp b/src/utils.cpp index d810997..e248081 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -6,274 +6,261 @@ #include #include -utils::utils(QObject *parent) : QObject(parent) -{ - setParent(parent); -} - -utils::~utils() -{ - this->deleteLater(); -} - -//calculate dir size -quint64 utils::dir_size(const QString & directory) -{ - quint64 sizex = 0; - QFileInfo str_info(directory); - if (str_info.isDir()) - { - QDir dir(directory); - QFileInfoList list = dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::Hidden | QDir::NoSymLinks | QDir::NoDotAndDotDot); - for (int i = 0; i < list.size(); ++i) - { - QFileInfo fileInfo = list.at(i); - if(fileInfo.isDir()) - { - sizex += dir_size(fileInfo.absoluteFilePath()); - } - else{ - sizex += fileInfo.size(); - } - } +utils::utils(QObject *parent) : QObject(parent) { setParent(parent); } + +utils::~utils() { this->deleteLater(); } + +// calculate dir size +quint64 utils::dir_size(const QString &directory) { + quint64 sizex = 0; + QFileInfo str_info(directory); + if (str_info.isDir()) { + QDir dir(directory); + QFileInfoList list = + dir.entryInfoList(QDir::Files | QDir::Dirs | QDir::Hidden | + QDir::NoSymLinks | QDir::NoDotAndDotDot); + for (int i = 0; i < list.size(); ++i) { + QFileInfo fileInfo = list.at(i); + if (fileInfo.isDir()) { + sizex += dir_size(fileInfo.absoluteFilePath()); + } else { + sizex += fileInfo.size(); + } } - return sizex; + } + return sizex; } -//get the size of cache folder in human readble format -QString utils::refreshCacheSize(const QString cache_dir) -{ - qint64 cache_size = dir_size(cache_dir); - QString cache_unit; - if(cache_size > 1024*1024*1024) - { - cache_size = cache_size/(1024*1024*1024); - cache_unit = " GB"; - } - if(cache_size > 1024*1024) - { - cache_size = cache_size/(1024*1024); - cache_unit = " MB"; - } - else if(cache_size > 1024) - { - cache_size = cache_size/(1024); - cache_unit = " kB"; - } - else - { - cache_unit = " B"; - } - return QString::number(cache_size) + cache_unit; +// get the size of cache folder in human readble format +QString utils::refreshCacheSize(const QString cache_dir) { + qint64 cache_size = dir_size(cache_dir); + QString cache_unit; + if (cache_size > 1024 * 1024 * 1024) { + cache_size = cache_size / (1024 * 1024 * 1024); + cache_unit = " GB"; + } + if (cache_size > 1024 * 1024) { + cache_size = cache_size / (1024 * 1024); + cache_unit = " MB"; + } else if (cache_size > 1024) { + cache_size = cache_size / (1024); + cache_unit = " kB"; + } else { + cache_unit = " B"; + } + return QString::number(cache_size) + cache_unit; } -bool utils::delete_cache(const QString cache_dir) -{ - bool deleted = QDir(cache_dir).removeRecursively(); - QDir(cache_dir).mkpath(cache_dir); - return deleted; +bool utils::delete_cache(const QString cache_dir) { + bool deleted = QDir(cache_dir).removeRecursively(); + QDir(cache_dir).mkpath(cache_dir); + return deleted; } -//returns string with first letter capitalized -QString utils::toCamelCase(const QString& s) -{ - QStringList parts = s.split(' ', QString::SkipEmptyParts); - for (int i = 0; i < parts.size(); ++i) - parts[i].replace(0, 1, parts[i][0].toUpper()); - return parts.join(" "); +// returns string with first letter capitalized +QString utils::toCamelCase(const QString &s) { + QStringList parts = s.split(' ', QString::SkipEmptyParts); + for (int i = 0; i < parts.size(); ++i) + parts[i].replace(0, 1, parts[i][0].toUpper()); + return parts.join(" "); } -QString utils::generateRandomId(int length){ +QString utils::generateRandomId(int length) { - QString str = QUuid::createUuid().toString(); - str.remove(QRegularExpression("{|}|-")); - if(str.length()length){ - while(str.length() != length){ - str = str.remove(str.length()-1,1); - } + } + if (str.length() > length) { + while (str.length() != length) { + str = str.remove(str.length() - 1, 1); } - return str; + } + return str; } -QString utils::genRand(int length) -{ - QDateTime cd = QDateTime::currentDateTime(); - const QString possibleCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"+QString::number(cd.currentMSecsSinceEpoch()).remove(QRegExp("[^a-zA-Z\\d\\s]"))); - - const int randomStringLength = length; - QString randomString; - qsrand(cd.toTime_t()); - for(int i=0; i': - temp += ">"; break; + case '>': + temp += ">"; + break; - default: - temp += character; - break; - } + default: + temp += character; + break; } + } - return temp; + return temp; } QString utils::DecodeXML(const QString &decodeMe) { - QString temp(decodeMe); + QString temp(decodeMe); - temp.replace("&", "&"); - temp.replace("'", "'"); - temp.replace(""", "\""); - temp.replace("<", "<"); - temp.replace(">", ">"); + temp.replace("&", "&"); + temp.replace("'", "'"); + temp.replace(""", "\""); + temp.replace("<", "<"); + temp.replace(">", ">"); - return temp; + return temp; } - -QString utils::htmlToPlainText(QString str){ - QString out; - QTextDocument text; - text.setHtml(str); - out = text.toPlainText(); - text.deleteLater(); - return out .replace("\\\"","'") - .replace("&","&") - .replace(">",">") - .replace("<","<") - .replace("'","'"); +QString utils::htmlToPlainText(QString str) { + QString out; + QTextDocument text; + text.setHtml(str); + out = text.toPlainText(); + text.deleteLater(); + return out.replace("\\\"", "'") + .replace("&", "&") + .replace(">", ">") + .replace("<", "<") + .replace("'", "'"); } - -QString utils::appDebugInfo() -{ - - QStringList debugInfo; - debugInfo << "

"+QApplication::applicationName()+"

" - << "
    " - << "
  • " + QObject::tr("Version") + ": " + QString(VERSIONSTR) + "
  • " - << "
  • " + QObject::tr("Build Date") + ": " + QString::fromLatin1(__DATE__) + "
  • " - << "
  • " + QObject::tr("Build Time") + ": " + QString::fromLatin1(__TIME__) + "
  • " - << "
  • " + QObject::tr("Qt Runtime Version")+ ": " + QString(qVersion()) + "
  • " - << "
  • " + QObject::tr("Qt Compiled Version") + ": " + QString(QT_VERSION_STR) + "
  • " - << "
  • " + QObject::tr("System") + ": " + QSysInfo::prettyProductName() + "
  • " - << "
  • " + QObject::tr("Architecture") + ": " + QSysInfo::currentCpuArchitecture() + "
  • "; - debugInfo << "
"; - return debugInfo.join("\n"); - +QString utils::appDebugInfo() { + + QStringList debugInfo; + debugInfo << "

" + QApplication::applicationName() + "

" + << "
    " + << "
  • " + QObject::tr("Version") + ": " + + QString(VERSIONSTR) + "
  • " + << "
  • " + QObject::tr("Build Date") + ": " + + QString::fromLatin1(__DATE__) + "
  • " + << "
  • " + QObject::tr("Build Time") + ": " + + QString::fromLatin1(__TIME__) + "
  • " + << "
  • " + QObject::tr("Qt Runtime Version") + ": " + + QString(qVersion()) + "
  • " + << "
  • " + QObject::tr("Qt Compiled Version") + ": " + + QString(QT_VERSION_STR) + "
  • " + << "
  • " + QObject::tr("System") + ": " + + QSysInfo::prettyProductName() + "
  • " + << "
  • " + QObject::tr("Architecture") + ": " + + QSysInfo::currentCpuArchitecture() + "
  • "; + debugInfo << "
"; + return debugInfo.join("\n"); } -void utils::DisplayExceptionErrorDialog(const QString &error_info) -{ - QMessageBox message_box(QApplication::activeWindow()); - message_box.setAttribute(Qt::WA_DeleteOnClose,true); - message_box.setWindowFlags(Qt::Window | Qt::WindowStaysOnTopHint); - message_box.setModal(true); - message_box.setIcon(QMessageBox::Critical); - message_box.setWindowTitle(QApplication::applicationName()+QObject::tr("Exception")); - //spaces are added to the end because otherwise the dialog is too small - message_box.setText(QApplication::applicationName()+QObject::tr(" has encountered a problem.")); - message_box.setInformativeText(QApplication::applicationName()+QObject::tr(" may need to Restart. Please report the error to developer.")); - message_box.setStandardButtons(QMessageBox::Close); - QStringList detailed_text; - detailed_text << "Error info: " + error_info - << "\nApp version: " + QString(VERSIONSTR) - << "\nQt Runtime Version: " + QString(qVersion()) - << "\nQt Compiled Version: " + QString(QT_VERSION_STR) - << "\nSystem: " + QSysInfo::prettyProductName() - << "\nArchitecture: " + QSysInfo::currentCpuArchitecture(); - message_box.setDetailedText(detailed_text.join("\n")); - message_box.exec(); +void utils::DisplayExceptionErrorDialog(const QString &error_info) { + QMessageBox message_box(QApplication::activeWindow()); + message_box.setAttribute(Qt::WA_DeleteOnClose, true); + message_box.setWindowFlags(Qt::Window | Qt::WindowStaysOnTopHint); + message_box.setModal(true); + message_box.setIcon(QMessageBox::Critical); + message_box.setWindowTitle(QApplication::applicationName() + + QObject::tr("Exception")); + // spaces are added to the end because otherwise the dialog is too small + message_box.setText(QApplication::applicationName() + + QObject::tr(" has encountered a problem.")); + message_box.setInformativeText( + QApplication::applicationName() + + QObject::tr( + " may need to Restart. Please report the error to developer.")); + message_box.setStandardButtons(QMessageBox::Close); + QStringList detailed_text; + detailed_text << "Error info: " + error_info + << "\nApp version: " + QString(VERSIONSTR) + << "\nQt Runtime Version: " + QString(qVersion()) + << "\nQt Compiled Version: " + QString(QT_VERSION_STR) + << "\nSystem: " + QSysInfo::prettyProductName() + << "\nArchitecture: " + QSysInfo::currentCpuArchitecture(); + message_box.setDetailedText(detailed_text.join("\n")); + message_box.exec(); } // Returns the same number, but rounded to one decimal place -float utils::RoundToOneDecimal(float number) -{ - return QString::number(number, 'f', 1).toFloat(); +float utils::RoundToOneDecimal(float number) { + return QString::number(number, 'f', 1).toFloat(); } // Returns a value for the environment variable name passed; // if the env var isn't set, it returns an empty string -QString utils::GetEnvironmentVar(const QString &variable_name) -{ +QString utils::GetEnvironmentVar(const QString &variable_name) { #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) - // The only time this might fall down is on Linux when an - // environment variable holds bytedata. Don't use this - // utility function for retrieval if that's the case. - return qEnvironmentVariable(variable_name.toUtf8().constData(), "").trimmed(); + // The only time this might fall down is on Linux when an + // environment variable holds bytedata. Don't use this + // utility function for retrieval if that's the case. + return qEnvironmentVariable(variable_name.toUtf8().constData(), "").trimmed(); #else - // This will typically only be used on older Qts on Linux - return QProcessEnvironment::systemEnvironment().value(variable_name, "").trimmed(); + // This will typically only be used on older Qts on Linux + return QProcessEnvironment::systemEnvironment() + .value(variable_name, "") + .trimmed(); #endif } - - - - diff --git a/src/webenginepage.cpp b/src/webenginepage.cpp index f0155bc..d5ecfff 100644 --- a/src/webenginepage.cpp +++ b/src/webenginepage.cpp @@ -4,275 +4,290 @@ #include #include - WebEnginePage::WebEnginePage(QWebEngineProfile *profile, QObject *parent) - : QWebEnginePage(profile, parent) -{ - // Connect signals and slots - profile->setHttpUserAgent(profile->httpUserAgent().replace("QtWebEngine/5.13.0","")); - connect(this, &QWebEnginePage::loadFinished,this, &WebEnginePage::handleLoadFinished); - connect(this, &QWebEnginePage::authenticationRequired, this, &WebEnginePage::handleAuthenticationRequired); - connect(this, &QWebEnginePage::featurePermissionRequested, this, &WebEnginePage::handleFeaturePermissionRequested); - connect(this, &QWebEnginePage::proxyAuthenticationRequired, this, &WebEnginePage::handleProxyAuthenticationRequired); - connect(this, &QWebEnginePage::registerProtocolHandlerRequested, this, &WebEnginePage::handleRegisterProtocolHandlerRequested); + : QWebEnginePage(profile, parent) { + // Connect signals and slots + profile->setHttpUserAgent( + profile->httpUserAgent().replace("QtWebEngine/5.13.0", "")); + connect(this, &QWebEnginePage::loadFinished, this, + &WebEnginePage::handleLoadFinished); + connect(this, &QWebEnginePage::authenticationRequired, this, + &WebEnginePage::handleAuthenticationRequired); + connect(this, &QWebEnginePage::featurePermissionRequested, this, + &WebEnginePage::handleFeaturePermissionRequested); + connect(this, &QWebEnginePage::proxyAuthenticationRequired, this, + &WebEnginePage::handleProxyAuthenticationRequired); + connect(this, &QWebEnginePage::registerProtocolHandlerRequested, this, + &WebEnginePage::handleRegisterProtocolHandlerRequested); #if !defined(QT_NO_SSL) || QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) - connect(this, &QWebEnginePage::selectClientCertificate, this, &WebEnginePage::handleSelectClientCertificate); + connect(this, &QWebEnginePage::selectClientCertificate, this, + &WebEnginePage::handleSelectClientCertificate); #endif } -bool WebEnginePage::acceptNavigationRequest(const QUrl &url, QWebEnginePage::NavigationType type, bool isMainFrame) -{ - qDebug() << "Navigation request: [" + url.toDisplayString() + "] " + type; +bool WebEnginePage::acceptNavigationRequest(const QUrl &url, + QWebEnginePage::NavigationType type, + bool isMainFrame) { + qDebug() << "Navigation request: [" + url.toDisplayString() + "] " + type; - if (QWebEnginePage::NavigationType::NavigationTypeLinkClicked == type) - { - QDesktopServices::openUrl(url); - return false; - } + if (QWebEnginePage::NavigationType::NavigationTypeLinkClicked == type) { + QDesktopServices::openUrl(url); + return false; + } - return QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame); + return QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame); } -QWebEnginePage *WebEnginePage::createWindow(QWebEnginePage::WebWindowType type) -{ - Q_UNUSED(type); - return new WebEnginePage(this->profile()); +QWebEnginePage * +WebEnginePage::createWindow(QWebEnginePage::WebWindowType type) { + Q_UNUSED(type); + return new WebEnginePage(this->profile()); } - -inline QString questionForFeature(QWebEnginePage::Feature feature) -{ - switch (feature) { - case QWebEnginePage::Geolocation: - return WebEnginePage::tr("Allow %1 to access your location information?"); - case QWebEnginePage::MediaAudioCapture: - return WebEnginePage::tr("Allow %1 to access your microphone?"); - case QWebEnginePage::MediaVideoCapture: - return WebEnginePage::tr("Allow %1 to access your webcam?"); - case QWebEnginePage::MediaAudioVideoCapture: - return WebEnginePage::tr("Allow %1 to access your microphone and webcam?"); - case QWebEnginePage::MouseLock: - return WebEnginePage::tr("Allow %1 to lock your mouse cursor?"); - case QWebEnginePage::DesktopVideoCapture: - return WebEnginePage::tr("Allow %1 to capture video of your desktop?"); - case QWebEnginePage::DesktopAudioVideoCapture: - return WebEnginePage::tr("Allow %1 to capture audio and video of your desktop?"); - case QWebEnginePage::Notifications: - return WebEnginePage::tr("Allow %1 to show notification on your desktop?"); - } - return QString(); +inline QString questionForFeature(QWebEnginePage::Feature feature) { + switch (feature) { + case QWebEnginePage::Geolocation: + return WebEnginePage::tr("Allow %1 to access your location information?"); + case QWebEnginePage::MediaAudioCapture: + return WebEnginePage::tr("Allow %1 to access your microphone?"); + case QWebEnginePage::MediaVideoCapture: + return WebEnginePage::tr("Allow %1 to access your webcam?"); + case QWebEnginePage::MediaAudioVideoCapture: + return WebEnginePage::tr("Allow %1 to access your microphone and webcam?"); + case QWebEnginePage::MouseLock: + return WebEnginePage::tr("Allow %1 to lock your mouse cursor?"); + case QWebEnginePage::DesktopVideoCapture: + return WebEnginePage::tr("Allow %1 to capture video of your desktop?"); + case QWebEnginePage::DesktopAudioVideoCapture: + return WebEnginePage::tr( + "Allow %1 to capture audio and video of your desktop?"); + case QWebEnginePage::Notifications: + return WebEnginePage::tr("Allow %1 to show notification on your desktop?"); + } + return QString(); } -void WebEnginePage::handleFeaturePermissionRequested(const QUrl &securityOrigin, Feature feature) -{ - bool autoPlay = true; - if(settings.value("autoPlayMedia").isValid()) - autoPlay = settings.value("autoPlayMedia",false).toBool(); - if( autoPlay && (feature == QWebEnginePage::MediaVideoCapture || feature == QWebEnginePage::MediaAudioVideoCapture)) - { - QWebEngineProfile *defProfile = QWebEngineProfile::defaultProfile(); - auto* webSettings = defProfile->settings(); - webSettings->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture,false); - - profile()->settings()->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture,false); +void WebEnginePage::handleFeaturePermissionRequested(const QUrl &securityOrigin, + Feature feature) { + bool autoPlay = true; + if (settings.value("autoPlayMedia").isValid()) + autoPlay = settings.value("autoPlayMedia", false).toBool(); + if (autoPlay && (feature == QWebEnginePage::MediaVideoCapture || + feature == QWebEnginePage::MediaAudioVideoCapture)) { + QWebEngineProfile *defProfile = QWebEngineProfile::defaultProfile(); + auto *webSettings = defProfile->settings(); + webSettings->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, + false); + + profile()->settings()->setAttribute( + QWebEngineSettings::PlaybackRequiresUserGesture, false); + } + + QString title = tr("Permission Request"); + QString question = questionForFeature(feature).arg(securityOrigin.host()); + + QString featureStr = QVariant::fromValue(feature).toString(); + settings.beginGroup("permissions"); + if (settings.value(featureStr, false).toBool()) { + setFeaturePermission( + securityOrigin, feature, + QWebEnginePage::PermissionPolicy::PermissionGrantedByUser); + } else { + if (!question.isEmpty() && + QMessageBox::question(view()->window(), title, question) == + QMessageBox::Yes) { + setFeaturePermission( + securityOrigin, feature, + QWebEnginePage::PermissionPolicy::PermissionGrantedByUser); + settings.setValue(featureStr, true); + } else { + setFeaturePermission( + securityOrigin, feature, + QWebEnginePage::PermissionPolicy::PermissionDeniedByUser); + settings.setValue(featureStr, false); } + } + settings.endGroup(); +} - QString title = tr("Permission Request"); - QString question = questionForFeature(feature).arg(securityOrigin.host()); - - QString featureStr = QVariant::fromValue(feature).toString(); +void WebEnginePage::handleLoadFinished(bool ok) { + Q_UNUSED(ok); + // turn on Notification settings by default + if (settings.value("permissions/Notifications").isValid() == false) { settings.beginGroup("permissions"); - if(settings.value(featureStr,false).toBool()){ - setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionPolicy::PermissionGrantedByUser); - }else{ - if (!question.isEmpty() && QMessageBox::question(view()->window(), title, question) == QMessageBox::Yes) - { - setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionPolicy::PermissionGrantedByUser); - settings.setValue(featureStr,true); - }else{ - setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionPolicy::PermissionDeniedByUser); - settings.setValue(featureStr,false); - } - } + settings.setValue("Notifications", true); + setFeaturePermission( + QUrl("https://web.whatsapp.com/"), + QWebEnginePage::Feature::Notifications, + QWebEnginePage::PermissionPolicy::PermissionGrantedByUser); settings.endGroup(); + } else if (settings.value("permissions/Notifications", true).toBool()) { + setFeaturePermission( + QUrl("https://web.whatsapp.com/"), + QWebEnginePage::Feature::Notifications, + QWebEnginePage::PermissionPolicy::PermissionGrantedByUser); + } } -void WebEnginePage::handleLoadFinished(bool ok) -{ - Q_UNUSED(ok); - //turn on Notification settings by default - if(settings.value("permissions/Notifications").isValid()==false) - { - settings.beginGroup("permissions"); - settings.setValue("Notifications",true); - setFeaturePermission( - QUrl("https://web.whatsapp.com/"), - QWebEnginePage::Feature::Notifications, - QWebEnginePage::PermissionPolicy::PermissionGrantedByUser - ); - settings.endGroup(); - } else if (settings.value("permissions/Notifications",true).toBool()) { - setFeaturePermission( - QUrl("https://web.whatsapp.com/"), - QWebEnginePage::Feature::Notifications, - QWebEnginePage::PermissionPolicy::PermissionGrantedByUser - ); - } -} - -void WebEnginePage::fullScreenRequestedByPage(QWebEngineFullScreenRequest request) -{ - //qDebug()<<"Fullscreen"; - request.accept(); +void WebEnginePage::fullScreenRequestedByPage( + QWebEngineFullScreenRequest request) { + // qDebug()<<"Fullscreen"; + request.accept(); } -QStringList WebEnginePage::chooseFiles(QWebEnginePage::FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes) -{ - qDebug()<setOption(QFileDialog::DontUseNativeDialog,true); - } - - dialog->setFileMode(dialogMode); - - QStringList mimeFilters; - mimeFilters.append("application/octet-stream"); // to show All files(*) - mimeFilters.append(acceptedMimeTypes); - - if(acceptedMimeTypes.contains("image/*")){ - foreach(QByteArray mime,QImageReader::supportedImageFormats()){ - mimeFilters.append("image/"+mime); - } - } - - mimeFilters.sort(Qt::CaseSensitive); - dialog->setMimeTypeFilters(mimeFilters); - - QStringList selectedFiles; - if(dialog->exec()) { - selectedFiles = dialog->selectedFiles(); - } - return selectedFiles; -} - -bool WebEnginePage::certificateError(const QWebEngineCertificateError &error) -{ - QWidget *mainWindow = view()->window(); - if (error.isOverridable()) { - QDialog dialog(mainWindow); - dialog.setModal(true); - dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); - Ui::CertificateErrorDialog certificateDialog; - certificateDialog.setupUi(&dialog); - certificateDialog.m_iconLabel->setText(QString()); - QIcon icon(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxWarning, nullptr, mainWindow)); - certificateDialog.m_iconLabel->setPixmap(icon.pixmap(32, 32)); - certificateDialog.m_errorLabel->setText(error.errorDescription()); - dialog.setWindowTitle(tr("Certificate Error")); - return dialog.exec() == QDialog::Accepted; +QStringList WebEnginePage::chooseFiles(QWebEnginePage::FileSelectionMode mode, + const QStringList &oldFiles, + const QStringList &acceptedMimeTypes) { + qDebug() << mode << oldFiles << acceptedMimeTypes; + QFileDialog::FileMode dialogMode; + if (mode == QWebEnginePage::FileSelectOpen) { + dialogMode = QFileDialog::ExistingFile; + } else { + dialogMode = QFileDialog::ExistingFiles; + } + + QFileDialog *dialog = new QFileDialog(); + bool usenativeFileDialog = + settings.value("useNativeFileDialog", false).toBool(); + + if (usenativeFileDialog == false) { + dialog->setOption(QFileDialog::DontUseNativeDialog, true); + } + + dialog->setFileMode(dialogMode); + + QStringList mimeFilters; + mimeFilters.append("application/octet-stream"); // to show All files(*) + mimeFilters.append(acceptedMimeTypes); + + if (acceptedMimeTypes.contains("image/*")) { + foreach (QByteArray mime, QImageReader::supportedImageFormats()) { + mimeFilters.append("image/" + mime); } + } - QMessageBox::critical(mainWindow, tr("Certificate Error"), error.errorDescription()); - return false; -} - -void WebEnginePage::handleAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth) -{ - QWidget *mainWindow = view()->window(); - QDialog dialog(mainWindow); - dialog.setModal(true); - dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); - - Ui::PasswordDialog passwordDialog; - passwordDialog.setupUi(&dialog); - - passwordDialog.m_iconLabel->setText(QString()); - QIcon icon(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, nullptr, mainWindow)); - passwordDialog.m_iconLabel->setPixmap(icon.pixmap(32, 32)); + mimeFilters.sort(Qt::CaseSensitive); + dialog->setMimeTypeFilters(mimeFilters); - QString introMessage(tr("Enter username and password for \"%1\" at %2") - .arg(auth->realm()).arg(requestUrl.toString().toHtmlEscaped())); - passwordDialog.m_infoLabel->setText(introMessage); - passwordDialog.m_infoLabel->setWordWrap(true); - - if (dialog.exec() == QDialog::Accepted) { - auth->setUser(passwordDialog.m_userNameLineEdit->text()); - auth->setPassword(passwordDialog.m_passwordLineEdit->text()); - } else { - // Set authenticator null if dialog is cancelled - *auth = QAuthenticator(); - } + QStringList selectedFiles; + if (dialog->exec()) { + selectedFiles = dialog->selectedFiles(); + } + return selectedFiles; } -void WebEnginePage::handleProxyAuthenticationRequired(const QUrl &, QAuthenticator *auth, const QString &proxyHost) -{ - QWidget *mainWindow = view()->window(); +bool WebEnginePage::certificateError(const QWebEngineCertificateError &error) { + QWidget *mainWindow = view()->window(); + if (error.isOverridable()) { QDialog dialog(mainWindow); dialog.setModal(true); - dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); - - Ui::PasswordDialog passwordDialog; - passwordDialog.setupUi(&dialog); - - passwordDialog.m_iconLabel->setText(QString()); - QIcon icon(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, nullptr, mainWindow)); - passwordDialog.m_iconLabel->setPixmap(icon.pixmap(32, 32)); + dialog.setWindowFlags(dialog.windowFlags() & + ~Qt::WindowContextHelpButtonHint); + Ui::CertificateErrorDialog certificateDialog; + certificateDialog.setupUi(&dialog); + certificateDialog.m_iconLabel->setText(QString()); + QIcon icon(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxWarning, + nullptr, mainWindow)); + certificateDialog.m_iconLabel->setPixmap(icon.pixmap(32, 32)); + certificateDialog.m_errorLabel->setText(error.errorDescription()); + dialog.setWindowTitle(tr("Certificate Error")); + return dialog.exec() == QDialog::Accepted; + } + + QMessageBox::critical(mainWindow, tr("Certificate Error"), + error.errorDescription()); + return false; +} - QString introMessage = tr("Connect to proxy \"%1\" using:"); - introMessage = introMessage.arg(proxyHost.toHtmlEscaped()); - passwordDialog.m_infoLabel->setText(introMessage); - passwordDialog.m_infoLabel->setWordWrap(true); +void WebEnginePage::handleAuthenticationRequired(const QUrl &requestUrl, + QAuthenticator *auth) { + QWidget *mainWindow = view()->window(); + QDialog dialog(mainWindow); + dialog.setModal(true); + dialog.setWindowFlags(dialog.windowFlags() & + ~Qt::WindowContextHelpButtonHint); + + Ui::PasswordDialog passwordDialog; + passwordDialog.setupUi(&dialog); + + passwordDialog.m_iconLabel->setText(QString()); + QIcon icon(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, + nullptr, mainWindow)); + passwordDialog.m_iconLabel->setPixmap(icon.pixmap(32, 32)); + + QString introMessage(tr("Enter username and password for \"%1\" at %2") + .arg(auth->realm()) + .arg(requestUrl.toString().toHtmlEscaped())); + passwordDialog.m_infoLabel->setText(introMessage); + passwordDialog.m_infoLabel->setWordWrap(true); + + if (dialog.exec() == QDialog::Accepted) { + auth->setUser(passwordDialog.m_userNameLineEdit->text()); + auth->setPassword(passwordDialog.m_passwordLineEdit->text()); + } else { + // Set authenticator null if dialog is cancelled + *auth = QAuthenticator(); + } +} - if (dialog.exec() == QDialog::Accepted) { - auth->setUser(passwordDialog.m_userNameLineEdit->text()); - auth->setPassword(passwordDialog.m_passwordLineEdit->text()); - } else { - // Set authenticator null if dialog is cancelled - *auth = QAuthenticator(); - } +void WebEnginePage::handleProxyAuthenticationRequired( + const QUrl &, QAuthenticator *auth, const QString &proxyHost) { + QWidget *mainWindow = view()->window(); + QDialog dialog(mainWindow); + dialog.setModal(true); + dialog.setWindowFlags(dialog.windowFlags() & + ~Qt::WindowContextHelpButtonHint); + + Ui::PasswordDialog passwordDialog; + passwordDialog.setupUi(&dialog); + + passwordDialog.m_iconLabel->setText(QString()); + QIcon icon(mainWindow->style()->standardIcon(QStyle::SP_MessageBoxQuestion, + nullptr, mainWindow)); + passwordDialog.m_iconLabel->setPixmap(icon.pixmap(32, 32)); + + QString introMessage = tr("Connect to proxy \"%1\" using:"); + introMessage = introMessage.arg(proxyHost.toHtmlEscaped()); + passwordDialog.m_infoLabel->setText(introMessage); + passwordDialog.m_infoLabel->setWordWrap(true); + + if (dialog.exec() == QDialog::Accepted) { + auth->setUser(passwordDialog.m_userNameLineEdit->text()); + auth->setPassword(passwordDialog.m_passwordLineEdit->text()); + } else { + // Set authenticator null if dialog is cancelled + *auth = QAuthenticator(); + } } //! [registerProtocolHandlerRequested] -void WebEnginePage::handleRegisterProtocolHandlerRequested(QWebEngineRegisterProtocolHandlerRequest request) -{ - auto answer = QMessageBox::question( - view()->window(), - tr("Permission Request"), - tr("Allow %1 to open all %2 links?") - .arg(request.origin().host()) - .arg(request.scheme())); - if (answer == QMessageBox::Yes) - request.accept(); - else - request.reject(); +void WebEnginePage::handleRegisterProtocolHandlerRequested( + QWebEngineRegisterProtocolHandlerRequest request) { + auto answer = + QMessageBox::question(view()->window(), tr("Permission Request"), + tr("Allow %1 to open all %2 links?") + .arg(request.origin().host()) + .arg(request.scheme())); + if (answer == QMessageBox::Yes) + request.accept(); + else + request.reject(); } //! [registerProtocolHandlerRequested] #if !defined(QT_NO_SSL) || QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) -void WebEnginePage::handleSelectClientCertificate(QWebEngineClientCertificateSelection selection) -{ - // Just select one. - selection.select(selection.certificates().at(0)); - - qDebug() << __FUNCTION__; - for(QSslCertificate cert : selection.certificates()) { - qDebug() << cert; - selection.select(cert); // select the first available cert - break; - } - qDebug() << selection.host(); +void WebEnginePage::handleSelectClientCertificate( + QWebEngineClientCertificateSelection selection) { + // Just select one. + selection.select(selection.certificates().at(0)); + + qDebug() << __FUNCTION__; + for (QSslCertificate cert : selection.certificates()) { + qDebug() << cert; + selection.select(cert); // select the first available cert + break; + } + qDebug() << selection.host(); } #endif - - diff --git a/src/webview.cpp b/src/webview.cpp index 5fc00f4..39273eb 100644 --- a/src/webview.cpp +++ b/src/webview.cpp @@ -2,92 +2,94 @@ #include #include -#include #include +#include #include WebView::WebView(QWidget *parent, QStringList dictionaries) - : QWebEngineView(parent) -{ - m_dictionaries = dictionaries; + : QWebEngineView(parent) { + m_dictionaries = dictionaries; - QObject *parentMainWindow = this->parent(); - while (!parentMainWindow -> objectName().contains("MainWindow")){ - parentMainWindow = parentMainWindow -> parent(); - } - MainWindow *mainWindow = dynamic_cast(parentMainWindow); + QObject *parentMainWindow = this->parent(); + while (!parentMainWindow->objectName().contains("MainWindow")) { + parentMainWindow = parentMainWindow->parent(); + } + MainWindow *mainWindow = dynamic_cast(parentMainWindow); - connect(this, &WebView::titleChanged, - mainWindow, &MainWindow::handleWebViewTitleChanged); - connect(this, &WebView::loadFinished, - mainWindow, &MainWindow::handleLoadFinished); - connect(this, &WebView::renderProcessTerminated, - [this](QWebEnginePage::RenderProcessTerminationStatus termStatus, int statusCode) { - QString status; - switch (termStatus) { - case QWebEnginePage::NormalTerminationStatus: - status = tr("Render process normal exit"); - break; - case QWebEnginePage::AbnormalTerminationStatus: - status = tr("Render process abnormal exit"); - break; - case QWebEnginePage::CrashedTerminationStatus: - status = tr("Render process crashed"); - break; - case QWebEnginePage::KilledTerminationStatus: - status = tr("Render process killed"); - break; - } - QMessageBox::StandardButton btn = QMessageBox::question(window(), status, - tr("Render process exited with code: %1\n" "Do you want to reload the page ?").arg(statusCode)); - if (btn == QMessageBox::Yes) - QTimer::singleShot(0, [this] { this->reload(); }); - }); + connect(this, &WebView::titleChanged, mainWindow, + &MainWindow::handleWebViewTitleChanged); + connect(this, &WebView::loadFinished, mainWindow, + &MainWindow::handleLoadFinished); + connect(this, &WebView::renderProcessTerminated, + [this](QWebEnginePage::RenderProcessTerminationStatus termStatus, + int statusCode) { + QString status; + switch (termStatus) { + case QWebEnginePage::NormalTerminationStatus: + status = tr("Render process normal exit"); + break; + case QWebEnginePage::AbnormalTerminationStatus: + status = tr("Render process abnormal exit"); + break; + case QWebEnginePage::CrashedTerminationStatus: + status = tr("Render process crashed"); + break; + case QWebEnginePage::KilledTerminationStatus: + status = tr("Render process killed"); + break; + } + QMessageBox::StandardButton btn = + QMessageBox::question(window(), status, + tr("Render process exited with code: %1\n" + "Do you want to reload the page ?") + .arg(statusCode)); + if (btn == QMessageBox::Yes) + QTimer::singleShot(0, [this] { this->reload(); }); + }); } +void WebView::contextMenuEvent(QContextMenuEvent *event) { + const QWebEngineContextMenuData &data = page()->contextMenuData(); + Q_ASSERT(data.isValid()); -void WebView::contextMenuEvent(QContextMenuEvent *event) -{ - const QWebEngineContextMenuData &data = page()->contextMenuData(); - Q_ASSERT(data.isValid()); - - //allow context menu on image - if (data.mediaType() == QWebEngineContextMenuData::MediaTypeImage) { - QWebEngineView::contextMenuEvent(event); - return; - } - // if content is not editable - if (!data.isContentEditable()) { - event->ignore(); - return; - } + // allow context menu on image + if (data.mediaType() == QWebEngineContextMenuData::MediaTypeImage) { + QWebEngineView::contextMenuEvent(event); + return; + } + // if content is not editable + if (!data.isContentEditable()) { + event->ignore(); + return; + } - QWebEngineProfile *profile = page()->profile(); - const QStringList &languages = profile->spellCheckLanguages(); - QMenu *menu = page()->createStandardContextMenu(); - menu->addSeparator(); + QWebEngineProfile *profile = page()->profile(); + const QStringList &languages = profile->spellCheckLanguages(); + QMenu *menu = page()->createStandardContextMenu(); + menu->addSeparator(); - QAction *spellcheckAction = new QAction(tr("Check Spelling"), nullptr); - spellcheckAction->setCheckable(true); - spellcheckAction->setChecked(profile->isSpellCheckEnabled()); - connect(spellcheckAction, &QAction::toggled, this, [profile,this](bool toogled) { - profile->setSpellCheckEnabled(toogled); - settings.setValue("sc_enabled",toogled); - }); - menu->addAction(spellcheckAction); + QAction *spellcheckAction = new QAction(tr("Check Spelling"), nullptr); + spellcheckAction->setCheckable(true); + spellcheckAction->setChecked(profile->isSpellCheckEnabled()); + connect(spellcheckAction, &QAction::toggled, this, + [profile, this](bool toogled) { + profile->setSpellCheckEnabled(toogled); + settings.setValue("sc_enabled", toogled); + }); + menu->addAction(spellcheckAction); - if (profile->isSpellCheckEnabled()) { - QMenu *subMenu = menu->addMenu(tr("Select Language")); - for (const QString &dict : m_dictionaries) { - QAction *action = subMenu->addAction(dict); - action->setCheckable(true); - action->setChecked(languages.contains(dict)); - connect(action, &QAction::triggered, this, [profile, dict,this](){ - profile->setSpellCheckLanguages(QStringList()<isSpellCheckEnabled()) { + QMenu *subMenu = menu->addMenu(tr("Select Language")); + for (const QString &dict : m_dictionaries) { + QAction *action = subMenu->addAction(dict); + action->setCheckable(true); + action->setChecked(languages.contains(dict)); + connect(action, &QAction::triggered, this, [profile, dict, this]() { + profile->setSpellCheckLanguages(QStringList() << dict); + settings.setValue("sc_dict", dict); + }); } - connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater); - menu->popup(event->globalPos()); + } + connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater); + menu->popup(event->globalPos()); } diff --git a/src/widgets/scrolltext/scrolltext.cpp b/src/widgets/scrolltext/scrolltext.cpp index 00696af..b03b761 100644 --- a/src/widgets/scrolltext/scrolltext.cpp +++ b/src/widgets/scrolltext/scrolltext.cpp @@ -1,179 +1,152 @@ #include "scrolltext.h" -#include #include +#include -ScrollText::ScrollText(QWidget *parent) : - QWidget(parent), scrollPos(0) -{ +ScrollText::ScrollText(QWidget *parent) : QWidget(parent), scrollPos(0) { - staticText.setTextFormat(Qt::PlainText); + staticText.setTextFormat(Qt::PlainText); - setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding); + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - setMinimumHeight(fontMetrics().height()+10); - setMaximumHeight(this->minimumHeight()+6); + setMinimumHeight(fontMetrics().height() + 10); + setMaximumHeight(this->minimumHeight() + 6); - leftMargin = 0; //height() / 3; + leftMargin = 0; // height() / 3; - setSeparator(" "); + setSeparator(" "); - connect(&timer, SIGNAL(timeout()), this, SLOT(timer_timeout())); - timer.setInterval(50); + connect(&timer, SIGNAL(timeout()), this, SLOT(timer_timeout())); + timer.setInterval(50); } -QString ScrollText::text() const -{ - return _text; -} +QString ScrollText::text() const { return _text; } -void ScrollText::setText(QString text) -{ - _text = text; - updateText(); - update(); +void ScrollText::setText(QString text) { + _text = text; + updateText(); + update(); } -QString ScrollText::separator() const -{ - return _separator; -} - -void ScrollText::setSeparator(QString separator) -{ - _separator = separator; - updateText(); - update(); -} +QString ScrollText::separator() const { return _separator; } -void ScrollText::setLeftMargin(int pixels) -{ - leftMargin = pixels; - update(); +void ScrollText::setSeparator(QString separator) { + _separator = separator; + updateText(); + update(); } -void ScrollText::pause() -{ - if(scrollEnabled){ - timer.stop(); - } +void ScrollText::setLeftMargin(int pixels) { + leftMargin = pixels; + update(); } -void ScrollText::resume() -{ - if(scrollEnabled){ - timer.start(); - scrolledOnce = false; - } +void ScrollText::pause() { + if (scrollEnabled) { + timer.stop(); + } } -void ScrollText::updateText() -{ +void ScrollText::resume() { + if (scrollEnabled) { + timer.start(); scrolledOnce = false; - timer.stop(); - - singleTextWidth = fontMetrics().horizontalAdvance(_text); -// scrollEnabled = true; - scrollEnabled = (singleTextWidth > width() - leftMargin); - - if(scrollEnabled) - { - scrollPos = -64; - staticText.setText(_text + _separator); - timer.start(); - } - else{ - staticText.setText(_text); - } - staticText.prepare(QTransform(), font()); - //wholeTextSize = QSize(fontMetrics().width(staticText.text()), fontMetrics().height()); - wholeTextSize = QSize(fontMetrics().horizontalAdvance(staticText.text()), fontMetrics().height()); - + } } -void ScrollText::paintEvent(QPaintEvent*) -{ - QPainter p(this); - - if(scrollEnabled) - { - buffer.fill(qRgba(0, 0, 0, 0)); - QPainter pb(&buffer); - pb.setPen(p.pen()); - pb.setFont(p.font()); - - int x = qMin(-scrollPos, 0) + leftMargin; - while(x < width()) - { - pb.drawStaticText(QPointF(x, (height() - wholeTextSize.height()) / 2) + QPoint(2, 2), staticText); - x += wholeTextSize.width(); - } - - //Apply Alpha Channel - pb.setCompositionMode(QPainter::CompositionMode_DestinationIn); - pb.setClipRect(width() - 15, 0, 15, height()); - pb.drawImage(0, 0, alphaChannel); - pb.setClipRect(0, 0, 15, height()); - //initial situation: don't apply alpha channel in the left half of the image at all; apply it more and more until scrollPos gets positive - if(scrollPos < 0) - pb.setOpacity((qreal)(qMax(-8, scrollPos) + 8) / 8.0); - pb.drawImage(0, 0, alphaChannel); - p.drawImage(0, 0, buffer); - } - else - { - p.drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, text()); -// p.drawStaticText(QPointF(leftMargin, (height() - wholeTextSize.height()) / 2), staticText); - } +void ScrollText::updateText() { + scrolledOnce = false; + timer.stop(); + + singleTextWidth = fontMetrics().horizontalAdvance(_text); + // scrollEnabled = true; + scrollEnabled = (singleTextWidth > width() - leftMargin); + + if (scrollEnabled) { + scrollPos = -64; + staticText.setText(_text + _separator); + timer.start(); + } else { + staticText.setText(_text); + } + staticText.prepare(QTransform(), font()); + // wholeTextSize = QSize(fontMetrics().width(staticText.text()), + // fontMetrics().height()); + wholeTextSize = QSize(fontMetrics().horizontalAdvance(staticText.text()), + fontMetrics().height()); } -void ScrollText::resizeEvent(QResizeEvent*) -{ - //When the widget is resized, we need to update the alpha channel. - - alphaChannel = QImage(size(), QImage::Format_ARGB32_Premultiplied); - buffer = QImage(size(), QImage::Format_ARGB32_Premultiplied); - - //Create Alpha Channel: - if(width() > 64) - { - //create first scanline - QRgb* scanline1 = (QRgb*)alphaChannel.scanLine(0); - for(int x = 1; x < 16; ++x) - scanline1[x - 1] = scanline1[width() - x] = qRgba(0, 0, 0, x << 4); - for(int x = 15; x < width() - 15; ++x) - scanline1[x] = qRgb(0, 0, 0); - //copy scanline to the other ones - for(int y = 1; y < height(); ++y) - memcpy(alphaChannel.scanLine(y), (uchar*)scanline1, width() * 4); +void ScrollText::paintEvent(QPaintEvent *) { + QPainter p(this); + + if (scrollEnabled) { + buffer.fill(qRgba(0, 0, 0, 0)); + QPainter pb(&buffer); + pb.setPen(p.pen()); + pb.setFont(p.font()); + + int x = qMin(-scrollPos, 0) + leftMargin; + while (x < width()) { + pb.drawStaticText(QPointF(x, (height() - wholeTextSize.height()) / 2) + + QPoint(2, 2), + staticText); + x += wholeTextSize.width(); } - else - alphaChannel.fill(qRgb(0, 0, 0)); - - //Update scrolling state - bool newScrollEnabled = (singleTextWidth > width() - leftMargin); - if(newScrollEnabled != scrollEnabled) - updateText(); + // Apply Alpha Channel + pb.setCompositionMode(QPainter::CompositionMode_DestinationIn); + pb.setClipRect(width() - 15, 0, 15, height()); + pb.drawImage(0, 0, alphaChannel); + pb.setClipRect(0, 0, 15, height()); + // initial situation: don't apply alpha channel in the left half of the + // image at all; apply it more and more until scrollPos gets positive + if (scrollPos < 0) + pb.setOpacity((qreal)(qMax(-8, scrollPos) + 8) / 8.0); + pb.drawImage(0, 0, alphaChannel); + p.drawImage(0, 0, buffer); + } else { + p.drawText(QRectF(0, 0, width(), height()), Qt::AlignCenter, text()); + // p.drawStaticText(QPointF(leftMargin, (height() - + // wholeTextSize.height()) / 2), staticText); + } } -void ScrollText::timer_timeout() -{ - scrollPos = (scrollPos + 2) - % wholeTextSize.width(); - pauseAfterOneRotation(scrollPos); - update(); +void ScrollText::resizeEvent(QResizeEvent *) { + // When the widget is resized, we need to update the alpha channel. + + alphaChannel = QImage(size(), QImage::Format_ARGB32_Premultiplied); + buffer = QImage(size(), QImage::Format_ARGB32_Premultiplied); + + // Create Alpha Channel: + if (width() > 64) { + // create first scanline + QRgb *scanline1 = (QRgb *)alphaChannel.scanLine(0); + for (int x = 1; x < 16; ++x) + scanline1[x - 1] = scanline1[width() - x] = qRgba(0, 0, 0, x << 4); + for (int x = 15; x < width() - 15; ++x) + scanline1[x] = qRgb(0, 0, 0); + // copy scanline to the other ones + for (int y = 1; y < height(); ++y) + memcpy(alphaChannel.scanLine(y), (uchar *)scanline1, width() * 4); + } else + alphaChannel.fill(qRgb(0, 0, 0)); + + // Update scrolling state + bool newScrollEnabled = (singleTextWidth > width() - leftMargin); + if (newScrollEnabled != scrollEnabled) + updateText(); } -void ScrollText::pauseAfterOneRotation(int scrollPos) -{ - if(scrolledOnce == false && scrollPos+2==wholeTextSize.width()){ - scrolledOnce = true; - } - if(scrolledOnce){ - pause(); - } +void ScrollText::timer_timeout() { + scrollPos = (scrollPos + 2) % wholeTextSize.width(); + pauseAfterOneRotation(scrollPos); + update(); } - - - +void ScrollText::pauseAfterOneRotation(int scrollPos) { + if (scrolledOnce == false && scrollPos + 2 == wholeTextSize.width()) { + scrolledOnce = true; + } + if (scrolledOnce) { + pause(); + } +} -- cgit v1.2.3 From 51ac5fdaabfb45efd94e31b9fdadd489117a8baa Mon Sep 17 00:00:00 2001 From: Keshav Date: Mon, 14 Mar 2022 01:35:56 +0530 Subject: release webengine properly on exit --- src/mainwindow.cpp | 134 +++++++++++++++++++++++------------------------------ src/mainwindow.h | 13 ++---- 2 files changed, 60 insertions(+), 87 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 216ccd6..a0da733 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1,11 +1,11 @@ #include "mainwindow.h" #include +#include #include #include #include #include -#include extern QString defaultUserAgentStr; @@ -73,6 +73,11 @@ MainWindow::MainWindow(QWidget *parent) }); } +MainWindow::~MainWindow() +{ + webEngine->deleteLater(); +} + void MainWindow::loadAppWithArgument(const QString &arg) { // https://faq.whatsapp.com/iphone/how-to-link-to-whatsapp-from-a-different-app/?lang=en @@ -166,7 +171,9 @@ void MainWindow::updateWindowTheme() { QList widgets = this->findChildren(); - foreach (QWidget *w, widgets) { w->setPalette(qApp->palette()); } + foreach (QWidget *w, widgets) { + w->setPalette(qApp->palette()); + } setNotificationPresenter(webEngine->page()->profile()); @@ -198,7 +205,7 @@ void MainWindow::init_settingWidget() { connect(settingsWidget, SIGNAL(updatePageTheme()), this, SLOT(updatePageTheme())); - connect(settingsWidget, &SettingsWidget::muteToggled,settingsWidget, + connect(settingsWidget, &SettingsWidget::muteToggled, settingsWidget, [=](const bool checked) { this->toggleMute(checked); }); connect(settingsWidget, &SettingsWidget::userAgentChanged, settingsWidget, [=](QString userAgentStr) { @@ -209,8 +216,8 @@ void MainWindow::init_settingWidget() { this->askToReloadPage(); } }); - connect(settingsWidget, &SettingsWidget::autoPlayMediaToggled,settingsWidget, - [=](bool checked) { + connect(settingsWidget, &SettingsWidget::autoPlayMediaToggled, + settingsWidget, [=](bool checked) { QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); auto *webSettings = profile->settings(); webSettings->setAttribute( @@ -228,24 +235,25 @@ void MainWindow::init_settingWidget() { } }); - connect(settingsWidget, &SettingsWidget::spellCheckChanged,settingsWidget, + connect(settingsWidget, &SettingsWidget::spellCheckChanged, settingsWidget, [=](bool checked) { if (webEngine && webEngine->page()) { webEngine->page()->profile()->setSpellCheckEnabled(checked); } }); - connect(settingsWidget, &SettingsWidget::zoomChanged,settingsWidget, [=]() { - double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); - webEngine->page()->setZoomFactor(currentFactor); - }); + connect( + settingsWidget, &SettingsWidget::zoomChanged, settingsWidget, [=]() { + double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); + webEngine->page()->setZoomFactor(currentFactor); + }); - connect(settingsWidget, &SettingsWidget::notificationPopupTimeOutChanged,settingsWidget, - [=]() { + connect(settingsWidget, &SettingsWidget::notificationPopupTimeOutChanged, + settingsWidget, [=]() { setNotificationPresenter(this->webEngine->page()->profile()); }); - connect(settingsWidget, &SettingsWidget::notify,settingsWidget, + connect(settingsWidget, &SettingsWidget::notify, settingsWidget, [=](QString message) { notify("", message); }); settingsWidget->appLockSetChecked( @@ -276,7 +284,8 @@ void MainWindow::lockApp() { msgBox.setStandardButtons(QMessageBox::Cancel); QPushButton *setAppLock = new QPushButton("Yes", nullptr); msgBox.addButton(setAppLock, QMessageBox::NoRole); - connect(setAppLock, &QPushButton::clicked,setAppLock, [=]() { init_lock(); }); + connect(setAppLock, &QPushButton::clicked, setAppLock, + [=]() { init_lock(); }); msgBox.exec(); } } @@ -329,7 +338,7 @@ void MainWindow::closeEvent(QCloseEvent *event) { settings.setValue("geometry", saveGeometry()); settings.setValue("windowState", saveState()); getPageTheme(); - QTimer::singleShot(500,settingsWidget, [=]() { settingsWidget->refresh(); }); + QTimer::singleShot(500, settingsWidget, [=]() { settingsWidget->refresh(); }); if (QSystemTrayIcon::isSystemTrayAvailable() && settings.value("closeButtonActionCombo", 0).toInt() == 0) { @@ -362,7 +371,7 @@ void MainWindow::notify(QString title, QString message) { trayIcon->showMessage(title, message, QIcon(":/icons/app/icon-64.png"), settings.value("notificationTimeOut", 9000).toInt()); trayIcon->disconnect(trayIcon, SIGNAL(messageClicked())); - connect(trayIcon, &QSystemTrayIcon::messageClicked,trayIcon, [=]() { + connect(trayIcon, &QSystemTrayIcon::messageClicked, trayIcon, [=]() { if (windowState() == Qt::WindowMinimized || windowState() != Qt::WindowActive) { activateWindow(); @@ -372,7 +381,7 @@ void MainWindow::notify(QString title, QString message) { }); } else { auto popup = new NotificationPopup(webEngine); - connect(popup, &NotificationPopup::notification_clicked, popup,[=]() { + connect(popup, &NotificationPopup::notification_clicked, popup, [=]() { if (windowState() == Qt::WindowMinimized || windowState() != Qt::WindowActive) { activateWindow(); @@ -396,7 +405,7 @@ void MainWindow::createActions() { fullscreenAction = new QAction(tr("Fullscreen"), this); fullscreenAction->setShortcut(Qt::Key_F11); - connect(fullscreenAction, &QAction::triggered,fullscreenAction, + connect(fullscreenAction, &QAction::triggered, fullscreenAction, [=]() { setWindowState(windowState() ^ Qt::WindowFullScreen); }); this->addAction(fullscreenAction); @@ -436,7 +445,7 @@ void MainWindow::createActions() { void MainWindow::quitApp() { getPageTheme(); - QTimer::singleShot(500, &settings,[=]() { + QTimer::singleShot(500, &settings, [=]() { qWarning() << "THEME" << settings.value("windowTheme").toString(); settings.setValue("firstrun_tray", true); qApp->quit(); @@ -489,7 +498,7 @@ void MainWindow::init_lock() { lockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); lockWidget->setGeometry(this->rect()); - connect(lockWidget, &Lock::passwordNotSet,settingsWidget, [=]() { + connect(lockWidget, &Lock::passwordNotSet, settingsWidget, [=]() { settings.setValue("lockscreen", false); settingsWidget->appLockSetChecked(false); }); @@ -498,7 +507,7 @@ void MainWindow::init_lock() { // unlock event }); - connect(lockWidget, &Lock::passwordSet,settingsWidget, [=]() { + connect(lockWidget, &Lock::passwordSet, settingsWidget, [=]() { // enable disable lock screen if (settings.value("asdfg").isValid()) { settingsWidget->setCurrentPasswordText( @@ -596,11 +605,6 @@ void MainWindow::createWebEngine() { webEngine->addAction(quitAction); createWebPage(false); - - // QWebEngineCookieStore *browser_cookie_store = - // this->webEngine->page()->profile()->cookieStore(); connect( - // browser_cookie_store, &QWebEngineCookieStore::cookieAdded, this, - // &MainWindow::handleCookieAdded ); } void MainWindow::createWebPage(bool offTheRecord) { @@ -656,7 +660,7 @@ void MainWindow::setNotificationPresenter(QWebEngineProfile *profile) { auto popup = new NotificationPopup(webEngine); popup->setObjectName("engineNotifier"); - connect(popup, &NotificationPopup::notification_clicked,popup,[=]() { + connect(popup, &NotificationPopup::notification_clicked, popup, [=]() { if (windowState() == Qt::WindowMinimized || windowState() != Qt::WindowActive) { activateWindow(); @@ -678,7 +682,7 @@ void MainWindow::setNotificationPresenter(QWebEngineProfile *profile) { notification->title(), notification->message(), icon, settings.value("notificationTimeOut", 9000).toInt()); trayIcon->disconnect(trayIcon, SIGNAL(messageClicked())); - connect(trayIcon, &QSystemTrayIcon::messageClicked,trayIcon, [=]() { + connect(trayIcon, &QSystemTrayIcon::messageClicked, trayIcon, [=]() { if (windowState() == Qt::WindowMinimized || windowState() != Qt::WindowActive) { activateWindow(); @@ -707,7 +711,7 @@ void MainWindow::fullScreenRequested(QWebEngineFullScreenRequest request) { } void MainWindow::handleWebViewTitleChanged(QString title) { - setWindowTitle( QApplication::applicationName() +": "+ title); + setWindowTitle(QApplication::applicationName() + ": " + title); if (notificationsTitleRegExp.exactMatch(title)) { if (notificationsTitleRegExp.isEmpty() == false) { @@ -743,54 +747,30 @@ void MainWindow::checkLoadedCorrectly() { if (webEngine && webEngine->page()) { // test 1 based on the class name of body of the page webEngine->page()->runJavaScript( - "document.querySelector('body').className", - [this](const QVariant &result) { - if (result.toString().contains("page-version", Qt::CaseInsensitive)) { - qWarning() << "Test 1 found" << result.toString(); - webEngine->page()->runJavaScript( - "document.getElementsByTagName('body')[0].innerText = ''"); - loadingQuirk("test1"); - } else if (webEngine->title().contains("Error", - Qt::CaseInsensitive)) { - utils::delete_cache(webEngine->page()->profile()->cachePath()); - utils::delete_cache( - webEngine->page()->profile()->persistentStoragePath()); - settings.setValue("useragent", defaultUserAgentStr); - utils *util = new utils(this); - util->DisplayExceptionErrorDialog( - "test1 handleWebViewTitleChanged(title) title: Error, " - "Resetting UA, Quiting!\nUA: " + - settings.value("useragent", "DefaultUA").toString()); - - quitAction->trigger(); - } else { - qWarning() << "Test 1 Loaded correctly value:" << result.toString(); - } - }); - - // //test #2 based on the content of landing-title class of page - // webEngine->page()->runJavaScript( - // "document.getElementsByClassName('landing-title')[0].innerText", - // [this](const QVariant &result){ - // qWarning()<<"Test #1 Loaded correctly - // value:"<title().contains("Error",Qt::CaseInsensitive)){ - // utils::delete_cache(webEngine->page()->profile()->cachePath()); - // utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); - // settings.setValue("useragent",defaultUserAgentStr); - // utils * util = new utils(this); - // util->DisplayExceptionErrorDialog("handleWebViewTitleChanged(title) - // title: Error, Resetting UA, Quiting!\nUA: - // "+settings.value("useragent","DefaultUA").toString()); - - // quitAction->trigger(); - // } - // } - // ); + "document.querySelector('body').className", + [this](const QVariant &result) { + if (result.toString().contains("page-version", Qt::CaseInsensitive)) { + qWarning() << "Test 1 found" << result.toString(); + webEngine->page()->runJavaScript( + "document.getElementsByTagName('body')[0].innerText = ''"); + loadingQuirk("test1"); + } else if (webEngine->title().contains("Error", + Qt::CaseInsensitive)) { + utils::delete_cache(webEngine->page()->profile()->cachePath()); + utils::delete_cache( + webEngine->page()->profile()->persistentStoragePath()); + settings.setValue("useragent", defaultUserAgentStr); + utils *util = new utils(this); + util->DisplayExceptionErrorDialog( + "test1 handleWebViewTitleChanged(title) title: Error, " + "Resetting UA, Quiting!\nUA: " + + settings.value("useragent", "DefaultUA").toString()); + + quitAction->trigger(); + } else { + qWarning() << "Test 1 Loaded correctly value:" << result.toString(); + } + }); } } diff --git a/src/mainwindow.h b/src/mainwindow.h index dbc59e7..7676cb0 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -10,21 +10,20 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include #include #include -#include -#include - #include "lock.h" #include "notificationpopup.h" #include "requestinterceptor.h" @@ -41,6 +40,7 @@ class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow(); public slots: void updateWindowTheme(); void updatePageTheme(); @@ -61,7 +61,6 @@ private: void createWebEngine(); QSettings settings; - QRegExp notificationsTitleRegExp; QIcon trayIconRead; QIcon trayIconUnread; @@ -78,18 +77,12 @@ private: QMenu *trayIconMenu; QSystemTrayIcon *trayIcon; - QWebEngineView *webEngine; - SettingsWidget *settingsWidget = nullptr; - DownloadManagerWidget m_downloadManagerWidget; QScopedPointer m_otrProfile; - Lock *lockWidget = nullptr; - int correctlyLoaderRetries = 4; - QStringList m_dictionaries; private slots: -- cgit v1.2.3 From c5bf7a98f5f85eb3af53630b424c6a5d42868621 Mon Sep 17 00:00:00 2001 From: Keshav Date: Sun, 20 Mar 2022 13:40:33 +0530 Subject: feat: start application minimized. closes #19 - there is a setting to enable this feature --- src/main.cpp | 10 +- src/mainwindow.cpp | 60 +-- src/mainwindow.h | 2 +- src/settingswidget.cpp | 52 +- src/settingswidget.h | 6 + src/settingswidget.ui | 1319 ++++++++++++++++++++++++------------------------ 6 files changed, 750 insertions(+), 699 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/main.cpp b/src/main.cpp index 6aaa42a..68fbe3a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -68,14 +68,18 @@ int main(int argc, char *argv[]) { MainWindow window; QStringList argsList = app.arguments(); - qWarning() << "Launching with argument" << argsList; foreach (QString argStr, argsList) { if (argStr.contains("whatsapp://")) { - qWarning() << "Link passed as argument" << argStr; window.loadAppWithArgument(argStr); } } - window.show(); + QSettings settings; + if (QSystemTrayIcon::isSystemTrayAvailable() && + settings.value("startMinimized", false).toBool()) { + window.runMinimized(); + }else{ + window.show(); + } return app.exec(); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a0da733..f8b29d1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -73,10 +73,9 @@ MainWindow::MainWindow(QWidget *parent) }); } -MainWindow::~MainWindow() -{ - webEngine->deleteLater(); -} +void MainWindow::runMinimized() { this->minimizeAction->trigger(); } + +MainWindow::~MainWindow() { webEngine->deleteLater(); } void MainWindow::loadAppWithArgument(const QString &arg) { // https://faq.whatsapp.com/iphone/how-to-link-to-whatsapp-from-a-different-app/?lang=en @@ -261,9 +260,6 @@ void MainWindow::init_settingWidget() { // spell checker settingsWidget->loadDictionaries(m_dictionaries); - - settingsWidget->resize(settingsWidget->sizeHint().width(), - settingsWidget->minimumSizeHint().height()); } } @@ -307,7 +303,7 @@ void MainWindow::showSettings() { if (!settingsWidget->isVisible()) { this->updateSettingsUserAgentWidget(); settingsWidget->refresh(); - settingsWidget->showNormal(); + settingsWidget->show(); } } @@ -747,30 +743,30 @@ void MainWindow::checkLoadedCorrectly() { if (webEngine && webEngine->page()) { // test 1 based on the class name of body of the page webEngine->page()->runJavaScript( - "document.querySelector('body').className", - [this](const QVariant &result) { - if (result.toString().contains("page-version", Qt::CaseInsensitive)) { - qWarning() << "Test 1 found" << result.toString(); - webEngine->page()->runJavaScript( - "document.getElementsByTagName('body')[0].innerText = ''"); - loadingQuirk("test1"); - } else if (webEngine->title().contains("Error", - Qt::CaseInsensitive)) { - utils::delete_cache(webEngine->page()->profile()->cachePath()); - utils::delete_cache( - webEngine->page()->profile()->persistentStoragePath()); - settings.setValue("useragent", defaultUserAgentStr); - utils *util = new utils(this); - util->DisplayExceptionErrorDialog( - "test1 handleWebViewTitleChanged(title) title: Error, " - "Resetting UA, Quiting!\nUA: " + - settings.value("useragent", "DefaultUA").toString()); - - quitAction->trigger(); - } else { - qWarning() << "Test 1 Loaded correctly value:" << result.toString(); - } - }); + "document.querySelector('body').className", + [this](const QVariant &result) { + if (result.toString().contains("page-version", Qt::CaseInsensitive)) { + qWarning() << "Test 1 found" << result.toString(); + webEngine->page()->runJavaScript( + "document.getElementsByTagName('body')[0].innerText = ''"); + loadingQuirk("test1"); + } else if (webEngine->title().contains("Error", + Qt::CaseInsensitive)) { + utils::delete_cache(webEngine->page()->profile()->cachePath()); + utils::delete_cache( + webEngine->page()->profile()->persistentStoragePath()); + settings.setValue("useragent", defaultUserAgentStr); + utils *util = new utils(this); + util->DisplayExceptionErrorDialog( + "test1 handleWebViewTitleChanged(title) title: Error, " + "Resetting UA, Quiting!\nUA: " + + settings.value("useragent", "DefaultUA").toString()); + + quitAction->trigger(); + } else { + qWarning() << "Test 1 Loaded correctly value:" << result.toString(); + } + }); } } diff --git a/src/mainwindow.h b/src/mainwindow.h index 7676cb0..5ffe9b1 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -49,7 +49,7 @@ public slots: void handleLoadFinished(bool loaded); void handleDownloadRequested(QWebEngineDownloadItem *download); void loadAppWithArgument(const QString &arg); - + void runMinimized(); protected slots: void closeEvent(QCloseEvent *event) override; void resizeEvent(QResizeEvent *event) override; diff --git a/src/settingswidget.cpp b/src/settingswidget.cpp index ba42372..b07340c 100644 --- a/src/settingswidget.cpp +++ b/src/settingswidget.cpp @@ -19,7 +19,6 @@ SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, ui->zoomFactorSpinBox->setRange(0.25, 5.0); ui->zoomFactorSpinBox->setValue(settings.value("zoomFactor", 1.0).toDouble()); - // emit zoomChanged(); ui->closeButtonActionComboBox->setCurrentIndex( settings.value("closeButtonActionCombo", 0).toInt()); @@ -40,6 +39,8 @@ SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, settings.value("notificationCombo", 1).toInt()); ui->useNativeFileDialog->setChecked( settings.value("useNativeFileDialog", false).toBool()); + ui->startMinimized->setChecked( + settings.value("startMinimized", false).toBool()); ui->automaticThemeCheckBox->blockSignals(true); bool automaticThemeSwitching = @@ -66,6 +67,51 @@ SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, applyThemeQuirks(); ui->setUserAgent->setEnabled(false); + + // event filter to prevent wheel event on certain widgets + foreach (QSlider *slider, this->findChildren()) { + slider->installEventFilter(this); + } + foreach (QComboBox *box, this->findChildren()) { + box->installEventFilter(this); + } + foreach (QSpinBox *spinBox, this->findChildren()) { + spinBox->installEventFilter(this); + } + + ui->scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + this->setMinimumHeight(580); + + ui->scrollArea->setMinimumWidth( + ui->groupBox_8->sizeHint().width() + ui->scrollArea->sizeHint().width() + + ui->scrollAreaWidgetContents->layout()->spacing()); + if (settings.value("settingsGeo").isValid()) { + this->restoreGeometry(settings.value("settingsGeo").toByteArray()); + } +} + +bool SettingsWidget::eventFilter(QObject *obj, QEvent *event) { + + if (isChildOf(this, obj)) { + if (event->type() == QEvent::Wheel) { + return true; + } + } + return QWidget::eventFilter(obj, event); +} + +void SettingsWidget::closeEvent(QCloseEvent *event) { + settings.setValue("settingsGeo", this->saveGeometry()); + QWidget::closeEvent(event); +} + +bool SettingsWidget::isChildOf(QObject *Of, QObject *self) { + bool ischild = false; + if (Of->findChild(self->objectName())) { + ischild = true; + } + return ischild; } inline bool inRange(unsigned low, unsigned high, unsigned x) { @@ -441,3 +487,7 @@ void SettingsWidget::on_zoomReset_clicked() { settings.setValue("zoomFactor", ui->zoomFactorSpinBox->value()); emit zoomChanged(); } + +void SettingsWidget::on_startMinimized_toggled(bool checked) { + settings.setValue("startMinimized", checked); +} diff --git a/src/settingswidget.h b/src/settingswidget.h index 6f0fa4a..d7353ec 100644 --- a/src/settingswidget.h +++ b/src/settingswidget.h @@ -41,6 +41,9 @@ public slots: void appLockSetChecked(bool checked); void setCurrentPasswordText(QString str); void loadDictionaries(QStringList dictionaries); +protected slots: + bool eventFilter(QObject *obj, QEvent *event); + void closeEvent(QCloseEvent *event); private slots: QString cachePath(); QString persistentStoragePath(); @@ -94,6 +97,9 @@ private slots: void on_zoomReset_clicked(); + bool isChildOf(QObject *Of, QObject *self); + void on_startMinimized_toggled(bool checked); + private: Ui::SettingsWidget *ui; QString engineCachePath,enginePersistentStoragePath; diff --git a/src/settingswidget.ui b/src/settingswidget.ui index 55f55a1..09e5639 100644 --- a/src/settingswidget.ui +++ b/src/settingswidget.ui @@ -6,8 +6,8 @@ 0 0 - 512 - 644 + 537 + 580 @@ -88,698 +88,693 @@ background:transparent;
- - - - - 9 - - - 9 - - - 9 - - - 9 + + + + true + + + + + 0 + 0 + 521 + 592 + - - - - General settings - - - - - - - - Close button action - - - - - - - - Minimize to tray + + + + + General settings + + + + + + + + Close button action + + + + + + + + Minimize to tray + + + + :/icons/window-2-line.png:/icons/window-2-line.png + + + + + Quit Application + + + + :/icons/shut-down-line.png:/icons/shut-down-line.png + + + + + + + + + + 0 + + + + + <html><head/><body><p>Enable application lock screen.</p></body></html> + + + Enable App Lock on Start + + + + + + + Current Password: + + + + + + + + + + + + 1 + 0 + + + + + 1 + 16777215 + + + + background-color: rgba(63, 129, 216, 48); + + + Qt::Vertical + + + + + + + Disable Notifications PopUp + + + + + + + Disable Auto Playback of Media + + + + + + + Mute Audio from Page + + + + + + + + + PopUp timeout + + + + + + + Secs + + + 2 + + + 20 + + + + + + + + + + + + 0 + 1 + + + + + 16777215 + 1 + + + + background-color: rgba(63, 129, 216, 48); + + + QFrame::Raised + + + Qt::Horizontal + + + + + + + + + Start minimized + + + + + + + Use Native File Dialog + + + + + + + + + + + Enable Spell Checker + + + + + + + + 1 + 0 + + + + + 1 + 16777215 + + + + background-color: rgba(63, 129, 216, 48); + + + QFrame::Raised + + + Qt::Vertical + + + + + + + SpellChecker Language + + + + + + + + + + + + 0 + + + + + App permissions + + + + + + + Show permissions + + + + :/icons/categories/security.png:/icons/categories/security.png + + + + + + + + + + + Global App shortcuts + + + + + + + Show shortcuts + + + + :/icons/share-forward-line.png:/icons/share-forward-line.png + + + + + + + + + + + Notification type + + + + + + + + Native notification + + + + :/icons/categories/featured.png:/icons/categories/featured.png + + + + + Customized notification + + + + :/icons/categories/devices-and-iot.png:/icons/categories/devices-and-iot.png + + + + + + + + + 0 + 0 + + + + Try + + + + :/icons/categories/science.png:/icons/categories/science.png + + + + + + + + + + 0 + 1 + + + + + 16777215 + 1 + + + + background-color: rgba(63, 129, 216, 48); + + + QFrame::Raised + + + Qt::Horizontal + + + + + + + + + User Agent + + + + + + + + + + Set - :/icons/window-2-line.png:/icons/window-2-line.png + :/icons/categories/utilities.png:/icons/categories/utilities.png - - + + + + - Quit Application + Default - :/icons/shut-down-line.png:/icons/shut-down-line.png - - - - - - - - - - 0 - - - - - <html><head/><body><p>Enable application lock screen.</p></body></html> - - - Enable App Lock on Start - - - - - - - Current Password: - - - - - - - - - - - - 1 - 0 - - - - - 1 - 16777215 - - - - background-color: rgba(63, 129, 216, 48); - - - Qt::Vertical - - - - - - - Disable Notifications PopUp - - - - - - - Disable Auto Playback of Media - - - - - - - Mute Audio from Page - - - - - - - + :/icons/refresh-line.png:/icons/refresh-line.png + + + + + + + + + + + Theme + + + + + + + + 0 + 0 + + + + <html><head/><body><p>Based on your system timezone and location.</p></body></html> + + + Automatic + + + + + + - PopUp timeout + Dark - - - - - - Secs + + + :/icons/moon-line.png:/icons/moon-line.png - - 2 + + + + Light - - 20 + + + :/icons/lightbulb-line.png:/icons/lightbulb-line.png - - - - - - - - - - - 0 - 1 - - - - - 16777215 - 1 - - - - background-color: rgba(63, 129, 216, 48); - - - QFrame::Raised - - - Qt::Horizontal - - - - - - - - - Use Native File Dialog - - - - - - - - - - - Enable Spell Checker - - - - - - - - 1 - 0 - - - - - 1 - 16777215 - - - - background-color: rgba(63, 129, 216, 48); - - - QFrame::Raised - - - Qt::Vertical - - - - - - - SpellChecker Language - - - - - - - - - - - - 0 - - - - - App permissions - - - - - - - Show permissions - - - - :/icons/categories/security.png:/icons/categories/security.png - - - - - - - - - - - Global App shortcuts - - - - - - - Show shortcuts - - - - :/icons/share-forward-line.png:/icons/share-forward-line.png - - - - - - - - - - - Notification type - - - - - - - - Native notification + + + + + + + + + 0 + + + + + Zoom factor + + + + + + + + 0 + 0 + + + + Zoom Out + + + - :/icons/categories/featured.png:/icons/categories/featured.png + :/icons/minus.png:/icons/minus.png + + + + + + + + 0 + 0 + + + + Qt::AlignCenter + + + true + + + QAbstractSpinBox::NoButtons + + + + + + + + 0 + 0 + + + + Zoom In - - - Customized notification + - :/icons/categories/devices-and-iot.png:/icons/categories/devices-and-iot.png - - - - - - - - - 0 - 0 - - - - Try - - - - :/icons/categories/science.png:/icons/categories/science.png - - - - - - - - - - 0 - 1 - - - - - 16777215 - 1 - - - - background-color: rgba(63, 129, 216, 48); - - - QFrame::Raised - - - Qt::Horizontal - - - - - - - - - User Agent - - - - - - - - - - Set - - - - :/icons/categories/utilities.png:/icons/categories/utilities.png - - - - - - - Default - - - - :/icons/refresh-line.png:/icons/refresh-line.png - - - - - - - - - - - Theme - - - - - - - - 0 - 0 - - - - <html><head/><body><p>Based on your system timezone and location.</p></body></html> - - - Automatic - - - - - - - - Dark + :/icons/plus.png:/icons/plus.png + + + + + + + + 1 + 0 + + + + + 1 + 16777215 + + + + background-color: rgba(63, 129, 216, 48); + + + QFrame::Raised + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + reset + + + - :/icons/moon-line.png:/icons/moon-line.png + :/icons/arrow-go-back-line.png:/icons/arrow-go-back-line.png - - + + + + + + + + + + + Application Storage and Other Settings + + + + + + - Light + Clear - :/icons/lightbulb-line.png:/icons/lightbulb-line.png - - - - - - - - - - 0 - - - - - Zoom factor - - - - - - - - 0 - 0 - - - - Zoom Out - - - - - - - :/icons/minus.png:/icons/minus.png - - - - - - - - 0 - 0 - - - - Qt::AlignCenter - - - true - - - QAbstractSpinBox::NoButtons - - - - - - - - 0 - 0 - - - - Zoom In - - - - - - - :/icons/plus.png:/icons/plus.png - - - - - - - - 1 - 0 - - - - - 1 - 16777215 - - - - background-color: rgba(63, 129, 216, 48); - - - QFrame::Raised - - - Qt::Vertical - - - - - - - - 0 - 0 - - - - reset - - - - - - - :/icons/arrow-go-back-line.png:/icons/arrow-go-back-line.png - - - - - - - - - - - - Application Storage and Other Settings - - - - - - - - Clear - - - - :/icons/delete-bin-3-line.png:/icons/delete-bin-3-line.png - - - - - - - Application Cache - - - - - - - - - - - Qt::AlignCenter - - - - - - - - 10 - false - - - - Property - - - - - - - - 10 - false - - - - Option - - - Qt::AlignCenter - - - - - - - - 10 - false - - - - Size - - - Qt::AlignCenter - - - - - - - <html><head/><body><p>Persistent data includes persistent cookies, HTML5 local storage, and visited links.</p></body></html> - - - Persistent data - - - - - - - - - - - Qt::AlignCenter - - - - - - - Clear - - - - :/icons/delete-bin-3-line.png:/icons/delete-bin-3-line.png - - - - - - - - - + :/icons/delete-bin-3-line.png:/icons/delete-bin-3-line.png + + + + + + + Application Cache + + + + + + + - + + + Qt::AlignCenter + + + + + + + + 10 + false + + + + Property + + + + + + + + 10 + false + + + + Option + + + Qt::AlignCenter + + + + + + + + 10 + false + + + + Size + + + Qt::AlignCenter + + + + + + + <html><head/><body><p>Persistent data includes persistent cookies, HTML5 local storage, and visited links.</p></body></html> + + + Persistent data + + + + + + + - + + + Qt::AlignCenter + + + + + + + Clear + + + + :/icons/delete-bin-3-line.png:/icons/delete-bin-3-line.png + + + + + + + + + + - - - - Qt::Vertical - - - - 20 - 40 - - - - -- cgit v1.2.3 From 474b9212a6630c8404d5f4cf7aa02428deddd3fd Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Wed, 30 Mar 2022 04:24:36 +0530 Subject: feat: v4.0 (#35) * add new widgets * feat: version 4.0 - SystemTray: tray icon uses png rather than svg - SystemTray: added settings to lets user change the systemtray icon click behavior(minimize/maximize on right click) - Download: added settiing that lets user set default download directory, avoid asking while saving files - Lock: added setting to let user change current set password for lock screen - Lock: current set password now hidden by default and can be revealed for 5 seconds by pressing view button - Style/Theme: added ability to change widget style on the fly, added default light palatte (prevent breaking of light theme on KDE EVs) - Theme: dark theme update - WebApp: added setting to set zoom factor when window is maximized and fullscreen (gives user ability to set different zoom factor for Normal , Maximized/Fullscreen WindowStates) - Setting: settings UI is more oraganized - WebApp: enable JavaScript execCommand("paste") - WebApp: tested for new WhatsApp Web that lets users use whatsie without requiring the phone connected to internet --- snap/snapcraft.yaml | 2 +- src/WhatsApp.pro | 2 +- src/common.h | 8 +- src/downloadmanagerwidget.cpp | 30 +- src/downloadwidget.cpp | 30 +- src/elidedlabel.cpp | 12 +- src/elidedlabel.h | 6 +- src/icons.qrc | 9 +- src/icons/app/whatsapp-message-32.png | Bin 0 -> 1797 bytes src/icons/icon-512.xcf | Bin 410837 -> 0 bytes src/icons/others/Histogram.png | Bin 291 -> 0 bytes src/icons/others/Omonitor.png | Bin 13176 -> 0 bytes src/icons/others/greendot.png | Bin 7109 -> 0 bytes src/icons/others/monitor.png | Bin 3922 -> 0 bytes src/icons/others/snapcraft.png | Bin 1602 -> 0 bytes src/icons/others/snapcraft.svg | 59 -- src/icons/others/tt_tbc_head.png | Bin 83727 -> 0 bytes src/icons/others/wall_placeholder_180.jpg | Bin 5155 -> 0 bytes src/icons/tiktok-downloader.png | Bin 76834 -> 0 bytes src/lock.cpp | 15 +- src/lock.h | 61 +- src/main.cpp | 6 +- src/mainwindow.cpp | 263 ++++++--- src/mainwindow.h | 25 +- src/rateapp.cpp | 3 +- src/settingswidget.cpp | 254 ++++++++- src/settingswidget.h | 166 +++--- src/settingswidget.ui | 917 +++++++++++++++++++----------- src/utils.cpp | 14 +- src/utils.h | 2 +- src/webenginepage.cpp | 21 +- src/webview.cpp | 4 +- src/webview.h | 15 +- 33 files changed, 1205 insertions(+), 719 deletions(-) create mode 100644 src/icons/app/whatsapp-message-32.png delete mode 100644 src/icons/icon-512.xcf delete mode 100644 src/icons/others/Histogram.png delete mode 100644 src/icons/others/Omonitor.png delete mode 100644 src/icons/others/greendot.png delete mode 100644 src/icons/others/monitor.png delete mode 100644 src/icons/others/snapcraft.png delete mode 100644 src/icons/others/snapcraft.svg delete mode 100644 src/icons/others/tt_tbc_head.png delete mode 100644 src/icons/others/wall_placeholder_180.jpg delete mode 100644 src/icons/tiktok-downloader.png (limited to 'src/mainwindow.h') diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 1228d00..23850cb 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,5 +1,5 @@ name: whatsie -version: '3.0' +version: '4.0' summary: Qt Based WhatsApp Client description: | Fast Light weight WhatsApp Client based on Qt's WebEngine, With lots of settings and packed goodies. diff --git a/src/WhatsApp.pro b/src/WhatsApp.pro index 083f339..b83ec8e 100644 --- a/src/WhatsApp.pro +++ b/src/WhatsApp.pro @@ -42,7 +42,7 @@ BUILD_TIMESTAMP="\\\"$$system(date -u +\""%Y-%m-%dT%H:%M:%SUTC\"")\\\"" DEFINES += GIT_HASH=$$GIT_HASH GIT_BRANCH=$$GIT_BRANCH BUILD_TIMESTAMP=$$BUILD_TIMESTAMP # Set program version -VERSION = 3.0 +VERSION = 4.0 DEFINES += VERSIONSTR=\\\"$${VERSION}\\\" # You can also make your code fail to compile if you use deprecated APIs. diff --git a/src/common.h b/src/common.h index 92a67c2..0d57ab8 100644 --- a/src/common.h +++ b/src/common.h @@ -2,9 +2,13 @@ #define COMMON_H #include -//QString defaultUserAgentStr = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.4389.114 Safari/537.36"; - +// userAgent QString defaultUserAgentStr = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"; +//appAutoLock +int defaultAppAutoLockDuration = 60; +bool defaultAppAutoLock = false; +double defaultZoomFactorMaximized = 1.50; + #endif // COMMON_H diff --git a/src/downloadmanagerwidget.cpp b/src/downloadmanagerwidget.cpp index 6480e10..7f5b300 100644 --- a/src/downloadmanagerwidget.cpp +++ b/src/downloadmanagerwidget.cpp @@ -3,6 +3,7 @@ #include "downloadwidget.h" #include +#include #include DownloadManagerWidget::DownloadManagerWidget(QWidget *parent) @@ -14,23 +15,18 @@ void DownloadManagerWidget::downloadRequested( QWebEngineDownloadItem *download) { Q_ASSERT(download && download->state() == QWebEngineDownloadItem::DownloadRequested); - QString path; - - bool usenativeFileDialog = - settings.value("useNativeFileDialog", false).toBool(); - if (usenativeFileDialog == false) { - path = QFileDialog::getSaveFileName(this, tr("Save as"), download->downloadFileName(), - tr("Any file (*)"), nullptr, - QFileDialog::DontUseNativeDialog); - } else { - path = QFileDialog::getSaveFileName(this, tr("Save as"), download->downloadFileName(), - tr("Any file (*)"), nullptr); - } - - if (path.isEmpty()) - return; - - download->setDownloadFileName(path); + QString path = + settings + .value("defaultDownloadLocation", + QStandardPaths::writableLocation( + QStandardPaths::DownloadLocation) + + QDir::separator() + QApplication::applicationName()) + .toString(); + QDir d; + d.mkpath(path); + + download->setDownloadFileName(path + QDir::separator() + + download->downloadFileName()); download->accept(); add(new DownloadWidget(download)); show(); diff --git a/src/downloadwidget.cpp b/src/downloadwidget.cpp index 4af29d3..d228074 100644 --- a/src/downloadwidget.cpp +++ b/src/downloadwidget.cpp @@ -11,7 +11,7 @@ DownloadWidget::DownloadWidget(QWebEngineDownloadItem *download, m_dstName->setText(QFileInfo(m_download->downloadDirectory()).fileName()); m_srcUrl->setText(m_download->url().toDisplayString()); - connect(m_cancelButton, &QPushButton::clicked, [this](bool) { + connect(m_cancelButton, &QPushButton::clicked, m_download, [this](bool) { if (m_download->state() == QWebEngineDownloadItem::DownloadInProgress) m_download->cancel(); else @@ -53,30 +53,30 @@ void DownloadWidget::updateWidget() { m_progressBar->setValue(qRound(100 * receivedBytes / totalBytes)); m_progressBar->setDisabled(false); m_progressBar->setFormat(tr("%p% - %1 of %2 downloaded - %3/s") - .arg(withUnit(receivedBytes)) - .arg(withUnit(totalBytes)) - .arg(withUnit(bytesPerSecond))); + .arg(withUnit(receivedBytes), + withUnit(totalBytes), + withUnit(bytesPerSecond))); } else { m_progressBar->setValue(0); m_progressBar->setDisabled(false); - m_progressBar->setFormat(tr("unknown size - %1 downloaded - %2/s") - .arg(withUnit(receivedBytes)) - .arg(withUnit(bytesPerSecond))); + m_progressBar->setFormat( + tr("unknown size - %1 downloaded - %2/s") + .arg(withUnit(receivedBytes), withUnit(bytesPerSecond))); } break; case QWebEngineDownloadItem::DownloadCompleted: m_progressBar->setValue(100); m_progressBar->setDisabled(true); - m_progressBar->setFormat(tr("completed - %1 downloaded - %2/s") - .arg(withUnit(receivedBytes)) - .arg(withUnit(bytesPerSecond))); + m_progressBar->setFormat( + tr("completed - %1 downloaded - %2/s") + .arg(withUnit(receivedBytes), withUnit(bytesPerSecond))); break; case QWebEngineDownloadItem::DownloadCancelled: m_progressBar->setValue(0); m_progressBar->setDisabled(true); - m_progressBar->setFormat(tr("cancelled - %1 downloaded - %2/s") - .arg(withUnit(receivedBytes)) - .arg(withUnit(bytesPerSecond))); + m_progressBar->setFormat( + tr("cancelled - %1 downloaded - %2/s") + .arg(withUnit(receivedBytes), withUnit(bytesPerSecond))); break; case QWebEngineDownloadItem::DownloadInterrupted: m_progressBar->setValue(0); @@ -87,11 +87,11 @@ void DownloadWidget::updateWidget() { } if (state == QWebEngineDownloadItem::DownloadInProgress) { - static QIcon cancelIcon(QStringLiteral(":/icons/stop-line.png")); + static QIcon cancelIcon(":/icons/stop-line.png"); m_cancelButton->setIcon(cancelIcon); m_cancelButton->setToolTip(tr("Stop downloading")); } else { - static QIcon removeIcon(QStringLiteral(":/icons/close-fill.png")); + static QIcon removeIcon(":/icons/close-fill.png"); m_cancelButton->setIcon(removeIcon); m_cancelButton->setToolTip(tr("Remove from list")); } diff --git a/src/elidedlabel.cpp b/src/elidedlabel.cpp index b88ed4f..e870959 100644 --- a/src/elidedlabel.cpp +++ b/src/elidedlabel.cpp @@ -5,19 +5,19 @@ #include #include -ElidedLabel::ElidedLabel(QWidget *parent, Qt::WindowFlags f) - : QLabel(parent, f), m_elide_mode(Qt::ElideRight) { +ElidedLabel::ElidedLabel(QWidget *parent) + : QLabel(parent), m_elide_mode(Qt::ElideRight) { setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); } -ElidedLabel::ElidedLabel(const QString &txt, QWidget *parent, Qt::WindowFlags f) - : QLabel(txt, parent, f), m_elide_mode(Qt::ElideRight) { +ElidedLabel::ElidedLabel(const QString &txt, QWidget *parent) + : QLabel(txt, parent), m_elide_mode(Qt::ElideRight) { setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); } ElidedLabel::ElidedLabel(const QString &txt, Qt::TextElideMode elideMode, - QWidget *parent, Qt::WindowFlags f) - : QLabel(txt, parent, f), m_elide_mode(elideMode) { + QWidget *parent) + : QLabel(txt, parent), m_elide_mode(elideMode) { setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); } diff --git a/src/elidedlabel.h b/src/elidedlabel.h index 1ce5210..7dc610a 100644 --- a/src/elidedlabel.h +++ b/src/elidedlabel.h @@ -16,9 +16,9 @@ private: public: - ElidedLabel(QWidget* parent = NULL, Qt::WindowFlags f = 0); - ElidedLabel(const QString& txt, QWidget* parent = NULL, Qt::WindowFlags f = 0); - ElidedLabel(const QString& txt, Qt::TextElideMode elideMode = Qt::ElideRight, QWidget* parent = NULL, Qt::WindowFlags f = 0); + ElidedLabel(QWidget* parent = NULL); + ElidedLabel(const QString& txt, QWidget* parent = NULL); + ElidedLabel(const QString& txt, Qt::TextElideMode elideMode = Qt::ElideRight, QWidget* parent = NULL); public: // Set the elide mode used for displaying text. diff --git a/src/icons.qrc b/src/icons.qrc index b5d99cb..6c3a11c 100644 --- a/src/icons.qrc +++ b/src/icons.qrc @@ -80,8 +80,6 @@ icons/white/white_arrow-right-line.png icons/white/white_arrow-left-line.png icons/white/white_picture-in-picture-line.png - icons/others/monitor.png - icons/others/wall_placeholder_180.jpg icons/categories/devices-and-iot.png icons/categories/social.png icons/categories/server-and-cloud.png @@ -102,7 +100,6 @@ icons/categories/development.png icons/categories/books-and-reference.png icons/categories/utilities.png - icons/others/snapcraft.png icons/mail-line.png icons/app/icon-256.png icons/app/icon-128.png @@ -111,7 +108,6 @@ icons/app/icon-16.png icons/app/icon-512.png icons/app/resize.sh - icons/others/greendot.png icons/anticlockwise-line.png icons/arrow-go-back-line.png icons/arrow-go-forward-line.png @@ -133,14 +129,10 @@ icons/fullscreen-line.png icons/clockwise-fill.png icons/anticlockwise-fill.png - icons/others/Histogram.png - icons/tiktok-downloader.png - icons/icon-512.xcf icons/blur-off-line.png icons/lock-line.png icons/lock-unlock-line.png icons/funds-line.png - icons/others/tt_tbc_head.png icons/app/whatsapp-message.svg icons/app/whatsapp.svg icons/wa_bg.png @@ -403,5 +395,6 @@ icons/flags/zw.png icons/minus.png icons/plus.png + icons/app/whatsapp-message-32.png diff --git a/src/icons/app/whatsapp-message-32.png b/src/icons/app/whatsapp-message-32.png new file mode 100644 index 0000000..77e3b56 Binary files /dev/null and b/src/icons/app/whatsapp-message-32.png differ diff --git a/src/icons/icon-512.xcf b/src/icons/icon-512.xcf deleted file mode 100644 index b9275f6..0000000 Binary files a/src/icons/icon-512.xcf and /dev/null differ diff --git a/src/icons/others/Histogram.png b/src/icons/others/Histogram.png deleted file mode 100644 index d2bddb3..0000000 Binary files a/src/icons/others/Histogram.png and /dev/null differ diff --git a/src/icons/others/Omonitor.png b/src/icons/others/Omonitor.png deleted file mode 100644 index f1c1a64..0000000 Binary files a/src/icons/others/Omonitor.png and /dev/null differ diff --git a/src/icons/others/greendot.png b/src/icons/others/greendot.png deleted file mode 100644 index be914c6..0000000 Binary files a/src/icons/others/greendot.png and /dev/null differ diff --git a/src/icons/others/monitor.png b/src/icons/others/monitor.png deleted file mode 100644 index 7ba4759..0000000 Binary files a/src/icons/others/monitor.png and /dev/null differ diff --git a/src/icons/others/snapcraft.png b/src/icons/others/snapcraft.png deleted file mode 100644 index da50180..0000000 Binary files a/src/icons/others/snapcraft.png and /dev/null differ diff --git a/src/icons/others/snapcraft.svg b/src/icons/others/snapcraft.svg deleted file mode 100644 index a14c440..0000000 --- a/src/icons/others/snapcraft.svg +++ /dev/null @@ -1,59 +0,0 @@ - - diff --git a/src/icons/others/tt_tbc_head.png b/src/icons/others/tt_tbc_head.png deleted file mode 100644 index 20cac2c..0000000 Binary files a/src/icons/others/tt_tbc_head.png and /dev/null differ diff --git a/src/icons/others/wall_placeholder_180.jpg b/src/icons/others/wall_placeholder_180.jpg deleted file mode 100644 index d696b5f..0000000 Binary files a/src/icons/others/wall_placeholder_180.jpg and /dev/null differ diff --git a/src/icons/tiktok-downloader.png b/src/icons/tiktok-downloader.png deleted file mode 100644 index 7ca80f6..0000000 Binary files a/src/icons/tiktok-downloader.png and /dev/null differ diff --git a/src/lock.cpp b/src/lock.cpp index 4eb65d1..c2b8a13 100644 --- a/src/lock.cpp +++ b/src/lock.cpp @@ -23,11 +23,7 @@ Lock::Lock(QWidget *parent) : QWidget(parent), ui(new Ui::Lock) { animate(); if (settings.value("asdfg").isValid() == false) { - isLocked = false; - ui->signup->show(); - ui->login->hide(); - animate(); - ui->passcode1->setFocus(); + signUp(); } else { lock_app(); } @@ -43,6 +39,15 @@ Lock::Lock(QWidget *parent) : QWidget(parent), ui(new Ui::Lock) { ui->wrong->setStyleSheet(capsStyle); } + +void Lock::signUp(){ + isLocked = false; + ui->signup->show(); + ui->login->hide(); + animate(); + ui->passcode1->setFocus(); +} + void Lock::animate() { ui->centerWidget->hide(); QPropertyAnimation *a = diff --git a/src/lock.h b/src/lock.h index f079c9d..972e6ed 100644 --- a/src/lock.h +++ b/src/lock.h @@ -1,55 +1,50 @@ #ifndef LOCK_H #define LOCK_H -#include #include +#include namespace Ui { class Lock; } -class Lock : public QWidget -{ - Q_OBJECT +class Lock : public QWidget { + Q_OBJECT public: - explicit Lock(QWidget *parent = nullptr); - ~Lock(); - bool isLocked = true; + explicit Lock(QWidget *parent = nullptr); + ~Lock(); + bool isLocked = true; private slots: - void on_passcode1_textChanged(const QString &arg1); - - void on_passcode2_textChanged(const QString &arg1); - - void on_setPass_clicked(); - bool check_password_set(); - void on_unlock_clicked(); - - void on_passcodeLogin_textChanged(const QString &arg1); - - void on_passcodeLogin_returnPressed(); - - bool getCapsLockOn(); - void checkCaps(); - void on_cancelSetting_clicked(); - - void animate(); + void on_passcode1_textChanged(const QString &arg1); + void on_passcode2_textChanged(const QString &arg1); + void on_setPass_clicked(); + bool check_password_set(); + void on_unlock_clicked(); + void on_passcodeLogin_textChanged(const QString &arg1); + void on_passcodeLogin_returnPressed(); + bool getCapsLockOn(); + void checkCaps(); + void on_cancelSetting_clicked(); + void animate(); public slots: - void lock_app(); - void applyThemeQuirks(); + void lock_app(); + void applyThemeQuirks(); + void signUp(); signals: - void passwordSet(); - void passwordNotSet(); - void unLocked(); + void passwordSet(); + void passwordNotSet(); + void unLocked(); protected slots: - void keyReleaseEvent(QKeyEvent *event); + void keyReleaseEvent(QKeyEvent *event); + + bool event(QEvent *e); - bool event(QEvent *e); private: - Ui::Lock *ui; - QSettings settings; + Ui::Lock *ui; + QSettings settings; }; #endif // LOCK_H diff --git a/src/main.cpp b/src/main.cpp index 68fbe3a..57c2852 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -38,23 +38,19 @@ int main(int argc, char *argv[]) { qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-logging --single-process"); QApplication app(argc, argv); + app.setQuitOnLastWindowClosed(false); app.setWindowIcon(QIcon(":/icons/app/icon-256.png")); - QApplication::setApplicationName("WhatSie"); QApplication::setOrganizationName("org.keshavnrj.ubuntu"); QApplication::setApplicationVersion(VERSIONSTR); - QString appname = QApplication::applicationName(); -// allow multiple instances in debug builds -#ifndef QT_DEBUG RunGuard guard("org.keshavnrj.ubuntu." + appname); if (!guard.tryToRun()) { QMessageBox::critical(0, appname, "An instance of " + appname + " is already running."); return 0; } -#endif QWebEngineSettings::defaultSettings()->setAttribute( QWebEngineSettings::PluginsEnabled, true); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f8b29d1..683072f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -8,53 +8,90 @@ #include extern QString defaultUserAgentStr; +extern double defaultZoomFactorMaximized; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), notificationsTitleRegExp("^\\([1-9]\\d*\\).*"), - trayIconRead(":/icons/app/whatsapp.svg"), - trayIconUnread(":/icons/app/whatsapp-message.svg") { - this->setObjectName("MainWindow"); - - qApp->setQuitOnLastWindowClosed(false); - - lightPalette = qApp->palette(); - lightPalette.setColor(QPalette::Window, - QColor(240, 240, 240)); // whatsapp light palette + trayIconRead(":/icons/app/icon-32.png"), + trayIconUnread(":/icons/app/whatsapp-message-32.png") { + setObjectName("MainWindow"); setWindowTitle(QApplication::applicationName()); setWindowIcon(QIcon(":/icons/app/icon-256.png")); setMinimumWidth(750); setMinimumHeight(640); - restoreGeometry(settings.value("geometry").toByteArray()); restoreState(settings.value("windowState").toByteArray()); - + initThemes(); createActions(); createTrayIcon(); createWebEngine(); - - if (settings.value("lockscreen", false).toBool()) { - init_lock(); - } - QTimer *timer = new QTimer(this); - timer->setInterval(1000); - connect(timer, &QTimer::timeout, lockWidget, [=]() { - if (settings.value("asdfg").isValid()) { - if (lockWidget && lockWidget->isLocked == false) { - timer->stop(); - } - } - }); - timer->start(); - init_settingWidget(); - - // quit application if the download manager window is the only remaining - // window - m_downloadManagerWidget.setAttribute(Qt::WA_QuitOnClose, false); - + initRateWidget(); + tryLock(); updateWindowTheme(); +} +void MainWindow::initThemes() { + // Light + lightPalette.setColor(QPalette::Window, QColor(240, 240, 240)); + lightPalette.setColor(QPalette::WindowText, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::Button, QColor(240, 240, 240)); + lightPalette.setColor(QPalette::Light, QColor(180, 180, 180)); + lightPalette.setColor(QPalette::Midlight, QColor(200, 200, 200)); + lightPalette.setColor(QPalette::Dark, QColor(225, 225, 225)); + lightPalette.setColor(QPalette::Text, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::BrightText, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::ButtonText, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::Base, QColor(237, 237, 237)); + lightPalette.setColor(QPalette::Shadow, QColor(20, 20, 20)); + lightPalette.setColor(QPalette::Highlight, QColor(76, 163, 224)); + lightPalette.setColor(QPalette::HighlightedText, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::Link, QColor(0, 162, 232)); + lightPalette.setColor(QPalette::AlternateBase, QColor(225, 225, 225)); + lightPalette.setColor(QPalette::ToolTipBase, QColor(240, 240, 240)); + lightPalette.setColor(QPalette::ToolTipText, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::LinkVisited, QColor(222, 222, 222)); + lightPalette.setColor(QPalette::Disabled, QPalette::WindowText, + QColor(115, 115, 115)); + lightPalette.setColor(QPalette::Disabled, QPalette::Text, + QColor(115, 115, 115)); + lightPalette.setColor(QPalette::Disabled, QPalette::ButtonText, + QColor(115, 115, 115)); + lightPalette.setColor(QPalette::Disabled, QPalette::Highlight, + QColor(190, 190, 190)); + lightPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, + QColor(115, 115, 115)); + + // Dark + darkPalette.setColor(QPalette::Window, QColor(17, 27, 33)); + darkPalette.setColor(QPalette::Text, Qt::white); + darkPalette.setColor(QPalette::WindowText, Qt::white); + darkPalette.setColor(QPalette::Base, QColor(32, 44, 51)); + darkPalette.setColor(QPalette::AlternateBase, QColor(95, 108, 115)); + darkPalette.setColor(QPalette::ToolTipBase, QColor(66, 66, 66)); + darkPalette.setColor(QPalette::ToolTipText, QColor(192, 192, 192)); + darkPalette.setColor(QPalette::Dark, QColor(35, 35, 35)); + darkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20)); + darkPalette.setColor(QPalette::Button, QColor(17, 27, 33)); + darkPalette.setColor(QPalette::ButtonText, Qt::white); + darkPalette.setColor(QPalette::BrightText, Qt::red); + darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); + darkPalette.setColor(QPalette::Highlight, QColor(38, 140, 196)); + darkPalette.setColor(QPalette::HighlightedText, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, + QColor(127, 127, 127)); + darkPalette.setColor(QPalette::Disabled, QPalette::Window, + QColor(65, 65, 67)); + darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, + QColor(80, 80, 80)); + darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, + QColor(127, 127, 127)); + darkPalette.setColor(QPalette::Disabled, QPalette::Text, + QColor(127, 127, 127)); +} + +void MainWindow::initRateWidget() { RateApp *rateApp = new RateApp(this, "snap://whatsie", 5, 5, 1000 * 30); rateApp->setWindowTitle(QApplication::applicationName() + " | " + tr("Rate Application")); @@ -82,10 +119,10 @@ void MainWindow::loadAppWithArgument(const QString &arg) { // The WhatsApp Messenger application if (arg.contains("://app")) { - qWarning() << "WhatsApp Messenger application"; this->show(); // restore app return; } + // PASSED SCHEME whatsapp://send?text=Hello%2C%20World!&phone=919568388397" // CONVERTED URI // https://web.whatsapp.com/send?phone=919568388397&text=Hello%2C%20World New @@ -100,10 +137,8 @@ void MainWindow::loadAppWithArgument(const QString &arg) { // create send url equivalent phone = query.queryItemValue("phone"); text = query.queryItemValue("text"); - phoneStr = phone.isEmpty() ? "" : "phone=" + phone; textStr = text.isEmpty() ? "" : "text=" + text; - urlStr = "https://web.whatsapp.com/send?" + phoneStr + "&" + textStr; qWarning() << "Loading" << urlStr; this->webEngine->page()->load(QUrl(urlStr)); @@ -117,6 +152,7 @@ void MainWindow::updatePageTheme() { if (windowTheme == "dark") { webPageTheme = "web dark"; } +#ifdef QT_DEBUG if (webEngine && webEngine->page()) { webEngine->page()->runJavaScript( "document.querySelector('body').className='" + webPageTheme + "';", @@ -124,6 +160,7 @@ void MainWindow::updatePageTheme() { qDebug() << "Value is: " << result.toString() << Qt::endl; }); } +#endif } void MainWindow::resizeEvent(QResizeEvent *event) { @@ -133,35 +170,12 @@ void MainWindow::resizeEvent(QResizeEvent *event) { } void MainWindow::updateWindowTheme() { + qApp->setStyle(QStyleFactory::create( + settings.value("widgetStyle", "Fusion").toString())); if (settings.value("windowTheme", "light").toString() == "dark") { - qApp->setStyle(QStyleFactory::create("fusion")); - QPalette palette; - palette.setColor(QPalette::Window, QColor(38, 45, 49)); - palette.setColor(QPalette::Text, Qt::white); - palette.setColor(QPalette::WindowText, Qt::white); - palette.setColor(QPalette::Base, QColor(50, 55, 57)); - palette.setColor(QPalette::AlternateBase, QColor(95, 108, 115)); - palette.setColor(QPalette::ToolTipBase, QColor(66, 66, 66)); - palette.setColor(QPalette::Disabled, QPalette::Window, QColor(65, 65, 67)); - palette.setColor(QPalette::ToolTipText, QColor("silver")); - palette.setColor(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127)); - palette.setColor(QPalette::Dark, QColor(35, 35, 35)); - palette.setColor(QPalette::Shadow, QColor(20, 20, 20)); - palette.setColor(QPalette::Button, QColor(38, 45, 49)); - palette.setColor(QPalette::ButtonText, Qt::white); - palette.setColor(QPalette::Disabled, QPalette::ButtonText, - QColor(127, 127, 127)); - palette.setColor(QPalette::BrightText, Qt::red); - palette.setColor(QPalette::Link, QColor(42, 130, 218)); - palette.setColor(QPalette::Highlight, QColor(38, 140, 196)); - palette.setColor(QPalette::Disabled, QPalette::Highlight, - QColor(80, 80, 80)); - palette.setColor(QPalette::HighlightedText, Qt::white); - palette.setColor(QPalette::Disabled, QPalette::HighlightedText, - QColor(127, 127, 127)); - qApp->setPalette(palette); + qApp->setPalette(darkPalette); this->webEngine->setStyleSheet( - "QWebEngineView{background:#131C21;}"); // whatsapp dark color + "QWebEngineView{background:rgb(17, 27, 33);}"); // whatsapp dark color } else { qApp->setPalette(lightPalette); this->webEngine->setStyleSheet( @@ -170,9 +184,7 @@ void MainWindow::updateWindowTheme() { QList widgets = this->findChildren(); - foreach (QWidget *w, widgets) { - w->setPalette(qApp->palette()); - } + foreach (QWidget *w, widgets) { w->setPalette(qApp->palette()); } setNotificationPresenter(webEngine->page()->profile()); @@ -199,6 +211,9 @@ void MainWindow::init_settingWidget() { settingsWidget->setWindowFlags(Qt::Dialog); connect(settingsWidget, SIGNAL(init_lock()), this, SLOT(init_lock())); + connect(settingsWidget, SIGNAL(change_lock_password()), this, + SLOT(change_lock_password())); + connect(settingsWidget, SIGNAL(updateWindowTheme()), this, SLOT(updateWindowTheme())); connect(settingsWidget, SIGNAL(updatePageTheme()), this, @@ -243,10 +258,24 @@ void MainWindow::init_settingWidget() { connect( settingsWidget, &SettingsWidget::zoomChanged, settingsWidget, [=]() { - double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); - webEngine->page()->setZoomFactor(currentFactor); + if (windowState() == Qt::WindowNoState) { + double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); + webEngine->page()->setZoomFactor(currentFactor); + } }); + connect(settingsWidget, &SettingsWidget::zoomMaximizedChanged, + settingsWidget, [=]() { + if (windowState() == Qt::WindowMaximized || + windowState() == Qt::WindowFullScreen) { + double currentFactor = settings + .value("zoomFactorMaximized", + defaultZoomFactorMaximized) + .toDouble(); + webEngine->page()->setZoomFactor(currentFactor); + } + }); + connect(settingsWidget, &SettingsWidget::notificationPopupTimeOutChanged, settingsWidget, [=]() { setNotificationPresenter(this->webEngine->page()->profile()); @@ -263,6 +292,40 @@ void MainWindow::init_settingWidget() { } } +void MainWindow::changeEvent(QEvent *e) { + if (e->type() == QEvent::WindowStateChange) { + handleZoomOnWindowStateChange(static_cast(e)); + } + QMainWindow::changeEvent(e); +} + +void MainWindow::handleZoomOnWindowStateChange(QWindowStateChangeEvent *ev) { + if (settingsWidget != nullptr) { + if (ev->oldState().testFlag(Qt::WindowMaximized) && + windowState().testFlag(Qt::WindowNoState)) { + emit settingsWidget->zoomChanged(); + } else if ((!ev->oldState().testFlag(Qt::WindowMaximized) && + windowState().testFlag(Qt::WindowMaximized)) || + (!ev->oldState().testFlag(Qt::WindowMaximized) && + windowState().testFlag(Qt::WindowFullScreen))) { + emit settingsWidget->zoomMaximizedChanged(); + } + } +} + +void MainWindow::handleZoom() { + if (windowState() == Qt::WindowMaximized || + windowState() == Qt::WindowFullScreen) { + double currentFactor = + settings.value("zoomFactorMaximized", defaultZoomFactorMaximized) + .toDouble(); + webEngine->page()->setZoomFactor(currentFactor); + } else if (windowState() == Qt::WindowNoState) { + double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); + webEngine->page()->setZoomFactor(currentFactor); + } +} + void MainWindow::lockApp() { if (lockWidget != nullptr && lockWidget->isLocked) return; @@ -278,7 +341,9 @@ void MainWindow::lockApp() { .scaled(42, 42, Qt::KeepAspectRatio, Qt::SmoothTransformation)); msgBox.setInformativeText("Do you want to setup App lock now ?"); msgBox.setStandardButtons(QMessageBox::Cancel); - QPushButton *setAppLock = new QPushButton("Yes", nullptr); + QPushButton *setAppLock = + new QPushButton(this->style()->standardIcon(QStyle::SP_DialogYesButton), + "Yes", nullptr); msgBox.addButton(setAppLock, QMessageBox::NoRole); connect(setAppLock, &QPushButton::clicked, setAppLock, [=]() { init_lock(); }); @@ -484,15 +549,18 @@ void MainWindow::createTrayIcon() { } void MainWindow::init_lock() { + if (lockWidget == nullptr) { lockWidget = new Lock(this); lockWidget->setObjectName("lockWidget"); } + lockWidget->setWindowFlags(Qt::Widget); lockWidget->setStyleSheet("QWidget#login{background-color:palette(window)};" "QWidget#signup{background-color:palette(window)}"); lockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); lockWidget->setGeometry(this->rect()); + // lockWidget->disconnect(); connect(lockWidget, &Lock::passwordNotSet, settingsWidget, [=]() { settings.setValue("lockscreen", false); @@ -504,28 +572,38 @@ void MainWindow::init_lock() { }); connect(lockWidget, &Lock::passwordSet, settingsWidget, [=]() { - // enable disable lock screen if (settings.value("asdfg").isValid()) { settingsWidget->setCurrentPasswordText( - "Current Password: " + - QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8()) + - ""); + QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())); } else { - settingsWidget->setCurrentPasswordText( - "Current Password: Require setup"); + settingsWidget->setCurrentPasswordText("Require setup"); } settingsWidget->appLockSetChecked( settings.value("lockscreen", false).toBool()); }); + lockWidget->applyThemeQuirks(); lockWidget->show(); if (settings.value("asdfg").isValid() && - settings.value("lockscreen").toBool() == true) { + settings.value("lockscreen").toBool()) { lockWidget->lock_app(); + } else if (settings.value("lockscreen").toBool() && + !settings.value("asdfg").isValid()) { + lockWidget->signUp(); + } else { + lockWidget->hide(); } updateWindowTheme(); } +void MainWindow::change_lock_password() { + settings.remove("asdfg"); + settingsWidget->appLockSetChecked(false); + settingsWidget->clearAllData(); + doReload(true); + init_lock(); +} + // check window state and set tray menus void MainWindow::check_window_state() { QObject *tray_icon_menu = this->findChild("trayIconMenu"); @@ -574,6 +652,10 @@ void MainWindow::init_globalWebProfile() { false); webSettings->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, false); + webSettings->setAttribute(QWebEngineSettings::SpatialNavigationEnabled, true); + webSettings->setAttribute(QWebEngineSettings::JavascriptCanPaste, true); + webSettings->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, + true); webSettings->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, settings.value("autoPlayMedia", false).toBool()); } @@ -622,7 +704,7 @@ void MainWindow::createWebPage(bool offTheRecord) { QWebEnginePage *page = new WebEnginePage(profile, webEngine); if (settings.value("windowTheme", "light").toString() == "dark") { - page->setBackgroundColor(QColor(19, 28, 33)); // whatsapp dark bg color + page->setBackgroundColor(QColor(17, 27, 33)); // whatsapp dark bg color } else { page->setBackgroundColor(QColor(240, 240, 240)); // whatsapp light bg color } @@ -710,13 +792,14 @@ void MainWindow::handleWebViewTitleChanged(QString title) { setWindowTitle(QApplication::applicationName() + ": " + title); if (notificationsTitleRegExp.exactMatch(title)) { - if (notificationsTitleRegExp.isEmpty() == false) { - QString capturedTitle = notificationsTitleRegExp.capturedTexts().first(); + if (notificationsTitleRegExp.isEmpty() == false && + notificationsTitleRegExp.capturedTexts().isEmpty() == false) { + QString capturedTitle = + notificationsTitleRegExp.capturedTexts().constFirst(); QRegExp rgex("\\([^\\d]*(\\d+)[^\\d]*\\)"); rgex.setMinimal(true); if (rgex.indexIn(capturedTitle) != -1) { - qDebug() << rgex.capturedTexts(); - QString unreadMessageCount = rgex.capturedTexts().last(); + QString unreadMessageCount = rgex.capturedTexts().constLast(); QString suffix = unreadMessageCount.toInt() > 1 ? tr("messages") : tr("message"); restoreAction->setText(tr("Restore") + " | " + unreadMessageCount + @@ -733,9 +816,9 @@ void MainWindow::handleWebViewTitleChanged(QString title) { void MainWindow::handleLoadFinished(bool loaded) { if (loaded) { - // check if page has loaded correctly checkLoadedCorrectly(); updatePageTheme(); + handleZoom(); } } @@ -764,7 +847,7 @@ void MainWindow::checkLoadedCorrectly() { quitAction->trigger(); } else { - qWarning() << "Test 1 Loaded correctly value:" << result.toString(); + qWarning() << "Test 1 loaded correctly value:" << result.toString(); } }); } @@ -816,6 +899,8 @@ void MainWindow::handleDownloadRequested(QWebEngineDownloadItem *download) { void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) { Q_UNUSED(reason); + if (settings.value("minimizeOnTrayIconClick", false).toBool() == false) + return; if (isVisible()) { hide(); } else { @@ -863,9 +948,9 @@ bool MainWindow::isPhoneNumber(const QString &phoneNumber) { return reg.match(phoneNumber).hasMatch(); } -void MainWindow::doReload() { +void MainWindow::doReload(bool byPassCache) { this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, - false); + byPassCache); } void MainWindow::toggleMute(const bool &checked) { @@ -886,3 +971,15 @@ QString MainWindow::getPageTheme() { } return theme; } + +void MainWindow::tryLock() { + if (settings.value("asdfg").isValid() && + settings.value("lockscreen", false).toBool()) { + init_lock(); + } + if (settings.value("asdfg").isValid() == false) { + settings.setValue("lockscreen", false); + settingsWidget->appLockSetChecked(false); + init_lock(); + } +} diff --git a/src/mainwindow.h b/src/mainwindow.h index 5ffe9b1..e1298b0 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -24,16 +24,15 @@ #include #include +#include "about.h" +#include "dictionaries.h" +#include "downloadmanagerwidget.h" #include "lock.h" #include "notificationpopup.h" +#include "rateapp.h" #include "requestinterceptor.h" #include "settingswidget.h" #include "webenginepage.h" - -#include "about.h" -#include "dictionaries.h" -#include "downloadmanagerwidget.h" -#include "rateapp.h" #include "webview.h" class MainWindow : public QMainWindow { @@ -53,9 +52,10 @@ public slots: protected slots: void closeEvent(QCloseEvent *event) override; void resizeEvent(QResizeEvent *event) override; + void changeEvent(QEvent *e) override; private: - QPalette lightPalette; + QPalette lightPalette, darkPalette; void createActions(); void createTrayIcon(); void createWebEngine(); @@ -87,34 +87,37 @@ private: private slots: + QString getPageTheme(); void iconActivated(QSystemTrayIcon::ActivationReason reason); void messageClicked(); - void doReload(); + void doReload(bool byPassCache = false); void showAbout(); void notify(QString title, QString message); void showSettings(); void handleCookieAdded(const QNetworkCookie &cookie); - - QString getPageTheme(); void toggleMute(const bool &checked); void doAppReload(); void askToReloadPage(); void updateSettingsUserAgentWidget(); void fullScreenRequested(QWebEngineFullScreenRequest request); - void createWebPage(bool offTheRecord = false); void init_settingWidget(); void init_globalWebProfile(); void check_window_state(); void init_lock(); void lockApp(); - void checkLoadedCorrectly(); void loadingQuirk(QString test); void setNotificationPresenter(QWebEngineProfile *profile); void newChat(); bool isPhoneNumber(const QString &phoneNumber); void quitApp(); + void initRateWidget(); + void initThemes(); + void handleZoomOnWindowStateChange(QWindowStateChangeEvent *ev); + void handleZoom(); + void change_lock_password(); + void tryLock(); }; #endif // MAINWINDOW_H diff --git a/src/rateapp.cpp b/src/rateapp.cpp index f69080e..430716d 100644 --- a/src/rateapp.cpp +++ b/src/rateapp.cpp @@ -38,7 +38,7 @@ RateApp::RateApp(QWidget *parent, QString app_rating_url, int app_launch_count, settings.setValue("app_install_time", QDateTime::currentSecsSinceEpoch()); } else if (settings.value("app_install_time").isValid()) { - qDebug() << "RATEAPP should show:" << shouldShow(); + //qDebug() << "RATEAPP should show:" << shouldShow(); if (shouldShow()) { showTimer->start(); } else { @@ -86,7 +86,6 @@ bool RateApp::shouldShow() { } RateApp::~RateApp() { - qDebug() << "RateApp Obj deleted"; showTimer->disconnect(); showTimer->deleteLater(); delete ui; diff --git a/src/settingswidget.cpp b/src/settingswidget.cpp index b07340c..473e1a2 100644 --- a/src/settingswidget.cpp +++ b/src/settingswidget.cpp @@ -4,10 +4,14 @@ #include "mainwindow.h" #include #include +#include #include "automatictheme.h" extern QString defaultUserAgentStr; +extern int defaultAppAutoLockDuration; +extern bool defaultAppAutoLock; +extern double defaultZoomFactorMaximized; SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, QString enginePersistentStoragePath) @@ -20,6 +24,11 @@ SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, ui->zoomFactorSpinBox->setRange(0.25, 5.0); ui->zoomFactorSpinBox->setValue(settings.value("zoomFactor", 1.0).toDouble()); + ui->zoomFactorSpinBoxMaximized->setRange(0.25, 5.0); + ui->zoomFactorSpinBoxMaximized->setValue( + settings.value("zoomFactorMaximized", defaultZoomFactorMaximized) + .toDouble()); + ui->closeButtonActionComboBox->setCurrentIndex( settings.value("closeButtonActionCombo", 0).toInt()); ui->notificationCheckBox->setChecked( @@ -30,8 +39,12 @@ SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, settings.value("autoPlayMedia", false).toBool()); ui->themeComboBox->setCurrentText( utils::toCamelCase(settings.value("windowTheme", "light").toString())); + ui->userAgentLineEdit->setText( settings.value("useragent", defaultUserAgentStr).toString()); + ui->userAgentLineEdit->home(true); + ui->userAgentLineEdit->deselect(); + ui->enableSpellCheck->setChecked(settings.value("sc_enabled", true).toBool()); ui->notificationTimeOutspinBox->setValue( settings.value("notificationTimeOut", 9000).toInt() / 1000); @@ -41,6 +54,25 @@ SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, settings.value("useNativeFileDialog", false).toBool()); ui->startMinimized->setChecked( settings.value("startMinimized", false).toBool()); + ui->appAutoLockcheckBox->setChecked( + settings.value("appAutoLocking", defaultAppAutoLock).toBool()); + ui->autoLockDurationSpinbox->setValue( + settings.value("autoLockDuration", defaultAppAutoLockDuration).toInt()); + ui->minimizeOnTrayIconClick->setChecked( + settings.value("minimizeOnTrayIconClick", false).toBool()); + ui->defaultDownloadLocation->setText( + settings + .value("defaultDownloadLocation", + QStandardPaths::writableLocation( + QStandardPaths::DownloadLocation) + + QDir::separator() + QApplication::applicationName()) + .toString()); + + ui->styleComboBox->blockSignals(true); + ui->styleComboBox->addItems(QStyleFactory::keys()); + ui->styleComboBox->blockSignals(false); + ui->styleComboBox->setCurrentText( + settings.value("widgetStyle", "Fusion").toString()); ui->automaticThemeCheckBox->blockSignals(true); bool automaticThemeSwitching = @@ -50,7 +82,7 @@ SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, themeSwitchTimer = new QTimer(this); themeSwitchTimer->setInterval(60000); // 1 min - connect(themeSwitchTimer, &QTimer::timeout, + connect(themeSwitchTimer, &QTimer::timeout, &settings, [=]() { themeSwitchTimerTimeout(); }); // instantly call the timeout slot if automatic theme switching enabled @@ -60,9 +92,7 @@ SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, updateAutomaticTheme(); this->setCurrentPasswordText( - "Current Password: " + - QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8()) + - ""); + QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())); applyThemeQuirks(); @@ -152,7 +182,11 @@ void SettingsWidget::updateAutomaticTheme() { } } -SettingsWidget::~SettingsWidget() { delete ui; } +SettingsWidget::~SettingsWidget() { + themeSwitchTimer->stop(); + themeSwitchTimer->deleteLater(); + delete ui; +} void SettingsWidget::loadDictionaries(QStringList dictionaries) { // set up supported spellcheck dictionaries @@ -240,7 +274,7 @@ void SettingsWidget::on_deleteCache_clicked() { QPixmap(":/icons/information-line.png") .scaled(42, 42, Qt::KeepAspectRatio, Qt::SmoothTransformation)); - msgBox.setInformativeText("Delete Application cache ?"); + msgBox.setInformativeText("Delete Application cache?"); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int ret = msgBox.exec(); @@ -263,14 +297,13 @@ void SettingsWidget::on_deletePersistentData_clicked() { msgBox.setIconPixmap( QPixmap(":/icons/information-line.png") .scaled(42, 42, Qt::KeepAspectRatio, Qt::SmoothTransformation)); - msgBox.setInformativeText("Delete Application Cookies ?"); + msgBox.setInformativeText("Delete Application Cookies?"); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int ret = msgBox.exec(); switch (ret) { case QMessageBox::Yes: { - utils::delete_cache(this->persistentStoragePath()); - refresh(); + clearAllData(); break; } case QMessageBox::No: @@ -278,6 +311,12 @@ void SettingsWidget::on_deletePersistentData_clicked() { } } +void SettingsWidget::clearAllData() { + utils::delete_cache(this->cachePath()); + utils::delete_cache(this->persistentStoragePath()); + refresh(); +} + void SettingsWidget::on_notificationCheckBox_toggled(bool checked) { settings.setValue("disableNotificationPopups", checked); } @@ -356,21 +395,54 @@ void SettingsWidget::on_closeButtonActionComboBox_currentIndexChanged( } void SettingsWidget::appLockSetChecked(bool checked) { + ui->applock_checkbox->blockSignals(true); ui->applock_checkbox->setChecked(checked); + ui->applock_checkbox->blockSignals(false); } void SettingsWidget::setCurrentPasswordText(QString str) { - ui->current_password->setText(str); + ui->current_password->setStyleSheet( + "QLineEdit[echoMode=\"2\"]{lineedit-password-character: 9899}"); + if (str == "Require setup") { + ui->current_password->setEchoMode(QLineEdit::Normal); + } else { + ui->current_password->setEchoMode(QLineEdit::Password); + ui->current_password->setText(str); + } } void SettingsWidget::on_applock_checkbox_toggled(bool checked) { if (settings.value("asdfg").isValid()) { settings.setValue("lockscreen", checked); + } else if (checked && !settings.value("asdfg").isValid()) { + settings.setValue("lockscreen", true); + if (checked) + showSetApplockPasswordDialog(); } else { settings.setValue("lockscreen", false); + if (checked) + showSetApplockPasswordDialog(); } - if (checked) { - emit init_lock(); +} + +void SettingsWidget::showSetApplockPasswordDialog() { + QMessageBox msgBox; + msgBox.setText("App lock is not configured."); + msgBox.setIconPixmap( + QPixmap(":/icons/information-line.png") + .scaled(42, 42, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + msgBox.setInformativeText("Do you want to setup App lock now?"); + msgBox.setStandardButtons(QMessageBox::Cancel); + QPushButton *setAppLock = new QPushButton( + this->style()->standardIcon(QStyle::SP_DialogYesButton), "Yes", nullptr); + msgBox.addButton(setAppLock, QMessageBox::NoRole); + connect(setAppLock, &QPushButton::clicked, setAppLock, + [=]() { emit init_lock(); }); + int ret = msgBox.exec(); + if (ret == QMessageBox::Cancel) { + ui->applock_checkbox->blockSignals(true); + ui->applock_checkbox->setChecked(false); + ui->applock_checkbox->blockSignals(false); } } @@ -443,14 +515,15 @@ void SettingsWidget::on_automaticThemeCheckBox_toggled(bool checked) { " | Automatic theme switcher setup"); automaticTheme->setWindowFlag(Qt::Dialog); automaticTheme->setAttribute(Qt::WA_DeleteOnClose, true); - connect(automaticTheme, &AutomaticTheme::destroyed, [=]() { - bool automaticThemeSwitching = - settings.value("automaticTheme", false).toBool(); - ui->automaticThemeCheckBox->setChecked(automaticThemeSwitching); - if (automaticThemeSwitching) - themeSwitchTimerTimeout(); - updateAutomaticTheme(); - }); + connect(automaticTheme, &AutomaticTheme::destroyed, + ui->automaticThemeCheckBox, [=]() { + bool automaticThemeSwitching = + settings.value("automaticTheme", false).toBool(); + ui->automaticThemeCheckBox->setChecked(automaticThemeSwitching); + if (automaticThemeSwitching) + themeSwitchTimerTimeout(); + updateAutomaticTheme(); + }); automaticTheme->show(); } else { settings.setValue("automaticTheme", false); @@ -462,11 +535,38 @@ void SettingsWidget::on_useNativeFileDialog_toggled(bool checked) { settings.setValue("useNativeFileDialog", checked); } +void SettingsWidget::on_startMinimized_toggled(bool checked) { + settings.setValue("startMinimized", checked); +} + +void SettingsWidget::on_appAutoLockcheckBox_toggled(bool checked) { + settings.setValue("appAutoLocking", checked); +} + +void SettingsWidget::on_autoLockDurationSpinbox_valueChanged(int arg1) { + settings.setValue("autoLockDuration", arg1); +} + +void SettingsWidget::on_resetAppAutoLockPushButton_clicked() { + ui->appAutoLockcheckBox->setChecked(defaultAppAutoLock); + ui->autoLockDurationSpinbox->setValue(defaultAppAutoLockDuration); +} + +void SettingsWidget::on_minimizeOnTrayIconClick_toggled(bool checked) { + settings.setValue("minimizeOnTrayIconClick", checked); +} + +void SettingsWidget::on_styleComboBox_currentTextChanged(const QString &arg1) { + applyThemeQuirks(); + settings.setValue("widgetStyle", arg1); + emit updateWindowTheme(); + emit updatePageTheme(); +} + void SettingsWidget::on_zoomPlus_clicked() { double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); double newFactor = currentFactor + 0.25; ui->zoomFactorSpinBox->setValue(newFactor); - settings.setValue("zoomFactor", ui->zoomFactorSpinBox->value()); emit zoomChanged(); } @@ -475,19 +575,119 @@ void SettingsWidget::on_zoomMinus_clicked() { double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); double newFactor = currentFactor - 0.25; ui->zoomFactorSpinBox->setValue(newFactor); - settings.setValue("zoomFactor", ui->zoomFactorSpinBox->value()); emit zoomChanged(); } void SettingsWidget::on_zoomReset_clicked() { - double newFactor = 1.0; - ui->zoomFactorSpinBox->setValue(newFactor); - + ui->zoomFactorSpinBox->setValue(1.0); settings.setValue("zoomFactor", ui->zoomFactorSpinBox->value()); emit zoomChanged(); } -void SettingsWidget::on_startMinimized_toggled(bool checked) { - settings.setValue("startMinimized", checked); +void SettingsWidget::on_zoomResetMaximized_clicked() { + ui->zoomFactorSpinBoxMaximized->setValue(defaultZoomFactorMaximized); + settings.setValue("zoomFactorMaximized", + ui->zoomFactorSpinBoxMaximized->value()); + emit zoomMaximizedChanged(); +} + +void SettingsWidget::on_zoomPlusMaximized_clicked() { + double currentFactor = + settings.value("zoomFactorMaximized", defaultZoomFactorMaximized) + .toDouble(); + double newFactor = currentFactor + 0.25; + ui->zoomFactorSpinBoxMaximized->setValue(newFactor); + settings.setValue("zoomFactorMaximized", + ui->zoomFactorSpinBoxMaximized->value()); + emit zoomMaximizedChanged(); +} + +void SettingsWidget::on_zoomMinusMaximized_clicked() { + double currentFactor = + settings.value("zoomFactorMaximized", defaultZoomFactorMaximized) + .toDouble(); + double newFactor = currentFactor - 0.25; + ui->zoomFactorSpinBoxMaximized->setValue(newFactor); + settings.setValue("zoomFactorMaximized", + ui->zoomFactorSpinBoxMaximized->value()); + emit zoomMaximizedChanged(); +} + +void SettingsWidget::on_changeDefaultDownloadLocationPb_clicked() { + QFileDialog dialog(this); + dialog.setFileMode(QFileDialog::Directory); + dialog.setOption(QFileDialog::ShowDirsOnly); + + QString path; + bool usenativeFileDialog = + settings.value("useNativeFileDialog", false).toBool(); + if (usenativeFileDialog == false) { + path = QFileDialog::getExistingDirectory( + this, tr("Select download directory"), + settings + .value("defaultDownloadLocation", + QStandardPaths::writableLocation( + QStandardPaths::DownloadLocation) + + QDir::separator() + QApplication::applicationName()) + .toString(), + QFileDialog::DontUseNativeDialog); + } else { + path = QFileDialog::getSaveFileName( + this, tr("Select download directory"), + settings + .value("defaultDownloadLocation", + QStandardPaths::writableLocation( + QStandardPaths::DownloadLocation) + + QDir::separator() + QApplication::applicationName()) + .toString()); + } + + if (!path.isNull() && !path.isEmpty()) { + ui->defaultDownloadLocation->setText(path); + settings.setValue("defaultDownloadLocation", path); + } +} + +void SettingsWidget::on_userAgentLineEdit_editingFinished() { + ui->userAgentLineEdit->home(true); + ui->userAgentLineEdit->deselect(); +} + +void SettingsWidget::on_viewPassword_clicked() { + ui->current_password->setEchoMode(QLineEdit::Normal); + ui->viewPassword->setEnabled(false); + QTimer *timer = new QTimer(this); + timer->setInterval(5000); + connect(timer, &QTimer::timeout, ui->current_password, [=]() { + ui->current_password->setEchoMode(QLineEdit::Password); + ui->viewPassword->setEnabled(true); + timer->stop(); + timer->deleteLater(); + }); + timer->start(); +} + +void SettingsWidget::on_chnageCurrentPasswordPushButton_clicked() { + if (settings.value("asdfg").isValid()) { + QMessageBox msgBox; + msgBox.setText("You are about to change your current app lock password!" + "\n\nThis will LogOut your current session."); + msgBox.setIconPixmap( + QPixmap(":/icons/information-line.png") + .scaled(42, 42, Qt::KeepAspectRatio, Qt::SmoothTransformation)); + msgBox.setInformativeText("Do you want to proceed?"); + msgBox.setStandardButtons(QMessageBox::Cancel); + QPushButton *changePassword = + new QPushButton(this->style()->standardIcon(QStyle::SP_DialogYesButton), + "Change password", nullptr); + msgBox.addButton(changePassword, QMessageBox::NoRole); + connect(changePassword, &QPushButton::clicked, changePassword, + [=]() { emit change_lock_password(); }); + msgBox.exec(); + + } else { + settings.setValue("lockscreen", false); + showSetApplockPasswordDialog(); + } } diff --git a/src/settingswidget.h b/src/settingswidget.h index d7353ec..c9931a2 100644 --- a/src/settingswidget.h +++ b/src/settingswidget.h @@ -1,110 +1,102 @@ #ifndef SETTINGSWIDGET_H #define SETTINGSWIDGET_H -#include -#include -#include "utils.h" - #include "permissiondialog.h" +#include "utils.h" - +#include +#include namespace Ui { class SettingsWidget; } -class SettingsWidget : public QWidget -{ - Q_OBJECT +class SettingsWidget : public QWidget { + Q_OBJECT signals: - void updateWindowTheme(); - void updatePageTheme(); - void muteToggled(const bool checked); - void autoPlayMediaToggled(const bool checked); - void userAgentChanged(QString userAgentStr); - void init_lock(); - void dictChanged(QString dict); - void spellCheckChanged(bool checked); - void notificationPopupTimeOutChanged(); - void notify(QString message); - void zoomChanged(); + void updateWindowTheme(); + void updatePageTheme(); + void muteToggled(const bool checked); + void autoPlayMediaToggled(const bool checked); + void userAgentChanged(QString userAgentStr); + void init_lock(); + void change_lock_password(); + void dictChanged(QString dict); + void spellCheckChanged(bool checked); + void notificationPopupTimeOutChanged(); + void notify(QString message); + void zoomChanged(); + void zoomMaximizedChanged(); public: - explicit SettingsWidget(QWidget *parent = nullptr,QString engineCachePath = "", - QString enginePersistentStoragePath = ""); - ~SettingsWidget(); + explicit SettingsWidget(QWidget *parent = nullptr, + QString engineCachePath = "", + QString enginePersistentStoragePath = ""); + ~SettingsWidget(); public slots: - void refresh(); - void updateDefaultUAButton(const QString engineUA); - void appLockSetChecked(bool checked); - void setCurrentPasswordText(QString str); - void loadDictionaries(QStringList dictionaries); -protected slots: - bool eventFilter(QObject *obj, QEvent *event); - void closeEvent(QCloseEvent *event); -private slots: - QString cachePath(); - QString persistentStoragePath(); - - void on_deleteCache_clicked(); - - void on_deletePersistentData_clicked(); - - void on_notificationCheckBox_toggled(bool checked); - - void on_themeComboBox_currentTextChanged(const QString &arg1); - - void applyThemeQuirks(); - void on_muteAudioCheckBox_toggled(bool checked); - - void on_defaultUserAgentButton_clicked(); - - void on_userAgentLineEdit_textChanged(const QString &arg1); + void refresh(); + void updateDefaultUAButton(const QString engineUA); + void appLockSetChecked(bool checked); + void setCurrentPasswordText(QString str); + void loadDictionaries(QStringList dictionaries); - void on_setUserAgent_clicked(); - - void on_autoPlayMediaCheckBox_toggled(bool checked); - - void on_closeButtonActionComboBox_currentIndexChanged(int index); - - void on_applock_checkbox_toggled(bool checked); - - void on_dictComboBox_currentIndexChanged(const QString &arg1); - - void on_enableSpellCheck_toggled(bool checked); - - void on_showShortcutsButton_clicked(); - - void on_showPermissionsButton_clicked(); - - - void on_notificationTimeOutspinBox_valueChanged(int arg1); - - void on_notificationCombo_currentIndexChanged(int index); - - void on_tryNotification_clicked(); - - void on_automaticThemeCheckBox_toggled(bool checked); - - void updateAutomaticTheme(); - void themeSwitchTimerTimeout(); - void on_useNativeFileDialog_toggled(bool checked); - - void on_zoomPlus_clicked(); - void on_zoomMinus_clicked(); - - void on_zoomReset_clicked(); + void clearAllData(); +protected slots: + bool eventFilter(QObject *obj, QEvent *event); + void closeEvent(QCloseEvent *event); - bool isChildOf(QObject *Of, QObject *self); - void on_startMinimized_toggled(bool checked); +private slots: + QString cachePath(); + QString persistentStoragePath(); + bool isChildOf(QObject *Of, QObject *self); + void applyThemeQuirks(); + void on_appAutoLockcheckBox_toggled(bool checked); + void on_applock_checkbox_toggled(bool checked); + void on_autoLockDurationSpinbox_valueChanged(int arg1); + void on_autoPlayMediaCheckBox_toggled(bool checked); + void on_automaticThemeCheckBox_toggled(bool checked); + void on_changeDefaultDownloadLocationPb_clicked(); + void on_chnageCurrentPasswordPushButton_clicked(); + void on_closeButtonActionComboBox_currentIndexChanged(int index); + void on_defaultUserAgentButton_clicked(); + void on_deleteCache_clicked(); + void on_deletePersistentData_clicked(); + void on_dictComboBox_currentIndexChanged(const QString &arg1); + void on_enableSpellCheck_toggled(bool checked); + void on_minimizeOnTrayIconClick_toggled(bool checked); + void on_muteAudioCheckBox_toggled(bool checked); + void on_notificationCheckBox_toggled(bool checked); + void on_notificationCombo_currentIndexChanged(int index); + void on_notificationTimeOutspinBox_valueChanged(int arg1); + void on_resetAppAutoLockPushButton_clicked(); + void on_setUserAgent_clicked(); + void on_showPermissionsButton_clicked(); + void on_showShortcutsButton_clicked(); + void on_startMinimized_toggled(bool checked); + void on_styleComboBox_currentTextChanged(const QString &arg1); + void on_themeComboBox_currentTextChanged(const QString &arg1); + void on_tryNotification_clicked(); + void on_useNativeFileDialog_toggled(bool checked); + void on_userAgentLineEdit_editingFinished(); + void on_userAgentLineEdit_textChanged(const QString &arg1); + void on_viewPassword_clicked(); + void on_zoomMinusMaximized_clicked(); + void on_zoomMinus_clicked(); + void on_zoomPlusMaximized_clicked(); + void on_zoomPlus_clicked(); + void on_zoomResetMaximized_clicked(); + void on_zoomReset_clicked(); + void showSetApplockPasswordDialog(); + void themeSwitchTimerTimeout(); + void updateAutomaticTheme(); private: - Ui::SettingsWidget *ui; - QString engineCachePath,enginePersistentStoragePath; - QSettings settings; - QTimer *themeSwitchTimer; + Ui::SettingsWidget *ui; + QString engineCachePath, enginePersistentStoragePath; + QSettings settings; + QTimer *themeSwitchTimer; }; #endif // SETTINGSWIDGET_H diff --git a/src/settingswidget.ui b/src/settingswidget.ui index 09e5639..44f6b7a 100644 --- a/src/settingswidget.ui +++ b/src/settingswidget.ui @@ -6,8 +6,8 @@ 0 0 - 537 - 580 + 637 + 792 @@ -98,8 +98,8 @@ background:transparent; 0 0 - 521 - 592 + 621 + 791 @@ -112,128 +112,88 @@ background:transparent; - + - Close button action + Widget Style - - - - Minimize to tray - - - - :/icons/window-2-line.png:/icons/window-2-line.png - - - - - Quit Application - - - - :/icons/shut-down-line.png:/icons/shut-down-line.png - - - + - - - - 0 + + + + + 0 + 1 + - - - - <html><head/><body><p>Enable application lock screen.</p></body></html> - - - Enable App Lock on Start - - - - - - - Current Password: - - - - + + + 16777215 + 1 + + + + background-color: rgba(63, 129, 216, 48); + + + QFrame::Raised + + + Qt::Horizontal + + - - - - - - - 1 - 0 - - - - - 1 - 16777215 - - - - background-color: rgba(63, 129, 216, 48); - - - Qt::Vertical - - - + + - + - Disable Notifications PopUp + Widget Theme - - - - Disable Auto Playback of Media + + + + + 0 + 0 + + + + <html><head/><body><p>Based on your system timezone and location.</p></body></html> - - - - - Mute Audio from Page + Automatic - + - - - PopUp timeout - - + + Dark + + + + :/icons/moon-line.png:/icons/moon-line.png + - - - Secs - - - 2 - - - 20 - - + + Light + + + + :/icons/lightbulb-line.png:/icons/lightbulb-line.png + - + @@ -262,127 +222,9 @@ background:transparent; - - - - - - Start minimized - - - - - - - Use Native File Dialog - - - - - - - - - - - Enable Spell Checker - - - - - - - - 1 - 0 - - - - - 1 - 16777215 - - - - background-color: rgba(63, 129, 216, 48); - - - QFrame::Raised - - - Qt::Vertical - - - - - - - SpellChecker Language - - - - - - - - - - - - 0 - - - - - App permissions - - - - - - - Show permissions - - - - :/icons/categories/security.png:/icons/categories/security.png - - - - - - - - - - - Global App shortcuts - - - - - - - Show shortcuts - - - - :/icons/share-forward-line.png:/icons/share-forward-line.png - - - - - - - - - - Notification type - - - - + + @@ -404,7 +246,7 @@ background:transparent; - + @@ -421,10 +263,44 @@ background:transparent; + + + + Notification type + + + + + + + Disable Notifications PopUp + + + + + + + PopUp timeout + + + + + + + Secs + + + 2 + + + 20 + + + - - + + 0 @@ -448,7 +324,60 @@ background:transparent; - + + + + + + Spell checker Language + + + + + + + Use Native File Dialog + + + + + + + Mute Audio from Page + + + + + + + Disable Auto Playback of Media + + + + + + + Enable Spell Checker + + + + + + + Minimize app in tray on start + + + + + + + Minimize/Maximize on right clicking tray Icon + + + + + + @@ -473,164 +402,490 @@ background:transparent; + + Reset to default + - Default + - :/icons/refresh-line.png:/icons/refresh-line.png + :/icons/arrow-go-back-line.png:/icons/arrow-go-back-line.png - - - - - - Theme + + + + + + 0 - + + + + Zoom factor when normal + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + Zoom Out + + + + + + + :/icons/minus.png:/icons/minus.png + + + + + + + + 0 + 0 + + + + Qt::AlignCenter + + + true + + + QAbstractSpinBox::NoButtons + + + + + + + + 0 + 0 + + + + Zoom In + + + + + + + :/icons/plus.png:/icons/plus.png + + + + + + + + 1 + 0 + + + + + 1 + 16777215 + + + + background-color: rgba(63, 129, 216, 48); + + + QFrame::Raised + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + reset + + + + + + + :/icons/arrow-go-back-line.png:/icons/arrow-go-back-line.png + + + + + + - - - - - 0 - 0 - - - - <html><head/><body><p>Based on your system timezone and location.</p></body></html> - - - Automatic + + + + 0 - + + + + Zoom factor when maximized/fullscreen + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + Zoom Out + + + + + + + :/icons/minus.png:/icons/minus.png + + + + + + + + 0 + 0 + + + + Qt::AlignCenter + + + true + + + QAbstractSpinBox::NoButtons + + + + + + + + 0 + 0 + + + + Zoom In + + + + + + + :/icons/plus.png:/icons/plus.png + + + + + + + + 1 + 0 + + + + + 1 + 16777215 + + + + background-color: rgba(63, 129, 216, 48); + + + QFrame::Raised + + + Qt::Vertical + + + + + + + + 0 + 0 + + + + reset + + + + + + + :/icons/arrow-go-back-line.png:/icons/arrow-go-back-line.png + + + + + + - - + + + + + + - Dark + Minimize to tray - :/icons/moon-line.png:/icons/moon-line.png + :/icons/window-2-line.png:/icons/window-2-line.png - Light + Quit Application - :/icons/lightbulb-line.png:/icons/lightbulb-line.png + :/icons/shut-down-line.png:/icons/shut-down-line.png - - - - - - 0 - - - + + - Zoom factor + Global App shortcuts - - - - - 0 - 0 - - - - Zoom Out + + + + Close button action + + + + - + Show shortcuts - :/icons/minus.png:/icons/minus.png + :/icons/share-forward-line.png:/icons/share-forward-line.png - - - - - 0 - 0 - + + + + App permissions - - Qt::AlignCenter + + + + + + Show permissions - - true + + + :/icons/categories/security.png:/icons/categories/security.png - - QAbstractSpinBox::NoButtons + + + + + + + + + + <html><head/><body><p>Enable application lock screen.</p></body></html> + + + Enable App lock on start - - - - - 0 - 0 - + + + + Current Password + + + + - Zoom In + Change password - + Change - :/icons/plus.png:/icons/plus.png + :/icons/categories/utilities.png:/icons/categories/utilities.png - - - - - 1 - 0 - + + + + Enable App auto locking after - - - 1 - 16777215 - + + + + + + Secs - - background-color: rgba(63, 129, 216, 48); + + 10 - - QFrame::Raised + + 14400 - - Qt::Vertical + + 60 - - + + + + Change password + + + Reset + + + + :/icons/arrow-go-back-line.png:/icons/arrow-go-back-line.png + + + + + + + + + + + + QLineEdit::Password + + + true + + + + + + + + 0 + 0 + + + + View password + + + + + + + :/icons/eye-line.png:/icons/eye-line.png + + + + + + + + + + + + + true + + + + + + + Default Download location + + + + + 0 @@ -638,14 +893,14 @@ background:transparent; - reset + Change Download Location - + Change - :/icons/arrow-go-back-line.png:/icons/arrow-go-back-line.png + :/icons/folder-download-line.png:/icons/folder-download-line.png @@ -692,6 +947,12 @@ background:transparent; + + + 0 + 0 + + 10 @@ -705,6 +966,12 @@ background:transparent; + + + 0 + 0 + + 10 @@ -721,6 +988,12 @@ background:transparent; + + + 0 + 0 + + 10 diff --git a/src/utils.cpp b/src/utils.cpp index 802c51d..eeab445 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -122,14 +122,12 @@ QString utils::convertSectoDay(qint64 secs) { } // static on demand path maker -QString utils::returnPath(QString pathname) { - QString _data_path = - QStandardPaths::writableLocation(QStandardPaths::DataLocation); - if (!QDir(_data_path + "/" + pathname).exists()) { - QDir d(_data_path + "/" + pathname); - d.mkpath(_data_path + "/" + pathname); - } - return _data_path + "/" + pathname + "/"; +QString utils::returnPath(QString pathname,QString standardLocation = QStandardPaths::writableLocation( + QStandardPaths::DataLocation)) { + QChar sepe = QDir::separator(); + QDir d(standardLocation + sepe + pathname); + d.mkpath(standardLocation + sepe + pathname); + return standardLocation + sepe + pathname + sepe; } QString utils::EncodeXML(const QString &encodeMe) { diff --git a/src/utils.h b/src/utils.h index bd76e9d..93cbaca 100644 --- a/src/utils.h +++ b/src/utils.h @@ -23,7 +23,7 @@ public slots: static QString generateRandomId(int length); static QString genRand(int length); static QString convertSectoDay(qint64 secs); - static QString returnPath(QString pathname); + static QString returnPath(QString pathname, QString standardLocation); static QString EncodeXML ( const QString& encodeMe ); static QString DecodeXML ( const QString& decodeMe ); static QString htmlToPlainText(QString str); diff --git a/src/webenginepage.cpp b/src/webenginepage.cpp index d5ecfff..451d187 100644 --- a/src/webenginepage.cpp +++ b/src/webenginepage.cpp @@ -6,7 +6,6 @@ WebEnginePage::WebEnginePage(QWebEngineProfile *profile, QObject *parent) : QWebEnginePage(profile, parent) { - // Connect signals and slots profile->setHttpUserAgent( profile->httpUserAgent().replace("QtWebEngine/5.13.0", "")); connect(this, &QWebEnginePage::loadFinished, this, @@ -29,8 +28,6 @@ WebEnginePage::WebEnginePage(QWebEngineProfile *profile, QObject *parent) bool WebEnginePage::acceptNavigationRequest(const QUrl &url, QWebEnginePage::NavigationType type, bool isMainFrame) { - qDebug() << "Navigation request: [" + url.toDisplayString() + "] " + type; - if (QWebEnginePage::NavigationType::NavigationTypeLinkClicked == type) { QDesktopServices::openUrl(url); return false; @@ -132,7 +129,6 @@ void WebEnginePage::handleLoadFinished(bool ok) { void WebEnginePage::fullScreenRequestedByPage( QWebEngineFullScreenRequest request) { - // qDebug()<<"Fullscreen"; request.accept(); } @@ -216,9 +212,9 @@ void WebEnginePage::handleAuthenticationRequired(const QUrl &requestUrl, nullptr, mainWindow)); passwordDialog.m_iconLabel->setPixmap(icon.pixmap(32, 32)); - QString introMessage(tr("Enter username and password for \"%1\" at %2") - .arg(auth->realm()) - .arg(requestUrl.toString().toHtmlEscaped())); + QString introMessage( + tr("Enter username and password for \"%1\" at %2") + .arg(auth->realm(), requestUrl.toString().toHtmlEscaped())); passwordDialog.m_infoLabel->setText(introMessage); passwordDialog.m_infoLabel->setWordWrap(true); @@ -264,11 +260,10 @@ void WebEnginePage::handleProxyAuthenticationRequired( //! [registerProtocolHandlerRequested] void WebEnginePage::handleRegisterProtocolHandlerRequested( QWebEngineRegisterProtocolHandlerRequest request) { - auto answer = - QMessageBox::question(view()->window(), tr("Permission Request"), - tr("Allow %1 to open all %2 links?") - .arg(request.origin().host()) - .arg(request.scheme())); + auto answer = QMessageBox::question( + view()->window(), tr("Permission Request"), + tr("Allow %1 to open all %2 links?") + .arg(request.origin().host(), request.scheme())); if (answer == QMessageBox::Yes) request.accept(); else @@ -283,7 +278,7 @@ void WebEnginePage::handleSelectClientCertificate( selection.select(selection.certificates().at(0)); qDebug() << __FUNCTION__; - for (QSslCertificate cert : selection.certificates()) { + for (const QSslCertificate &cert : selection.certificates()) { qDebug() << cert; selection.select(cert); // select the first available cert break; diff --git a/src/webview.cpp b/src/webview.cpp index 39273eb..7f497a3 100644 --- a/src/webview.cpp +++ b/src/webview.cpp @@ -44,7 +44,7 @@ WebView::WebView(QWidget *parent, QStringList dictionaries) "Do you want to reload the page ?") .arg(statusCode)); if (btn == QMessageBox::Yes) - QTimer::singleShot(0, [this] { this->reload(); }); + QTimer::singleShot(0, this, [this] { this->reload(); }); }); } @@ -80,7 +80,7 @@ void WebView::contextMenuEvent(QContextMenuEvent *event) { if (profile->isSpellCheckEnabled()) { QMenu *subMenu = menu->addMenu(tr("Select Language")); - for (const QString &dict : m_dictionaries) { + for (const QString &dict : qAsConst(m_dictionaries)) { QAction *action = subMenu->addAction(dict); action->setCheckable(true); action->setChecked(languages.contains(dict)); diff --git a/src/webview.h b/src/webview.h index b896ad6..70b5a6e 100644 --- a/src/webview.h +++ b/src/webview.h @@ -1,22 +1,21 @@ #ifndef WEBVIEW_H #define WEBVIEW_H -#include #include +#include -class WebView: public QWebEngineView -{ - Q_OBJECT +class WebView : public QWebEngineView { + Q_OBJECT public: - WebView(QWidget *parent = nullptr, QStringList dictionaries = {}); + WebView(QWidget *parent = nullptr, QStringList dictionaries = {}); protected: - void contextMenuEvent(QContextMenuEvent *event) override; + void contextMenuEvent(QContextMenuEvent *event) override; private: - QStringList m_dictionaries; - QSettings settings; + QStringList m_dictionaries; + QSettings settings; }; #endif // WEBVIEW_H -- cgit v1.2.3 From ed5f760bf4c4126d0f5c64bb4a0cba75c963fb9b Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Wed, 30 Mar 2022 12:59:51 +0530 Subject: fix: improve logout flow, on change password --- src/mainwindow.cpp | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- src/mainwindow.h | 3 +++ 2 files changed, 50 insertions(+), 3 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b9ec4f5..1893448 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -199,6 +199,42 @@ void MainWindow::handleCookieAdded(const QNetworkCookie &cookie) { qDebug() << cookie.toRawForm() << "\n\n\n"; } +void MainWindow::forceLogOut() { + if (webEngine && webEngine->page()) { + webEngine->page()->runJavaScript( + "window.localStorage.clear();", + [=](const QVariant &result) { qDebug() << result; }); + } +} + +bool MainWindow::isLoggedIn(){ + static bool loggedIn = false; + if (webEngine && webEngine->page()) { + webEngine->page()->runJavaScript( + "window.localStorage.getItem('WAToken2')", + [=](const QVariant &result) { qDebug() <page()) { + webEngine->page()->runJavaScript( + "document.querySelector(\"span[data-testid|='menu']\").click();" + "document.querySelector(\"#side > header > div > div > span > div > " + "span > div > ul > li:nth-child(5) > div\").click()", + [=](const QVariant &result) { qDebug() << Q_FUNC_INFO << result; }); + } +} + void MainWindow::init_settingWidget() { if (settingsWidget == nullptr) { settingsWidget = new SettingsWidget( @@ -597,9 +633,17 @@ void MainWindow::init_lock() { void MainWindow::change_lock_password() { settings.remove("asdfg"); settingsWidget->appLockSetChecked(false); - settingsWidget->clearAllData(); - doAppReload(); - init_lock(); + + tryLogOut(); + QTimer::singleShot(2000, this, [=]() { + if(isLoggedIn()){ + forceLogOut(); + doAppReload(); + } + init_lock(); + }); + + } // check window state and set tray menus diff --git a/src/mainwindow.h b/src/mainwindow.h index e1298b0..1f966bd 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -118,6 +118,9 @@ private slots: void handleZoom(); void change_lock_password(); void tryLock(); + void forceLogOut(); + void tryLogOut(); + bool isLoggedIn(); }; #endif // MAINWINDOW_H -- cgit v1.2.3 From d06a4abb4755d0e97e8ef03688bc878117d90b4e Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Wed, 30 Mar 2022 17:30:58 +0530 Subject: feat: app auto locking - settings to allow app auto locking after set time interval --- src/WhatsApp.pro | 1 + src/autolockeventfilter.h | 48 ++++++++++++++++++++++++++++ src/common.h | 2 +- src/lock.cpp | 1 - src/mainwindow.cpp | 80 +++++++++++++++++++++++++++++++++-------------- src/mainwindow.h | 4 +++ src/settingswidget.cpp | 27 ++++++++++++++-- src/settingswidget.h | 3 ++ src/settingswidget.ui | 16 +++++----- 9 files changed, 146 insertions(+), 36 deletions(-) create mode 100644 src/autolockeventfilter.h (limited to 'src/mainwindow.h') diff --git a/src/WhatsApp.pro b/src/WhatsApp.pro index b83ec8e..9bff312 100644 --- a/src/WhatsApp.pro +++ b/src/WhatsApp.pro @@ -76,6 +76,7 @@ RESOURCES += \ HEADERS += \ SunClock.hpp \ about.h \ + autolockeventfilter.h \ automatictheme.h \ common.h \ dictionaries.h \ diff --git a/src/autolockeventfilter.h b/src/autolockeventfilter.h new file mode 100644 index 0000000..2f05504 --- /dev/null +++ b/src/autolockeventfilter.h @@ -0,0 +1,48 @@ +#ifndef AUTOLOCKEVENTFILTER_H +#define AUTOLOCKEVENTFILTER_H + +#include +#include +#include + +class AutoLockEventFilter : public QObject { + Q_OBJECT + +public: + explicit AutoLockEventFilter(int timeoutmillis) + : timeoutmillis(timeoutmillis) { + autoLockTimer = new QTimer(this); + connect(autoLockTimer, &QTimer::timeout, this, + QOverload<>::of(&AutoLockEventFilter::lockApp)); + resetTimer(); + } + + ~AutoLockEventFilter() { + autoLockTimer->stop(); + autoLockTimer->deleteLater(); + } + +signals: + void autoLockTimerTimeout(); + +private: + QTimer *autoLockTimer = nullptr; + int timeoutmillis; + +public slots: + void stopTimer() { autoLockTimer->stop(); } + void resetTimer() { autoLockTimer->start(timeoutmillis); } + void lockApp() { emit autoLockTimerTimeout(); } + void setTimeoutmillis(int newTimeoutmillis) { + timeoutmillis = newTimeoutmillis; + } + +protected: + bool eventFilter(QObject *obj, QEvent *ev) { + if (ev->type() == QEvent::KeyPress || ev->type() == QEvent::MouseMove) { + resetTimer(); + } + return QObject::eventFilter(obj, ev); + } +}; +#endif // AUTOLOCKEVENTFILTER_H diff --git a/src/common.h b/src/common.h index 0d57ab8..85b608d 100644 --- a/src/common.h +++ b/src/common.h @@ -6,7 +6,7 @@ QString defaultUserAgentStr = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.102 Safari/537.36"; //appAutoLock -int defaultAppAutoLockDuration = 60; +int defaultAppAutoLockDuration = 30; bool defaultAppAutoLock = false; double defaultZoomFactorMaximized = 1.50; diff --git a/src/lock.cpp b/src/lock.cpp index 6cd0d6c..f9d80ff 100644 --- a/src/lock.cpp +++ b/src/lock.cpp @@ -30,7 +30,6 @@ Lock::Lock(QWidget *parent) : QWidget(parent), ui(new Ui::Lock) { checkCaps(); QString capsStyle = QString("background-color: palette(window);" "padding:4px;" - "border:0px solid palette(highlight);" "border-radius: 2px;" "color:palette(window-text);"); ui->caps1->setStyleSheet(capsStyle); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 74f196c..5a29c60 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -9,6 +9,8 @@ extern QString defaultUserAgentStr; extern double defaultZoomFactorMaximized; +extern int defaultAppAutoLockDuration; +extern bool defaultAppAutoLock; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), notificationsTitleRegExp("^\\([1-9]\\d*\\).*"), @@ -30,6 +32,22 @@ MainWindow::MainWindow(QWidget *parent) initRateWidget(); tryLock(); updateWindowTheme(); + initAutoLock(); +} + +void MainWindow::initAutoLock() { + autoLockEventFilter = new AutoLockEventFilter( + settings.value("autoLockDuration", defaultAppAutoLockDuration).toInt() * + 1000); + connect(autoLockEventFilter, &AutoLockEventFilter::autoLockTimerTimeout, this, + [=]() { + if (settings.value("appAutoLocking", defaultAppAutoLock).toBool()) { + this->lockApp(); + } + }); + if (settings.value("appAutoLocking", defaultAppAutoLock).toBool()) { + qApp->installEventFilter(autoLockEventFilter); + } } void MainWindow::initThemes() { @@ -204,22 +222,22 @@ void MainWindow::forceLogOut() { } } -bool MainWindow::isLoggedIn(){ - static bool loggedIn = false; - if (webEngine && webEngine->page()) { - webEngine->page()->runJavaScript( - "window.localStorage.getItem('WAToken2')", - [=](const QVariant &result) { qDebug() <page()) { + webEngine->page()->runJavaScript( + "window.localStorage.getItem('WAToken2')", [=](const QVariant &result) { + qDebug() << Q_FUNC_INFO << result; + if (result.isValid() && result.toString().isEmpty() == false) { + loggedIn = true; + } }); - qDebug() << "isLoggedIn" <appLockSetChecked(false); - + settingsWidget->autoAppLockSetChecked(false); + settingsWidget->updateAppLockPasswordViewer(); tryLogOut(); - QTimer::singleShot(2000, this, [=]() { - if(isLoggedIn()){ - forceLogOut(); - doAppReload(); - } - init_lock(); + QTimer::singleShot(1500, this, [=]() { + if (isLoggedIn()) { + forceLogOut(); + doAppReload(); + } + appAutoLockChanged(); + init_lock(); }); +} - +void MainWindow::appAutoLockChanged() { + bool enabled = settings.value("appAutoLocking", defaultAppAutoLock).toBool(); + if (enabled) { + qApp->installEventFilter(autoLockEventFilter); + autoLockEventFilter->setTimeoutmillis( + settings.value("autoLockDuration", defaultAppAutoLockDuration).toInt() * + 1000); + autoLockEventFilter->resetTimer(); + } else { + qApp->removeEventFilter(autoLockEventFilter); + autoLockEventFilter->stopTimer(); + } } // check window state and set tray menus diff --git a/src/mainwindow.h b/src/mainwindow.h index 1f966bd..c3c82a2 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -34,6 +34,7 @@ #include "settingswidget.h" #include "webenginepage.h" #include "webview.h" +#include "autolockeventfilter.h" class MainWindow : public QMainWindow { Q_OBJECT @@ -84,6 +85,7 @@ private: Lock *lockWidget = nullptr; int correctlyLoaderRetries = 4; QStringList m_dictionaries; + AutoLockEventFilter *autoLockEventFilter = nullptr; private slots: @@ -121,6 +123,8 @@ private slots: void forceLogOut(); void tryLogOut(); bool isLoggedIn(); + void initAutoLock(); + void appAutoLockChanged(); }; #endif // MAINWINDOW_H diff --git a/src/settingswidget.cpp b/src/settingswidget.cpp index 2e2b095..75e1075 100644 --- a/src/settingswidget.cpp +++ b/src/settingswidget.cpp @@ -54,8 +54,10 @@ SettingsWidget::SettingsWidget(QWidget *parent, QString engineCachePath, settings.value("useNativeFileDialog", false).toBool()); ui->startMinimized->setChecked( settings.value("startMinimized", false).toBool()); - ui->appAutoLockcheckBox->setChecked( + + appLockSetChecked( settings.value("appAutoLocking", defaultAppAutoLock).toBool()); + ui->autoLockDurationSpinbox->setValue( settings.value("autoLockDuration", defaultAppAutoLockDuration).toInt()); ui->minimizeOnTrayIconClick->setChecked( @@ -394,6 +396,17 @@ void SettingsWidget::on_closeButtonActionComboBox_currentIndexChanged( settings.setValue("closeButtonActionCombo", index); } +void SettingsWidget::autoAppLockSetChecked(bool checked) { + ui->appAutoLockcheckBox->blockSignals(true); + ui->appAutoLockcheckBox->setChecked(checked); + ui->appAutoLockcheckBox->blockSignals(false); +} + +void SettingsWidget::updateAppLockPasswordViewer() { + this->setCurrentPasswordText( + QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())); +} + void SettingsWidget::appLockSetChecked(bool checked) { ui->applock_checkbox->blockSignals(true); ui->applock_checkbox->setChecked(checked); @@ -540,11 +553,21 @@ void SettingsWidget::on_startMinimized_toggled(bool checked) { } void SettingsWidget::on_appAutoLockcheckBox_toggled(bool checked) { - settings.setValue("appAutoLocking", checked); + if (settings.value("asdfg").isValid()) { + settings.setValue("appAutoLocking", checked); + } else { + showSetApplockPasswordDialog(); + if (settings.value("asdfg").isValid() == false) { + settings.setValue("appAutoLocking", false); + autoAppLockSetChecked(false); + } + } + emit appAutoLockChanged(); } void SettingsWidget::on_autoLockDurationSpinbox_valueChanged(int arg1) { settings.setValue("autoLockDuration", arg1); + emit appAutoLockChanged(); } void SettingsWidget::on_resetAppAutoLockPushButton_clicked() { diff --git a/src/settingswidget.h b/src/settingswidget.h index c9931a2..ccf48ec 100644 --- a/src/settingswidget.h +++ b/src/settingswidget.h @@ -28,6 +28,7 @@ signals: void notify(QString message); void zoomChanged(); void zoomMaximizedChanged(); + void appAutoLockChanged(); public: explicit SettingsWidget(QWidget *parent = nullptr, @@ -43,6 +44,8 @@ public slots: void loadDictionaries(QStringList dictionaries); void clearAllData(); + void autoAppLockSetChecked(bool checked); + void updateAppLockPasswordViewer(); protected slots: bool eventFilter(QObject *obj, QEvent *event); void closeEvent(QCloseEvent *event); diff --git a/src/settingswidget.ui b/src/settingswidget.ui index 44f6b7a..94cdcd7 100644 --- a/src/settingswidget.ui +++ b/src/settingswidget.ui @@ -6,8 +6,8 @@ 0 0 - 637 - 792 + 691 + 860 @@ -98,8 +98,8 @@ background:transparent; 0 0 - 621 - 791 + 675 + 808 @@ -371,7 +371,8 @@ background:transparent; - Minimize/Maximize on right clicking tray Icon + Minimize/Maximize on right clicking tray Icon +(if supported by system tray) @@ -805,14 +806,11 @@ background:transparent; Secs - 10 + 8 14400 - - 60 - -- cgit v1.2.3 From 81faa022735b155ac0773e1cc849474a0719c523 Mon Sep 17 00:00:00 2001 From: Keshav Date: Tue, 10 May 2022 10:09:53 +0530 Subject: feat: implement IPC & other improvements - lets run only one instance of application - lets pass arguments from secondary instances to main instance - open new chat without reloading page - restore application with commandline argument to secondary instance: example: whatsie whatsapp://whatsie will restore the primary instance of whatsie process --- src/WhatsApp.pro | 5 +- src/main.cpp | 47 ++- src/mainwindow.cpp | 98 +++-- src/mainwindow.h | 2 + src/singleapplication/LICENSE | 24 ++ src/singleapplication/SingleApplication | 1 + src/singleapplication/singleapplication.cpp | 272 +++++++++++++ src/singleapplication/singleapplication.h | 164 ++++++++ src/singleapplication/singleapplication.pri | 10 + src/singleapplication/singleapplication_p.cpp | 550 ++++++++++++++++++++++++++ src/singleapplication/singleapplication_p.h | 109 +++++ 11 files changed, 1235 insertions(+), 47 deletions(-) create mode 100644 src/singleapplication/LICENSE create mode 100644 src/singleapplication/SingleApplication create mode 100644 src/singleapplication/singleapplication.cpp create mode 100644 src/singleapplication/singleapplication.h create mode 100644 src/singleapplication/singleapplication.pri create mode 100644 src/singleapplication/singleapplication_p.cpp create mode 100644 src/singleapplication/singleapplication_p.h (limited to 'src/mainwindow.h') diff --git a/src/WhatsApp.pro b/src/WhatsApp.pro index a6aca88..2fce6ea 100644 --- a/src/WhatsApp.pro +++ b/src/WhatsApp.pro @@ -26,6 +26,9 @@ win32{ LIBS += User32.Lib } +include(singleapplication/singleapplication.pri) +DEFINES += QAPPLICATION_CLASS=QApplication + # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Refer to the documentation for the @@ -63,7 +66,6 @@ SOURCES += \ mainwindow.cpp \ permissiondialog.cpp \ rateapp.cpp \ - rungaurd.cpp \ settingswidget.cpp \ utils.cpp \ webenginepage.cpp \ @@ -89,7 +91,6 @@ HEADERS += \ permissiondialog.h \ rateapp.h \ requestinterceptor.h \ - rungaurd.h \ settingswidget.h \ utils.h \ webenginepage.h \ diff --git a/src/main.cpp b/src/main.cpp index b162833..0303f3a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,10 +6,9 @@ #include #include -#include "mainwindow.h" - #include "common.h" -#include "rungaurd.h" +#include "mainwindow.h" +#include int main(int argc, char *argv[]) { @@ -19,7 +18,7 @@ int main(int argc, char *argv[]) { if (args.contains("-v") || args.contains("--version")) { qInfo() << QString("version: %1, branch: %2, commit: %3, built_at: %4") - .arg(VERSIONSTR, GIT_BRANCH, GIT_HASH, BUILD_TIMESTAMP); + .arg(VERSIONSTR, GIT_BRANCH, GIT_HASH, BUILD_TIMESTAMP); return 0; } @@ -38,18 +37,20 @@ int main(int argc, char *argv[]) { qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-logging --single-process"); #endif - QApplication app(argc, argv); + SingleApplication app(argc, argv, true); app.setQuitOnLastWindowClosed(false); app.setWindowIcon(QIcon(":/icons/app/icon-128.png")); QApplication::setApplicationName("WhatSie"); QApplication::setOrganizationName("org.keshavnrj.ubuntu"); QApplication::setApplicationVersion(VERSIONSTR); - QString appname = QApplication::applicationName(); - RunGuard guard("org.keshavnrj.ubuntu." + appname); - if (!guard.tryToRun()) { - QMessageBox::critical(0, appname, - "An instance of " + appname + " is already running."); + // if secondary instance is invoked + if (app.isSecondary()) { + app.sendMessage(app.arguments().join(' ').toUtf8()); + qInfo() << QApplication::applicationName() + + " is already running with PID:" + + QString::number(app.primaryPid()) + "; by USER: " + << app.primaryUser(); return 0; } @@ -64,18 +65,38 @@ int main(int argc, char *argv[]) { MainWindow window; + // else + QObject::connect( + &app, &SingleApplication::receivedMessage, + [&window](int instanceId, QByteArray message) { + qInfo() << "Another instance with PID: " + QString::number(instanceId) + + ", sent argument: " + message; + QString messageStr = QTextCodec::codecForMib(106)->toUnicode(message); + if (messageStr.contains("whatsapp://whatsie", Qt::CaseInsensitive)) { + window.show(); + return; + } else if (messageStr.contains("whatsapp://", Qt::CaseInsensitive)) { + QString urlStr = + "whatsapp://" + messageStr.split("whatsapp://").last(); + window.loadAppWithArgument(urlStr); + } else { + window.alreadyRunning(); + } + }); + QStringList argsList = app.arguments(); foreach (QString argStr, argsList) { if (argStr.contains("whatsapp://")) { window.loadAppWithArgument(argStr); } } + QSettings settings; if (QSystemTrayIcon::isSystemTrayAvailable() && settings.value("startMinimized", false).toBool()) { - window.runMinimized(); - }else{ - window.show(); + window.runMinimized(); + } else { + window.show(); } return app.exec(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index b828593..f32d24b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -128,8 +128,8 @@ void MainWindow::initRateWidget() { } void MainWindow::runMinimized() { - this->minimizeAction->trigger(); - notify("Whatsie", "Whatsie started minimized in tray"); + this->minimizeAction->trigger(); + notify("Whatsie", "Whatsie started minimized in tray. Click to Open."); } MainWindow::~MainWindow() { webEngine->deleteLater(); } @@ -137,12 +137,6 @@ MainWindow::~MainWindow() { webEngine->deleteLater(); } void MainWindow::loadAppWithArgument(const QString &arg) { // https://faq.whatsapp.com/iphone/how-to-link-to-whatsapp-from-a-different-app/?lang=en - // The WhatsApp Messenger application - if (arg.contains("://app")) { - this->show(); // restore app - return; - } - // PASSED SCHEME whatsapp://send?text=Hello%2C%20World!&phone=919568388397" // CONVERTED URI // https://web.whatsapp.com/send?phone=919568388397&text=Hello%2C%20World New @@ -151,15 +145,28 @@ void MainWindow::loadAppWithArgument(const QString &arg) { QString newArg = arg; newArg = newArg.replace("?", "&"); QUrlQuery query(newArg); - QString phone, phoneStr, text, textStr, urlStr; - // create send url equivalent + + static QString phone, phoneStr, text, textStr, urlStr; phone = query.queryItemValue("phone"); text = query.queryItemValue("text"); - phoneStr = phone.isEmpty() ? "" : "phone=" + phone; - textStr = text.isEmpty() ? "" : "text=" + text; - urlStr = "https://web.whatsapp.com/send?" + phoneStr + "&" + textStr; - this->webEngine->page()->load(QUrl(urlStr)); - return; + + webEngine->page()->runJavaScript( + "openNewChatWhatsieDefined()", [this](const QVariant &result) { + if (result.toString().contains("true")) { + this->webEngine->page()->runJavaScript( + QString("openNewChatWhatsie(\"%1\",\"%2\")").arg(phone, text)); + this->notify(QApplication::applicationName(), + "New chat with " + phoneStr + + " is ready. Click to Open."); + } else { + // create send url equivalent + phoneStr = phone.isEmpty() ? "" : "phone=" + phone; + textStr = text.isEmpty() ? "" : "text=" + text; + urlStr = + "https://web.whatsapp.com/send?" + phoneStr + "&" + textStr; + this->webEngine->page()->load(QUrl(urlStr)); + } + }); } } @@ -198,7 +205,9 @@ void MainWindow::updateWindowTheme() { } QList widgets = this->findChildren(); - foreach (QWidget *w, widgets) { w->setPalette(qApp->palette()); } + foreach (QWidget *w, widgets) { + w->setPalette(qApp->palette()); + } setNotificationPresenter(webEngine->page()->profile()); if (lockWidget != nullptr) { @@ -485,19 +494,19 @@ void MainWindow::notify(QString title, QString message) { if (windowState().testFlag(Qt::WindowMinimized) || !windowState().testFlag(Qt::WindowActive)) { activateWindow(); - //raise(); + // raise(); this->show(); } }); } else { auto popup = new NotificationPopup(webEngine); connect(popup, &NotificationPopup::notification_clicked, popup, [=]() { - if (windowState().testFlag(Qt::WindowMinimized) || - !windowState().testFlag(Qt::WindowActive) || - this->isHidden()) { - this->show(); - setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); - } + if (windowState().testFlag(Qt::WindowMinimized) || + !windowState().testFlag(Qt::WindowActive) || this->isHidden()) { + this->show(); + setWindowState((windowState() & ~Qt::WindowMinimized) | + Qt::WindowActive); + } }); popup->style()->polish(qApp); popup->setMinimumWidth(300); @@ -794,8 +803,7 @@ void MainWindow::createWebPage(bool offTheRecord) { connect(profile, &QWebEngineProfile::downloadRequested, &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested); - connect(page, - SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)), this, + connect(page, SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)), this, SLOT(fullScreenRequested(QWebEngineFullScreenRequest))); double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); @@ -814,8 +822,8 @@ void MainWindow::setNotificationPresenter(QWebEngineProfile *profile) { connect(popup, &NotificationPopup::notification_clicked, popup, [=]() { if (windowState().testFlag(Qt::WindowMinimized) || !windowState().testFlag(Qt::WindowActive) || this->isHidden()) { - this->show(); - setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); + this->show(); + setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); } }); @@ -833,11 +841,12 @@ void MainWindow::setNotificationPresenter(QWebEngineProfile *profile) { settings.value("notificationTimeOut", 9000).toInt()); trayIcon->disconnect(trayIcon, SIGNAL(messageClicked())); connect(trayIcon, &QSystemTrayIcon::messageClicked, trayIcon, [=]() { - if (windowState().testFlag(Qt::WindowMinimized) || - !windowState().testFlag(Qt::WindowActive) || this->isHidden()) { - this->show(); - setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive); - } + if (windowState().testFlag(Qt::WindowMinimized) || + !windowState().testFlag(Qt::WindowActive) || this->isHidden()) { + this->show(); + setWindowState((windowState() & ~Qt::WindowMinimized) | + Qt::WindowActive); + } }); } else { @@ -890,10 +899,27 @@ void MainWindow::handleLoadFinished(bool loaded) { checkLoadedCorrectly(); updatePageTheme(); handleZoom(); + injectNewChatJavaScript(); settingsWidget->refresh(); } } +void MainWindow::injectNewChatJavaScript() { + QString js = "const openNewChatWhatsie = (phone,text) => { " + "const link = document.createElement('a');" + "link.setAttribute('href', " + "`whatsapp://send/?phone=${phone}&text=${text}`);" + "document.body.append(link);" + "link.click();" + "document.body.removeChild(link);" + "};" + "function openNewChatWhatsieDefined()" + "{" + " return (openNewChatWhatsie != 'undefined');" + "}"; + webEngine->page()->runJavaScript(js); +} + void MainWindow::checkLoadedCorrectly() { if (webEngine && webEngine->page()) { // test 1 based on the class name of body of the page @@ -1055,3 +1081,11 @@ void MainWindow::tryLock() { init_lock(); } } + +void MainWindow::alreadyRunning() { + QString appname = QApplication::applicationName(); + this->notify( + appname, + QString("An instance of %1 is already Running, click to restore.") + .arg(appname)); +} diff --git a/src/mainwindow.h b/src/mainwindow.h index c3c82a2..8573226 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -50,6 +50,7 @@ public slots: void handleDownloadRequested(QWebEngineDownloadItem *download); void loadAppWithArgument(const QString &arg); void runMinimized(); + void alreadyRunning(); protected slots: void closeEvent(QCloseEvent *event) override; void resizeEvent(QResizeEvent *event) override; @@ -125,6 +126,7 @@ private slots: bool isLoggedIn(); void initAutoLock(); void appAutoLockChanged(); + void injectNewChatJavaScript(); }; #endif // MAINWINDOW_H diff --git a/src/singleapplication/LICENSE b/src/singleapplication/LICENSE new file mode 100644 index 0000000..a82e5a6 --- /dev/null +++ b/src/singleapplication/LICENSE @@ -0,0 +1,24 @@ +The MIT License (MIT) + +Copyright (c) Itay Grudev 2015 - 2020 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Note: Some of the examples include code not distributed under the terms of the +MIT License. diff --git a/src/singleapplication/SingleApplication b/src/singleapplication/SingleApplication new file mode 100644 index 0000000..8ead1a4 --- /dev/null +++ b/src/singleapplication/SingleApplication @@ -0,0 +1 @@ +#include "singleapplication.h" diff --git a/src/singleapplication/singleapplication.cpp b/src/singleapplication/singleapplication.cpp new file mode 100644 index 0000000..1234ff9 --- /dev/null +++ b/src/singleapplication/singleapplication.cpp @@ -0,0 +1,272 @@ +// The MIT License (MIT) +// +// Copyright (c) Itay Grudev 2015 - 2020 +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include +#include +#include + +#include "singleapplication.h" +#include "singleapplication_p.h" + +/** + * @brief Constructor. Checks and fires up LocalServer or closes the program + * if another instance already exists + * @param argc + * @param argv + * @param allowSecondary Whether to enable secondary instance support + * @param options Optional flags to toggle specific behaviour + * @param timeout Maximum time blocking functions are allowed during app load + */ +SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout, const QString &userData ) + : app_t( argc, argv ), d_ptr( new SingleApplicationPrivate( this ) ) +{ + Q_D( SingleApplication ); + +#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) + // On Android and iOS since the library is not supported fallback to + // standard QApplication behaviour by simply returning at this point. + qWarning() << "SingleApplication is not supported on Android and iOS systems."; + return; +#endif + + // Store the current mode of the program + d->options = options; + + // Add any unique user data + if ( ! userData.isEmpty() ) + d->addAppData( userData ); + + // Generating an application ID used for identifying the shared memory + // block and QLocalServer + d->genBlockServerName(); + + // To mitigate QSharedMemory issues with large amount of processes + // attempting to attach at the same time + SingleApplicationPrivate::randomSleep(); + +#ifdef Q_OS_UNIX + // By explicitly attaching it and then deleting it we make sure that the + // memory is deleted even after the process has crashed on Unix. + d->memory = new QSharedMemory( d->blockServerName ); + d->memory->attach(); + delete d->memory; +#endif + // Guarantee thread safe behaviour with a shared memory block. + d->memory = new QSharedMemory( d->blockServerName ); + + // Create a shared memory block + if( d->memory->create( sizeof( InstancesInfo ) )){ + // Initialize the shared memory block + if( ! d->memory->lock() ){ + qCritical() << "SingleApplication: Unable to lock memory block after create."; + abortSafely(); + } + d->initializeMemoryBlock(); + } else { + if( d->memory->error() == QSharedMemory::AlreadyExists ){ + // Attempt to attach to the memory segment + if( ! d->memory->attach() ){ + qCritical() << "SingleApplication: Unable to attach to shared memory block."; + abortSafely(); + } + if( ! d->memory->lock() ){ + qCritical() << "SingleApplication: Unable to lock memory block after attach."; + abortSafely(); + } + } else { + qCritical() << "SingleApplication: Unable to create block."; + abortSafely(); + } + } + + auto *inst = static_cast( d->memory->data() ); + QElapsedTimer time; + time.start(); + + // Make sure the shared memory block is initialised and in consistent state + while( true ){ + // If the shared memory block's checksum is valid continue + if( d->blockChecksum() == inst->checksum ) break; + + // If more than 5s have elapsed, assume the primary instance crashed and + // assume it's position + if( time.elapsed() > 5000 ){ + qWarning() << "SingleApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure."; + d->initializeMemoryBlock(); + } + + // Otherwise wait for a random period and try again. The random sleep here + // limits the probability of a collision between two racing apps and + // allows the app to initialise faster + if( ! d->memory->unlock() ){ + qDebug() << "SingleApplication: Unable to unlock memory for random wait."; + qDebug() << d->memory->errorString(); + } + SingleApplicationPrivate::randomSleep(); + if( ! d->memory->lock() ){ + qCritical() << "SingleApplication: Unable to lock memory after random wait."; + abortSafely(); + } + } + + if( inst->primary == false ){ + d->startPrimary(); + if( ! d->memory->unlock() ){ + qDebug() << "SingleApplication: Unable to unlock memory after primary start."; + qDebug() << d->memory->errorString(); + } + return; + } + + // Check if another instance can be started + if( allowSecondary ){ + d->startSecondary(); + if( d->options & Mode::SecondaryNotification ){ + d->connectToPrimary( timeout, SingleApplicationPrivate::SecondaryInstance ); + } + if( ! d->memory->unlock() ){ + qDebug() << "SingleApplication: Unable to unlock memory after secondary start."; + qDebug() << d->memory->errorString(); + } + return; + } + + if( ! d->memory->unlock() ){ + qDebug() << "SingleApplication: Unable to unlock memory at end of execution."; + qDebug() << d->memory->errorString(); + } + + d->connectToPrimary( timeout, SingleApplicationPrivate::NewInstance ); + + delete d; + + ::exit( EXIT_SUCCESS ); +} + +SingleApplication::~SingleApplication() +{ + Q_D( SingleApplication ); + delete d; +} + +/** + * Checks if the current application instance is primary. + * @return Returns true if the instance is primary, false otherwise. + */ +bool SingleApplication::isPrimary() const +{ + Q_D( const SingleApplication ); + return d->server != nullptr; +} + +/** + * Checks if the current application instance is secondary. + * @return Returns true if the instance is secondary, false otherwise. + */ +bool SingleApplication::isSecondary() const +{ + Q_D( const SingleApplication ); + return d->server == nullptr; +} + +/** + * Allows you to identify an instance by returning unique consecutive instance + * ids. It is reset when the first (primary) instance of your app starts and + * only incremented afterwards. + * @return Returns a unique instance id. + */ +quint32 SingleApplication::instanceId() const +{ + Q_D( const SingleApplication ); + return d->instanceNumber; +} + +/** + * Returns the OS PID (Process Identifier) of the process running the primary + * instance. Especially useful when SingleApplication is coupled with OS. + * specific APIs. + * @return Returns the primary instance PID. + */ +qint64 SingleApplication::primaryPid() const +{ + Q_D( const SingleApplication ); + return d->primaryPid(); +} + +/** + * Returns the username the primary instance is running as. + * @return Returns the username the primary instance is running as. + */ +QString SingleApplication::primaryUser() const +{ + Q_D( const SingleApplication ); + return d->primaryUser(); +} + +/** + * Returns the username the current instance is running as. + * @return Returns the username the current instance is running as. + */ +QString SingleApplication::currentUser() const +{ + return SingleApplicationPrivate::getUsername(); +} + +/** + * Sends message to the Primary Instance. + * @param message The message to send. + * @param timeout the maximum timeout in milliseconds for blocking functions. + * @param sendMode mode of operation + * @return true if the message was sent successfuly, false otherwise. + */ +bool SingleApplication::sendMessage( const QByteArray &message, int timeout, SendMode sendMode ) +{ + Q_D( SingleApplication ); + + // Nobody to connect to + if( isPrimary() ) return false; + + // Make sure the socket is connected + if( ! d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect ) ) + return false; + + return d->writeConfirmedMessage( timeout, message, sendMode ); +} + +/** + * Cleans up the shared memory block and exits with a failure. + * This function halts program execution. + */ +void SingleApplication::abortSafely() +{ + Q_D( SingleApplication ); + + qCritical() << "SingleApplication: " << d->memory->error() << d->memory->errorString(); + delete d; + ::exit( EXIT_FAILURE ); +} + +QStringList SingleApplication::userData() const +{ + Q_D( const SingleApplication ); + return d->appData(); +} diff --git a/src/singleapplication/singleapplication.h b/src/singleapplication/singleapplication.h new file mode 100644 index 0000000..5565bb8 --- /dev/null +++ b/src/singleapplication/singleapplication.h @@ -0,0 +1,164 @@ +// The MIT License (MIT) +// +// Copyright (c) Itay Grudev 2015 - 2018 +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#ifndef SINGLE_APPLICATION_H +#define SINGLE_APPLICATION_H + +#include +#include + +#ifndef QAPPLICATION_CLASS + #define QAPPLICATION_CLASS QCoreApplication +#endif + +#include QT_STRINGIFY(QAPPLICATION_CLASS) + +class SingleApplicationPrivate; + +/** + * @brief The SingleApplication class handles multiple instances of the same + * Application + * @see QCoreApplication + */ +class SingleApplication : public QAPPLICATION_CLASS +{ + Q_OBJECT + + using app_t = QAPPLICATION_CLASS; + +public: + /** + * @brief Mode of operation of SingleApplication. + * Whether the block should be user-wide or system-wide and whether the + * primary instance should be notified when a secondary instance had been + * started. + * @note Operating system can restrict the shared memory blocks to the same + * user, in which case the User/System modes will have no effect and the + * block will be user wide. + * @enum + */ + enum Mode { + User = 1 << 0, + System = 1 << 1, + SecondaryNotification = 1 << 2, + ExcludeAppVersion = 1 << 3, + ExcludeAppPath = 1 << 4 + }; + Q_DECLARE_FLAGS(Options, Mode) + + /** + * @brief Intitializes a SingleApplication instance with argc command line + * arguments in argv + * @arg {int &} argc - Number of arguments in argv + * @arg {const char *[]} argv - Supplied command line arguments + * @arg {bool} allowSecondary - Whether to start the instance as secondary + * if there is already a primary instance. + * @arg {Mode} mode - Whether for the SingleApplication block to be applied + * User wide or System wide. + * @arg {int} timeout - Timeout to wait in milliseconds. + * @note argc and argv may be changed as Qt removes arguments that it + * recognizes + * @note Mode::SecondaryNotification only works if set on both the primary + * instance and the secondary instance. + * @note The timeout is just a hint for the maximum time of blocking + * operations. It does not guarantee that the SingleApplication + * initialisation will be completed in given time, though is a good hint. + * Usually 4*timeout would be the worst case (fail) scenario. + * @see See the corresponding QAPPLICATION_CLASS constructor for reference + */ + explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000, const QString &userData = {} ); + ~SingleApplication() override; + + /** + * @brief Returns if the instance is the primary instance + * @returns {bool} + */ + bool isPrimary() const; + + /** + * @brief Returns if the instance is a secondary instance + * @returns {bool} + */ + bool isSecondary() const; + + /** + * @brief Returns a unique identifier for the current instance + * @returns {qint32} + */ + quint32 instanceId() const; + + /** + * @brief Returns the process ID (PID) of the primary instance + * @returns {qint64} + */ + qint64 primaryPid() const; + + /** + * @brief Returns the username of the user running the primary instance + * @returns {QString} + */ + QString primaryUser() const; + + /** + * @brief Returns the username of the current user + * @returns {QString} + */ + QString currentUser() const; + + /** + * @brief Mode of operation of sendMessage. + * @enum + */ + enum SendMode { + NonBlocking, /** Do not wait for the primary instance termination and return immediately */ + BlockUntilPrimaryExit, /** Wait until the primary instance is terminated */ + }; + + /** + * @brief Sends a message to the primary instance. Returns true on success. + * @param {int} timeout - Timeout for connecting + * @param {SendMode} sendMode - Mode of operation. + * @returns {bool} + * @note sendMessage() will return false if invoked from the primary + * instance. + */ + bool sendMessage( const QByteArray &message, int timeout = 100, SendMode sendMode = NonBlocking ); + + /** + * @brief Get the set user data. + * @returns {QStringList} + */ + QStringList userData() const; + +Q_SIGNALS: + void instanceStarted(); + void receivedMessage( quint32 instanceId, QByteArray message ); + +private: + SingleApplicationPrivate *d_ptr; + Q_DECLARE_PRIVATE(SingleApplication) + void abortSafely(); +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options) + +#endif // SINGLE_APPLICATION_H diff --git a/src/singleapplication/singleapplication.pri b/src/singleapplication/singleapplication.pri new file mode 100644 index 0000000..3597909 --- /dev/null +++ b/src/singleapplication/singleapplication.pri @@ -0,0 +1,10 @@ +QT += core network +CONFIG += c++11 + +HEADERS += $$PWD/SingleApplication \ + $$PWD/singleapplication.h \ + $$PWD/singleapplication_p.h +SOURCES += $$PWD/singleapplication.cpp \ + $$PWD/singleapplication_p.cpp + +INCLUDEPATH += $$PWD diff --git a/src/singleapplication/singleapplication_p.cpp b/src/singleapplication/singleapplication_p.cpp new file mode 100644 index 0000000..2a369bc --- /dev/null +++ b/src/singleapplication/singleapplication_p.cpp @@ -0,0 +1,550 @@ +// The MIT License (MIT) +// +// Copyright (c) Itay Grudev 2015 - 2020 +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// +// W A R N I N G !!! +// ----------------- +// +// This file is not part of the SingleApplication API. It is used purely as an +// implementation detail. This header file may change from version to +// version without notice, or may even be removed. +// + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) +#include +#else +#include +#endif + +#include "singleapplication.h" +#include "singleapplication_p.h" + +#ifdef Q_OS_UNIX + #include + #include + #include +#endif + +#ifdef Q_OS_WIN + #ifndef NOMINMAX + #define NOMINMAX 1 + #endif + #include + #include +#endif + +SingleApplicationPrivate::SingleApplicationPrivate( SingleApplication *q_ptr ) + : q_ptr( q_ptr ) +{ + server = nullptr; + socket = nullptr; + memory = nullptr; + instanceNumber = 0; +} + +SingleApplicationPrivate::~SingleApplicationPrivate() +{ + if( socket != nullptr ){ + socket->close(); + delete socket; + } + + if( memory != nullptr ){ + memory->lock(); + auto *inst = static_cast(memory->data()); + if( server != nullptr ){ + server->close(); + delete server; + inst->primary = false; + inst->primaryPid = -1; + inst->primaryUser[0] = '\0'; + inst->checksum = blockChecksum(); + } + memory->unlock(); + + delete memory; + } +} + +QString SingleApplicationPrivate::getUsername() +{ +#ifdef Q_OS_WIN + wchar_t username[UNLEN + 1]; + // Specifies size of the buffer on input + DWORD usernameLength = UNLEN + 1; + if( GetUserNameW( username, &usernameLength ) ) + return QString::fromWCharArray( username ); +#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) + return QString::fromLocal8Bit( qgetenv( "USERNAME" ) ); +#else + return qEnvironmentVariable( "USERNAME" ); +#endif +#endif +#ifdef Q_OS_UNIX + QString username; + uid_t uid = geteuid(); + struct passwd *pw = getpwuid( uid ); + if( pw ) + username = QString::fromLocal8Bit( pw->pw_name ); + if ( username.isEmpty() ){ +#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) + username = QString::fromLocal8Bit( qgetenv( "USER" ) ); +#else + username = qEnvironmentVariable( "USER" ); +#endif + } + return username; +#endif +} + +void SingleApplicationPrivate::genBlockServerName() +{ + QCryptographicHash appData( QCryptographicHash::Sha256 ); +#if QT_VERSION < QT_VERSION_CHECK(6, 3, 0) + appData.addData( "SingleApplication", 17 ); +#else + appData.addData( QByteArrayView{"SingleApplication"} ); +#endif + appData.addData( SingleApplication::app_t::applicationName().toUtf8() ); + appData.addData( SingleApplication::app_t::organizationName().toUtf8() ); + appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() ); + + if ( ! appDataList.isEmpty() ) + appData.addData( appDataList.join(QString()).toUtf8() ); + + if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ){ + appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() ); + } + + if( ! (options & SingleApplication::Mode::ExcludeAppPath) ){ +#if defined(Q_OS_WIN) + appData.addData( SingleApplication::app_t::applicationFilePath().toLower().toUtf8() ); +#elif defined(Q_OS_LINUX) + // If the application is running as an AppImage then the APPIMAGE env var should be used + // instead of applicationPath() as each instance is launched with its own executable path + const QByteArray appImagePath = qgetenv( "APPIMAGE" ); + if( appImagePath.isEmpty() ){ // Not running as AppImage: use path to executable file + appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() ); + } else { // Running as AppImage: Use absolute path to AppImage file + appData.addData( appImagePath ); + }; +#else + appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() ); +#endif + } + + // User level block requires a user specific data in the hash + if( options & SingleApplication::Mode::User ){ + appData.addData( getUsername().toUtf8() ); + } + + // Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with + // server naming requirements. + blockServerName = QString::fromUtf8(appData.result().toBase64().replace("/", "_")); +} + +void SingleApplicationPrivate::initializeMemoryBlock() const +{ + auto *inst = static_cast( memory->data() ); + inst->primary = false; + inst->secondary = 0; + inst->primaryPid = -1; + inst->primaryUser[0] = '\0'; + inst->checksum = blockChecksum(); +} + +void SingleApplicationPrivate::startPrimary() +{ + // Reset the number of connections + auto *inst = static_cast ( memory->data() ); + + inst->primary = true; + inst->primaryPid = QCoreApplication::applicationPid(); + qstrncpy( inst->primaryUser, getUsername().toUtf8().data(), sizeof(inst->primaryUser) ); + inst->checksum = blockChecksum(); + instanceNumber = 0; + // Successful creation means that no main process exists + // So we start a QLocalServer to listen for connections + QLocalServer::removeServer( blockServerName ); + server = new QLocalServer(); + + // Restrict access to the socket according to the + // SingleApplication::Mode::User flag on User level or no restrictions + if( options & SingleApplication::Mode::User ){ + server->setSocketOptions( QLocalServer::UserAccessOption ); + } else { + server->setSocketOptions( QLocalServer::WorldAccessOption ); + } + + server->listen( blockServerName ); + QObject::connect( + server, + &QLocalServer::newConnection, + this, + &SingleApplicationPrivate::slotConnectionEstablished + ); +} + +void SingleApplicationPrivate::startSecondary() +{ + auto *inst = static_cast ( memory->data() ); + + inst->secondary += 1; + inst->checksum = blockChecksum(); + instanceNumber = inst->secondary; +} + +bool SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType connectionType ) +{ + QElapsedTimer time; + time.start(); + + // Connect to the Local Server of the Primary Instance if not already + // connected. + if( socket == nullptr ){ + socket = new QLocalSocket(); + } + + if( socket->state() == QLocalSocket::ConnectedState ) return true; + + if( socket->state() != QLocalSocket::ConnectedState ){ + + while( true ){ + randomSleep(); + + if( socket->state() != QLocalSocket::ConnectingState ) + socket->connectToServer( blockServerName ); + + if( socket->state() == QLocalSocket::ConnectingState ){ + socket->waitForConnected( static_cast(msecs - time.elapsed()) ); + } + + // If connected break out of the loop + if( socket->state() == QLocalSocket::ConnectedState ) break; + + // If elapsed time since start is longer than the method timeout return + if( time.elapsed() >= msecs ) return false; + } + } + + // Initialisation message according to the SingleApplication protocol + QByteArray initMsg; + QDataStream writeStream(&initMsg, QIODevice::WriteOnly); + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) + writeStream.setVersion(QDataStream::Qt_5_6); +#endif + + writeStream << blockServerName.toLatin1(); + writeStream << static_cast(connectionType); + writeStream << instanceNumber; +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + quint16 checksum = qChecksum(QByteArray(initMsg.constData(), static_cast(initMsg.length()))); +#else + quint16 checksum = qChecksum(initMsg.constData(), static_cast(initMsg.length())); +#endif + writeStream << checksum; + + return writeConfirmedMessage( static_cast(msecs - time.elapsed()), initMsg ); +} + +void SingleApplicationPrivate::writeAck( QLocalSocket *sock ) { + sock->putChar('\n'); +} + +bool SingleApplicationPrivate::writeConfirmedMessage (int msecs, const QByteArray &msg, SingleApplication::SendMode sendMode) +{ + QElapsedTimer time; + time.start(); + + // Frame 1: The header indicates the message length that follows + QByteArray header; + QDataStream headerStream(&header, QIODevice::WriteOnly); + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) + headerStream.setVersion(QDataStream::Qt_5_6); +#endif + headerStream << static_cast ( msg.length() ); + + if( ! writeConfirmedFrame( static_cast(msecs - time.elapsed()), header )) + return false; + + // Frame 2: The message + const bool result = writeConfirmedFrame( static_cast(msecs - time.elapsed()), msg ); + + // Block if needed + if (socket && sendMode == SingleApplication::BlockUntilPrimaryExit) + socket->waitForDisconnected(-1); + + return result; +} + +bool SingleApplicationPrivate::writeConfirmedFrame( int msecs, const QByteArray &msg ) +{ + socket->write( msg ); + socket->flush(); + + bool result = socket->waitForReadyRead( msecs ); // await ack byte + if (result) { + socket->read( 1 ); + return true; + } + + return false; +} + +quint16 SingleApplicationPrivate::blockChecksum() const +{ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + quint16 checksum = qChecksum(QByteArray(static_cast(memory->constData()), offsetof(InstancesInfo, checksum))); +#else + quint16 checksum = qChecksum(static_cast(memory->constData()), offsetof(InstancesInfo, checksum)); +#endif + return checksum; +} + +qint64 SingleApplicationPrivate::primaryPid() const +{ + qint64 pid; + + memory->lock(); + auto *inst = static_cast( memory->data() ); + pid = inst->primaryPid; + memory->unlock(); + + return pid; +} + +QString SingleApplicationPrivate::primaryUser() const +{ + QByteArray username; + + memory->lock(); + auto *inst = static_cast( memory->data() ); + username = inst->primaryUser; + memory->unlock(); + + return QString::fromUtf8( username ); +} + +/** + * @brief Executed when a connection has been made to the LocalServer + */ +void SingleApplicationPrivate::slotConnectionEstablished() +{ + QLocalSocket *nextConnSocket = server->nextPendingConnection(); + connectionMap.insert(nextConnSocket, ConnectionInfo()); + + QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose, this, + [nextConnSocket, this](){ + auto &info = connectionMap[nextConnSocket]; + this->slotClientConnectionClosed( nextConnSocket, info.instanceId ); + } + ); + + QObject::connect(nextConnSocket, &QLocalSocket::disconnected, nextConnSocket, &QLocalSocket::deleteLater); + + QObject::connect(nextConnSocket, &QLocalSocket::destroyed, this, + [nextConnSocket, this](){ + connectionMap.remove(nextConnSocket); + } + ); + + QObject::connect(nextConnSocket, &QLocalSocket::readyRead, this, + [nextConnSocket, this](){ + auto &info = connectionMap[nextConnSocket]; + switch(info.stage){ + case StageInitHeader: + readMessageHeader( nextConnSocket, StageInitBody ); + break; + case StageInitBody: + readInitMessageBody(nextConnSocket); + break; + case StageConnectedHeader: + readMessageHeader( nextConnSocket, StageConnectedBody ); + break; + case StageConnectedBody: + this->slotDataAvailable( nextConnSocket, info.instanceId ); + break; + default: + break; + }; + } + ); +} + +void SingleApplicationPrivate::readMessageHeader( QLocalSocket *sock, SingleApplicationPrivate::ConnectionStage nextStage ) +{ + if (!connectionMap.contains( sock )){ + return; + } + + if( sock->bytesAvailable() < ( qint64 )sizeof( quint64 ) ){ + return; + } + + QDataStream headerStream( sock ); + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) + headerStream.setVersion( QDataStream::Qt_5_6 ); +#endif + + // Read the header to know the message length + quint64 msgLen = 0; + headerStream >> msgLen; + ConnectionInfo &info = connectionMap[sock]; + info.stage = nextStage; + info.msgLen = msgLen; + + writeAck( sock ); +} + +bool SingleApplicationPrivate::isFrameComplete( QLocalSocket *sock ) +{ + if (!connectionMap.contains( sock )){ + return false; + } + + ConnectionInfo &info = connectionMap[sock]; + if( sock->bytesAvailable() < ( qint64 )info.msgLen ){ + return false; + } + + return true; +} + +void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock ) +{ + Q_Q(SingleApplication); + + if( !isFrameComplete( sock ) ) + return; + + // Read the message body + QByteArray msgBytes = sock->readAll(); + QDataStream readStream(msgBytes); + +#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) + readStream.setVersion( QDataStream::Qt_5_6 ); +#endif + + // server name + QByteArray latin1Name; + readStream >> latin1Name; + + // connection type + ConnectionType connectionType = InvalidConnection; + quint8 connTypeVal = InvalidConnection; + readStream >> connTypeVal; + connectionType = static_cast ( connTypeVal ); + + // instance id + quint32 instanceId = 0; + readStream >> instanceId; + + // checksum + quint16 msgChecksum = 0; + readStream >> msgChecksum; + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const quint16 actualChecksum = qChecksum(QByteArray(msgBytes.constData(), static_cast(msgBytes.length() - sizeof(quint16)))); +#else + const quint16 actualChecksum = qChecksum(msgBytes.constData(), static_cast(msgBytes.length() - sizeof(quint16))); +#endif + + bool isValid = readStream.status() == QDataStream::Ok && + QLatin1String(latin1Name) == blockServerName && + msgChecksum == actualChecksum; + + if( !isValid ){ + sock->close(); + return; + } + + ConnectionInfo &info = connectionMap[sock]; + info.instanceId = instanceId; + info.stage = StageConnectedHeader; + + if( connectionType == NewInstance || + ( connectionType == SecondaryInstance && + options & SingleApplication::Mode::SecondaryNotification ) ) + { + Q_EMIT q->instanceStarted(); + } + + writeAck( sock ); +} + +void SingleApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId ) +{ + Q_Q(SingleApplication); + + if ( !isFrameComplete( dataSocket ) ) + return; + + const QByteArray message = dataSocket->readAll(); + + writeAck( dataSocket ); + + ConnectionInfo &info = connectionMap[dataSocket]; + info.stage = StageConnectedHeader; + + Q_EMIT q->receivedMessage( instanceId, message); +} + +void SingleApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId ) +{ + if( closedSocket->bytesAvailable() > 0 ) + slotDataAvailable( closedSocket, instanceId ); +} + +void SingleApplicationPrivate::randomSleep() +{ +#if QT_VERSION >= QT_VERSION_CHECK( 5, 10, 0 ) + QThread::msleep( QRandomGenerator::global()->bounded( 8u, 18u )); +#else + qsrand( QDateTime::currentMSecsSinceEpoch() % std::numeric_limits::max() ); + QThread::msleep( qrand() % 11 + 8); +#endif +} + +void SingleApplicationPrivate::addAppData(const QString &data) +{ + appDataList.push_back(data); +} + +QStringList SingleApplicationPrivate::appData() const +{ + return appDataList; +} diff --git a/src/singleapplication/singleapplication_p.h b/src/singleapplication/singleapplication_p.h new file mode 100644 index 0000000..30a2b51 --- /dev/null +++ b/src/singleapplication/singleapplication_p.h @@ -0,0 +1,109 @@ +// The MIT License (MIT) +// +// Copyright (c) Itay Grudev 2015 - 2020 +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// +// W A R N I N G !!! +// ----------------- +// +// This file is not part of the SingleApplication API. It is used purely as an +// implementation detail. This header file may change from version to +// version without notice, or may even be removed. +// + +#ifndef SINGLEAPPLICATION_P_H +#define SINGLEAPPLICATION_P_H + +#include +#include +#include +#include "singleapplication.h" + +struct InstancesInfo { + bool primary; + quint32 secondary; + qint64 primaryPid; + char primaryUser[128]; + quint16 checksum; // Must be the last field +}; + +struct ConnectionInfo { + qint64 msgLen = 0; + quint32 instanceId = 0; + quint8 stage = 0; +}; + +class SingleApplicationPrivate : public QObject { +Q_OBJECT +public: + enum ConnectionType : quint8 { + InvalidConnection = 0, + NewInstance = 1, + SecondaryInstance = 2, + Reconnect = 3 + }; + enum ConnectionStage : quint8 { + StageInitHeader = 0, + StageInitBody = 1, + StageConnectedHeader = 2, + StageConnectedBody = 3, + }; + Q_DECLARE_PUBLIC(SingleApplication) + + SingleApplicationPrivate( SingleApplication *q_ptr ); + ~SingleApplicationPrivate() override; + + static QString getUsername(); + void genBlockServerName(); + void initializeMemoryBlock() const; + void startPrimary(); + void startSecondary(); + bool connectToPrimary( int msecs, ConnectionType connectionType ); + quint16 blockChecksum() const; + qint64 primaryPid() const; + QString primaryUser() const; + bool isFrameComplete(QLocalSocket *sock); + void readMessageHeader(QLocalSocket *socket, ConnectionStage nextStage); + void readInitMessageBody(QLocalSocket *socket); + void writeAck(QLocalSocket *sock); + bool writeConfirmedFrame(int msecs, const QByteArray &msg); + bool writeConfirmedMessage(int msecs, const QByteArray &msg, SingleApplication::SendMode sendMode = SingleApplication::NonBlocking); + static void randomSleep(); + void addAppData(const QString &data); + QStringList appData() const; + + SingleApplication *q_ptr; + QSharedMemory *memory; + QLocalSocket *socket; + QLocalServer *server; + quint32 instanceNumber; + QString blockServerName; + SingleApplication::Options options; + QMap connectionMap; + QStringList appDataList; + +public Q_SLOTS: + void slotConnectionEstablished(); + void slotDataAvailable( QLocalSocket*, quint32 ); + void slotClientConnectionClosed( QLocalSocket*, quint32 ); +}; + +#endif // SINGLEAPPLICATION_P_H -- cgit v1.2.3 From 1d950cd8bd6fbe3ad7dde1f78fd984dff6d7d25d Mon Sep 17 00:00:00 2001 From: Keshav Date: Tue, 10 May 2022 10:52:48 +0530 Subject: chore: use new chat trigger method to invoke new chats --- src/mainwindow.cpp | 49 ++++++++++++++++++++++++++----------------------- src/mainwindow.h | 1 + 2 files changed, 27 insertions(+), 23 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index f32d24b..23bfb44 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -146,27 +146,10 @@ void MainWindow::loadAppWithArgument(const QString &arg) { newArg = newArg.replace("?", "&"); QUrlQuery query(newArg); - static QString phone, phoneStr, text, textStr, urlStr; + QString phone, text; phone = query.queryItemValue("phone"); text = query.queryItemValue("text"); - - webEngine->page()->runJavaScript( - "openNewChatWhatsieDefined()", [this](const QVariant &result) { - if (result.toString().contains("true")) { - this->webEngine->page()->runJavaScript( - QString("openNewChatWhatsie(\"%1\",\"%2\")").arg(phone, text)); - this->notify(QApplication::applicationName(), - "New chat with " + phoneStr + - " is ready. Click to Open."); - } else { - // create send url equivalent - phoneStr = phone.isEmpty() ? "" : "phone=" + phone; - textStr = text.isEmpty() ? "" : "text=" + text; - urlStr = - "https://web.whatsapp.com/send?" + phoneStr + "&" + textStr; - this->webEngine->page()->load(QUrl(urlStr)); - } - }); + triggerNewChat(phone, text); } } @@ -1024,14 +1007,13 @@ void MainWindow::doAppReload() { void MainWindow::newChat() { bool ok; - QString text = QInputDialog::getText( + QString phoneNumber = QInputDialog::getText( this, tr("New Chat"), tr("Enter a valid WhatsApp number with country code (ex- +91XXXXXXXXXX)"), QLineEdit::Normal, "", &ok); if (ok) { - if (isPhoneNumber(text)) - this->webEngine->page()->load( - QUrl("https://web.whatsapp.com/send?phone=" + text)); + if (isPhoneNumber(phoneNumber)) + triggerNewChat(phoneNumber, ""); else QMessageBox::information(this, QApplication::applicationName() + "| Error", @@ -1039,6 +1021,27 @@ void MainWindow::newChat() { } } +void MainWindow::triggerNewChat(QString phone, QString text){ + static QString phoneStr, textStr; + webEngine->page()->runJavaScript( + "openNewChatWhatsieDefined()", [this, phone, text](const QVariant &result) { + if (result.toString().contains("true")) { + this->webEngine->page()->runJavaScript( + QString("openNewChatWhatsie(\"%1\",\"%2\")").arg(phone, text)); + this->notify(QApplication::applicationName(), + "New chat with " + phone + + " is ready. Click to Open."); + } else { + // create send url equivalent + phoneStr = phone.isEmpty() ? "" : "phone=" + phone; + textStr = text.isEmpty() ? "" : "text=" + text; + QString urlStr = + "https://web.whatsapp.com/send?" + phoneStr + "&" + textStr; + this->webEngine->page()->load(QUrl(urlStr)); + } + }); +} + bool MainWindow::isPhoneNumber(const QString &phoneNumber) { const QString phone = "^\\+(((\\d{2}))\\s?)?((\\d{2})|(\\((\\d{2})\\))\\s?)?(" "\\d{3,15})(\\-(\\d{3,15}))?$"; diff --git a/src/mainwindow.h b/src/mainwindow.h index 8573226..c925697 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -127,6 +127,7 @@ private slots: void initAutoLock(); void appAutoLockChanged(); void injectNewChatJavaScript(); + void triggerNewChat(QString phone, QString text); }; #endif // MAINWINDOW_H -- cgit v1.2.3 From 391171583a00d04b3f2fcfb57b9c9743ae286728 Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Tue, 10 May 2022 17:34:33 +0530 Subject: chore: restore window directly when another instance is launched --- src/main.cpp | 2 +- src/mainwindow.cpp | 56 +++++++++++++++++++++++++----------------------------- src/mainwindow.h | 2 +- 3 files changed, 28 insertions(+), 32 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/main.cpp b/src/main.cpp index 0303f3a..db07711 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -80,7 +80,7 @@ int main(int argc, char *argv[]) { "whatsapp://" + messageStr.split("whatsapp://").last(); window.loadAppWithArgument(urlStr); } else { - window.alreadyRunning(); + window.alreadyRunning(true); } }); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 23bfb44..13bfe5f 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -146,7 +146,7 @@ void MainWindow::loadAppWithArgument(const QString &arg) { newArg = newArg.replace("?", "&"); QUrlQuery query(newArg); - QString phone, text; + QString phone, text; phone = query.queryItemValue("phone"); text = query.queryItemValue("text"); triggerNewChat(phone, text); @@ -188,9 +188,7 @@ void MainWindow::updateWindowTheme() { } QList widgets = this->findChildren(); - foreach (QWidget *w, widgets) { - w->setPalette(qApp->palette()); - } + foreach (QWidget *w, widgets) { w->setPalette(qApp->palette()); } setNotificationPresenter(webEngine->page()->profile()); if (lockWidget != nullptr) { @@ -549,7 +547,6 @@ void MainWindow::quitApp() { settings.setValue("geometry", saveGeometry()); getPageTheme(); QTimer::singleShot(500, &settings, [=]() { - qWarning() << "THEME" << settings.value("windowTheme").toString(); settings.setValue("firstrun_tray", true); qApp->quit(); }); @@ -1021,25 +1018,24 @@ void MainWindow::newChat() { } } -void MainWindow::triggerNewChat(QString phone, QString text){ - static QString phoneStr, textStr; - webEngine->page()->runJavaScript( - "openNewChatWhatsieDefined()", [this, phone, text](const QVariant &result) { - if (result.toString().contains("true")) { - this->webEngine->page()->runJavaScript( - QString("openNewChatWhatsie(\"%1\",\"%2\")").arg(phone, text)); - this->notify(QApplication::applicationName(), - "New chat with " + phone + - " is ready. Click to Open."); - } else { - // create send url equivalent - phoneStr = phone.isEmpty() ? "" : "phone=" + phone; - textStr = text.isEmpty() ? "" : "text=" + text; - QString urlStr = - "https://web.whatsapp.com/send?" + phoneStr + "&" + textStr; - this->webEngine->page()->load(QUrl(urlStr)); - } - }); +void MainWindow::triggerNewChat(QString phone, QString text) { + static QString phoneStr, textStr; + webEngine->page()->runJavaScript( + "openNewChatWhatsieDefined()", + [this, phone, text](const QVariant &result) { + if (result.toString().contains("true")) { + this->webEngine->page()->runJavaScript( + QString("openNewChatWhatsie(\"%1\",\"%2\")").arg(phone, text)); + } else { + // create send url equivalent + phoneStr = phone.isEmpty() ? "" : "phone=" + phone; + textStr = text.isEmpty() ? "" : "text=" + text; + QString urlStr = + "https://web.whatsapp.com/send?" + phoneStr + "&" + textStr; + this->webEngine->page()->load(QUrl(urlStr)); + } + this->alreadyRunning(); + }); } bool MainWindow::isPhoneNumber(const QString &phoneNumber) { @@ -1085,10 +1081,10 @@ void MainWindow::tryLock() { } } -void MainWindow::alreadyRunning() { - QString appname = QApplication::applicationName(); - this->notify( - appname, - QString("An instance of %1 is already Running, click to restore.") - .arg(appname)); +void MainWindow::alreadyRunning(bool notify) { + this->show(); + if (notify) { + QString appname = QApplication::applicationName(); + this->notify(appname, "Restored an already running instance."); + } } diff --git a/src/mainwindow.h b/src/mainwindow.h index c925697..2c580b6 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -50,7 +50,7 @@ public slots: void handleDownloadRequested(QWebEngineDownloadItem *download); void loadAppWithArgument(const QString &arg); void runMinimized(); - void alreadyRunning(); + void alreadyRunning(bool notify = false); protected slots: void closeEvent(QCloseEvent *event) override; void resizeEvent(QResizeEvent *event) override; -- cgit v1.2.3 From 3a08d5d5801c7e902620e45305da838904bda1ab Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Thu, 16 Jun 2022 21:38:32 +0530 Subject: chore: improve window geo restore - show window on screen where the cursor is located - default window size if saved geometry is not valid --- src/mainwindow.cpp | 28 +++++++++++++++++++++++++--- src/mainwindow.h | 1 + 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 13b01eb..7ab2216 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -23,7 +23,7 @@ MainWindow::MainWindow(QWidget *parent) setWindowIcon(QIcon(":/icons/app/icon-128.png")); setMinimumWidth(525); setMinimumHeight(448); - restoreGeometry(settings.value("geometry").toByteArray()); + restoreMainWindow(); initThemes(); createActions(); createTrayIcon(); @@ -35,6 +35,21 @@ MainWindow::MainWindow(QWidget *parent) initAutoLock(); } +void MainWindow::restoreMainWindow() { + if (settings.value("geometry").isValid()) { + restoreGeometry(settings.value("geometry").toByteArray()); + QPoint pos = QCursor::pos(); + for (QScreen *screen : QGuiApplication::screens()) { + QRect screenRect = screen->geometry(); + if (screenRect.contains(pos)) { + this->move(screenRect.center() - this->rect().center()); + } + } + }else{ + this->resize(636, 760); + } +} + void MainWindow::initAutoLock() { autoLockEventFilter = new AutoLockEventFilter( settings.value("autoLockDuration", defaultAppAutoLockDuration).toInt() * @@ -252,9 +267,10 @@ void MainWindow::tryLogOut() { } void MainWindow::init_settingWidget() { + int screenNumber = qApp->desktop()->screenNumber(this); if (settingsWidget == nullptr) { settingsWidget = new SettingsWidget( - this, webEngine->page()->profile()->cachePath(), + this, screenNumber, webEngine->page()->profile()->cachePath(), webEngine->page()->profile()->persistentStoragePath()); settingsWidget->setWindowTitle(QApplication::applicationName() + " | Settings"); @@ -414,12 +430,18 @@ void MainWindow::showSettings() { if (webEngine == nullptr) { QMessageBox::critical( this, QApplication::applicationName() + "| Error", - "Unable to initialize settings module.\nIs webengine initialized?"); + "Unable to initialize settings module.\nWebengine is not initialized."); return; } if (!settingsWidget->isVisible()) { this->updateSettingsUserAgentWidget(); settingsWidget->refresh(); + int screenNumber = qApp->desktop()->screenNumber(this); + QRect screenRect = QGuiApplication::screens().at(screenNumber)->geometry(); + if (!screenRect.contains(settingsWidget->pos())) { + settingsWidget->move(screenRect.center() - + settingsWidget->rect().center()); + } settingsWidget->show(); } } diff --git a/src/mainwindow.h b/src/mainwindow.h index 2c580b6..43b02f5 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -128,6 +128,7 @@ private slots: void appAutoLockChanged(); void injectNewChatJavaScript(); void triggerNewChat(QString phone, QString text); + void restoreMainWindow(); }; #endif // MAINWINDOW_H -- cgit v1.2.3 From b96a28dbc329d38ba64184b0eae023010d9c2be6 Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Thu, 23 Jun 2022 21:10:13 +0530 Subject: chore: add full view support closes #46 - an option in setting to allow toggle full view mode - remove unused webchannel module --- src/WhatsApp.pro | 2 +- src/mainwindow.cpp | 130 +++++++++++++++++++++++++++++++++++++++---------- src/mainwindow.h | 3 ++ src/settingswidget.cpp | 11 +++++ src/settingswidget.h | 3 ++ src/settingswidget.ui | 18 +++++-- 6 files changed, 137 insertions(+), 30 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/WhatsApp.pro b/src/WhatsApp.pro index 765e0a7..64342d0 100644 --- a/src/WhatsApp.pro +++ b/src/WhatsApp.pro @@ -4,7 +4,7 @@ # #------------------------------------------------- -QT += core gui webengine webenginewidgets webchannel xml positioning +QT += core gui webengine webenginewidgets xml positioning CONFIG += c++11 diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7ab2216..e2bef52 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -45,8 +45,8 @@ void MainWindow::restoreMainWindow() { this->move(screenRect.center() - this->rect().center()); } } - }else{ - this->resize(636, 760); + } else { + this->resize(636, 760); } } @@ -171,17 +171,18 @@ void MainWindow::loadAppWithArgument(const QString &arg) { } void MainWindow::updatePageTheme() { - QString webPageTheme = "web"; // implies light - QString windowTheme = settings.value("windowTheme", "light").toString(); - if (windowTheme == "dark") { - webPageTheme = "web dark"; - } if (webEngine && webEngine->page()) { - webEngine->page()->runJavaScript( - "document.querySelector('body').className='" + webPageTheme + "';", - [](const QVariant &result) { - qDebug() << "Value is: " << result.toString() << Qt::endl; - }); + QString webPageTheme = "web"; + QString windowTheme = settings.value("windowTheme", "light").toString(); + if (windowTheme == "dark") { + webPageTheme = "dark"; + webEngine->page()->runJavaScript( + "document.querySelector('body').classList.add('" + webPageTheme + + "');"); + } else { + webEngine->page()->runJavaScript( + "document.querySelector('body').classList.remove('dark');"); + } } } @@ -352,6 +353,20 @@ void MainWindow::init_settingWidget() { connect(settingsWidget, &SettingsWidget::notify, settingsWidget, [=](QString message) { notify("", message); }); + connect(settingsWidget, &SettingsWidget::updateFullWidthView, + settingsWidget, [=](bool checked) { + if (webEngine && webEngine->page()) { + if (checked) + webEngine->page()->runJavaScript( + "document.querySelector('body').classList.add('whatsie-" + "full-view');"); + else + webEngine->page()->runJavaScript( + "document.querySelector('body').classList.remove('" + "whatsie-full-view');"); + } + }); + settingsWidget->appLockSetChecked( settings.value("lockscreen", false).toBool()); @@ -634,7 +649,6 @@ void MainWindow::init_lock() { "QWidget#signup{background-color:palette(window)}"); lockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); lockWidget->setGeometry(this->rect()); - // lockWidget->disconnect(); connect(lockWidget, &Lock::passwordNotSet, settingsWidget, [=]() { settings.setValue("lockscreen", false); @@ -915,24 +929,90 @@ void MainWindow::handleLoadFinished(bool loaded) { checkLoadedCorrectly(); updatePageTheme(); handleZoom(); + injectMutationObserver(); + injectClassChangeObserver(); injectNewChatJavaScript(); + injectFullWidthJavaScript(); settingsWidget->refresh(); } } +void MainWindow::injectClassChangeObserver() { + QString js = R"( + const observer = new MutationObserver(() => { + var haveFullView = document.body.classList.contains('whatsie-full-view'); + var container = document.querySelector('#app > .app-wrapper-web > div'); + if(haveFullView){ + container.style.width = '100%'; + container.style.height = '100%'; + container.style.top = '0'; + container.style.maxWidth = 'unset'; + }else{ + container.style.width = null; + container.style.height = null; + container.style.top = null; + container.style.maxWidth = null; + } + }); + observer.observe(document.body, { + attributes: true, + attributeFilter: ['class'], + childList: false, + characterData: false + });)"; + webEngine->page()->runJavaScript(js); +} + +void MainWindow::injectMutationObserver() { + QString js = + R"(function waitForElement(selector) { + return new Promise(resolve => { + if (document.querySelector(selector)) { + return resolve(document.querySelector(selector)); + } + const observer = new MutationObserver(mutations => { + if (document.querySelector(selector)) { + resolve(document.querySelector(selector)); + observer.disconnect(); + } + }); + observer.observe(document.body, { + childList: true, + subtree: true + }); + }); + })"; + webEngine->page()->runJavaScript(js); +} + +void MainWindow::injectFullWidthJavaScript() { + if (!settings.value("fullWidthView", true).toBool()) + return; + QString js = + R"(waitForElement('#pane-side').then( () => { + var container = document.querySelector('#app > .app-wrapper-web > div'); + container.style.width = '100%'; + container.style.height = '100%'; + container.style.top = '0'; + container.style.maxWidth = 'unset'; + }); + )"; + webEngine->page()->runJavaScript(js); +} + void MainWindow::injectNewChatJavaScript() { - QString js = "const openNewChatWhatsie = (phone,text) => { " - "const link = document.createElement('a');" - "link.setAttribute('href', " - "`whatsapp://send/?phone=${phone}&text=${text}`);" - "document.body.append(link);" - "link.click();" - "document.body.removeChild(link);" - "};" - "function openNewChatWhatsieDefined()" - "{" - " return (openNewChatWhatsie != 'undefined');" - "}"; + QString js = R"(const openNewChatWhatsie = (phone,text) => { + const link = document.createElement('a'); + link.setAttribute('href', + `whatsapp://send/?phone=${phone}&text=${text}`); + document.body.append(link); + link.click(); + document.body.removeChild(link); + }; + function openNewChatWhatsieDefined() + { + return (openNewChatWhatsie != 'undefined'); + })"; webEngine->page()->runJavaScript(js); } diff --git a/src/mainwindow.h b/src/mainwindow.h index 43b02f5..4c2c1b8 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -129,6 +129,9 @@ private slots: void injectNewChatJavaScript(); void triggerNewChat(QString phone, QString text); void restoreMainWindow(); + void injectFullWidthJavaScript(); + void injectMutationObserver(); + void injectClassChangeObserver(); }; #endif // MAINWINDOW_H diff --git a/src/settingswidget.cpp b/src/settingswidget.cpp index 38624f8..4d13cbb 100644 --- a/src/settingswidget.cpp +++ b/src/settingswidget.cpp @@ -76,6 +76,10 @@ SettingsWidget::SettingsWidget(QWidget *parent, int screenNumber, ui->styleComboBox->setCurrentText( settings.value("widgetStyle", "Fusion").toString()); + ui->fullWidthViewCheckbox->blockSignals(true); + ui->fullWidthViewCheckbox->setChecked(settings.value("fullWidthView", true).toBool()); + ui->fullWidthViewCheckbox->blockSignals(false); + ui->automaticThemeCheckBox->blockSignals(true); bool automaticThemeSwitching = settings.value("automaticTheme", false).toBool(); @@ -729,3 +733,10 @@ void SettingsWidget::on_chnageCurrentPasswordPushButton_clicked() { showSetApplockPasswordDialog(); } } + +void SettingsWidget::on_fullWidthViewCheckbox_toggled(bool checked) +{ + settings.setValue("fullWidthView", checked); + emit updateFullWidthView(checked); +} + diff --git a/src/settingswidget.h b/src/settingswidget.h index fdce322..3e76b20 100644 --- a/src/settingswidget.h +++ b/src/settingswidget.h @@ -29,6 +29,7 @@ signals: void zoomChanged(); void zoomMaximizedChanged(); void appAutoLockChanged(); + void updateFullWidthView(bool checked); public: explicit SettingsWidget(QWidget *parent = nullptr,int screenNumber = 0, @@ -95,6 +96,8 @@ private slots: void themeSwitchTimerTimeout(); void updateAutomaticTheme(); + void on_fullWidthViewCheckbox_toggled(bool checked); + private: Ui::SettingsWidget *ui; QString engineCachePath, enginePersistentStoragePath; diff --git a/src/settingswidget.ui b/src/settingswidget.ui index 76a7649..cbf98e1 100644 --- a/src/settingswidget.ui +++ b/src/settingswidget.ui @@ -6,8 +6,8 @@ 0 0 - 691 - 860 + 693 + 867 @@ -97,8 +97,8 @@ background:transparent; 0 - 0 - 675 + -14 + 677 791 @@ -375,6 +375,16 @@ background:transparent; + + + + Expand the view to full width of window + + + Full width view + + + -- cgit v1.2.3 From 211139005036fced3ae191c4989b32dfd9e95de1 Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Sat, 25 Jun 2022 23:12:28 +0530 Subject: feat: some new features - feat: new command line options, run: whatsie -h for more - feat: add theme toggle action in system tray action menu with shortcut CTRL+T - feat: shortcut to open settings CTRL+P - fix: Changes (mosty non visible) in applock flow --- src/main.cpp | 222 +++++++++++++++++++++++++++++++++++++++++-------- src/mainwindow.cpp | 180 +++++++++++++++++++++++---------------- src/mainwindow.h | 31 +++---- src/settingswidget.cpp | 43 +++++++--- src/settingswidget.h | 9 +- 5 files changed, 348 insertions(+), 137 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/main.cpp b/src/main.cpp index 88731a6..ffbb1a4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,16 +13,6 @@ int main(int argc, char *argv[]) { - QStringList args; - for (int i = 0; i < argc; i++) - args << QString(argv[i]); - - if (args.contains("-v") || args.contains("--version")) { - qInfo() << QString("version: %1, branch: %2, commit: %3, built_at: %4") - .arg(VERSIONSTR, GIT_BRANCH, GIT_HASH, BUILD_TIMESTAMP); - return 0; - } - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); static const char ENV_VAR_QT_DEVICE_PIXEL_RATIO[] = "QT_DEVICE_PIXEL_RATIO"; if (!qEnvironmentVariableIsSet(ENV_VAR_QT_DEVICE_PIXEL_RATIO) && @@ -38,20 +28,110 @@ int main(int argc, char *argv[]) { qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-logging --single-process"); #endif - SingleApplication app(argc, argv, true); - app.setQuitOnLastWindowClosed(false); - app.setWindowIcon(QIcon(":/icons/app/icon-128.png")); + SingleApplication instance(argc, argv, true); + //instance.setQuitOnLastWindowClosed(false); + instance.setWindowIcon(QIcon(":/icons/app/icon-128.png")); QApplication::setApplicationName("WhatSie"); + QApplication::setOrganizationDomain("com.ktechpit"); QApplication::setOrganizationName("org.keshavnrj.ubuntu"); QApplication::setApplicationVersion(VERSIONSTR); + QCommandLineParser parser; + parser.setApplicationDescription( + QObject::tr("Feature rich WhatsApp web client based on Qt WebEngine")); + + QList secondaryInstanceCLIOptions; + + QCommandLineOption showCLIHelpOption( + QStringList() << "h" + << "help", + QObject::tr("Displays help on commandline options")); + + QCommandLineOption openSettingsOption( + QStringList() << "s" + << "open-settings", + QObject::tr("Opens Settings dialog in a running instance of ") + + QApplication::applicationName()); + + QCommandLineOption lockAppOption(QStringList() << "l" + << "lock-app", + QObject::tr("Locks a running instance of ") + + QApplication::applicationName()); + + QCommandLineOption openAboutOption( + QStringList() << "i" + << "open-about", + QObject::tr("Opens About dialog in a running instance of ") + + QApplication::applicationName()); + + QCommandLineOption toggleThemeOption( + QStringList() << "t" + << "toggle-theme", + QObject::tr( + "Toggle between dark & light theme in a running instance of ") + + QApplication::applicationName()); + + QCommandLineOption reloadAppOption( + QStringList() << "r" + << "reload-app", + QObject::tr("Reload the app in a running instance of ") + + QApplication::applicationName()); + + QCommandLineOption newChatOption( + QStringList() << "n" + << "new-chat", + QObject::tr("Open new chat prompt in a running instance of ") + + QApplication::applicationName()); + + QCommandLineOption buildInfoOption(QStringList() << "b" + << "build-info", + "Shows detailed current build infomation"); + + QCommandLineOption showAppWindowOption( + QStringList() << "w" + << "show-window", + QObject::tr("Show main window of running instance of ") + + QApplication::applicationName()); + + parser.addOption(showCLIHelpOption); // [x] + parser.addVersionOption(); // [x] + parser.addOption(buildInfoOption); // [x] + parser.addOption(showAppWindowOption); // [x] + parser.addOption(openSettingsOption); // [x] + parser.addOption(lockAppOption); // [x] + parser.addOption(openAboutOption); // [x] + parser.addOption(toggleThemeOption); // [x] + parser.addOption(reloadAppOption); // [x] + parser.addOption(newChatOption); // [x] + + secondaryInstanceCLIOptions << showAppWindowOption << openSettingsOption + << lockAppOption << openAboutOption + << toggleThemeOption << reloadAppOption + << newChatOption; + + parser.process(instance); + + if (parser.isSet(showCLIHelpOption)) { + parser.showHelp(); + } + + if (parser.isSet(buildInfoOption)) { + + qInfo().noquote() + << parser.applicationDescription() << "\n" + << QStringLiteral("version: %1, branch: %2, commit: %3, built_at: %4") + .arg(VERSIONSTR, GIT_BRANCH, GIT_HASH, BUILD_TIMESTAMP); + return 0; + } + // if secondary instance is invoked - if (app.isSecondary()) { - app.sendMessage(app.arguments().join(' ').toUtf8()); - qInfo() << QApplication::applicationName() + - " is already running with PID:" + - QString::number(app.primaryPid()) + "; by USER: " - << app.primaryUser(); + if (instance.isSecondary()) { + instance.sendMessage(instance.arguments().join(' ').toUtf8()); + qInfo().noquote() << QApplication::applicationName() + + " is already running with PID: " + + QString::number(instance.primaryPid()) + + " by USER:" + << instance.primaryUser(); return 0; } @@ -64,41 +144,113 @@ int main(int argc, char *argv[]) { QWebEngineSettings::defaultSettings()->setAttribute( QWebEngineSettings::JavascriptCanAccessClipboard, true); - MainWindow window; + MainWindow whatsie; // else QObject::connect( - &app, &SingleApplication::receivedMessage, - [&window](int instanceId, QByteArray message) { - qInfo() << "Another instance with PID: " + QString::number(instanceId) + - ", sent argument: " + message; + &instance, &SingleApplication::receivedMessage, &whatsie, + [&whatsie, &secondaryInstanceCLIOptions](int instanceId, + QByteArray message) { + qInfo().noquote() << "Another instance with PID: " + + QString::number(instanceId) + + ", sent argument: " + message; QString messageStr = QTextCodec::codecForMib(106)->toUnicode(message); - if (messageStr.contains("whatsapp://whatsie", Qt::CaseInsensitive)) { - window.show(); + + QCommandLineParser p; + p.addOptions(secondaryInstanceCLIOptions); + p.parse(QStringList(messageStr.split(" "))); + + if (p.isSet("s")) { + qInfo() << "cmd:" + << "OpenAppSettings"; + whatsie.alreadyRunning(); + whatsie.showSettings(true); + return; + } + + if (p.isSet("l")) { + qInfo() << "cmd:" + << "LockApp"; + whatsie.alreadyRunning(); + QSettings settings; + if (!settings.value("asdfg").isValid()) { + whatsie.notify( + QApplication::applicationName(), + QObject::tr("App lock is not configured, \n" + "Please setup the password in the Settings " + "first.")); + } else { + whatsie.lockApp(); + } + return; + } + + if (p.isSet("i")) { + qInfo() << "cmd:" + << "OpenAppAbout"; + whatsie.alreadyRunning(); + whatsie.showAbout(); + return; + } + + if (p.isSet("t")) { + qInfo() << "cmd:" + << "ToggleAppTheme"; + whatsie.alreadyRunning(); + whatsie.toggleTheme(); return; - } else if (messageStr.contains("whatsapp://", Qt::CaseInsensitive)) { + } + + if (p.isSet("r")) { + qInfo() << "cmd:" + << "ReloadApp"; + whatsie.alreadyRunning(); + whatsie.doReload(false, true); + return; + } + + if (p.isSet("n")) { + qInfo() << "cmd:" + << "OpenNewChatPrompt"; + whatsie.alreadyRunning(); + whatsie.newChat(); //TODO: invetigate the crash + return; + } + + if (p.isSet("w")) { + qInfo() << "cmd:" + << "ShowAppWindow"; + whatsie.alreadyRunning(); + whatsie.show(); + return; + } + + if (messageStr.contains("whatsapp://", Qt::CaseInsensitive)) { QString urlStr = "whatsapp://" + messageStr.split("whatsapp://").last(); - window.loadAppWithArgument(urlStr); + qInfo() << "cmd:" + << "x-schema-handler"; + whatsie.loadSchemaUrl(urlStr); } else { - window.alreadyRunning(true); + whatsie.alreadyRunning(true); } }); - QStringList argsList = app.arguments(); - foreach (QString argStr, argsList) { + foreach (QString argStr, instance.arguments()) { if (argStr.contains("whatsapp://")) { - window.loadAppWithArgument(argStr); + qInfo() << "cmd:" + << "x-schema-handler"; + whatsie.loadSchemaUrl(argStr); } } QSettings settings; if (QSystemTrayIcon::isSystemTrayAvailable() && settings.value("startMinimized", false).toBool()) { - window.runMinimized(); + whatsie.runMinimized(); } else { - window.show(); + whatsie.show(); } - return app.exec(); + return instance.exec(); } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 553115a..2baaf4b 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -28,7 +28,7 @@ MainWindow::MainWindow(QWidget *parent) createActions(); createTrayIcon(); createWebEngine(); - init_settingWidget(); + initSettingWidget(); initRateWidget(); tryLock(); updateWindowTheme(); @@ -151,7 +151,7 @@ void MainWindow::runMinimized() { MainWindow::~MainWindow() { webEngine->deleteLater(); } -void MainWindow::loadAppWithArgument(const QString &arg) { +void MainWindow::loadSchemaUrl(const QString &arg) { // https://faq.whatsapp.com/iphone/how-to-link-to-whatsapp-from-a-different-app/?lang=en // PASSED SCHEME whatsapp://send?text=Hello%2C%20World!&phone=919568388397" @@ -267,7 +267,7 @@ void MainWindow::tryLogOut() { } } -void MainWindow::init_settingWidget() { +void MainWindow::initSettingWidget() { int screenNumber = qApp->desktop()->screenNumber(this); if (settingsWidget == nullptr) { settingsWidget = new SettingsWidget( @@ -277,9 +277,9 @@ void MainWindow::init_settingWidget() { " | Settings"); settingsWidget->setWindowFlags(Qt::Dialog); - connect(settingsWidget, SIGNAL(init_lock()), this, SLOT(init_lock())); - connect(settingsWidget, SIGNAL(change_lock_password()), this, - SLOT(change_lock_password())); + connect(settingsWidget, SIGNAL(initLock()), this, SLOT(initLock())); + connect(settingsWidget, SIGNAL(changeLockPassword()), this, + SLOT(changeLockPassword())); connect(settingsWidget, SIGNAL(appAutoLockChanged()), this, SLOT(appAutoLockChanged())); @@ -410,34 +410,40 @@ void MainWindow::handleZoom() { } void MainWindow::lockApp() { - if (lockWidget != nullptr && lockWidget->isLocked) + if (lockWidget != nullptr && lockWidget->getIsLocked()) return; if (settings.value("asdfg").isValid()) { - init_lock(); + initLock(); lockWidget->lock_app(); } else { - QMessageBox msgBox; - msgBox.setText("App lock is not configured."); - msgBox.setIconPixmap( - QPixmap(":/icons/information-line.png") - .scaled(42, 42, Qt::KeepAspectRatio, Qt::SmoothTransformation)); - msgBox.setInformativeText("Do you want to setup App lock now ?"); - msgBox.setStandardButtons(QMessageBox::Cancel); - QPushButton *setAppLock = - new QPushButton(this->style()->standardIcon(QStyle::SP_DialogYesButton), - "Yes", nullptr); - msgBox.addButton(setAppLock, QMessageBox::NoRole); - connect(setAppLock, &QPushButton::clicked, setAppLock, - [=]() { init_lock(); }); - msgBox.exec(); + int ret = QMessageBox::information( + this, tr(QApplication::applicationName().toUtf8()), + tr("App lock is not configured, \n" + "Please setup the password in the Settings first.\n\nOpen " + "Application Settings now?"), + QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel); + if (ret == QMessageBox::Yes) { + this->showSettings(); + } + } +} + +void MainWindow::toggleTheme() { + if (settingsWidget != nullptr) { + settingsWidget->toggleTheme(); } } -void MainWindow::showSettings() { - if (lockWidget && lockWidget->isLocked) { - QMessageBox::critical(this, QApplication::applicationName() + "| Error", - "UnLock Application to access Settings."); +void MainWindow::showSettings(bool isAskedByCLI) { + if (lockWidget && lockWidget->getIsLocked()) { + QString error = tr("UnLock Application to access Settings."); + if (isAskedByCLI) { + this->notify(QApplication::applicationName() + "| Error", error); + } else { + QMessageBox::critical(this, QApplication::applicationName() + "| Error", + error); + } this->show(); return; } @@ -573,7 +579,9 @@ void MainWindow::createActions() { reloadAction = new QAction(tr("Re&load"), this); reloadAction->setShortcut(Qt::Key_F5); - connect(reloadAction, &QAction::triggered, this, &MainWindow::doReload); + connect(reloadAction, &QAction::triggered,this, [=]{ + this->doReload(); + }); addAction(reloadAction); lockAction = new QAction(tr("Loc&k"), this); @@ -582,7 +590,15 @@ void MainWindow::createActions() { addAction(lockAction); settingsAction = new QAction(tr("&Settings"), this); + settingsAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_P)); connect(settingsAction, &QAction::triggered, this, &MainWindow::showSettings); + addAction(settingsAction); + + toggleThemeAction = new QAction(tr("&Toggle theme"), this); + toggleThemeAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_T)); + connect(toggleThemeAction, &QAction::triggered, this, + &MainWindow::toggleTheme); + addAction(toggleThemeAction); aboutAction = new QAction(tr("&About"), this); connect(aboutAction, &QAction::triggered, this, &MainWindow::showAbout); @@ -612,6 +628,7 @@ void MainWindow::createTrayIcon() { trayIconMenu->addAction(lockAction); trayIconMenu->addSeparator(); trayIconMenu->addAction(openUrlAction); + trayIconMenu->addAction(toggleThemeAction); trayIconMenu->addAction(settingsAction); trayIconMenu->addAction(aboutAction); trayIconMenu->addSeparator(); @@ -619,8 +636,7 @@ void MainWindow::createTrayIcon() { trayIcon = new QSystemTrayIcon(trayIconRead, this); trayIcon->setContextMenu(trayIconMenu); - connect(trayIconMenu, SIGNAL(aboutToShow()), this, - SLOT(check_window_state())); + connect(trayIconMenu, SIGNAL(aboutToShow()), this, SLOT(checkWindowState())); trayIcon->show(); @@ -637,54 +653,56 @@ void MainWindow::createTrayIcon() { } } -void MainWindow::init_lock() { +void MainWindow::initLock() { if (lockWidget == nullptr) { lockWidget = new Lock(this); lockWidget->setObjectName("lockWidget"); - } - lockWidget->setWindowFlags(Qt::Widget); - lockWidget->setStyleSheet("QWidget#login{background-color:palette(window)};" - "QWidget#signup{background-color:palette(window)}"); - lockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - lockWidget->setGeometry(this->rect()); + lockWidget->setWindowFlags(Qt::Widget); + lockWidget->setStyleSheet( + "QWidget#login{background-color:palette(window)};" + "QWidget#signup{background-color:palette(window)}"); + lockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - connect(lockWidget, &Lock::passwordNotSet, settingsWidget, [=]() { - settings.setValue("lockscreen", false); - settingsWidget->appLockSetChecked(false); - }); + connect(lockWidget, &Lock::passwordNotSet, settingsWidget, [=]() { + settings.setValue("lockscreen", false); + settingsWidget->appLockSetChecked(false); + }); - connect(lockWidget, &Lock::unLocked, [=]() { - // unlock event - }); + connect(lockWidget, &Lock::unLocked, [=]() { + // unlock event + }); + + connect(lockWidget, &Lock::passwordSet, settingsWidget, [=]() { + if (settings.value("asdfg").isValid()) { + settingsWidget->setCurrentPasswordText(QByteArray::fromBase64( + settings.value("asdfg").toString().toUtf8())); + } else { + settingsWidget->setCurrentPasswordText("Require setup"); + } + settingsWidget->appLockSetChecked( + settings.value("lockscreen", false).toBool()); + }); + lockWidget->applyThemeQuirks(); + } + + lockWidget->setGeometry(this->rect()); - connect(lockWidget, &Lock::passwordSet, settingsWidget, [=]() { + if (settings.value("lockscreen").toBool()) { if (settings.value("asdfg").isValid()) { - settingsWidget->setCurrentPasswordText( - QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())); + lockWidget->lock_app(); } else { - settingsWidget->setCurrentPasswordText("Require setup"); + lockWidget->signUp(); } - settingsWidget->appLockSetChecked( - settings.value("lockscreen", false).toBool()); - }); - - lockWidget->applyThemeQuirks(); - lockWidget->show(); - if (settings.value("asdfg").isValid() && - settings.value("lockscreen").toBool()) { - lockWidget->lock_app(); - } else if (settings.value("lockscreen").toBool() && - !settings.value("asdfg").isValid()) { - lockWidget->signUp(); + lockWidget->show(); } else { lockWidget->hide(); } updateWindowTheme(); } -void MainWindow::change_lock_password() { +void MainWindow::changeLockPassword() { settings.remove("asdfg"); settingsWidget->appLockSetChecked(false); settingsWidget->autoAppLockSetChecked(false); @@ -696,7 +714,7 @@ void MainWindow::change_lock_password() { doAppReload(); } appAutoLockChanged(); - init_lock(); + initLock(); }); } @@ -715,7 +733,7 @@ void MainWindow::appAutoLockChanged() { } // check window state and set tray menus -void MainWindow::check_window_state() { +void MainWindow::checkWindowState() { QObject *tray_icon_menu = this->findChild("trayIconMenu"); if (tray_icon_menu != nullptr) { if (this->isVisible()) { @@ -725,7 +743,7 @@ void MainWindow::check_window_state() { ((QMenu *)(tray_icon_menu))->actions().at(0)->setDisabled(true); ((QMenu *)(tray_icon_menu))->actions().at(1)->setDisabled(false); } - if (lockWidget && lockWidget->isLocked) { + if (lockWidget && lockWidget->getIsLocked()) { ((QMenu *)(tray_icon_menu))->actions().at(4)->setDisabled(true); } else { ((QMenu *)(tray_icon_menu))->actions().at(4)->setDisabled(false); @@ -733,7 +751,7 @@ void MainWindow::check_window_state() { } } -void MainWindow::init_globalWebProfile() { +void MainWindow::initGlobalWebProfile() { QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); profile->setHttpUserAgent( @@ -771,7 +789,7 @@ void MainWindow::init_globalWebProfile() { } void MainWindow::createWebEngine() { - init_globalWebProfile(); + initGlobalWebProfile(); QSizePolicy widgetSize; widgetSize.setHorizontalPolicy(QSizePolicy::Expanding); @@ -933,7 +951,9 @@ void MainWindow::handleLoadFinished(bool loaded) { injectFullWidthJavaScript(); injectClassChangeObserver(); injectNewChatJavaScript(); - settingsWidget->refresh(); + if (settingsWidget != nullptr) { + settingsWidget->refresh(); + } } } @@ -1130,7 +1150,7 @@ void MainWindow::newChat() { else QMessageBox::information(this, QApplication::applicationName() + "| Error", - "Invalid Phone Number"); + tr("Invalid Phone Number")); } } @@ -1161,7 +1181,20 @@ bool MainWindow::isPhoneNumber(const QString &phoneNumber) { return reg.match(phoneNumber).hasMatch(); } -void MainWindow::doReload(bool byPassCache) { +void MainWindow::doReload(bool byPassCache, bool isAskedByCLI) { + if (lockWidget && !lockWidget->getIsLocked()) { + this->notify(QApplication::applicationName(), QObject::tr("Reloading...")); + } else { + QString error = tr("UnLock Application to Reload the App."); + if (isAskedByCLI) { + this->notify(QApplication::applicationName() + "| Error", error); + } else { + QMessageBox::critical(this, QApplication::applicationName() + "| Error", + error); + } + this->show(); + return; + } this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, byPassCache); } @@ -1188,19 +1221,24 @@ QString MainWindow::getPageTheme() { void MainWindow::tryLock() { if (settings.value("asdfg").isValid() && settings.value("lockscreen", false).toBool()) { - init_lock(); + initLock(); + return; } if (settings.value("asdfg").isValid() == false) { settings.setValue("lockscreen", false); + settings.setValue("appAutoLocking", false); + settingsWidget->appAutoLockingSetChecked(false); settingsWidget->appLockSetChecked(false); - init_lock(); + initLock(); } } void MainWindow::alreadyRunning(bool notify) { - this->show(); if (notify) { QString appname = QApplication::applicationName(); this->notify(appname, "Restored an already running instance."); } + this->setWindowState((this->windowState() & ~Qt::WindowMinimized) | + Qt::WindowActive); + this->show(); } diff --git a/src/mainwindow.h b/src/mainwindow.h index 4c2c1b8..f8a4ff5 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -25,6 +25,7 @@ #include #include "about.h" +#include "autolockeventfilter.h" #include "dictionaries.h" #include "downloadmanagerwidget.h" #include "lock.h" @@ -34,7 +35,6 @@ #include "settingswidget.h" #include "webenginepage.h" #include "webview.h" -#include "autolockeventfilter.h" class MainWindow : public QMainWindow { Q_OBJECT @@ -44,13 +44,19 @@ public: public slots: void updateWindowTheme(); void updatePageTheme(); - void handleWebViewTitleChanged(QString title); void handleLoadFinished(bool loaded); void handleDownloadRequested(QWebEngineDownloadItem *download); - void loadAppWithArgument(const QString &arg); + void loadSchemaUrl(const QString &arg); + void showSettings(bool isAskedByCLI = false); + void showAbout(); + void lockApp(); void runMinimized(); void alreadyRunning(bool notify = false); + void notify(QString title, QString message); + void toggleTheme(); + void doReload(bool byPassCache = false, bool isAskedByCLI = false); + void newChat(); protected slots: void closeEvent(QCloseEvent *event) override; void resizeEvent(QResizeEvent *event) override; @@ -72,6 +78,7 @@ private: QAction *restoreAction; QAction *aboutAction; QAction *settingsAction; + QAction *toggleThemeAction; QAction *quitAction; QAction *lockAction; QAction *fullscreenAction; @@ -93,10 +100,6 @@ private slots: QString getPageTheme(); void iconActivated(QSystemTrayIcon::ActivationReason reason); void messageClicked(); - void doReload(bool byPassCache = false); - void showAbout(); - void notify(QString title, QString message); - void showSettings(); void handleCookieAdded(const QNetworkCookie &cookie); void toggleMute(const bool &checked); void doAppReload(); @@ -104,23 +107,21 @@ private slots: void updateSettingsUserAgentWidget(); void fullScreenRequested(QWebEngineFullScreenRequest request); void createWebPage(bool offTheRecord = false); - void init_settingWidget(); - void init_globalWebProfile(); - void check_window_state(); - void init_lock(); - void lockApp(); + void initSettingWidget(); + void initGlobalWebProfile(); + void checkWindowState(); + void initLock(); + void tryLock(); void checkLoadedCorrectly(); void loadingQuirk(QString test); void setNotificationPresenter(QWebEngineProfile *profile); - void newChat(); bool isPhoneNumber(const QString &phoneNumber); void quitApp(); void initRateWidget(); void initThemes(); void handleZoomOnWindowStateChange(QWindowStateChangeEvent *ev); void handleZoom(); - void change_lock_password(); - void tryLock(); + void changeLockPassword(); void forceLogOut(); void tryLogOut(); bool isLoggedIn(); diff --git a/src/settingswidget.cpp b/src/settingswidget.cpp index b272565..80d9047 100644 --- a/src/settingswidget.cpp +++ b/src/settingswidget.cpp @@ -56,8 +56,8 @@ SettingsWidget::SettingsWidget(QWidget *parent, int screenNumber, ui->startMinimized->setChecked( settings.value("startMinimized", false).toBool()); - ui->appAutoLockcheckBox->setChecked( - settings.value("appAutoLocking", defaultAppAutoLock).toBool()); + this->appAutoLockingSetChecked(settings.value("appAutoLocking", defaultAppAutoLock).toBool()); + ui->autoLockDurationSpinbox->setValue( settings.value("autoLockDuration", defaultAppAutoLockDuration).toInt()); ui->minimizeOnTrayIconClick->setChecked( @@ -77,7 +77,8 @@ SettingsWidget::SettingsWidget(QWidget *parent, int screenNumber, settings.value("widgetStyle", "Fusion").toString()); ui->fullWidthViewCheckbox->blockSignals(true); - ui->fullWidthViewCheckbox->setChecked(settings.value("fullWidthView", true).toBool()); + ui->fullWidthViewCheckbox->setChecked( + settings.value("fullWidthView", true).toBool()); ui->fullWidthViewCheckbox->blockSignals(false); ui->automaticThemeCheckBox->blockSignals(true); @@ -125,8 +126,8 @@ SettingsWidget::SettingsWidget(QWidget *parent, int screenNumber, if (settings.value("settingsGeo").isValid()) { this->restoreGeometry(settings.value("settingsGeo").toByteArray()); QRect screenRect = QGuiApplication::screens().at(screenNumber)->geometry(); - if(!screenRect.contains(this->pos())){ - this->move(screenRect.center()-this->rect().center()); + if (!screenRect.contains(this->pos())) { + this->move(screenRect.center() - this->rect().center()); } } } @@ -422,6 +423,26 @@ void SettingsWidget::appLockSetChecked(bool checked) { ui->applock_checkbox->blockSignals(false); } +void SettingsWidget::appAutoLockingSetChecked(bool checked) { + ui->appAutoLockcheckBox->blockSignals(true); + ui->appAutoLockcheckBox->setChecked(checked); + ui->appAutoLockcheckBox->blockSignals(false); +} + +void SettingsWidget::toggleTheme() +{ + //disable automatic theme first + if(settings.value("automaticTheme", false).toBool()){ + emit notify(tr("Automatic theme switching was disabled due to manual theme toggle.")); + ui->automaticThemeCheckBox->setChecked(false); + } + if(ui->themeComboBox->currentIndex() == 0){ + ui->themeComboBox->setCurrentIndex(1); + }else{ + ui->themeComboBox->setCurrentIndex(0); + } +} + void SettingsWidget::setCurrentPasswordText(QString str) { ui->current_password->setStyleSheet( "QLineEdit[echoMode=\"2\"]{lineedit-password-character: 9899}"); @@ -458,7 +479,7 @@ void SettingsWidget::showSetApplockPasswordDialog() { int ret = msgBox.exec(); if (ret == QMessageBox::Yes) { this->close(); - emit init_lock(); + emit initLock(); } else { ui->applock_checkbox->blockSignals(true); ui->applock_checkbox->setChecked(false); @@ -725,7 +746,7 @@ void SettingsWidget::on_chnageCurrentPasswordPushButton_clicked() { msgBox.addButton(changePassword, QMessageBox::NoRole); connect(changePassword, &QPushButton::clicked, changePassword, [=]() { this->close(); - emit change_lock_password(); + emit changeLockPassword(); }); msgBox.exec(); @@ -735,9 +756,7 @@ void SettingsWidget::on_chnageCurrentPasswordPushButton_clicked() { } } -void SettingsWidget::on_fullWidthViewCheckbox_toggled(bool checked) -{ - settings.setValue("fullWidthView", checked); - emit updateFullWidthView(checked); +void SettingsWidget::on_fullWidthViewCheckbox_toggled(bool checked) { + settings.setValue("fullWidthView", checked); + emit updateFullWidthView(checked); } - diff --git a/src/settingswidget.h b/src/settingswidget.h index 3e76b20..8e8eab8 100644 --- a/src/settingswidget.h +++ b/src/settingswidget.h @@ -20,8 +20,8 @@ signals: void muteToggled(const bool checked); void autoPlayMediaToggled(const bool checked); void userAgentChanged(QString userAgentStr); - void init_lock(); - void change_lock_password(); + void initLock(); + void changeLockPassword(); void dictChanged(QString dict); void spellCheckChanged(bool checked); void notificationPopupTimeOutChanged(); @@ -43,10 +43,11 @@ public slots: void appLockSetChecked(bool checked); void setCurrentPasswordText(QString str); void loadDictionaries(QStringList dictionaries); - void clearAllData(); void autoAppLockSetChecked(bool checked); void updateAppLockPasswordViewer(); + void appAutoLockingSetChecked(bool checked); + void toggleTheme(); protected slots: bool eventFilter(QObject *obj, QEvent *event); void closeEvent(QCloseEvent *event); @@ -54,6 +55,7 @@ protected slots: private slots: QString cachePath(); QString persistentStoragePath(); + void showSetApplockPasswordDialog(); bool isChildOf(QObject *Of, QObject *self); void applyThemeQuirks(); void on_appAutoLockcheckBox_toggled(bool checked); @@ -92,7 +94,6 @@ private slots: void on_zoomPlus_clicked(); void on_zoomResetMaximized_clicked(); void on_zoomReset_clicked(); - void showSetApplockPasswordDialog(); void themeSwitchTimerTimeout(); void updateAutomaticTheme(); -- cgit v1.2.3 From 6c6275c34bfc4d1e37dfa50495c977af485f9cf0 Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Mon, 4 Jul 2022 23:21:32 +0530 Subject: fix(web): bypass lock check while loading quirk - just reload without asking while loading quirks --- src/mainwindow.cpp | 40 ++++++++++++++++++++++------------------ src/mainwindow.h | 2 +- 2 files changed, 23 insertions(+), 19 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3cc8367..5a7e6e2 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -500,8 +500,7 @@ void MainWindow::closeEvent(QCloseEvent *event) { this->hide(); event->ignore(); if (settings.value("firstrun_tray", true).toBool()) { - notify(QApplication::applicationName(), - "Minimized to system tray."); + notify(QApplication::applicationName(), "Minimized to system tray."); settings.setValue("firstrun_tray", false); } return; @@ -579,9 +578,7 @@ void MainWindow::createActions() { reloadAction = new QAction(tr("Re&load"), this); reloadAction->setShortcut(Qt::Key_F5); - connect(reloadAction, &QAction::triggered,this, [=]{ - this->doReload(); - }); + connect(reloadAction, &QAction::triggered, this, [=] { this->doReload(); }); addAction(reloadAction); lockAction = new QAction(tr("Loc&k"), this); @@ -1072,7 +1069,7 @@ void MainWindow::loadingQuirk(QString test) { if (correctlyLoaderRetries > -1) { qWarning() << test << "checkLoadedCorrectly()/loadingQuirk()/doReload()" << correctlyLoaderRetries; - doReload(); + doReload(false, false, true); correctlyLoaderRetries--; } else { utils::delete_cache(webEngine->page()->profile()->cachePath()); @@ -1181,22 +1178,29 @@ bool MainWindow::isPhoneNumber(const QString &phoneNumber) { return reg.match(phoneNumber).hasMatch(); } -void MainWindow::doReload(bool byPassCache, bool isAskedByCLI) { - if (lockWidget && !lockWidget->getIsLocked()) { - this->notify(QApplication::applicationName(), QObject::tr("Reloading...")); +void MainWindow::doReload(bool byPassCache, bool isAskedByCLI, + bool byLoadingQuirk) { + if (byLoadingQuirk) { + this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, + byPassCache); } else { - QString error = tr("Unlock to Reload the App."); - if (isAskedByCLI) { - this->notify(QApplication::applicationName() + "| Error", error); + if (lockWidget && !lockWidget->getIsLocked()) { + this->notify(QApplication::applicationName(), + QObject::tr("Reloading...")); } else { - QMessageBox::critical(this, QApplication::applicationName() + "| Error", - error); + QString error = tr("Unlock to Reload the App."); + if (isAskedByCLI) { + this->notify(QApplication::applicationName() + "| Error", error); + } else { + QMessageBox::critical(this, QApplication::applicationName() + "| Error", + error); + } + this->show(); + return; } - this->show(); - return; + this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, + byPassCache); } - this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, - byPassCache); } void MainWindow::toggleMute(const bool &checked) { diff --git a/src/mainwindow.h b/src/mainwindow.h index f8a4ff5..76abe86 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -55,7 +55,7 @@ public slots: void alreadyRunning(bool notify = false); void notify(QString title, QString message); void toggleTheme(); - void doReload(bool byPassCache = false, bool isAskedByCLI = false); + void doReload(bool byPassCache = false, bool isAskedByCLI = false, bool byLoadingQuirk = false); void newChat(); protected slots: void closeEvent(QCloseEvent *event) override; -- cgit v1.2.3 From 530c24bf2bf672845d4d4f7c17f69ce213b7cf1d Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Wed, 31 Aug 2022 21:48:46 +0530 Subject: feat: systemtray notification counter other changes include: - no client side check on new chat numbers, whatsapp web doing check --- src/mainwindow.cpp | 73 +++++++++++++++++++++++++----------------------------- src/mainwindow.h | 10 +++++--- src/utils.cpp | 11 ++++++-- src/utils.h | 6 ++--- 4 files changed, 52 insertions(+), 48 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index a37e558..cd28707 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -15,12 +15,12 @@ extern bool defaultAppAutoLock; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), notificationsTitleRegExp("^\\([1-9]\\d*\\).*"), - trayIconRead(":/icons/app/icon-32.png"), - trayIconUnread(":/icons/app/whatsapp-message-32.png") { + trayIconNormal(":/icons/app/notification/whatsie-notify.png"), + unreadMessageCountRegExp("\\([^\\d]*(\\d+)[^\\d]*\\)") { setObjectName("MainWindow"); setWindowTitle(QApplication::applicationName()); - setWindowIcon(QIcon(":/icons/app/icon-128.png")); + setWindowIcon(QIcon(":/icons/app/icon-64.png")); setMinimumWidth(525); setMinimumHeight(448); restoreMainWindow(); @@ -523,20 +523,19 @@ void MainWindow::notify(QString title, QString message) { if (settings.value("notificationCombo", 1).toInt() == 0 && trayIcon != nullptr) { - trayIcon->showMessage(title, message, QIcon(":/icons/app/icon-64.png"), + trayIcon->showMessage(title, message, + QIcon(":/icons/app/notification/whatsie-notify.png"), settings.value("notificationTimeOut", 9000).toInt()); trayIcon->disconnect(trayIcon, SIGNAL(messageClicked())); connect(trayIcon, &QSystemTrayIcon::messageClicked, trayIcon, [=]() { if (windowState().testFlag(Qt::WindowMinimized) || !windowState().testFlag(Qt::WindowActive)) { activateWindow(); - // raise(); this->show(); } }); } else { auto popup = new NotificationPopup(webEngine); - popup->setAttribute(Qt::WA_DeleteOnClose, true); connect(popup, &NotificationPopup::notification_clicked, popup, [=]() { if (windowState().testFlag(Qt::WindowMinimized) || !windowState().testFlag(Qt::WindowActive) || this->isHidden()) { @@ -550,7 +549,7 @@ void MainWindow::notify(QString title, QString message) { popup->adjustSize(); int screenNumber = qApp->desktop()->screenNumber(this); popup->present(screenNumber < 0 ? 0 : screenNumber, title, message, - QPixmap(":/icons/app/icon-64.png")); + QPixmap(":/icons/app/notification/whatsie-notify.png")); } } @@ -634,7 +633,7 @@ void MainWindow::createTrayIcon() { trayIconMenu->addSeparator(); trayIconMenu->addAction(quitAction); - trayIcon = new QSystemTrayIcon(trayIconRead, this); + trayIcon = new QSystemTrayIcon(trayIconNormal, this); trayIcon->setContextMenu(trayIconMenu); connect(trayIconMenu, SIGNAL(aboutToShow()), this, SLOT(checkWindowState())); @@ -813,6 +812,17 @@ void MainWindow::createWebEngine() { createWebPage(false); } +const QIcon MainWindow::getTrayIcon(const int ¬ificationCount) const { + if (notificationCount == 0) { + return QIcon(":/icons/app/notification/whatsie-notify.png"); + } else if (notificationCount >= 10) { + return QIcon(":/icons/app/notification/whatsie-notify-10.png"); + } else { + return QIcon(":/icons/app/notification/whatsie-notify-" + + QString::number(notificationCount) + ".png"); + } +} + void MainWindow::createWebPage(bool offTheRecord) { if (offTheRecord && !m_otrProfile) { m_otrProfile.reset(new QWebEngineProfile); @@ -829,8 +839,6 @@ void MainWindow::createWebPage(bool offTheRecord) { settings.value("useragent", defaultUserAgentStr).toString()); setNotificationPresenter(profile); - //profile->setHttpCacheMaximumSize(209715200/2); - //profile->setHttpCacheType(QWebEngineProfile::MemoryHttpCache); QWebEnginePage *page = new WebEnginePage(profile, webEngine); if (settings.value("windowTheme", "light").toString() == "dark") { @@ -865,7 +873,6 @@ void MainWindow::setNotificationPresenter(QWebEngineProfile *profile) { } auto popup = new NotificationPopup(webEngine); - popup->setAttribute(Qt::WA_DeleteOnClose, true); popup->setObjectName("engineNotifier"); connect(popup, &NotificationPopup::notification_clicked, popup, [=]() { if (windowState().testFlag(Qt::WindowMinimized) || @@ -921,25 +928,25 @@ void MainWindow::handleWebViewTitleChanged(QString title) { setWindowTitle(QApplication::applicationName() + ": " + title); if (notificationsTitleRegExp.exactMatch(title)) { - if (notificationsTitleRegExp.isEmpty() == false && - notificationsTitleRegExp.capturedTexts().isEmpty() == false) { + if (notificationsTitleRegExp.capturedTexts().isEmpty() == false) { QString capturedTitle = notificationsTitleRegExp.capturedTexts().constFirst(); - QRegExp rgex("\\([^\\d]*(\\d+)[^\\d]*\\)"); - rgex.setMinimal(true); - if (rgex.indexIn(capturedTitle) != -1) { - QString unreadMessageCount = rgex.capturedTexts().constLast(); - QString suffix = - unreadMessageCount.toInt() > 1 ? tr("messages") : tr("message"); - restoreAction->setText(tr("Restore") + " | " + unreadMessageCount + - " " + suffix); + unreadMessageCountRegExp.setMinimal(true); + if (unreadMessageCountRegExp.indexIn(capturedTitle) != -1) { + QString unreadMessageCountStr = + unreadMessageCountRegExp.capturedTexts().constLast(); + int unreadMessageCount = unreadMessageCountStr.toInt(); + + restoreAction->setText( + tr("Restore") + " | " + unreadMessageCountStr + " " + + (unreadMessageCount > 1 ? tr("messages") : tr("message"))); + trayIcon->setIcon(getTrayIcon(unreadMessageCount)); + setWindowIcon(getTrayIcon(unreadMessageCount)); } } - trayIcon->setIcon(trayIconUnread); - setWindowIcon(trayIconUnread); } else { - trayIcon->setIcon(trayIconRead); - setWindowIcon(trayIconRead); + trayIcon->setIcon(trayIconNormal); + setWindowIcon(trayIconNormal); } } @@ -1144,12 +1151,7 @@ void MainWindow::newChat() { tr("Enter a valid WhatsApp number with country code (ex- +91XXXXXXXXXX)"), QLineEdit::Normal, "", &ok); if (ok) { - if (isPhoneNumber(phoneNumber)) - triggerNewChat(phoneNumber, ""); - else - QMessageBox::information(this, - QApplication::applicationName() + "| Error", - tr("Invalid Phone Number")); + triggerNewChat(phoneNumber, ""); } } @@ -1173,17 +1175,10 @@ void MainWindow::triggerNewChat(QString phone, QString text) { }); } -bool MainWindow::isPhoneNumber(const QString &phoneNumber) { - const QString phone = "^\\+(((\\d{2}))\\s?)?((\\d{2})|(\\((\\d{2})\\))\\s?)?(" - "\\d{3,15})(\\-(\\d{3,15}))?$"; - static QRegularExpression reg(phone); - return reg.match(phoneNumber).hasMatch(); -} - void MainWindow::doReload(bool byPassCache, bool isAskedByCLI, bool byLoadingQuirk) { if (byLoadingQuirk) { - this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, + this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, byPassCache); } else { if (lockWidget && !lockWidget->getIsLocked()) { diff --git a/src/mainwindow.h b/src/mainwindow.h index 76abe86..970458b 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -41,6 +41,7 @@ class MainWindow : public QMainWindow { public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); + public slots: void updateWindowTheme(); void updatePageTheme(); @@ -55,7 +56,8 @@ public slots: void alreadyRunning(bool notify = false); void notify(QString title, QString message); void toggleTheme(); - void doReload(bool byPassCache = false, bool isAskedByCLI = false, bool byLoadingQuirk = false); + void doReload(bool byPassCache = false, bool isAskedByCLI = false, + bool byLoadingQuirk = false); void newChat(); protected slots: void closeEvent(QCloseEvent *event) override; @@ -63,6 +65,7 @@ protected slots: void changeEvent(QEvent *e) override; private: + const QIcon getTrayIcon(const int ¬ificationCount) const; QPalette lightPalette, darkPalette; void createActions(); void createTrayIcon(); @@ -70,8 +73,8 @@ private: QSettings settings; QRegExp notificationsTitleRegExp; - QIcon trayIconRead; - QIcon trayIconUnread; + QIcon trayIconNormal; + QRegExp unreadMessageCountRegExp; QAction *reloadAction; QAction *minimizeAction; @@ -115,7 +118,6 @@ private slots: void checkLoadedCorrectly(); void loadingQuirk(QString test); void setNotificationPresenter(QWebEngineProfile *profile); - bool isPhoneNumber(const QString &phoneNumber); void quitApp(); void initRateWidget(); void initThemes(); diff --git a/src/utils.cpp b/src/utils.cpp index b231882..da8d2a2 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -175,7 +175,7 @@ QString utils::DecodeXML(const QString &decodeMe) { return temp; } -QString utils::htmlToPlainText(QString str) { +QString utils::htmlToPlainText(const QString &str) { QString out; QTextDocument text; text.setHtml(str); @@ -264,7 +264,7 @@ QString utils::GetEnvironmentVar(const QString &variable_name) { #endif } -void utils::desktopOpenUrl(const QString str) { +void utils::desktopOpenUrl(const QString &str) { QProcess *xdg_open = new QProcess(0); xdg_open->start("xdg-open", QStringList() << str); if (xdg_open->waitForStarted(1000) == false) { @@ -284,3 +284,10 @@ void utils::desktopOpenUrl(const QString str) { xdg_open->deleteLater(); }); } + +bool utils::isPhoneNumber(const QString &phoneNumber) { + const QString phone = "^\\+(((\\d{2}))\\s?)?((\\d{2})|(\\((\\d{2})\\))\\s?)?(" + "\\d{3,15})(\\-(\\d{3,15}))?$"; + static QRegularExpression reg(phone); + return reg.match(phoneNumber).hasMatch(); +} diff --git a/src/utils.h b/src/utils.h index 363dbe9..d5b9765 100644 --- a/src/utils.h +++ b/src/utils.h @@ -33,13 +33,13 @@ public slots: static QString returnPath(QString pathname, QString standardLocation); static QString EncodeXML(const QString &encodeMe); static QString DecodeXML(const QString &decodeMe); - static QString htmlToPlainText(QString str); + static QString htmlToPlainText(const QString &str); static QString GetEnvironmentVar(const QString &variable_name); static float RoundToOneDecimal(float number); static void DisplayExceptionErrorDialog(const QString &error_info); static QString appDebugInfo(); - static void desktopOpenUrl(const QString str); - + static void desktopOpenUrl(const QString &str); + static bool isPhoneNumber(const QString &phoneNumber); private slots: // use refreshCacheSize static quint64 dir_size(const QString &directory); -- cgit v1.2.3 From 0eb7ea05aa2eaeb451b713efa901eb7597c99b51 Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Thu, 26 Jan 2023 21:47:14 +0530 Subject: fix: prevent zoom with ctrl+mouse - set zoomfactor using settings --- src/mainwindow.cpp | 23 +++++++++++++++++++++++ src/mainwindow.h | 1 + src/webview.cpp | 10 ++++++++++ src/webview.h | 4 ++++ 4 files changed, 38 insertions(+) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 5cf7916..3d01ba0 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -965,6 +965,7 @@ void MainWindow::handleLoadFinished(bool loaded) { updatePageTheme(); handleZoom(); injectMutationObserver(); + injectPreventScrollWheelZoomHelper(); injectFullWidthJavaScript(); injectClassChangeObserver(); injectNewChatJavaScript(); @@ -974,6 +975,28 @@ void MainWindow::handleLoadFinished(bool loaded) { } } +void MainWindow::injectPreventScrollWheelZoomHelper() { + QString js = R"( + (function () { + const SSWZ = function () { + this.keyScrollHandler = function (e) { + if (e.ctrlKey) { + e.preventDefault(); + return false; + } + } + }; + if (window === top) { + const sswz = new SSWZ(); + window.addEventListener('wheel', sswz.keyScrollHandler, { + passive: false + }); + } + })(); + )"; + webEngine->page()->runJavaScript(js); +} + void MainWindow::injectClassChangeObserver() { QString js = R"( const observer = new MutationObserver(() => { diff --git a/src/mainwindow.h b/src/mainwindow.h index 970458b..98dbf8b 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -135,6 +135,7 @@ private slots: void injectFullWidthJavaScript(); void injectMutationObserver(); void injectClassChangeObserver(); + void injectPreventScrollWheelZoomHelper(); }; #endif // MAINWINDOW_H diff --git a/src/webview.cpp b/src/webview.cpp index 15958db..cfd9af9 100644 --- a/src/webview.cpp +++ b/src/webview.cpp @@ -48,6 +48,16 @@ WebView::WebView(QWidget *parent, QStringList dictionaries) }); } +void WebView::wheelEvent(QWheelEvent *event) { + if (event->modifiers().testFlag(Qt::ControlModifier)) { + qDebug() << "skipped ctrl + m_wheel event on webengineview"; + // do nothing + } else { + qDebug() << "wheel event on webengine view"; + QWebEngineView::wheelEvent(event); + } +} + void WebView::contextMenuEvent(QContextMenuEvent *event) { QMenu *menu = page()->createStandardContextMenu(); diff --git a/src/webview.h b/src/webview.h index 70b5a6e..81f5f43 100644 --- a/src/webview.h +++ b/src/webview.h @@ -3,6 +3,7 @@ #include #include +#include class WebView : public QWebEngineView { Q_OBJECT @@ -13,6 +14,9 @@ public: protected: void contextMenuEvent(QContextMenuEvent *event) override; +protected slots: + void wheelEvent(QWheelEvent *event); + private: QStringList m_dictionaries; QSettings settings; -- cgit v1.2.3 From 011db4495d98932cbffa5fc2268ee1a3e2984aa6 Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Fri, 27 Jan 2023 02:57:48 +0530 Subject: chore: cleanup - move methods to page --- src/SunClock.cpp | 276 -------------------------------- src/SunClock.hpp | 126 --------------- src/WhatsApp.pro | 10 +- src/automatictheme.cpp | 2 +- src/downloadwidget.h | 2 +- src/downloadwidget.ui | 3 +- src/elidedlabel.cpp | 52 ------ src/elidedlabel.h | 49 ------ src/mainwindow.cpp | 147 +++-------------- src/mainwindow.h | 5 - src/sunclock.cpp | 276 ++++++++++++++++++++++++++++++++ src/sunclock.hpp | 126 +++++++++++++++ src/webenginepage.cpp | 113 ++++++++++++- src/webenginepage.h | 5 + src/widgets/elidedlabel/elidedlabel.cpp | 52 ++++++ src/widgets/elidedlabel/elidedlabel.h | 49 ++++++ 16 files changed, 648 insertions(+), 645 deletions(-) delete mode 100644 src/SunClock.cpp delete mode 100644 src/SunClock.hpp delete mode 100644 src/elidedlabel.cpp delete mode 100644 src/elidedlabel.h create mode 100644 src/sunclock.cpp create mode 100644 src/sunclock.hpp create mode 100644 src/widgets/elidedlabel/elidedlabel.cpp create mode 100644 src/widgets/elidedlabel/elidedlabel.h (limited to 'src/mainwindow.h') diff --git a/src/SunClock.cpp b/src/SunClock.cpp deleted file mode 100644 index 132c0a6..0000000 --- a/src/SunClock.cpp +++ /dev/null @@ -1,276 +0,0 @@ -#include -#include -#include - -inline double rad(double degrees) { - static const double degToRad = 4.0 * atan(1.0) / 180.0; - return degrees * degToRad; -} - -inline double deg(double radians) { - static const double radToDeg = 180.0 / (4.0 * atan(1.0)); - return radians * radToDeg; -} - -Sunclock::Sunclock(double const &latitude_, double const &longitude_, - double const &tz_offset_) - : latitude(latitude_), longitude(longitude_), tz_offset(tz_offset_) {} - -double Sunclock::irradiance() { return irradiance(time(0)); } - -double Sunclock::irradiance(time_t when) { - when = when + (time_t)(tz_offset * 60 * 60); - struct tm *t = gmtime(&when); - double _time_of_day = time_of_day(when); - double _julian_day = julian_day(t, _time_of_day, tz_offset); - double _julian_century = julian_century(_julian_day); - double _mean_obliq_ecliptic = mean_obliq_ecliptic(_julian_century); - double _mean_long_sun = mean_long_sun(_julian_century); - double _mean_anom_sun = mean_anom_sun(_julian_century); - double _sun_eq_of_centre = sun_eq_of_centre(_mean_anom_sun, _julian_century); - double _sun_true_long = sun_true_long(_mean_long_sun, _sun_eq_of_centre); - double _obliq_corr = obliq_corr(_mean_obliq_ecliptic, _julian_century); - double _sun_app_long = sun_app_long(_sun_true_long, _julian_century); - double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); - double _var_y = var_y(_obliq_corr); - double _eq_of_time = - eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); - double _declination = declination(_obliq_corr, _sun_app_long); - double _true_solar_time = true_solar_time(_time_of_day, _eq_of_time); - double _hour_angle = hour_angle(_true_solar_time); - double _solar_zenith = solar_zenith(_declination, _hour_angle); - return std::cos(rad(_solar_zenith)); -} - -time_t Sunclock::sunrise() { return sunrise(time(0)); } - -time_t Sunclock::sunrise(time_t date) { - date = date + (time_t)(tz_offset * 60 * 60); - struct tm *t = gmtime(&date); - double _time_of_day = time_of_day(date); - double _julian_day = julian_day(t, _time_of_day, tz_offset); - double _julian_century = julian_century(_julian_day); - double _mean_obliq_ecliptic = mean_obliq_ecliptic(_julian_century); - double _mean_long_sun = mean_long_sun(_julian_century); - double _mean_anom_sun = mean_anom_sun(_julian_century); - double _sun_eq_of_centre = sun_eq_of_centre(_mean_anom_sun, _julian_century); - double _sun_true_long = sun_true_long(_mean_long_sun, _sun_eq_of_centre); - double _obliq_corr = obliq_corr(_mean_obliq_ecliptic, _julian_century); - double _sun_app_long = sun_app_long(_sun_true_long, _julian_century); - double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); - double _var_y = var_y(_obliq_corr); - double _eq_of_time = - eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); - double _declination = declination(_obliq_corr, _sun_app_long); - double _hour_angle_sunrise = hour_angle_sunrise(_declination); - - double noon_decimal_day = - (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; - double decimal_day = noon_decimal_day - _hour_angle_sunrise * 4 / 1440; - return time_from_decimal_day(date, decimal_day) - - (time_t)(tz_offset * 60 * 60); -} - -time_t Sunclock::solar_noon() { return solar_noon(time(0)); } - -time_t Sunclock::solar_noon(time_t date) { - date = date + (time_t)(tz_offset * 60 * 60); - struct tm *t = gmtime(&date); - double _time_of_day = time_of_day(date); - double _julian_day = julian_day(t, _time_of_day, tz_offset); - double _julian_century = julian_century(_julian_day); - double _mean_obliq_ecliptic = mean_obliq_ecliptic(_julian_century); - double _mean_long_sun = mean_long_sun(_julian_century); - double _mean_anom_sun = mean_anom_sun(_julian_century); - double _obliq_corr = obliq_corr(_mean_obliq_ecliptic, _julian_century); - double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); - double _var_y = var_y(_obliq_corr); - double _eq_of_time = - eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); - - double decimal_day = - (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; - return time_from_decimal_day(date, decimal_day) - - (time_t)(tz_offset * 60 * 60); -} - -time_t Sunclock::sunset() { return sunset(time(0)); } - -time_t Sunclock::sunset(time_t date) { - date = date + (time_t)(tz_offset * 60 * 60); - struct tm *t = gmtime(&date); - double _time_of_day = time_of_day(date); - double _julian_day = julian_day(t, _time_of_day, tz_offset); - double _julian_century = julian_century(_julian_day); - double _mean_obliq_ecliptic = mean_obliq_ecliptic(_julian_century); - double _mean_long_sun = mean_long_sun(_julian_century); - double _mean_anom_sun = mean_anom_sun(_julian_century); - double _sun_eq_of_centre = sun_eq_of_centre(_mean_anom_sun, _julian_century); - double _sun_true_long = sun_true_long(_mean_long_sun, _sun_eq_of_centre); - double _obliq_corr = obliq_corr(_mean_obliq_ecliptic, _julian_century); - double _sun_app_long = sun_app_long(_sun_true_long, _julian_century); - double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); - double _var_y = var_y(_obliq_corr); - double _eq_of_time = - eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); - double _declination = declination(_obliq_corr, _sun_app_long); - double _hour_angle_sunrise = hour_angle_sunrise(_declination); - - double noon_decimal_day = - (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; - double decimal_day = noon_decimal_day + _hour_angle_sunrise * 4 / 1440; - return time_from_decimal_day(date, decimal_day) - - (time_t)(tz_offset * 60 * 60); -} - -double Sunclock::time_of_day(time_t date) { - struct tm *t = gmtime(&date); - return (t->tm_hour + t->tm_min / 60.0 + t->tm_sec / 3600.0) / 24.0; -} - -time_t Sunclock::time_from_decimal_day(time_t date, double decimal_day) { - struct std::tm epoch; - epoch.tm_isdst = 0; - epoch.tm_sec = epoch.tm_min = epoch.tm_hour = epoch.tm_mon = 0; - epoch.tm_mday = 1; - epoch.tm_year = 70; - time_t local_tz_offset = mktime(&epoch); - - struct tm *dt = gmtime(&date); - struct tm t = {}; - t.tm_year = dt->tm_year; - t.tm_mon = dt->tm_mon; - t.tm_mday = dt->tm_mday; - double hours = 24.0 * decimal_day; - t.tm_hour = int(hours); - double minutes = (hours - t.tm_hour) * 60; - t.tm_min = int(minutes); - double seconds = (minutes - t.tm_sec) * 60; - t.tm_sec = int(seconds) % 60; - return mktime(&t) - local_tz_offset; -} - -int Sunclock::days_since_1900(struct tm *t) { - int year = t->tm_year; - if (year < 0 || year > 199) { - throw std::invalid_argument( - "days_since_1900 - Date must be between 1900 and 2099"); - } - int month = t->tm_mon + 1; - int days = t->tm_mday; - - if (month < 3) { - month += 12; - year--; - } - int yearDays = (int)(year * 365.25); - int monthDays = (int)((month + 1) * 30.61); - - return (yearDays + monthDays + days - 63); -} - -double Sunclock::julian_day(struct tm *t, double const &time_of_day, - double const &tz_offset) { - return days_since_1900(t) + 2415018.5 + time_of_day - tz_offset / 24; -} - -double Sunclock::julian_century(double _julian_day) { - return (_julian_day - 2451545.0) / 36525.0; -} - -double Sunclock::mean_long_sun(double _julian_century) { - return ( - 280.46646 + - fmod(_julian_century * (36000.76983 + _julian_century * 0.0003032), 360)); -} - -double Sunclock::mean_anom_sun(double _julian_century) { - return 357.52911 + - _julian_century * (35999.05029 - 0.0001537 * _julian_century); -} - -double Sunclock::sun_eq_of_centre(double _mean_anom_sun, - double _julian_century) { - return sin(rad(_mean_anom_sun)) * - (1.914602 - - _julian_century * (0.004817 + 0.000014 * _julian_century)) + - sin(rad(2 * _mean_anom_sun)) * - (0.019993 - 0.000101 * _julian_century) + - sin(rad(3 * _mean_anom_sun)) * 0.000289; -} - -double Sunclock::sun_true_long(double _mean_long_sun, - double _sun_eq_of_centre) { - return _mean_long_sun + _sun_eq_of_centre; -} - -double Sunclock::eccent_earth_orbit(double _julian_century) { - return 0.016708634 - - _julian_century * (0.000042037 + 0.0001537 * _julian_century); -} - -double Sunclock::var_y(double _obliq_corr) { - return tan(rad(_obliq_corr / 2)) * tan(rad(_obliq_corr / 2)); -} - -double Sunclock::mean_obliq_ecliptic(double _julian_century) { - return (23 + (26 + ((21.448 - _julian_century * - (46.815 + _julian_century * - (0.00059 - _julian_century * - 0.001813)))) / - 60) / - 60); -} - -double Sunclock::obliq_corr(double _mean_obliq_ecliptic, - double _julian_century) { - return _mean_obliq_ecliptic + - 0.00256 * cos(deg(125.04 - 1934.136 * _julian_century)); -} - -double Sunclock::sun_app_long(double _sun_true_long, double _julian_century) { - return (_sun_true_long - 0.00569 - - 0.00478 * sin(deg(125.04 - 1934.136 * _julian_century))); -} - -double Sunclock::declination(double _obliq_corr, double _sun_app_long) { - return deg(asin(sin(rad(_obliq_corr)) * sin(rad(_sun_app_long)))); -} - -double Sunclock::eq_of_time(double _var_y, double _mean_long_sun, - double _eccent_earth_orbit, double _mean_anom_sun) { - return 4 * deg(_var_y * sin(2 * rad(_mean_long_sun)) - - 2 * _eccent_earth_orbit * sin(rad(_mean_anom_sun)) + - 4 * _eccent_earth_orbit * _var_y * sin(rad(_mean_anom_sun)) * - cos(2 * rad(_mean_long_sun)) - - 0.5 * _var_y * _var_y * sin(4 * rad(_mean_long_sun)) - - 1.25 * _eccent_earth_orbit * _eccent_earth_orbit * - sin(2 * rad(_mean_anom_sun))); -} - -double Sunclock::true_solar_time(double _time_of_day, double _eq_of_time) { - return fmod( - (_time_of_day * 1440 + _eq_of_time + 4 * longitude - 60 * tz_offset), - 1440); -} - -double Sunclock::hour_angle(double _true_solar_time) { - return (_true_solar_time / 4 < 0 ? _true_solar_time / 4 + 180 - : _true_solar_time / 4 - 180); -} - -double Sunclock::hour_angle_sunrise(double _declination) { - return deg( - acos(cos(rad(90.833)) / (cos(rad(latitude)) * cos(rad(_declination))) - - tan(rad(latitude)) * tan(rad(_declination)))); -} - -double Sunclock::solar_zenith(double _declination, double _hour_angle) { - return deg(acos(sin(rad(latitude)) * sin(rad(_declination)) + - cos(rad(latitude)) * cos(rad(_declination)) * - cos(rad(_hour_angle)))); -} - -double Sunclock::solar_elevation(double _solar_zenith) { - return 90 - _solar_zenith; -} diff --git a/src/SunClock.hpp b/src/SunClock.hpp deleted file mode 100644 index 4cfad57..0000000 --- a/src/SunClock.hpp +++ /dev/null @@ -1,126 +0,0 @@ -#ifndef DAYLIGHT_SUNCLOCK_HPP -#define DAYLIGHT_SUNCLOCK_HPP - -#include - -class Sunclock { -public: - Sunclock(double const &latitude_, double const &longitude_, double const &tz_offset_ = 0); - - /** - * \overload double Sunclock::irradiance(time_t when) - */ - double irradiance(); - - /** - * Specifically, we calculate Direct Normal Irradiance - * That is we do not consider atmospheric components like cloud cover, - * moisture content etc. - * - * @param when - * @return a value representing irradiance (power per unit area) - */ - double irradiance(time_t when); - - /** - * \overload time_t Sunclock::sunrise(time_t date) - */ - time_t sunrise(); - - /** - * Returns sunrise time for given date - * - * @param date only date is considered - * @return sunrise time - */ - time_t sunrise(time_t date); - - /** - * \overload time_t Sunclock::solar_noon(time_t date) - */ - time_t solar_noon(); - - /** - * Returns solar_noon time for given date - * - * @param date only date is considered - * @return solar_noon time - */ - time_t solar_noon(time_t date); - - /** - * \overload time_t Sunclock::sunset(time_t date) - */ - time_t sunset(); - - /** - * Returns sunset time for given date - * - * @param date only date is considered - * @return sunset time - */ - time_t sunset(time_t date); - -private: - // in decimal degrees, east is positive - double const latitude; - - // in decimal degrees, north is positive - double const longitude; - - // in hours, east is positive, i.e. IST (+05:30) is 5.5 - double const tz_offset; - - /** - * @param date - * @return percentage past midnight, i.e. noon is 0.5 - */ - double time_of_day(time_t date); - - static int days_since_1900(struct tm *t); - - /** - * @param date - * @param decimal_day decimal between 0.0 and 1.0, e.g. noon = 0.5 - * @return time_t with date and time set accordingly - */ - static time_t time_from_decimal_day(time_t date, double decimal_day); - - /** - * Get day count since Monday, January 1, 4713 BC - * https://en.wikipedia.org/wiki/Julian_day - * - * @param t - * @param time_of_day percentage past midnight, i.e. noon is 0.5 - * @param tz_offset in hours, east is positive, i.e. IST (+05:30) is 5.5 - * @return julian day - */ - static double julian_day(struct tm *t, double const &time_of_day, double const &tz_offset); - - /** - * Extract information in a suitable format from a time_t object. - */ - void prepare_time(time_t const &when, struct tm *ptm); - - double julian_century(double _julian_day); - double mean_long_sun(double _julian_century); - double mean_anom_sun(double _julian_century); - double sun_eq_of_centre(double _mean_anom_sun, double _julian_century); - double eccent_earth_orbit(double _julian_century); - double var_y(double _obliq_corr); - double mean_obliq_ecliptic(double _julian_century); - double sun_true_long(double _mean_long_sun, double _sun_eq_of_centre); - double obliq_corr(double _mean_obliq_ecliptic, double _julian_century); - double sun_app_long(double _sun_true_long, double _julian_century); - double declination(double _obliq_corr, double _sun_app_long); - double eq_of_time(double _var_y, double _mean_long_sun, double _eccent_earth_orbit, - double _mean_anom_sun); - double true_solar_time(double _time_of_day, double _eq_of_time); - double hour_angle(double _true_solar_time); - double hour_angle_sunrise(double _declination); - double solar_zenith(double _declination, double _hour_angle); - double solar_elevation(double _solar_zenith); -}; - -#endif - diff --git a/src/WhatsApp.pro b/src/WhatsApp.pro index 36b1ca2..844c000 100644 --- a/src/WhatsApp.pro +++ b/src/WhatsApp.pro @@ -59,29 +59,27 @@ DEFINES += VERSIONSTR=\\\"$${VERSION}\\\" # DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ - SunClock.cpp \ about.cpp \ automatictheme.cpp \ dictionaries.cpp \ downloadmanagerwidget.cpp \ downloadwidget.cpp \ - elidedlabel.cpp \ lock.cpp \ main.cpp \ mainwindow.cpp \ permissiondialog.cpp \ rateapp.cpp \ settingswidget.cpp \ + sunclock.cpp \ utils.cpp \ webenginepage.cpp \ webview.cpp \ + widgets/elidedlabel/elidedlabel.cpp \ widgets/scrolltext/scrolltext.cpp - RESOURCES += \ icons.qrc HEADERS += \ - SunClock.hpp \ about.h \ autolockeventfilter.h \ automatictheme.h \ @@ -90,7 +88,6 @@ HEADERS += \ dictionaries.h \ downloadmanagerwidget.h \ downloadwidget.h \ - elidedlabel.h \ lock.h \ mainwindow.h \ notificationpopup.h \ @@ -98,11 +95,12 @@ HEADERS += \ rateapp.h \ requestinterceptor.h \ settingswidget.h \ + sunclock.hpp \ utils.h \ webenginepage.h \ webview.h \ + widgets/elidedlabel/elidedlabel.h \ widgets/scrolltext/scrolltext.h - FORMS += \ about.ui \ automatictheme.ui \ diff --git a/src/automatictheme.cpp b/src/automatictheme.cpp index 6e14623..3cf33c8 100644 --- a/src/automatictheme.cpp +++ b/src/automatictheme.cpp @@ -1,7 +1,7 @@ #include "automatictheme.h" #include "ui_automatictheme.h" -#include "SunClock.hpp" +#include "sunclock.hpp" #include AutomaticTheme::AutomaticTheme(QWidget *parent) diff --git a/src/downloadwidget.h b/src/downloadwidget.h index ff9e488..074a979 100644 --- a/src/downloadwidget.h +++ b/src/downloadwidget.h @@ -52,7 +52,7 @@ #define DOWNLOADWIDGET_H #include "ui_downloadwidget.h" -#include "elidedlabel.h" +#include "widgets/elidedlabel/elidedlabel.h" #include diff --git a/src/downloadwidget.ui b/src/downloadwidget.ui index d405b8f..45d16e9 100644 --- a/src/downloadwidget.ui +++ b/src/downloadwidget.ui @@ -47,7 +47,6 @@ - 75 true @@ -72,7 +71,7 @@ ElidedLabel QLabel -
elidedlabel.h
+
widgets/elidedlabel/elidedlabel.h
diff --git a/src/elidedlabel.cpp b/src/elidedlabel.cpp deleted file mode 100644 index e870959..0000000 --- a/src/elidedlabel.cpp +++ /dev/null @@ -1,52 +0,0 @@ -#include "elidedlabel.h" - -#include -#include -#include -#include - -ElidedLabel::ElidedLabel(QWidget *parent) - : QLabel(parent), m_elide_mode(Qt::ElideRight) { - setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); -} - -ElidedLabel::ElidedLabel(const QString &txt, QWidget *parent) - : QLabel(txt, parent), m_elide_mode(Qt::ElideRight) { - setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); -} - -ElidedLabel::ElidedLabel(const QString &txt, Qt::TextElideMode elideMode, - QWidget *parent) - : QLabel(txt, parent), m_elide_mode(elideMode) { - setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); -} - -void ElidedLabel::setText(const QString &txt) { - QLabel::setText(txt); - cacheElidedText(geometry().width()); - setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); -} - -void ElidedLabel::cacheElidedText(int w) { - m_cached_elided_text = fontMetrics().elidedText( - text(), m_elide_mode, w, (buddy() == nullptr) ? 0 : Qt::TextShowMnemonic); -} - -void ElidedLabel::resizeEvent(QResizeEvent *e) { - QLabel::resizeEvent(e); - cacheElidedText(e->size().width()); -} - -void ElidedLabel::paintEvent(QPaintEvent *e) { - if (m_elide_mode == Qt::ElideNone) { - QLabel::paintEvent(e); - } else { - QPainter p(this); - p.drawText(0, 0, geometry().width(), geometry().height(), - QStyle::visualAlignment(text().isRightToLeft() ? Qt::RightToLeft - : Qt::LeftToRight, - alignment()) | - ((buddy() == nullptr) ? 0 : Qt::TextShowMnemonic), - m_cached_elided_text); - } -} diff --git a/src/elidedlabel.h b/src/elidedlabel.h deleted file mode 100644 index 7dc610a..0000000 --- a/src/elidedlabel.h +++ /dev/null @@ -1,49 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include - -// A label that elides its text when not enough geometry is available to show all of the text. -// Currently only capable of one-line. -class ElidedLabel : public QLabel { - Q_OBJECT - -private: - Qt::TextElideMode m_elide_mode; - QString m_cached_elided_text; - - -public: - ElidedLabel(QWidget* parent = NULL); - ElidedLabel(const QString& txt, QWidget* parent = NULL); - ElidedLabel(const QString& txt, Qt::TextElideMode elideMode = Qt::ElideRight, QWidget* parent = NULL); - -public: - // Set the elide mode used for displaying text. - inline void setElideMode(Qt::TextElideMode elideMode) { - m_elide_mode = elideMode; - updateGeometry(); - } - - // Get the elide mode currently used to display text. - inline Qt::TextElideMode elideMode() const { - return m_elide_mode; - } - - - -public: // QLabel overrides - void setText(const QString&); // note: not virtual so no polymorphism ... - - -protected: // QLabel overrides - virtual void paintEvent(QPaintEvent*) override; - virtual void resizeEvent(QResizeEvent*) override; - -protected: - // Cache the elided text so as to not recompute it every paint event - void cacheElidedText(int w); - -}; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 3d01ba0..ae8fdbe 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -205,11 +205,11 @@ void MainWindow::updateWindowTheme() { settings.value("widgetStyle", "Fusion").toString())); if (settings.value("windowTheme", "light").toString() == "dark") { qApp->setPalette(darkPalette); - this->webEngine->setStyleSheet( + webEngine->setStyleSheet( "QWebEngineView{background:rgb(17, 27, 33);}"); // whatsapp dark color } else { qApp->setPalette(lightPalette); - this->webEngine->setStyleSheet( + webEngine->setStyleSheet( "QWebEngineView{background:#F0F0F0;}"); // whatsapp light color } @@ -316,7 +316,7 @@ void MainWindow::initSettingWidget() { webSettings->setAttribute( QWebEngineSettings::PlaybackRequiresUserGesture, checked); - this->webEngine->page()->profile()->settings()->setAttribute( + webEngine->page()->profile()->settings()->setAttribute( QWebEngineSettings::PlaybackRequiresUserGesture, checked); }); @@ -357,7 +357,7 @@ void MainWindow::initSettingWidget() { connect(settingsWidget, &SettingsWidget::notificationPopupTimeOutChanged, settingsWidget, [=]() { - setNotificationPresenter(this->webEngine->page()->profile()); + setNotificationPresenter(webEngine->page()->profile()); }); connect(settingsWidget, &SettingsWidget::notify, settingsWidget, @@ -479,7 +479,7 @@ void MainWindow::showSettings(bool isAskedByCLI) { void MainWindow::updateSettingsUserAgentWidget() { settingsWidget->updateDefaultUAButton( - this->webEngine->page()->profile()->httpUserAgent()); + webEngine->page()->profile()->httpUserAgent()); } void MainWindow::askToReloadPage() { @@ -806,16 +806,16 @@ void MainWindow::createWebEngine() { m_dictionaries = Dictionaries::GetDictionaries(); - WebView *webEngine = new WebView(this, m_dictionaries); - setCentralWidget(webEngine); - webEngine->setSizePolicy(widgetSize); - webEngine->show(); + WebView *webEngineView = new WebView(this, m_dictionaries); + setCentralWidget(webEngineView); + webEngineView->setSizePolicy(widgetSize); + webEngineView->show(); - this->webEngine = webEngine; + this->webEngine = webEngineView; - webEngine->addAction(minimizeAction); - webEngine->addAction(lockAction); - webEngine->addAction(quitAction); + webEngineView->addAction(minimizeAction); + webEngineView->addAction(lockAction); + webEngineView->addAction(quitAction); createWebPage(false); } @@ -964,119 +964,14 @@ void MainWindow::handleLoadFinished(bool loaded) { checkLoadedCorrectly(); updatePageTheme(); handleZoom(); - injectMutationObserver(); - injectPreventScrollWheelZoomHelper(); - injectFullWidthJavaScript(); - injectClassChangeObserver(); - injectNewChatJavaScript(); + if (settingsWidget != nullptr) { settingsWidget->refresh(); } } } -void MainWindow::injectPreventScrollWheelZoomHelper() { - QString js = R"( - (function () { - const SSWZ = function () { - this.keyScrollHandler = function (e) { - if (e.ctrlKey) { - e.preventDefault(); - return false; - } - } - }; - if (window === top) { - const sswz = new SSWZ(); - window.addEventListener('wheel', sswz.keyScrollHandler, { - passive: false - }); - } - })(); - )"; - webEngine->page()->runJavaScript(js); -} - -void MainWindow::injectClassChangeObserver() { - QString js = R"( - const observer = new MutationObserver(() => { - var haveFullView = document.body.classList.contains('whatsie-full-view'); - var container = document.querySelector('#app > .app-wrapper-web > div'); - if(container){ - if(haveFullView){ - container.style.width = '100%'; - container.style.height = '100%'; - container.style.top = '0'; - container.style.maxWidth = 'unset'; - }else{ - container.style.width = null; - container.style.height = null; - container.style.top = null; - container.style.maxWidth = null; - } - } - }); - observer.observe(document.body, { - attributes: true, - attributeFilter: ['class'], - childList: false, - characterData: false - });)"; - webEngine->page()->runJavaScript(js); -} -void MainWindow::injectMutationObserver() { - QString js = - R"(function waitForElement(selector) { - return new Promise(resolve => { - if (document.querySelector(selector)) { - return resolve(document.querySelector(selector)); - } - const observer = new MutationObserver(mutations => { - if (document.querySelector(selector)) { - resolve(document.querySelector(selector)); - observer.disconnect(); - } - }); - observer.observe(document.body, { - childList: true, - subtree: true - }); - }); - };)"; - webEngine->page()->runJavaScript(js); -} - -void MainWindow::injectFullWidthJavaScript() { - if (!settings.value("fullWidthView", true).toBool()) - return; - QString js = - R"(waitForElement('#pane-side').then( () => { - var container = document.querySelector('#app > .app-wrapper-web > div'); - container.style.width = '100%'; - container.style.height = '100%'; - container.style.top = '0'; - container.style.maxWidth = 'unset'; - }); - )"; - webEngine->page()->runJavaScript(js); -} - -void MainWindow::injectNewChatJavaScript() { - QString js = R"(const openNewChatWhatsie = (phone,text) => { - const link = document.createElement('a'); - link.setAttribute('href', - `whatsapp://send/?phone=${phone}&text=${text}`); - document.body.append(link); - link.click(); - document.body.removeChild(link); - }; - function openNewChatWhatsieDefined() - { - return (openNewChatWhatsie != 'undefined'); - })"; - webEngine->page()->runJavaScript(js); -} void MainWindow::checkLoadedCorrectly() { if (webEngine && webEngine->page()) { @@ -1172,8 +1067,8 @@ void MainWindow::messageClicked() { void MainWindow::doAppReload() { - if (this->webEngine->page()) { - this->webEngine->page()->disconnect(); + if (webEngine->page()) { + webEngine->page()->disconnect(); } createWebPage(false); } @@ -1195,7 +1090,7 @@ void MainWindow::triggerNewChat(QString phone, QString text) { "openNewChatWhatsieDefined()", [this, phone, text](const QVariant &result) { if (result.toString().contains("true")) { - this->webEngine->page()->runJavaScript( + webEngine->page()->runJavaScript( QString("openNewChatWhatsie(\"%1\",\"%2\")").arg(phone, text)); } else { // create send url equivalent @@ -1203,7 +1098,7 @@ void MainWindow::triggerNewChat(QString phone, QString text) { textStr = text.isEmpty() ? "" : "text=" + text; QString urlStr = "https://web.whatsapp.com/send?" + phoneStr + "&" + textStr; - this->webEngine->page()->load(QUrl(urlStr)); + webEngine->page()->load(QUrl(urlStr)); } this->alreadyRunning(); }); @@ -1212,7 +1107,7 @@ void MainWindow::triggerNewChat(QString phone, QString text) { void MainWindow::doReload(bool byPassCache, bool isAskedByCLI, bool byLoadingQuirk) { if (byLoadingQuirk) { - this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, + webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, byPassCache); } else { if (lockWidget && !lockWidget->getIsLocked()) { @@ -1229,13 +1124,13 @@ void MainWindow::doReload(bool byPassCache, bool isAskedByCLI, this->show(); return; } - this->webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, + webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, byPassCache); } } void MainWindow::toggleMute(const bool &checked) { - this->webEngine->page()->setAudioMuted(checked); + webEngine->page()->setAudioMuted(checked); } // get value of page theme when page is loaded diff --git a/src/mainwindow.h b/src/mainwindow.h index 98dbf8b..f6346ad 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -129,13 +129,8 @@ private slots: bool isLoggedIn(); void initAutoLock(); void appAutoLockChanged(); - void injectNewChatJavaScript(); void triggerNewChat(QString phone, QString text); void restoreMainWindow(); - void injectFullWidthJavaScript(); - void injectMutationObserver(); - void injectClassChangeObserver(); - void injectPreventScrollWheelZoomHelper(); }; #endif // MAINWINDOW_H diff --git a/src/sunclock.cpp b/src/sunclock.cpp new file mode 100644 index 0000000..29400f1 --- /dev/null +++ b/src/sunclock.cpp @@ -0,0 +1,276 @@ +#include +#include +#include + +inline double rad(double degrees) { + static const double degToRad = 4.0 * atan(1.0) / 180.0; + return degrees * degToRad; +} + +inline double deg(double radians) { + static const double radToDeg = 180.0 / (4.0 * atan(1.0)); + return radians * radToDeg; +} + +Sunclock::Sunclock(double const &latitude_, double const &longitude_, + double const &tz_offset_) + : latitude(latitude_), longitude(longitude_), tz_offset(tz_offset_) {} + +double Sunclock::irradiance() { return irradiance(time(0)); } + +double Sunclock::irradiance(time_t when) { + when = when + (time_t)(tz_offset * 60 * 60); + struct tm *t = gmtime(&when); + double _time_of_day = time_of_day(when); + double _julian_day = julian_day(t, _time_of_day, tz_offset); + double _julian_century = julian_century(_julian_day); + double _mean_obliq_ecliptic = mean_obliq_ecliptic(_julian_century); + double _mean_long_sun = mean_long_sun(_julian_century); + double _mean_anom_sun = mean_anom_sun(_julian_century); + double _sun_eq_of_centre = sun_eq_of_centre(_mean_anom_sun, _julian_century); + double _sun_true_long = sun_true_long(_mean_long_sun, _sun_eq_of_centre); + double _obliq_corr = obliq_corr(_mean_obliq_ecliptic, _julian_century); + double _sun_app_long = sun_app_long(_sun_true_long, _julian_century); + double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); + double _var_y = var_y(_obliq_corr); + double _eq_of_time = + eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); + double _declination = declination(_obliq_corr, _sun_app_long); + double _true_solar_time = true_solar_time(_time_of_day, _eq_of_time); + double _hour_angle = hour_angle(_true_solar_time); + double _solar_zenith = solar_zenith(_declination, _hour_angle); + return std::cos(rad(_solar_zenith)); +} + +time_t Sunclock::sunrise() { return sunrise(time(0)); } + +time_t Sunclock::sunrise(time_t date) { + date = date + (time_t)(tz_offset * 60 * 60); + struct tm *t = gmtime(&date); + double _time_of_day = time_of_day(date); + double _julian_day = julian_day(t, _time_of_day, tz_offset); + double _julian_century = julian_century(_julian_day); + double _mean_obliq_ecliptic = mean_obliq_ecliptic(_julian_century); + double _mean_long_sun = mean_long_sun(_julian_century); + double _mean_anom_sun = mean_anom_sun(_julian_century); + double _sun_eq_of_centre = sun_eq_of_centre(_mean_anom_sun, _julian_century); + double _sun_true_long = sun_true_long(_mean_long_sun, _sun_eq_of_centre); + double _obliq_corr = obliq_corr(_mean_obliq_ecliptic, _julian_century); + double _sun_app_long = sun_app_long(_sun_true_long, _julian_century); + double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); + double _var_y = var_y(_obliq_corr); + double _eq_of_time = + eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); + double _declination = declination(_obliq_corr, _sun_app_long); + double _hour_angle_sunrise = hour_angle_sunrise(_declination); + + double noon_decimal_day = + (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; + double decimal_day = noon_decimal_day - _hour_angle_sunrise * 4 / 1440; + return time_from_decimal_day(date, decimal_day) - + (time_t)(tz_offset * 60 * 60); +} + +time_t Sunclock::solar_noon() { return solar_noon(time(0)); } + +time_t Sunclock::solar_noon(time_t date) { + date = date + (time_t)(tz_offset * 60 * 60); + struct tm *t = gmtime(&date); + double _time_of_day = time_of_day(date); + double _julian_day = julian_day(t, _time_of_day, tz_offset); + double _julian_century = julian_century(_julian_day); + double _mean_obliq_ecliptic = mean_obliq_ecliptic(_julian_century); + double _mean_long_sun = mean_long_sun(_julian_century); + double _mean_anom_sun = mean_anom_sun(_julian_century); + double _obliq_corr = obliq_corr(_mean_obliq_ecliptic, _julian_century); + double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); + double _var_y = var_y(_obliq_corr); + double _eq_of_time = + eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); + + double decimal_day = + (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; + return time_from_decimal_day(date, decimal_day) - + (time_t)(tz_offset * 60 * 60); +} + +time_t Sunclock::sunset() { return sunset(time(0)); } + +time_t Sunclock::sunset(time_t date) { + date = date + (time_t)(tz_offset * 60 * 60); + struct tm *t = gmtime(&date); + double _time_of_day = time_of_day(date); + double _julian_day = julian_day(t, _time_of_day, tz_offset); + double _julian_century = julian_century(_julian_day); + double _mean_obliq_ecliptic = mean_obliq_ecliptic(_julian_century); + double _mean_long_sun = mean_long_sun(_julian_century); + double _mean_anom_sun = mean_anom_sun(_julian_century); + double _sun_eq_of_centre = sun_eq_of_centre(_mean_anom_sun, _julian_century); + double _sun_true_long = sun_true_long(_mean_long_sun, _sun_eq_of_centre); + double _obliq_corr = obliq_corr(_mean_obliq_ecliptic, _julian_century); + double _sun_app_long = sun_app_long(_sun_true_long, _julian_century); + double _eccent_earth_orbit = eccent_earth_orbit(_julian_century); + double _var_y = var_y(_obliq_corr); + double _eq_of_time = + eq_of_time(_var_y, _mean_long_sun, _eccent_earth_orbit, _mean_anom_sun); + double _declination = declination(_obliq_corr, _sun_app_long); + double _hour_angle_sunrise = hour_angle_sunrise(_declination); + + double noon_decimal_day = + (720 - 4 * longitude - _eq_of_time + tz_offset * 60) / 1440; + double decimal_day = noon_decimal_day + _hour_angle_sunrise * 4 / 1440; + return time_from_decimal_day(date, decimal_day) - + (time_t)(tz_offset * 60 * 60); +} + +double Sunclock::time_of_day(time_t date) { + struct tm *t = gmtime(&date); + return (t->tm_hour + t->tm_min / 60.0 + t->tm_sec / 3600.0) / 24.0; +} + +time_t Sunclock::time_from_decimal_day(time_t date, double decimal_day) { + struct std::tm epoch; + epoch.tm_isdst = 0; + epoch.tm_sec = epoch.tm_min = epoch.tm_hour = epoch.tm_mon = 0; + epoch.tm_mday = 1; + epoch.tm_year = 70; + time_t local_tz_offset = mktime(&epoch); + + struct tm *dt = gmtime(&date); + struct tm t = {}; + t.tm_year = dt->tm_year; + t.tm_mon = dt->tm_mon; + t.tm_mday = dt->tm_mday; + double hours = 24.0 * decimal_day; + t.tm_hour = int(hours); + double minutes = (hours - t.tm_hour) * 60; + t.tm_min = int(minutes); + double seconds = (minutes - t.tm_sec) * 60; + t.tm_sec = int(seconds) % 60; + return mktime(&t) - local_tz_offset; +} + +int Sunclock::days_since_1900(struct tm *t) { + int year = t->tm_year; + if (year < 0 || year > 199) { + throw std::invalid_argument( + "days_since_1900 - Date must be between 1900 and 2099"); + } + int month = t->tm_mon + 1; + int days = t->tm_mday; + + if (month < 3) { + month += 12; + year--; + } + int yearDays = (int)(year * 365.25); + int monthDays = (int)((month + 1) * 30.61); + + return (yearDays + monthDays + days - 63); +} + +double Sunclock::julian_day(struct tm *t, double const &time_of_day, + double const &tz_offset) { + return days_since_1900(t) + 2415018.5 + time_of_day - tz_offset / 24; +} + +double Sunclock::julian_century(double _julian_day) { + return (_julian_day - 2451545.0) / 36525.0; +} + +double Sunclock::mean_long_sun(double _julian_century) { + return ( + 280.46646 + + fmod(_julian_century * (36000.76983 + _julian_century * 0.0003032), 360)); +} + +double Sunclock::mean_anom_sun(double _julian_century) { + return 357.52911 + + _julian_century * (35999.05029 - 0.0001537 * _julian_century); +} + +double Sunclock::sun_eq_of_centre(double _mean_anom_sun, + double _julian_century) { + return sin(rad(_mean_anom_sun)) * + (1.914602 - + _julian_century * (0.004817 + 0.000014 * _julian_century)) + + sin(rad(2 * _mean_anom_sun)) * + (0.019993 - 0.000101 * _julian_century) + + sin(rad(3 * _mean_anom_sun)) * 0.000289; +} + +double Sunclock::sun_true_long(double _mean_long_sun, + double _sun_eq_of_centre) { + return _mean_long_sun + _sun_eq_of_centre; +} + +double Sunclock::eccent_earth_orbit(double _julian_century) { + return 0.016708634 - + _julian_century * (0.000042037 + 0.0001537 * _julian_century); +} + +double Sunclock::var_y(double _obliq_corr) { + return tan(rad(_obliq_corr / 2)) * tan(rad(_obliq_corr / 2)); +} + +double Sunclock::mean_obliq_ecliptic(double _julian_century) { + return (23 + (26 + ((21.448 - _julian_century * + (46.815 + _julian_century * + (0.00059 - _julian_century * + 0.001813)))) / + 60) / + 60); +} + +double Sunclock::obliq_corr(double _mean_obliq_ecliptic, + double _julian_century) { + return _mean_obliq_ecliptic + + 0.00256 * cos(deg(125.04 - 1934.136 * _julian_century)); +} + +double Sunclock::sun_app_long(double _sun_true_long, double _julian_century) { + return (_sun_true_long - 0.00569 - + 0.00478 * sin(deg(125.04 - 1934.136 * _julian_century))); +} + +double Sunclock::declination(double _obliq_corr, double _sun_app_long) { + return deg(asin(sin(rad(_obliq_corr)) * sin(rad(_sun_app_long)))); +} + +double Sunclock::eq_of_time(double _var_y, double _mean_long_sun, + double _eccent_earth_orbit, double _mean_anom_sun) { + return 4 * deg(_var_y * sin(2 * rad(_mean_long_sun)) - + 2 * _eccent_earth_orbit * sin(rad(_mean_anom_sun)) + + 4 * _eccent_earth_orbit * _var_y * sin(rad(_mean_anom_sun)) * + cos(2 * rad(_mean_long_sun)) - + 0.5 * _var_y * _var_y * sin(4 * rad(_mean_long_sun)) - + 1.25 * _eccent_earth_orbit * _eccent_earth_orbit * + sin(2 * rad(_mean_anom_sun))); +} + +double Sunclock::true_solar_time(double _time_of_day, double _eq_of_time) { + return fmod( + (_time_of_day * 1440 + _eq_of_time + 4 * longitude - 60 * tz_offset), + 1440); +} + +double Sunclock::hour_angle(double _true_solar_time) { + return (_true_solar_time / 4 < 0 ? _true_solar_time / 4 + 180 + : _true_solar_time / 4 - 180); +} + +double Sunclock::hour_angle_sunrise(double _declination) { + return deg( + acos(cos(rad(90.833)) / (cos(rad(latitude)) * cos(rad(_declination))) - + tan(rad(latitude)) * tan(rad(_declination)))); +} + +double Sunclock::solar_zenith(double _declination, double _hour_angle) { + return deg(acos(sin(rad(latitude)) * sin(rad(_declination)) + + cos(rad(latitude)) * cos(rad(_declination)) * + cos(rad(_hour_angle)))); +} + +double Sunclock::solar_elevation(double _solar_zenith) { + return 90 - _solar_zenith; +} diff --git a/src/sunclock.hpp b/src/sunclock.hpp new file mode 100644 index 0000000..4cfad57 --- /dev/null +++ b/src/sunclock.hpp @@ -0,0 +1,126 @@ +#ifndef DAYLIGHT_SUNCLOCK_HPP +#define DAYLIGHT_SUNCLOCK_HPP + +#include + +class Sunclock { +public: + Sunclock(double const &latitude_, double const &longitude_, double const &tz_offset_ = 0); + + /** + * \overload double Sunclock::irradiance(time_t when) + */ + double irradiance(); + + /** + * Specifically, we calculate Direct Normal Irradiance + * That is we do not consider atmospheric components like cloud cover, + * moisture content etc. + * + * @param when + * @return a value representing irradiance (power per unit area) + */ + double irradiance(time_t when); + + /** + * \overload time_t Sunclock::sunrise(time_t date) + */ + time_t sunrise(); + + /** + * Returns sunrise time for given date + * + * @param date only date is considered + * @return sunrise time + */ + time_t sunrise(time_t date); + + /** + * \overload time_t Sunclock::solar_noon(time_t date) + */ + time_t solar_noon(); + + /** + * Returns solar_noon time for given date + * + * @param date only date is considered + * @return solar_noon time + */ + time_t solar_noon(time_t date); + + /** + * \overload time_t Sunclock::sunset(time_t date) + */ + time_t sunset(); + + /** + * Returns sunset time for given date + * + * @param date only date is considered + * @return sunset time + */ + time_t sunset(time_t date); + +private: + // in decimal degrees, east is positive + double const latitude; + + // in decimal degrees, north is positive + double const longitude; + + // in hours, east is positive, i.e. IST (+05:30) is 5.5 + double const tz_offset; + + /** + * @param date + * @return percentage past midnight, i.e. noon is 0.5 + */ + double time_of_day(time_t date); + + static int days_since_1900(struct tm *t); + + /** + * @param date + * @param decimal_day decimal between 0.0 and 1.0, e.g. noon = 0.5 + * @return time_t with date and time set accordingly + */ + static time_t time_from_decimal_day(time_t date, double decimal_day); + + /** + * Get day count since Monday, January 1, 4713 BC + * https://en.wikipedia.org/wiki/Julian_day + * + * @param t + * @param time_of_day percentage past midnight, i.e. noon is 0.5 + * @param tz_offset in hours, east is positive, i.e. IST (+05:30) is 5.5 + * @return julian day + */ + static double julian_day(struct tm *t, double const &time_of_day, double const &tz_offset); + + /** + * Extract information in a suitable format from a time_t object. + */ + void prepare_time(time_t const &when, struct tm *ptm); + + double julian_century(double _julian_day); + double mean_long_sun(double _julian_century); + double mean_anom_sun(double _julian_century); + double sun_eq_of_centre(double _mean_anom_sun, double _julian_century); + double eccent_earth_orbit(double _julian_century); + double var_y(double _obliq_corr); + double mean_obliq_ecliptic(double _julian_century); + double sun_true_long(double _mean_long_sun, double _sun_eq_of_centre); + double obliq_corr(double _mean_obliq_ecliptic, double _julian_century); + double sun_app_long(double _sun_true_long, double _julian_century); + double declination(double _obliq_corr, double _sun_app_long); + double eq_of_time(double _var_y, double _mean_long_sun, double _eccent_earth_orbit, + double _mean_anom_sun); + double true_solar_time(double _time_of_day, double _eq_of_time); + double hour_angle(double _true_solar_time); + double hour_angle_sunrise(double _declination); + double solar_zenith(double _declination, double _hour_angle); + double solar_elevation(double _solar_zenith); +}; + +#endif + diff --git a/src/webenginepage.cpp b/src/webenginepage.cpp index 6cd5f44..e27d928 100644 --- a/src/webenginepage.cpp +++ b/src/webenginepage.cpp @@ -116,7 +116,7 @@ void WebEnginePage::handleFeaturePermissionRequested(const QUrl &securityOrigin, } void WebEnginePage::handleLoadFinished(bool ok) { - Q_UNUSED(ok); + // turn on Notification settings by default if (settings.value("permissions/Notifications").isValid() == false) { settings.beginGroup("permissions"); @@ -132,6 +132,14 @@ void WebEnginePage::handleLoadFinished(bool ok) { QWebEnginePage::Feature::Notifications, QWebEnginePage::PermissionPolicy::PermissionGrantedByUser); } + + if(ok){ + injectMutationObserver(); + injectPreventScrollWheelZoomHelper(); + injectFullWidthJavaScript(); + injectClassChangeObserver(); + injectNewChatJavaScript(); + } } void WebEnginePage::fullScreenRequestedByPage( @@ -301,3 +309,106 @@ void WebEnginePage::javaScriptConsoleMessage( Q_UNUSED(lineId); Q_UNUSED(sourceId); } + +void WebEnginePage::injectPreventScrollWheelZoomHelper() { + QString js = R"( + (function () { + const SSWZ = function () { + this.keyScrollHandler = function (e) { + if (e.ctrlKey) { + e.preventDefault(); + return false; + } + } + }; + if (window === top) { + const sswz = new SSWZ(); + window.addEventListener('wheel', sswz.keyScrollHandler, { + passive: false + }); + } + })(); + )"; + this->runJavaScript(js); +} + +void WebEnginePage::injectClassChangeObserver() { + QString js = R"( + const observer = new MutationObserver(() => { + var haveFullView = document.body.classList.contains('whatsie-full-view'); + var container = document.querySelector('#app > .app-wrapper-web > div'); + if(container){ + if(haveFullView){ + container.style.width = '100%'; + container.style.height = '100%'; + container.style.top = '0'; + container.style.maxWidth = 'unset'; + }else{ + container.style.width = null; + container.style.height = null; + container.style.top = null; + container.style.maxWidth = null; + } + } + }); + observer.observe(document.body, { + attributes: true, + attributeFilter: ['class'], + childList: false, + characterData: false + });)"; + this->runJavaScript(js); +} + +void WebEnginePage::injectMutationObserver() { + QString js = + R"(function waitForElement(selector) { + return new Promise(resolve => { + if (document.querySelector(selector)) { + return resolve(document.querySelector(selector)); + } + const observer = new MutationObserver(mutations => { + if (document.querySelector(selector)) { + resolve(document.querySelector(selector)); + observer.disconnect(); + } + }); + observer.observe(document.body, { + childList: true, + subtree: true + }); + }); + };)"; + this->runJavaScript(js); +} + +void WebEnginePage::injectFullWidthJavaScript() { + if (!settings.value("fullWidthView", true).toBool()) + return; + QString js = + R"(waitForElement('#pane-side').then( () => { + var container = document.querySelector('#app > .app-wrapper-web > div'); + container.style.width = '100%'; + container.style.height = '100%'; + container.style.top = '0'; + container.style.maxWidth = 'unset'; + }); + )"; + this->runJavaScript(js); +} + +void WebEnginePage::injectNewChatJavaScript() { + QString js = R"(const openNewChatWhatsie = (phone,text) => { + const link = document.createElement('a'); + link.setAttribute('href', + `whatsapp://send/?phone=${phone}&text=${text}`); + document.body.append(link); + link.click(); + document.body.removeChild(link); + }; + function openNewChatWhatsieDefined() + { + return (openNewChatWhatsie != 'undefined'); + })"; + this->runJavaScript(js); +} diff --git a/src/webenginepage.h b/src/webenginepage.h index e2684f3..d039288 100644 --- a/src/webenginepage.h +++ b/src/webenginepage.h @@ -61,6 +61,11 @@ private slots: QWebEngineClientCertificateSelection clientCertSelection); #endif void fullScreenRequestedByPage(QWebEngineFullScreenRequest request); + void injectPreventScrollWheelZoomHelper(); + void injectClassChangeObserver(); + void injectMutationObserver(); + void injectFullWidthJavaScript(); + void injectNewChatJavaScript(); }; #endif // WEBENGINEPAGE_H diff --git a/src/widgets/elidedlabel/elidedlabel.cpp b/src/widgets/elidedlabel/elidedlabel.cpp new file mode 100644 index 0000000..e870959 --- /dev/null +++ b/src/widgets/elidedlabel/elidedlabel.cpp @@ -0,0 +1,52 @@ +#include "elidedlabel.h" + +#include +#include +#include +#include + +ElidedLabel::ElidedLabel(QWidget *parent) + : QLabel(parent), m_elide_mode(Qt::ElideRight) { + setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); +} + +ElidedLabel::ElidedLabel(const QString &txt, QWidget *parent) + : QLabel(txt, parent), m_elide_mode(Qt::ElideRight) { + setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); +} + +ElidedLabel::ElidedLabel(const QString &txt, Qt::TextElideMode elideMode, + QWidget *parent) + : QLabel(txt, parent), m_elide_mode(elideMode) { + setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); +} + +void ElidedLabel::setText(const QString &txt) { + QLabel::setText(txt); + cacheElidedText(geometry().width()); + setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred); +} + +void ElidedLabel::cacheElidedText(int w) { + m_cached_elided_text = fontMetrics().elidedText( + text(), m_elide_mode, w, (buddy() == nullptr) ? 0 : Qt::TextShowMnemonic); +} + +void ElidedLabel::resizeEvent(QResizeEvent *e) { + QLabel::resizeEvent(e); + cacheElidedText(e->size().width()); +} + +void ElidedLabel::paintEvent(QPaintEvent *e) { + if (m_elide_mode == Qt::ElideNone) { + QLabel::paintEvent(e); + } else { + QPainter p(this); + p.drawText(0, 0, geometry().width(), geometry().height(), + QStyle::visualAlignment(text().isRightToLeft() ? Qt::RightToLeft + : Qt::LeftToRight, + alignment()) | + ((buddy() == nullptr) ? 0 : Qt::TextShowMnemonic), + m_cached_elided_text); + } +} diff --git a/src/widgets/elidedlabel/elidedlabel.h b/src/widgets/elidedlabel/elidedlabel.h new file mode 100644 index 0000000..7dc610a --- /dev/null +++ b/src/widgets/elidedlabel/elidedlabel.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include +#include +#include +#include + +// A label that elides its text when not enough geometry is available to show all of the text. +// Currently only capable of one-line. +class ElidedLabel : public QLabel { + Q_OBJECT + +private: + Qt::TextElideMode m_elide_mode; + QString m_cached_elided_text; + + +public: + ElidedLabel(QWidget* parent = NULL); + ElidedLabel(const QString& txt, QWidget* parent = NULL); + ElidedLabel(const QString& txt, Qt::TextElideMode elideMode = Qt::ElideRight, QWidget* parent = NULL); + +public: + // Set the elide mode used for displaying text. + inline void setElideMode(Qt::TextElideMode elideMode) { + m_elide_mode = elideMode; + updateGeometry(); + } + + // Get the elide mode currently used to display text. + inline Qt::TextElideMode elideMode() const { + return m_elide_mode; + } + + + +public: // QLabel overrides + void setText(const QString&); // note: not virtual so no polymorphism ... + + +protected: // QLabel overrides + virtual void paintEvent(QPaintEvent*) override; + virtual void resizeEvent(QResizeEvent*) override; + +protected: + // Cache the elided text so as to not recompute it every paint event + void cacheElidedText(int w); + +}; -- cgit v1.2.3 From 085205eb692332ac694ca92c784fa027906aac3b Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Fri, 27 Jan 2023 10:09:49 +0530 Subject: chore: code cleanup --- src/mainwindow.cpp | 44 ++++++++++++++++++++++---------------------- src/mainwindow.h | 8 ++++---- src/webenginepage.cpp | 12 ++++++------ src/webview.cpp | 41 ++++++++++++++++++++++------------------- src/webview.h | 2 +- 5 files changed, 55 insertions(+), 52 deletions(-) (limited to 'src/mainwindow.h') diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ae8fdbe..c8d688e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -39,7 +39,8 @@ void MainWindow::restoreMainWindow() { if (settings.value("geometry").isValid()) { restoreGeometry(settings.value("geometry").toByteArray()); QPoint pos = QCursor::pos(); - for (QScreen *screen : QGuiApplication::screens()) { + auto localScreens = QGuiApplication::screens(); + for (auto screen : qAsConst(localScreens)) { QRect screenRect = screen->geometry(); if (screenRect.contains(pos)) { this->move(screenRect.center() - this->rect().center()); @@ -356,9 +357,8 @@ void MainWindow::initSettingWidget() { }); connect(settingsWidget, &SettingsWidget::notificationPopupTimeOutChanged, - settingsWidget, [=]() { - setNotificationPresenter(webEngine->page()->profile()); - }); + settingsWidget, + [=]() { setNotificationPresenter(webEngine->page()->profile()); }); connect(settingsWidget, &SettingsWidget::notify, settingsWidget, [=](QString message) { notify("", message); }); @@ -381,7 +381,7 @@ void MainWindow::initSettingWidget() { settings.value("lockscreen", false).toBool()); // spell checker - settingsWidget->loadDictionaries(m_dictionaries); + settingsWidget->loadDictionaries(dictionaries); } } @@ -392,7 +392,8 @@ void MainWindow::changeEvent(QEvent *e) { QMainWindow::changeEvent(e); } -void MainWindow::handleZoomOnWindowStateChange(QWindowStateChangeEvent *ev) { +void MainWindow::handleZoomOnWindowStateChange( + const QWindowStateChangeEvent *ev) { if (settingsWidget != nullptr) { if (ev->oldState().testFlag(Qt::WindowMaximized) && windowState().testFlag(Qt::WindowNoState)) { @@ -743,17 +744,18 @@ void MainWindow::appAutoLockChanged() { void MainWindow::checkWindowState() { QObject *tray_icon_menu = this->findChild("trayIconMenu"); if (tray_icon_menu != nullptr) { + QMenu *menu = qobject_cast(tray_icon_menu); if (this->isVisible()) { - ((QMenu *)(tray_icon_menu))->actions().at(0)->setDisabled(false); - ((QMenu *)(tray_icon_menu))->actions().at(1)->setDisabled(true); + menu->actions().at(0)->setDisabled(false); + menu->actions().at(1)->setDisabled(true); } else { - ((QMenu *)(tray_icon_menu))->actions().at(0)->setDisabled(true); - ((QMenu *)(tray_icon_menu))->actions().at(1)->setDisabled(false); + menu->actions().at(0)->setDisabled(true); + menu->actions().at(1)->setDisabled(false); } if (lockWidget && lockWidget->getIsLocked()) { - ((QMenu *)(tray_icon_menu))->actions().at(4)->setDisabled(true); + menu->actions().at(4)->setDisabled(true); } else { - ((QMenu *)(tray_icon_menu))->actions().at(4)->setDisabled(false); + menu->actions().at(4)->setDisabled(false); } } } @@ -804,9 +806,9 @@ void MainWindow::createWebEngine() { widgetSize.setHorizontalStretch(1); widgetSize.setVerticalStretch(1); - m_dictionaries = Dictionaries::GetDictionaries(); + dictionaries = Dictionaries::GetDictionaries(); - WebView *webEngineView = new WebView(this, m_dictionaries); + WebView *webEngineView = new WebView(this, dictionaries); setCentralWidget(webEngineView); webEngineView->setSizePolicy(widgetSize); webEngineView->show(); @@ -832,11 +834,11 @@ const QIcon MainWindow::getTrayIcon(const int ¬ificationCount) const { } void MainWindow::createWebPage(bool offTheRecord) { - if (offTheRecord && !m_otrProfile) { - m_otrProfile.reset(new QWebEngineProfile); + if (offTheRecord && !otrProfile) { + otrProfile.reset(new QWebEngineProfile); } auto profile = - offTheRecord ? m_otrProfile.get() : QWebEngineProfile::defaultProfile(); + offTheRecord ? otrProfile.get() : QWebEngineProfile::defaultProfile(); QStringList dict_names; dict_names.append(settings.value("sc_dict", "en-US").toString()); @@ -864,7 +866,7 @@ void MainWindow::createWebPage(bool offTheRecord) { QUrl("https://web.whatsapp.com?v=" + QString::number(randomValue))); connect(profile, &QWebEngineProfile::downloadRequested, - &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested); + &downloadManagerWidget, &DownloadManagerWidget::downloadRequested); connect(page, SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)), this, SLOT(fullScreenRequested(QWebEngineFullScreenRequest))); @@ -971,8 +973,6 @@ void MainWindow::handleLoadFinished(bool loaded) { } } - - void MainWindow::checkLoadedCorrectly() { if (webEngine && webEngine->page()) { // test 1 based on the class name of body tag of the page @@ -1108,7 +1108,7 @@ void MainWindow::doReload(bool byPassCache, bool isAskedByCLI, bool byLoadingQuirk) { if (byLoadingQuirk) { webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, - byPassCache); + byPassCache); } else { if (lockWidget && !lockWidget->getIsLocked()) { this->notify(QApplication::applicationName(), @@ -1125,7 +1125,7 @@ void MainWindow::doReload(bool byPassCache, bool isAskedByCLI, return; } webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, - byPassCache); + byPassCache); } } diff --git a/src/mainwindow.h b/src/mainwindow.h index f6346ad..4ca25d5 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -91,11 +91,11 @@ private: QSystemTrayIcon *trayIcon; QWebEngineView *webEngine; SettingsWidget *settingsWidget = nullptr; - DownloadManagerWidget m_downloadManagerWidget; - QScopedPointer m_otrProfile; + DownloadManagerWidget downloadManagerWidget; + QScopedPointer otrProfile; Lock *lockWidget = nullptr; int correctlyLoaderRetries = 4; - QStringList m_dictionaries; + QStringList dictionaries; AutoLockEventFilter *autoLockEventFilter = nullptr; private slots: @@ -121,7 +121,7 @@ private slots: void quitApp(); void initRateWidget(); void initThemes(); - void handleZoomOnWindowStateChange(QWindowStateChangeEvent *ev); + void handleZoomOnWindowStateChange(const QWindowStateChangeEvent *ev); void handleZoom(); void changeLockPassword(); void forceLogOut(); diff --git a/src/webenginepage.cpp b/src/webenginepage.cpp index e27d928..849895e 100644 --- a/src/webenginepage.cpp +++ b/src/webenginepage.cpp @@ -133,12 +133,12 @@ void WebEnginePage::handleLoadFinished(bool ok) { QWebEnginePage::PermissionPolicy::PermissionGrantedByUser); } - if(ok){ - injectMutationObserver(); - injectPreventScrollWheelZoomHelper(); - injectFullWidthJavaScript(); - injectClassChangeObserver(); - injectNewChatJavaScript(); + if (ok) { + injectMutationObserver(); + injectPreventScrollWheelZoomHelper(); + injectFullWidthJavaScript(); + injectClassChangeObserver(); + injectNewChatJavaScript(); } } diff --git a/src/webview.cpp b/src/webview.cpp index cfd9af9..8029ffd 100644 --- a/src/webview.cpp +++ b/src/webview.cpp @@ -8,7 +8,7 @@ WebView::WebView(QWidget *parent, QStringList dictionaries) : QWebEngineView(parent) { - m_dictionaries = dictionaries; + dictionaries = dictionaries; QObject *parentMainWindow = this->parent(); while (!parentMainWindow->objectName().contains("MainWindow")) { @@ -49,18 +49,23 @@ WebView::WebView(QWidget *parent, QStringList dictionaries) } void WebView::wheelEvent(QWheelEvent *event) { - if (event->modifiers().testFlag(Qt::ControlModifier)) { + bool controlKeyIsHeld = + QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier); + // this doesn't work, (even after checking the global QApplication keyboard + // modifiers) as expected, the Ctrl+wheel is managed by Chromium + // WebenginePage directly. So, we manage it by injecting js to page using + // WebEnginePage::injectPreventScrollWheelZoomHelper + if ((event->modifiers() & Qt::ControlModifier) != 0 || controlKeyIsHeld) { qDebug() << "skipped ctrl + m_wheel event on webengineview"; - // do nothing + event->ignore(); } else { - qDebug() << "wheel event on webengine view"; QWebEngineView::wheelEvent(event); } } void WebView::contextMenuEvent(QContextMenuEvent *event) { - QMenu *menu = page()->createStandardContextMenu(); + auto menu = page()->createStandardContextMenu(); menu->setAttribute(Qt::WA_DeleteOnClose, true); // hide reload, back, forward, savepage, copyimagelink menus foreach (auto *action, menu->actions()) { @@ -87,29 +92,27 @@ void WebView::contextMenuEvent(QContextMenuEvent *event) { return; } - QWebEngineProfile *profile = page()->profile(); - const QStringList &languages = profile->spellCheckLanguages(); - + auto pageWebengineProfile = page()->profile(); + const QStringList &languages = pageWebengineProfile->spellCheckLanguages(); menu->addSeparator(); - - QAction *spellcheckAction = new QAction(tr("Check Spelling"), menu); + auto *spellcheckAction = new QAction(tr("Check Spelling"), menu); spellcheckAction->setCheckable(true); - spellcheckAction->setChecked(profile->isSpellCheckEnabled()); + spellcheckAction->setChecked(pageWebengineProfile->isSpellCheckEnabled()); connect(spellcheckAction, &QAction::toggled, this, - [profile, this](bool toogled) { - profile->setSpellCheckEnabled(toogled); + [pageWebengineProfile, this](bool toogled) { + pageWebengineProfile->setSpellCheckEnabled(toogled); settings.setValue("sc_enabled", toogled); }); menu->addAction(spellcheckAction); - if (profile->isSpellCheckEnabled()) { - QMenu *subMenu = menu->addMenu(tr("Select Language")); - for (const QString &dict : qAsConst(m_dictionaries)) { - QAction *action = subMenu->addAction(dict); + if (pageWebengineProfile->isSpellCheckEnabled()) { + auto subMenu = menu->addMenu(tr("Select Language")); + for (const QString &dict : qAsConst(dictionaries)) { + auto action = subMenu->addAction(dict); action->setCheckable(true); action->setChecked(languages.contains(dict)); - connect(action, &QAction::triggered, this, [profile, dict, this]() { - profile->setSpellCheckLanguages(QStringList() << dict); + connect(action, &QAction::triggered, this, [pageWebengineProfile, dict, this]() { + pageWebengineProfile->setSpellCheckLanguages(QStringList() << dict); settings.setValue("sc_dict", dict); }); } diff --git a/src/webview.h b/src/webview.h index 81f5f43..e03fa49 100644 --- a/src/webview.h +++ b/src/webview.h @@ -18,7 +18,7 @@ protected slots: void wheelEvent(QWheelEvent *event); private: - QStringList m_dictionaries; + QStringList dictionaries; QSettings settings; }; -- cgit v1.2.3 From 5f10a0f9657358fcd86c55ec065f3855bad0c160 Mon Sep 17 00:00:00 2001 From: Keshav Bhatt Date: Wed, 17 May 2023 21:59:43 +0530 Subject: feat: minor fixes + code cleanup --- src/about.cpp | 17 +- src/about.h | 29 +- src/about.ui | 9 +- src/autolockeventfilter.h | 21 +- src/automatictheme.cpp | 85 ++-- src/automatictheme.h | 42 +- src/common.h | 3 +- src/dictionaries.cpp | 2 +- src/downloadmanagerwidget.cpp | 13 +- src/downloadmanagerwidget.h | 8 +- src/lock.cpp | 51 +- src/lock.h | 9 +- src/main.cpp | 44 +- src/mainwindow.cpp | 905 ++++++++++++++++++---------------- src/mainwindow.h | 105 ++-- src/notificationpopup.h | 16 +- src/permissiondialog.cpp | 11 +- src/permissiondialog.h | 9 +- src/rateapp.cpp | 56 ++- src/rateapp.h | 52 +- src/requestinterceptor.h | 50 +- src/settingsmanager.h | 21 + src/settingswidget.cpp | 327 ++++++++---- src/settingswidget.h | 7 +- src/theme.cpp | 69 +++ src/theme.h | 27 + src/utils.cpp | 214 ++++++-- src/utils.h | 13 +- src/webenginepage.cpp | 51 +- src/webenginepage.h | 23 +- src/webview.cpp | 19 +- src/webview.h | 12 +- src/widgets/MoreApps/moreapps.cpp | 14 +- src/widgets/scrolltext/scrolltext.cpp | 2 +- 34 files changed, 1384 insertions(+), 952 deletions(-) create mode 100644 src/settingsmanager.h create mode 100644 src/theme.cpp create mode 100644 src/theme.h (limited to 'src/mainwindow.h') diff --git a/src/about.cpp b/src/about.cpp index 81657e8..3c7f826 100644 --- a/src/about.cpp +++ b/src/about.cpp @@ -17,7 +17,7 @@ About::About(QWidget *parent) : QWidget(parent), ui(new Ui::About) { appAuthorEmail = "keshavnrj@gmail.com"; appAuthorLink = "http://ktechpit.com"; donateLink = "https://paypal.me/keshavnrj/5"; - moreAppsLink = "https://snapcraft.io/search?q=keshavnrj"; + moreAppsLink = "https://snapcraft.io/publisher/keshavnrj"; appSourceCodeLink = "https://github.com/keshavbhatt/whatsie"; appRateLink = "snap://whatsie"; @@ -42,7 +42,7 @@ About::About(QWidget *parent) : QWidget(parent), ui(new Ui::About) { ui->version->setText("Version: " + QApplication::applicationVersion()); - ui->debugInfoText->setHtml(utils::appDebugInfo()); + ui->debugInfoText->setHtml(Utils::appDebugInfo()); ui->debugInfoText->hide(); @@ -92,14 +92,9 @@ void About::on_debugInfoButton_clicked() { } } -void About::keyPressEvent(QKeyEvent *e) -{ - if (e->key() == Qt::Key_Escape) - this->close(); +void About::keyPressEvent(QKeyEvent *e) { + if (e->key() == Qt::Key_Escape) + this->close(); - QWidget::keyPressEvent(e); -} - -void About::on_donate_2_clicked() { - QDesktopServices::openUrl(QUrl("https://opencollective.com/whatsie")); + QWidget::keyPressEvent(e); } diff --git a/src/about.h b/src/about.h index cd9e978..fc946e6 100644 --- a/src/about.h +++ b/src/about.h @@ -1,36 +1,31 @@ #ifndef ABOUT_H #define ABOUT_H -#include #include +#include namespace Ui { class About; } -class About : public QWidget -{ - Q_OBJECT +class About : public QWidget { + Q_OBJECT public: - explicit About(QWidget *parent = nullptr); - ~About(); + explicit About(QWidget *parent = nullptr); + ~About(); -protected slots: - void keyPressEvent(QKeyEvent *e); +protected: + void keyPressEvent(QKeyEvent *e) override; private slots: - void on_debugInfoButton_clicked(); - - void on_donate_2_clicked(); + void on_debugInfoButton_clicked(); private: - Ui::About *ui; + Ui::About *ui; - QString appName, appDescription, - appSourceCodeLink, appAuthorLink, - appAuthorName, appAuthorEmail, - donateLink,moreAppsLink, appRateLink; - bool isOpenSource; + QString appName, appDescription, appSourceCodeLink, appAuthorLink, + appAuthorName, appAuthorEmail, donateLink, moreAppsLink, appRateLink; + bool isOpenSource; }; #endif // ABOUT_H diff --git a/src/about.ui b/src/about.ui index b828eb2..9bad693 100644 --- a/src/about.ui +++ b/src/about.ui @@ -7,7 +7,7 @@ 0 0 522 - 486 + 487 @@ -172,13 +172,6 @@ p, li { white-space: pre-wrap; }
- - - - Donate OpenCollective - - - diff --git a/src/autolockeventfilter.h b/src/autolockeventfilter.h index 9c35c45..c061fe8 100644 --- a/src/autolockeventfilter.h +++ b/src/autolockeventfilter.h @@ -19,7 +19,7 @@ public: ~AutoLockEventFilter() { autoLockTimer->stop(); - autoLockTimer->deleteLater(); + delete autoLockTimer; } signals: @@ -39,18 +39,13 @@ public slots: protected: bool eventFilter(QObject *obj, QEvent *ev) { - if (ev->type() == QEvent::KeyPress - || ev->type() == QEvent::MouseMove - || ev->type() == QEvent::Wheel - || ev->type() == QEvent::TouchUpdate - || ev->type() == QEvent::MouseButtonRelease - || ev->type() == QEvent::MouseButtonPress - || ev->type() == QEvent::MouseButtonDblClick - || ev->type() == QEvent::Gesture - || ev->type() == QEvent::FocusIn - || ev->type() == QEvent::FocusOut - || ev->type() == QEvent::Enter - ) { + if (ev->type() == QEvent::KeyPress || ev->type() == QEvent::MouseMove || + ev->type() == QEvent::Wheel || ev->type() == QEvent::TouchUpdate || + ev->type() == QEvent::MouseButtonRelease || + ev->type() == QEvent::MouseButtonPress || + ev->type() == QEvent::MouseButtonDblClick || + ev->type() == QEvent::Gesture || ev->type() == QEvent::FocusIn || + ev->type() == QEvent::FocusOut || ev->type() == QEvent::Enter) { resetTimer(); } return QObject::eventFilter(obj, ev); diff --git a/src/automatictheme.cpp b/src/automatictheme.cpp index 3cf33c8..9b1f3e7 100644 --- a/src/automatictheme.cpp +++ b/src/automatictheme.cpp @@ -2,26 +2,27 @@ #include "ui_automatictheme.h" #include "sunclock.hpp" -#include AutomaticTheme::AutomaticTheme(QWidget *parent) : QWidget(parent), ui(new Ui::AutomaticTheme) { ui->setupUi(this); ui->refresh->setEnabled(false); - sunrise.setSecsSinceEpoch(settings.value("sunrise").toLongLong()); - sunset.setSecsSinceEpoch(settings.value("sunset").toLongLong()); + m_sunrise.setSecsSinceEpoch( + SettingsManager::instance().settings().value("sunrise").toLongLong()); + m_sunset.setSecsSinceEpoch( + SettingsManager::instance().settings().value("sunset").toLongLong()); - ui->sunrise->setTime(sunrise.time()); - ui->sunset->setTime(sunset.time()); + ui->sunrise->setTime(m_sunrise.time()); + ui->sunset->setTime(m_sunset.time()); QTimeZone zone = QTimeZone::systemTimeZone(); QDateTime dt = QDateTime::currentDateTime(); if (zone.isValid()) { - hour_offset = (double)zone.standardTimeOffset(dt) / (double)3600; + m_hourOffset = (double)zone.standardTimeOffset(dt) / (double)3600; } else { - settings.setValue("automaticTheme", false); + SettingsManager::instance().settings().setValue("automaticTheme", false); QMessageBox::critical( this, "Error", "Unable to get system TimeZone information.\n\nAutomatic theme " @@ -29,34 +30,34 @@ AutomaticTheme::AutomaticTheme(QWidget *parent) return; } - gPosInfoSrc = QGeoPositionInfoSource::createDefaultSource(this); + m_gPosInfoSrc = QGeoPositionInfoSource::createDefaultSource(this); - if (gPosInfoSrc) // sudo apt install geoclue-2.0 + if (m_gPosInfoSrc) // sudo apt install geoclue-2.0 { ui->refresh->setEnabled(true); - connect(gPosInfoSrc, &QGeoPositionInfoSource::positionUpdated, + connect(m_gPosInfoSrc, &QGeoPositionInfoSource::positionUpdated, this, [=](const QGeoPositionInfo &update) { QGeoCoordinate cor = update.coordinate(); if (cor.isValid()) { - this->lon = cor.longitude(); - this->lat = cor.latitude(); + this->m_longitude = cor.longitude(); + this->m_latitube = cor.latitude(); ui->refresh->setEnabled(true); - gPosInfoSrc->stopUpdates(); + m_gPosInfoSrc->stopUpdates(); } else { ui->refresh->setEnabled(false); } }); - connect(gPosInfoSrc, &QGeoPositionInfoSource::updateTimeout, [=]() { - if (!settings.value("sunrise").isValid() || - !settings.value("sunset").isValid()) { + connect(m_gPosInfoSrc, &QGeoPositionInfoSource::updateTimeout, this, [=]() { + if (!SettingsManager::instance().settings().value("sunrise").isValid() || + !SettingsManager::instance().settings().value("sunset").isValid()) { if (ui->refresh->isEnabled()) ui->refresh->click(); } }); - gPosInfoSrc->startUpdates(); + m_gPosInfoSrc->startUpdates(); } else { ui->refresh->setEnabled(false); - settings.setValue("automaticTheme", false); + SettingsManager::instance().settings().setValue("automaticTheme", false); QMessageBox::critical( this, "Error", "Unable to initialize QGeoPositionInfoSource.\n\nAutomatic theme " @@ -66,52 +67,56 @@ AutomaticTheme::AutomaticTheme(QWidget *parent) } AutomaticTheme::~AutomaticTheme() { - gPosInfoSrc->disconnect(); - gPosInfoSrc->deleteLater(); + m_gPosInfoSrc->disconnect(); + m_gPosInfoSrc->deleteLater(); delete ui; } void AutomaticTheme::on_refresh_clicked() { - QGeoCoordinate geoCor = QGeoCoordinate(this->lat, this->lon); + QGeoCoordinate geoCor = QGeoCoordinate(this->m_latitube, this->m_longitude); if (geoCor.isValid()) { - Sunclock sun(this->lat, this->lon, this->hour_offset); - sunrise.setSecsSinceEpoch( - sun.sunrise(QDateTime::currentDateTime().toTime_t())); - sunset.setSecsSinceEpoch( - sun.sunset(QDateTime::currentDateTime().toTime_t())); + Sunclock sun(this->m_latitube, this->m_longitude, this->m_hourOffset); + m_sunrise.setSecsSinceEpoch( + sun.sunrise(QDateTime::currentDateTimeUtc().toTime_t())); + m_sunset.setSecsSinceEpoch( + sun.sunset(QDateTime::currentDateTimeUtc().toTime_t())); - ui->sunrise->setTime(sunrise.time()); - ui->sunset->setTime(sunset.time()); + ui->sunrise->setTime(m_sunrise.time()); + ui->sunset->setTime(m_sunset.time()); } else { - settings.setValue("automaticTheme", false); + SettingsManager::instance().settings().setValue("automaticTheme", false); QMessageBox::critical(this, "Error", "Invalid Geo-Coordinates.\n\nPlease try again."); } } void AutomaticTheme::on_save_clicked() { - if (sunrise.toSecsSinceEpoch() == sunset.toSecsSinceEpoch()) { - settings.setValue("automaticTheme", false); - QMessageBox::critical(this, "Error", - "Invalid settings.\n\nSunrise and Sunset time cannot " - "have similar values.\n\nPlease try again."); + if (m_sunrise.toSecsSinceEpoch() == m_sunset.toSecsSinceEpoch()) { + SettingsManager::instance().settings().setValue("automaticTheme", false); + QMessageBox::critical( + this, "Error", + "Invalid SettingsManager::instance().settings().\n\nSunrise and Sunset " + "time cannot " + "have similar values.\n\nPlease try again."); } else { - settings.setValue("sunrise", sunrise.toSecsSinceEpoch()); - settings.setValue("sunset", sunset.toSecsSinceEpoch()); - settings.setValue("automaticTheme", true); + SettingsManager::instance().settings().setValue( + "sunrise", m_sunrise.toSecsSinceEpoch()); + SettingsManager::instance().settings().setValue( + "sunset", m_sunset.toSecsSinceEpoch()); + SettingsManager::instance().settings().setValue("automaticTheme", true); this->close(); } } void AutomaticTheme::on_cancel_clicked() { - settings.setValue("automaticTheme", false); + SettingsManager::instance().settings().setValue("automaticTheme", false); this->close(); } void AutomaticTheme::on_sunrise_timeChanged(const QTime &time) { - sunrise.setTime(QTime(time.hour(), time.minute(), 0)); + m_sunrise.setTime(QTime(time.hour(), time.minute(), 0)); } void AutomaticTheme::on_sunset_timeChanged(const QTime &time) { - sunset.setTime(QTime(time.hour(), time.minute(), 0)); + m_sunset.setTime(QTime(time.hour(), time.minute(), 0)); } diff --git a/src/automatictheme.h b/src/automatictheme.h index 55904e5..f013713 100644 --- a/src/automatictheme.h +++ b/src/automatictheme.h @@ -1,47 +1,45 @@ #ifndef AUTOMATICTHEME_H #define AUTOMATICTHEME_H -#include -#include #include +#include +#include #include -#include +#include + +#include "settingsmanager.h" namespace Ui { class AutomaticTheme; } -class AutomaticTheme : public QWidget -{ - Q_OBJECT +class AutomaticTheme : public QWidget { + Q_OBJECT public: - explicit AutomaticTheme(QWidget *parent = nullptr); - ~AutomaticTheme(); - + explicit AutomaticTheme(QWidget *parent = nullptr); + ~AutomaticTheme(); private slots: - void on_refresh_clicked(); + void on_refresh_clicked(); - void on_save_clicked(); + void on_save_clicked(); - void on_cancel_clicked(); + void on_cancel_clicked(); - void on_sunrise_timeChanged(const QTime &time); + void on_sunrise_timeChanged(const QTime &time); - void on_sunset_timeChanged(const QTime &time); + void on_sunset_timeChanged(const QTime &time); private: - Ui::AutomaticTheme *ui; - - QGeoPositionInfoSource *gPosInfoSrc; - QDateTime sunrise, sunset; + Ui::AutomaticTheme *ui; - double hour_offset = 0.0; - double lon = 0.0; - double lat = 0.0; + QGeoPositionInfoSource *m_gPosInfoSrc; + QDateTime m_sunrise, m_sunset; - QSettings settings; + double m_hourOffset = 0.0; + double m_longitude = 0.0; + double m_latitube = 0.0; }; #endif // AUTOMATICTHEME_H diff --git a/src/common.h b/src/common.h index f7c32b9..295dd18 100644 --- a/src/common.h +++ b/src/common.h @@ -3,7 +3,8 @@ #include // userAgent -QString defaultUserAgentStr = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"; +//QString defaultUserAgentStr = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"; +QString defaultUserAgentStr = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36"; //appAutoLock int defaultAppAutoLockDuration = 30; diff --git a/src/dictionaries.cpp b/src/dictionaries.cpp index fc8e7c0..5299806 100644 --- a/src/dictionaries.cpp +++ b/src/dictionaries.cpp @@ -19,7 +19,7 @@ QString Dictionaries::GetDictionaryPath() { // the environment variable takes precedence on all platforms if (qEnvironmentVariableIsSet("QTWEBENGINE_DICTIONARIES_PATH")) { - dict_path = utils::GetEnvironmentVar("QTWEBENGINE_DICTIONARIES_PATH"); + dict_path = Utils::GetEnvironmentVar("QTWEBENGINE_DICTIONARIES_PATH"); return dict_path; } diff --git a/src/downloadmanagerwidget.cpp b/src/downloadmanagerwidget.cpp index 812c471..13643e8 100644 --- a/src/downloadmanagerwidget.cpp +++ b/src/downloadmanagerwidget.cpp @@ -1,11 +1,6 @@ #include "downloadmanagerwidget.h" - #include "downloadwidget.h" -#include -#include -#include - DownloadManagerWidget::DownloadManagerWidget(QWidget *parent) : QWidget(parent), m_numDownloads(0) { setupUi(this); @@ -22,8 +17,7 @@ void DownloadManagerWidget::downloadRequested( Q_ASSERT(download && download->state() == QWebEngineDownloadItem::DownloadRequested); QString path = - settings - .value("defaultDownloadLocation", + SettingsManager::instance().settings().value("defaultDownloadLocation", QStandardPaths::writableLocation( QStandardPaths::DownloadLocation) + QDir::separator() + QApplication::applicationName()) @@ -46,7 +40,7 @@ void DownloadManagerWidget::downloadRequested( switch (msgBox.exec()) { case QMessageBox::Save: { QString n_proposed_file_name = path + QDir::separator() + - utils::generateRandomId(5) + "_" + + Utils::generateRandomId(5) + "_" + download->downloadFileName(); download->setDownloadFileName(n_proposed_file_name); acceptDownload(download); @@ -81,8 +75,7 @@ void DownloadManagerWidget::remove(DownloadWidget *downloadWidget) { } void DownloadManagerWidget::on_open_download_dir_clicked() { - utils::desktopOpenUrl(settings - .value("defaultDownloadLocation", + Utils::desktopOpenUrl(SettingsManager::instance().settings().value("defaultDownloadLocation", QStandardPaths::writableLocation( QStandardPaths::DownloadLocation) + QDir::separator() + diff --git a/src/downloadmanagerwidget.h b/src/downloadmanagerwidget.h index 76464e8..8367041 100644 --- a/src/downloadmanagerwidget.h +++ b/src/downloadmanagerwidget.h @@ -51,10 +51,13 @@ #ifndef DOWNLOADMANAGERWIDGET_H #define DOWNLOADMANAGERWIDGET_H +#include "settingsmanager.h" #include "ui_downloadmanagerwidget.h" - #include "utils.h" -#include + +#include +#include +#include #include QT_BEGIN_NAMESPACE @@ -89,7 +92,6 @@ private: void remove(DownloadWidget *downloadWidget); int m_numDownloads; - QSettings settings; }; #endif // DOWNLOADMANAGERWIDGET_H diff --git a/src/lock.cpp b/src/lock.cpp index ffbf144..3026573 100644 --- a/src/lock.cpp +++ b/src/lock.cpp @@ -1,10 +1,5 @@ #include "lock.h" -#include "moreapps.h" #include "ui_lock.h" -#include -#include -#include -#include #include "X11/XKBlib.h" // keep this header at bottom @@ -25,25 +20,28 @@ Lock::Lock(QWidget *parent) : QWidget(parent), ui(new Ui::Lock) { passcodeLoginAction = ui->passcodeLogin->addAction( QIcon(":/icons/green_arrow-right-line.png"), QLineEdit::TrailingPosition); passcodeLoginAction->setEnabled(false); - connect(passcodeLoginAction, &QAction::triggered, passcodeLoginAction, - [this]() { - QString password = - QByteArray::fromBase64(settings.value("asdfg").toByteArray()); - if (ui->passcodeLogin->text() == password && check_password_set()) { - isLocked = false; - this->animateOut(); - emit unLocked(); - } else { - ui->wrong->show(); - } - }); + connect( + passcodeLoginAction, &QAction::triggered, passcodeLoginAction, [this]() { + QString password = QByteArray::fromBase64(SettingsManager::instance() + .settings() + .value("asdfg") + .toByteArray()); + if (ui->passcodeLogin->text() == password && check_password_set()) { + isLocked = false; + this->animateOut(); + emit unLocked(); + } else { + ui->wrong->show(); + } + }); QGraphicsOpacityEffect *eff = new QGraphicsOpacityEffect(this); ui->centerWidget->setGraphicsEffect(eff); animateIn(); - if (settings.value("asdfg").isValid() == false) { + if (SettingsManager::instance().settings().value("asdfg").isValid() == + false) { signUp(); } else { lock_app(); @@ -143,7 +141,10 @@ void Lock::applyThemeQuirks() { "border-bottom-left-radius: 4px;"; QString lightBg = "background-color: rgb(37, 211, 102);"; QString darkBg = "background-color: rgb(0, 117, 96);"; - if (QString::compare(settings.value("windowTheme", "light").toString(), + if (QString::compare(SettingsManager::instance() + .settings() + .value("windowTheme", "light") + .toString(), "dark", Qt::CaseInsensitive) == 0) { // light ui->bottomLine->setStyleSheet(darkBg + border); ui->bottomLine_2->setStyleSheet(darkBg + border); @@ -194,8 +195,9 @@ void Lock::on_setPass_clicked() { pass1 = ui->passcode1->text().trimmed(); pass2 = ui->passcode2->text().trimmed(); if (pass1 == pass2) { - settings.setValue("asdfg", QByteArray(pass1.toUtf8()).toBase64()); - settings.setValue("lockscreen", true); + SettingsManager::instance().settings().setValue( + "asdfg", QByteArray(pass1.toUtf8()).toBase64()); + SettingsManager::instance().settings().setValue("lockscreen", true); ui->passcode1->clear(); ui->passcode2->clear(); emit passwordSet(); @@ -207,7 +209,9 @@ void Lock::on_setPass_clicked() { } } -bool Lock::check_password_set() { return settings.value("asdfg").isValid(); } +bool Lock::check_password_set() { + return SettingsManager::instance().settings().value("asdfg").isValid(); +} void Lock::on_passcodeLogin_textChanged(const QString &arg1) { if (arg1.contains(" ")) { @@ -231,12 +235,13 @@ void Lock::lock_app() { void Lock::on_passcodeLogin_returnPressed() { passcodeLoginAction->trigger(); } bool Lock::getCapsLockOn() { - Display *d = XOpenDisplay((char *)0); + Display *d = XOpenDisplay(nullptr); bool caps_state = false; if (d) { unsigned n; XkbGetIndicatorState(d, XkbUseCoreKbd, &n); caps_state = (n & 0x01) == 1; + XCloseDisplay(d); } return caps_state; } diff --git a/src/lock.h b/src/lock.h index 23af8e0..809ca3c 100644 --- a/src/lock.h +++ b/src/lock.h @@ -2,9 +2,15 @@ #define LOCK_H #include -#include +#include +#include +#include +#include #include +#include "moreapps.h" +#include "settingsmanager.h" + namespace Ui { class Lock; } @@ -47,7 +53,6 @@ protected slots: private: Ui::Lock *ui; bool isLocked = false; - QSettings settings; QAction *passcodeLoginAction; }; diff --git a/src/main.cpp b/src/main.cpp index 5a17d78..c771f71 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -9,6 +8,7 @@ #include "common.h" #include "def.h" #include "mainwindow.h" +#include "settingsmanager.h" #include int main(int argc, char *argv[]) { @@ -16,14 +16,18 @@ int main(int argc, char *argv[]) { QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); #ifdef QT_DEBUG - qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--remote-debugging-port=9421 --ignore-gpu-blocklist --no-sandbox"); + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", + "--remote-debugging-port=9421 --ignore-gpu-blocklist --no-sandbox " + "--single-process --disable-extensions"); #else - qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--disable-logging --ignore-gpu-blocklist --no-sandbox"); //--single-process + qputenv("QTWEBENGINE_CHROMIUM_FLAGS", + "--disable-logging --ignore-gpu-blocklist --no-sandbox " + "--single-process --disable-extensions"); #endif SingleApplication instance(argc, argv, true); instance.setQuitOnLastWindowClosed(false); - instance.setWindowIcon(QIcon(":/icons/app/icon-128.png")); + instance.setWindowIcon(QIcon(":/icons/app/icon-64.png")); QApplication::setApplicationName("WhatSie"); QApplication::setDesktopFileName("com.ktechpit.whatsie"); QApplication::setOrganizationDomain("com.ktechpit"); @@ -87,16 +91,16 @@ int main(int argc, char *argv[]) { QObject::tr("Show main window of running instance of ") + QApplication::applicationName()); - parser.addOption(showCLIHelpOption); // [x] - parser.addVersionOption(); // [x] - parser.addOption(buildInfoOption); // [x] - parser.addOption(showAppWindowOption); // [x] - parser.addOption(openSettingsOption); // [x] - parser.addOption(lockAppOption); // [x] - parser.addOption(openAboutOption); // [x] - parser.addOption(toggleThemeOption); // [x] - parser.addOption(reloadAppOption); // [x] - parser.addOption(newChatOption); // [-] + parser.addOption(showCLIHelpOption); + parser.addVersionOption(); + parser.addOption(buildInfoOption); + parser.addOption(showAppWindowOption); + parser.addOption(openSettingsOption); + parser.addOption(lockAppOption); + parser.addOption(openAboutOption); + parser.addOption(toggleThemeOption); + parser.addOption(reloadAppOption); + parser.addOption(newChatOption); secondaryInstanceCLIOptions << showAppWindowOption << openSettingsOption << lockAppOption << openAboutOption @@ -165,7 +169,10 @@ int main(int argc, char *argv[]) { << "LockApp"; whatsie.alreadyRunning(); QSettings settings; - if (!settings.value("asdfg").isValid()) { + if (!SettingsManager::instance() + .settings() + .value("asdfg") + .isValid()) { whatsie.notify( QApplication::applicationName(), QObject::tr("App lock is not configured, \n" @@ -205,7 +212,7 @@ int main(int argc, char *argv[]) { qInfo() << "cmd:" << "OpenNewChatPrompt"; whatsie.alreadyRunning(); - whatsie.newChat(); //TODO: invetigate the crash + whatsie.newChat(); // TODO: invetigate the crash return; } @@ -238,7 +245,10 @@ int main(int argc, char *argv[]) { QSettings settings; if (QSystemTrayIcon::isSystemTrayAvailable() && - settings.value("startMinimized", false).toBool()) { + SettingsManager::instance() + .settings() + .value("startMinimized", false) + .toBool()) { whatsie.runMinimized(); } else { whatsie.show(); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 72b6d4e..1ba43f1 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -14,9 +14,10 @@ extern int defaultAppAutoLockDuration; extern bool defaultAppAutoLock; MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent), notificationsTitleRegExp("^\\([1-9]\\d*\\).*"), - trayIconNormal(":/icons/app/notification/whatsie-notify.png"), - unreadMessageCountRegExp("\\([^\\d]*(\\d+)[^\\d]*\\)") { + : QMainWindow(parent), + m_trayIconNormal(":/icons/app/notification/whatsie-notify.png"), + m_notificationsTitleRegExp("^\\([1-9]\\d*\\).*"), + m_unreadMessageCountRegExp("\\([^\\d]*(\\d+)[^\\d]*\\)") { setObjectName("MainWindow"); setWindowTitle(QApplication::applicationName()); @@ -24,7 +25,6 @@ MainWindow::MainWindow(QWidget *parent) setMinimumWidth(525); setMinimumHeight(448); restoreMainWindow(); - initThemes(); createActions(); createTrayIcon(); createWebEngine(); @@ -36,8 +36,9 @@ MainWindow::MainWindow(QWidget *parent) } void MainWindow::restoreMainWindow() { - if (settings.value("geometry").isValid()) { - restoreGeometry(settings.value("geometry").toByteArray()); + if (SettingsManager::instance().settings().value("geometry").isValid()) { + restoreGeometry( + SettingsManager::instance().settings().value("geometry").toByteArray()); QPoint pos = QCursor::pos(); auto localScreens = QGuiApplication::screens(); for (auto screen : qAsConst(localScreens)) { @@ -52,80 +53,30 @@ void MainWindow::restoreMainWindow() { } void MainWindow::initAutoLock() { - autoLockEventFilter = new AutoLockEventFilter( - settings.value("autoLockDuration", defaultAppAutoLockDuration).toInt() * + m_autoLockEventFilter = new AutoLockEventFilter( + SettingsManager::instance() + .settings() + .value("autoLockDuration", defaultAppAutoLockDuration) + .toInt() * 1000); - connect(autoLockEventFilter, &AutoLockEventFilter::autoLockTimerTimeout, this, - [=]() { - if ((settingsWidget && !settingsWidget->isVisible()) && - settings.value("appAutoLocking", defaultAppAutoLock).toBool()) { + connect(m_autoLockEventFilter, &AutoLockEventFilter::autoLockTimerTimeout, + this, [=]() { + if ((m_settingsWidget && !m_settingsWidget->isVisible()) && + SettingsManager::instance() + .settings() + .value("appAutoLocking", defaultAppAutoLock) + .toBool()) { this->lockApp(); } }); - if (settings.value("appAutoLocking", defaultAppAutoLock).toBool()) { - qApp->installEventFilter(autoLockEventFilter); + if (SettingsManager::instance() + .settings() + .value("appAutoLocking", defaultAppAutoLock) + .toBool()) { + qApp->installEventFilter(m_autoLockEventFilter); } } -void MainWindow::initThemes() { - // Light - lightPalette.setColor(QPalette::Window, QColor(240, 240, 240)); - lightPalette.setColor(QPalette::WindowText, QColor(0, 0, 0)); - lightPalette.setColor(QPalette::Button, QColor(240, 240, 240)); - lightPalette.setColor(QPalette::Light, QColor(180, 180, 180)); - lightPalette.setColor(QPalette::Midlight, QColor(200, 200, 200)); - lightPalette.setColor(QPalette::Dark, QColor(225, 225, 225)); - lightPalette.setColor(QPalette::Text, QColor(0, 0, 0)); - lightPalette.setColor(QPalette::BrightText, QColor(0, 0, 0)); - lightPalette.setColor(QPalette::ButtonText, QColor(0, 0, 0)); - lightPalette.setColor(QPalette::Base, QColor(237, 237, 237)); - lightPalette.setColor(QPalette::Shadow, QColor(20, 20, 20)); - lightPalette.setColor(QPalette::Highlight, QColor(76, 163, 224)); - lightPalette.setColor(QPalette::HighlightedText, QColor(0, 0, 0)); - lightPalette.setColor(QPalette::Link, QColor(0, 162, 232)); - lightPalette.setColor(QPalette::AlternateBase, QColor(225, 225, 225)); - lightPalette.setColor(QPalette::ToolTipBase, QColor(240, 240, 240)); - lightPalette.setColor(QPalette::ToolTipText, QColor(0, 0, 0)); - lightPalette.setColor(QPalette::LinkVisited, QColor(222, 222, 222)); - lightPalette.setColor(QPalette::Disabled, QPalette::WindowText, - QColor(115, 115, 115)); - lightPalette.setColor(QPalette::Disabled, QPalette::Text, - QColor(115, 115, 115)); - lightPalette.setColor(QPalette::Disabled, QPalette::ButtonText, - QColor(115, 115, 115)); - lightPalette.setColor(QPalette::Disabled, QPalette::Highlight, - QColor(190, 190, 190)); - lightPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, - QColor(115, 115, 115)); - - // Dark - darkPalette.setColor(QPalette::Window, QColor(17, 27, 33)); - darkPalette.setColor(QPalette::Text, Qt::white); - darkPalette.setColor(QPalette::WindowText, Qt::white); - darkPalette.setColor(QPalette::Base, QColor(32, 44, 51)); - darkPalette.setColor(QPalette::AlternateBase, QColor(95, 108, 115)); - darkPalette.setColor(QPalette::ToolTipBase, QColor(66, 66, 66)); - darkPalette.setColor(QPalette::ToolTipText, QColor(192, 192, 192)); - darkPalette.setColor(QPalette::Dark, QColor(35, 35, 35)); - darkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20)); - darkPalette.setColor(QPalette::Button, QColor(17, 27, 33)); - darkPalette.setColor(QPalette::ButtonText, Qt::white); - darkPalette.setColor(QPalette::BrightText, Qt::red); - darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); - darkPalette.setColor(QPalette::Highlight, QColor(38, 140, 196)); - darkPalette.setColor(QPalette::HighlightedText, Qt::white); - darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, - QColor(127, 127, 127)); - darkPalette.setColor(QPalette::Disabled, QPalette::Window, - QColor(65, 65, 67)); - darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, - QColor(80, 80, 80)); - darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, - QColor(127, 127, 127)); - darkPalette.setColor(QPalette::Disabled, QPalette::Text, - QColor(127, 127, 127)); -} - void MainWindow::initRateWidget() { RateApp *rateApp = new RateApp(this, "snap://whatsie", 5, 5, 1000 * 30); rateApp->setWindowTitle(QApplication::applicationName() + " | " + @@ -146,11 +97,11 @@ void MainWindow::initRateWidget() { } void MainWindow::runMinimized() { - this->minimizeAction->trigger(); + this->m_minimizeAction->trigger(); notify("Whatsie", "Whatsie started minimized in tray. Click to Open."); } -MainWindow::~MainWindow() { webEngine->deleteLater(); } +MainWindow::~MainWindow() { m_webEngine->deleteLater(); } void MainWindow::loadSchemaUrl(const QString &arg) { // https://faq.whatsapp.com/iphone/how-to-link-to-whatsapp-from-a-different-app/?lang=en @@ -172,45 +123,53 @@ void MainWindow::loadSchemaUrl(const QString &arg) { } void MainWindow::updatePageTheme() { - if (webEngine && webEngine->page()) { + if (m_webEngine && m_webEngine->page()) { - QString windowTheme = settings.value("windowTheme", "light").toString(); + QString windowTheme = SettingsManager::instance() + .settings() + .value("windowTheme", "light") + .toString(); if (windowTheme == "dark") { - webEngine->page()->runJavaScript( + m_webEngine->page()->runJavaScript( "localStorage['system-theme-mode']='false'; " "localStorage.theme='\"dark\"'; "); - webEngine->page()->runJavaScript( + m_webEngine->page()->runJavaScript( "document.querySelector('body').classList.add('" + windowTheme + "');"); } else { - webEngine->page()->runJavaScript( + m_webEngine->page()->runJavaScript( "localStorage['system-theme-mode']='false'; " "localStorage.theme='\"light\"'; "); - webEngine->page()->runJavaScript( + m_webEngine->page()->runJavaScript( "document.querySelector('body').classList.remove('dark');"); } } } void MainWindow::resizeEvent(QResizeEvent *event) { - if (lockWidget != nullptr) { - lockWidget->resize(event->size()); + if (m_lockWidget != nullptr) { + m_lockWidget->resize(event->size()); } } void MainWindow::updateWindowTheme() { - qApp->setStyle(QStyleFactory::create( - settings.value("widgetStyle", "Fusion").toString())); - if (settings.value("windowTheme", "light").toString() == "dark") { - qApp->setPalette(darkPalette); - webEngine->setStyleSheet( + qApp->setStyle(QStyleFactory::create(SettingsManager::instance() + .settings() + .value("widgetStyle", "Fusion") + .toString())); + if (SettingsManager::instance() + .settings() + .value("windowTheme", "light") + .toString() == "dark") { + qApp->setPalette(Theme::getDarkPalette()); + m_webEngine->setStyleSheet( "QWebEngineView{background:rgb(17, 27, 33);}"); // whatsapp dark color } else { - qApp->setPalette(lightPalette); - webEngine->setStyleSheet( + qApp->setPalette(Theme::getLightPalette()); + m_webEngine->setStyleSheet( "QWebEngineView{background:#F0F0F0;}"); // whatsapp light color } @@ -218,13 +177,13 @@ void MainWindow::updateWindowTheme() { foreach (QWidget *w, widgets) { w->setPalette(qApp->palette()); } - setNotificationPresenter(webEngine->page()->profile()); + setNotificationPresenter(m_webEngine->page()->profile()); - if (lockWidget != nullptr) { - lockWidget->setStyleSheet( + if (m_lockWidget != nullptr) { + m_lockWidget->setStyleSheet( "QWidget#login{background-color:palette(window)};" "QWidget#signup{background-color:palette(window)};"); - lockWidget->applyThemeQuirks(); + m_lockWidget->applyThemeQuirks(); } this->update(); } @@ -234,8 +193,8 @@ void MainWindow::handleCookieAdded(const QNetworkCookie &cookie) { } void MainWindow::forceLogOut() { - if (webEngine && webEngine->page()) { - webEngine->page()->runJavaScript( + if (m_webEngine && m_webEngine->page()) { + m_webEngine->page()->runJavaScript( "window.localStorage.clear();", [=](const QVariant &result) { qDebug() << result; }); } @@ -243,8 +202,8 @@ void MainWindow::forceLogOut() { bool MainWindow::isLoggedIn() { static bool loggedIn = false; - if (webEngine && webEngine->page()) { - webEngine->page()->runJavaScript( + if (m_webEngine && m_webEngine->page()) { + m_webEngine->page()->runJavaScript( "window.localStorage.getItem('last-wid-md')", [=](const QVariant &result) { qDebug() << Q_FUNC_INFO << result; @@ -261,8 +220,8 @@ bool MainWindow::isLoggedIn() { } void MainWindow::tryLogOut() { - if (webEngine && webEngine->page()) { - webEngine->page()->runJavaScript( + if (m_webEngine && m_webEngine->page()) { + m_webEngine->page()->runJavaScript( "document.querySelector(\"span[data-testid|='menu']\").click();" "document.querySelector(\"#side > header > div > div > span > div > " "span > div > ul > li:nth-child(4) > div\").click();" @@ -280,108 +239,116 @@ void MainWindow::tryLogOut() { void MainWindow::initSettingWidget() { int screenNumber = qApp->desktop()->screenNumber(this); - if (settingsWidget == nullptr) { - settingsWidget = new SettingsWidget( - this, screenNumber, webEngine->page()->profile()->cachePath(), - webEngine->page()->profile()->persistentStoragePath()); - settingsWidget->setWindowTitle(QApplication::applicationName() + - " | Settings"); - settingsWidget->setWindowFlags(Qt::Dialog); - - connect(settingsWidget, SIGNAL(initLock()), this, SLOT(initLock())); - connect(settingsWidget, SIGNAL(changeLockPassword()), this, - SLOT(changeLockPassword())); - connect(settingsWidget, SIGNAL(appAutoLockChanged()), this, - SLOT(appAutoLockChanged())); - - connect(settingsWidget, SIGNAL(updateWindowTheme()), this, - SLOT(updateWindowTheme())); - connect(settingsWidget, SIGNAL(updatePageTheme()), this, - SLOT(updatePageTheme())); - - connect(settingsWidget, &SettingsWidget::muteToggled, settingsWidget, - [=](const bool checked) { this->toggleMute(checked); }); - connect(settingsWidget, &SettingsWidget::userAgentChanged, settingsWidget, - [=](QString userAgentStr) { - if (webEngine->page()->profile()->httpUserAgent() != + if (m_settingsWidget == nullptr) { + m_settingsWidget = new SettingsWidget( + this, screenNumber, m_webEngine->page()->profile()->cachePath(), + m_webEngine->page()->profile()->persistentStoragePath()); + m_settingsWidget->setWindowTitle(QApplication::applicationName() + + " | Settings"); + m_settingsWidget->setWindowFlags(Qt::Dialog); + + connect(m_settingsWidget, &SettingsWidget::initLock, this, + &MainWindow::initLock); + connect(m_settingsWidget, &SettingsWidget::changeLockPassword, this, + &MainWindow::changeLockPassword); + connect(m_settingsWidget, &SettingsWidget::appAutoLockChanged, this, + &MainWindow::appAutoLockChanged); + + connect(m_settingsWidget, &SettingsWidget::updateWindowTheme, this, + &MainWindow::updateWindowTheme); + connect(m_settingsWidget, &SettingsWidget::updatePageTheme, this, + &MainWindow::updatePageTheme); + + connect(m_settingsWidget, &SettingsWidget::muteToggled, this, + &MainWindow::toggleMute); + connect(m_settingsWidget, &SettingsWidget::userAgentChanged, + m_settingsWidget, [=](QString userAgentStr) { + if (m_webEngine->page()->profile()->httpUserAgent() != userAgentStr) { - settings.setValue("useragent", userAgentStr); + SettingsManager::instance().settings().setValue("useragent", + userAgentStr); this->updateSettingsUserAgentWidget(); this->askToReloadPage(); } }); - connect(settingsWidget, &SettingsWidget::autoPlayMediaToggled, - settingsWidget, [=](bool checked) { + connect(m_settingsWidget, &SettingsWidget::autoPlayMediaToggled, + m_settingsWidget, [=](bool checked) { QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); auto *webSettings = profile->settings(); webSettings->setAttribute( QWebEngineSettings::PlaybackRequiresUserGesture, checked); - webEngine->page()->profile()->settings()->setAttribute( + m_webEngine->page()->profile()->settings()->setAttribute( QWebEngineSettings::PlaybackRequiresUserGesture, checked); }); - connect(settingsWidget, &SettingsWidget::dictChanged, settingsWidget, + connect(m_settingsWidget, &SettingsWidget::dictChanged, m_settingsWidget, [=](QString dictName) { - if (webEngine && webEngine->page()) { - webEngine->page()->profile()->setSpellCheckLanguages( + if (m_webEngine && m_webEngine->page()) { + m_webEngine->page()->profile()->setSpellCheckLanguages( QStringList() << dictName); } }); - connect(settingsWidget, &SettingsWidget::spellCheckChanged, settingsWidget, - [=](bool checked) { - if (webEngine && webEngine->page()) { - webEngine->page()->profile()->setSpellCheckEnabled(checked); + connect(m_settingsWidget, &SettingsWidget::spellCheckChanged, + m_settingsWidget, [=](bool checked) { + if (m_webEngine && m_webEngine->page()) { + m_webEngine->page()->profile()->setSpellCheckEnabled(checked); } }); - connect( - settingsWidget, &SettingsWidget::zoomChanged, settingsWidget, [=]() { - if (windowState() == Qt::WindowNoState) { - double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); - webEngine->page()->setZoomFactor(currentFactor); - } - }); + connect(m_settingsWidget, &SettingsWidget::zoomChanged, m_settingsWidget, + [=]() { + if (windowState() == Qt::WindowNoState) { + double currentFactor = SettingsManager::instance() + .settings() + .value("zoomFactor", 1.0) + .toDouble(); + m_webEngine->page()->setZoomFactor(currentFactor); + } + }); - connect(settingsWidget, &SettingsWidget::zoomMaximizedChanged, - settingsWidget, [=]() { + connect(m_settingsWidget, &SettingsWidget::zoomMaximizedChanged, + m_settingsWidget, [=]() { if (windowState() == Qt::WindowMaximized || windowState() == Qt::WindowFullScreen) { - double currentFactor = settings + double currentFactor = SettingsManager::instance() + .settings() .value("zoomFactorMaximized", defaultZoomFactorMaximized) .toDouble(); - webEngine->page()->setZoomFactor(currentFactor); + m_webEngine->page()->setZoomFactor(currentFactor); } }); - connect(settingsWidget, &SettingsWidget::notificationPopupTimeOutChanged, - settingsWidget, - [=]() { setNotificationPresenter(webEngine->page()->profile()); }); + connect(m_settingsWidget, &SettingsWidget::notificationPopupTimeOutChanged, + m_settingsWidget, [=]() { + setNotificationPresenter(m_webEngine->page()->profile()); + }); - connect(settingsWidget, &SettingsWidget::notify, settingsWidget, + connect(m_settingsWidget, &SettingsWidget::notify, m_settingsWidget, [=](QString message) { notify("", message); }); - connect(settingsWidget, &SettingsWidget::updateFullWidthView, - settingsWidget, [=](bool checked) { - if (webEngine && webEngine->page()) { + connect(m_settingsWidget, &SettingsWidget::updateFullWidthView, + m_settingsWidget, [=](bool checked) { + if (m_webEngine && m_webEngine->page()) { if (checked) - webEngine->page()->runJavaScript( + m_webEngine->page()->runJavaScript( "document.querySelector('body').classList.add('whatsie-" "full-view');"); else - webEngine->page()->runJavaScript( + m_webEngine->page()->runJavaScript( "document.querySelector('body').classList.remove('" "whatsie-full-view');"); } }); - settingsWidget->appLockSetChecked( - settings.value("lockscreen", false).toBool()); + m_settingsWidget->appLockSetChecked(SettingsManager::instance() + .settings() + .value("lockscreen", false) + .toBool()); - // spell checker - settingsWidget->loadDictionaries(dictionaries); + m_settingsWidget->loadDictionaries(m_dictionaries); } } @@ -394,15 +361,15 @@ void MainWindow::changeEvent(QEvent *e) { void MainWindow::handleZoomOnWindowStateChange( const QWindowStateChangeEvent *ev) { - if (settingsWidget != nullptr) { + if (m_settingsWidget != nullptr) { if (ev->oldState().testFlag(Qt::WindowMaximized) && windowState().testFlag(Qt::WindowNoState)) { - emit settingsWidget->zoomChanged(); + emit m_settingsWidget->zoomChanged(); } else if ((!ev->oldState().testFlag(Qt::WindowMaximized) && windowState().testFlag(Qt::WindowMaximized)) || (!ev->oldState().testFlag(Qt::WindowMaximized) && windowState().testFlag(Qt::WindowFullScreen))) { - emit settingsWidget->zoomMaximizedChanged(); + emit m_settingsWidget->zoomMaximizedChanged(); } } } @@ -411,22 +378,27 @@ void MainWindow::handleZoom() { if (windowState().testFlag(Qt::WindowMaximized) || windowState().testFlag(Qt::WindowFullScreen)) { double currentFactor = - settings.value("zoomFactorMaximized", defaultZoomFactorMaximized) + SettingsManager::instance() + .settings() + .value("zoomFactorMaximized", defaultZoomFactorMaximized) .toDouble(); - webEngine->page()->setZoomFactor(currentFactor); + m_webEngine->page()->setZoomFactor(currentFactor); } else if (windowState().testFlag(Qt::WindowNoState)) { - double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); - webEngine->page()->setZoomFactor(currentFactor); + double currentFactor = SettingsManager::instance() + .settings() + .value("zoomFactor", 1.0) + .toDouble(); + m_webEngine->page()->setZoomFactor(currentFactor); } } void MainWindow::lockApp() { - if (lockWidget != nullptr && lockWidget->getIsLocked()) + if (m_lockWidget != nullptr && m_lockWidget->getIsLocked()) return; - if (settings.value("asdfg").isValid()) { + if (SettingsManager::instance().settings().value("asdfg").isValid()) { initLock(); - lockWidget->lock_app(); + m_lockWidget->lock_app(); } else { int ret = QMessageBox::information( this, tr(QApplication::applicationName().toUtf8()), @@ -441,13 +413,13 @@ void MainWindow::lockApp() { } void MainWindow::toggleTheme() { - if (settingsWidget != nullptr) { - settingsWidget->toggleTheme(); + if (m_settingsWidget != nullptr) { + m_settingsWidget->toggleTheme(); } } void MainWindow::showSettings(bool isAskedByCLI) { - if (lockWidget && lockWidget->getIsLocked()) { + if (m_lockWidget && m_lockWidget->getIsLocked()) { QString error = tr("Unlock to access Settings."); if (isAskedByCLI) { this->notify(QApplication::applicationName() + "| Error", error); @@ -459,28 +431,28 @@ void MainWindow::showSettings(bool isAskedByCLI) { return; } - if (webEngine == nullptr) { + if (m_webEngine == nullptr) { QMessageBox::critical( this, QApplication::applicationName() + "| Error", "Unable to initialize settings module.\nWebengine is not initialized."); return; } - if (!settingsWidget->isVisible()) { + if (!m_settingsWidget->isVisible()) { this->updateSettingsUserAgentWidget(); - settingsWidget->refresh(); + m_settingsWidget->refresh(); int screenNumber = qApp->desktop()->screenNumber(this); QRect screenRect = QGuiApplication::screens().at(screenNumber)->geometry(); - if (!screenRect.contains(settingsWidget->pos())) { - settingsWidget->move(screenRect.center() - - settingsWidget->rect().center()); + if (!screenRect.contains(m_settingsWidget->pos())) { + m_settingsWidget->move(screenRect.center() - + m_settingsWidget->rect().center()); } - settingsWidget->show(); + m_settingsWidget->show(); } } void MainWindow::updateSettingsUserAgentWidget() { - settingsWidget->updateDefaultUAButton( - webEngine->page()->profile()->httpUserAgent()); + m_settingsWidget->updateDefaultUAButton( + m_webEngine->page()->profile()->httpUserAgent()); } void MainWindow::askToReloadPage() { @@ -497,22 +469,29 @@ void MainWindow::showAbout() { about->setWindowFlag(Qt::Dialog); about->setMinimumSize(about->sizeHint()); about->adjustSize(); - about->setAttribute(Qt::WA_DeleteOnClose); + about->setAttribute(Qt::WA_DeleteOnClose, true); about->show(); } void MainWindow::closeEvent(QCloseEvent *event) { - settings.setValue("geometry", saveGeometry()); + SettingsManager::instance().settings().setValue("geometry", saveGeometry()); getPageTheme(); - QTimer::singleShot(500, settingsWidget, [=]() { settingsWidget->refresh(); }); + QTimer::singleShot(500, m_settingsWidget, + [=]() { m_settingsWidget->refresh(); }); if (QSystemTrayIcon::isSystemTrayAvailable() && - settings.value("closeButtonActionCombo", 0).toInt() == 0) { + SettingsManager::instance() + .settings() + .value("closeButtonActionCombo", 0) + .toInt() == 0) { this->hide(); event->ignore(); - if (settings.value("firstrun_tray", true).toBool()) { + if (SettingsManager::instance() + .settings() + .value("firstrun_tray", true) + .toBool()) { notify(QApplication::applicationName(), "Minimized to system tray."); - settings.setValue("firstrun_tray", false); + SettingsManager::instance().settings().setValue("firstrun_tray", false); } return; } @@ -523,28 +502,38 @@ void MainWindow::closeEvent(QCloseEvent *event) { void MainWindow::notify(QString title, QString message) { - if (settings.value("disableNotificationPopups", false).toBool() == true) { + if (SettingsManager::instance() + .settings() + .value("disableNotificationPopups", false) + .toBool() == true) { return; } if (title.isEmpty()) title = QApplication::applicationName(); - if (settings.value("notificationCombo", 1).toInt() == 0 && - trayIcon != nullptr) { - trayIcon->showMessage(title, message, - QIcon(":/icons/app/notification/whatsie-notify.png"), - settings.value("notificationTimeOut", 9000).toInt()); - trayIcon->disconnect(trayIcon, SIGNAL(messageClicked())); - connect(trayIcon, &QSystemTrayIcon::messageClicked, trayIcon, [=]() { - if (windowState().testFlag(Qt::WindowMinimized) || - !windowState().testFlag(Qt::WindowActive)) { - activateWindow(); - this->show(); - } - }); + if (SettingsManager::instance() + .settings() + .value("notificationCombo", 1) + .toInt() == 0 && + m_systemTrayIcon != nullptr) { + m_systemTrayIcon->showMessage( + title, message, QIcon(":/icons/app/notification/whatsie-notify.png"), + SettingsManager::instance() + .settings() + .value("notificationTimeOut", 9000) + .toInt()); + m_systemTrayIcon->disconnect(m_systemTrayIcon, SIGNAL(messageClicked())); + connect(m_systemTrayIcon, &QSystemTrayIcon::messageClicked, + m_systemTrayIcon, [=]() { + if (windowState().testFlag(Qt::WindowMinimized) || + !windowState().testFlag(Qt::WindowActive)) { + activateWindow(); + this->show(); + } + }); } else { - auto popup = new NotificationPopup(webEngine); + auto popup = new NotificationPopup(m_webEngine); connect(popup, &NotificationPopup::notification_clicked, popup, [=]() { if (windowState().testFlag(Qt::WindowMinimized) || !windowState().testFlag(Qt::WindowActive) || this->isHidden()) { @@ -564,98 +553,102 @@ void MainWindow::notify(QString title, QString message) { void MainWindow::createActions() { - openUrlAction = new QAction("New Chat", this); - openUrlAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_N)); - connect(openUrlAction, &QAction::triggered, this, &MainWindow::newChat); - addAction(openUrlAction); + m_openUrlAction = new QAction("New Chat", this); + m_openUrlAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_N)); + connect(m_openUrlAction, &QAction::triggered, this, &MainWindow::newChat); + addAction(m_openUrlAction); - fullscreenAction = new QAction(tr("Fullscreen"), this); - fullscreenAction->setShortcut(Qt::Key_F11); - connect(fullscreenAction, &QAction::triggered, fullscreenAction, + m_fullscreenAction = new QAction(tr("Fullscreen"), this); + m_fullscreenAction->setShortcut(Qt::Key_F11); + connect(m_fullscreenAction, &QAction::triggered, m_fullscreenAction, [=]() { setWindowState(windowState() ^ Qt::WindowFullScreen); }); - addAction(fullscreenAction); + addAction(m_fullscreenAction); - minimizeAction = new QAction(tr("Mi&nimize to tray"), this); - connect(minimizeAction, &QAction::triggered, this, &QMainWindow::hide); - addAction(minimizeAction); + m_minimizeAction = new QAction(tr("Mi&nimize to tray"), this); + connect(m_minimizeAction, &QAction::triggered, this, &QMainWindow::hide); + addAction(m_minimizeAction); QShortcut *minimizeShortcut = new QShortcut( QKeySequence(Qt::Modifier::CTRL + Qt::Key_W), this, SLOT(hide())); minimizeShortcut->setAutoRepeat(false); - restoreAction = new QAction(tr("&Restore"), this); - connect(restoreAction, &QAction::triggered, this, &QMainWindow::show); - addAction(restoreAction); - - reloadAction = new QAction(tr("Re&load"), this); - reloadAction->setShortcut(Qt::Key_F5); - connect(reloadAction, &QAction::triggered, this, [=] { this->doReload(); }); - addAction(reloadAction); - - lockAction = new QAction(tr("Loc&k"), this); - lockAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_L)); - connect(lockAction, &QAction::triggered, this, &MainWindow::lockApp); - addAction(lockAction); - - settingsAction = new QAction(tr("&Settings"), this); - settingsAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_P)); - connect(settingsAction, &QAction::triggered, this, &MainWindow::showSettings); - addAction(settingsAction); - - toggleThemeAction = new QAction(tr("&Toggle theme"), this); - toggleThemeAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_T)); - connect(toggleThemeAction, &QAction::triggered, this, + m_restoreAction = new QAction(tr("&Restore"), this); + connect(m_restoreAction, &QAction::triggered, this, &QMainWindow::show); + addAction(m_restoreAction); + + m_reloadAction = new QAction(tr("Re&load"), this); + m_reloadAction->setShortcut(Qt::Key_F5); + connect(m_reloadAction, &QAction::triggered, this, + [=]() { this->doReload(); }); + addAction(m_reloadAction); + + m_lockAction = new QAction(tr("Loc&k"), this); + m_lockAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_L)); + connect(m_lockAction, &QAction::triggered, this, &MainWindow::lockApp); + addAction(m_lockAction); + + m_settingsAction = new QAction(tr("&Settings"), this); + m_settingsAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_P)); + connect(m_settingsAction, &QAction::triggered, this, + &MainWindow::showSettings); + addAction(m_settingsAction); + + m_toggleThemeAction = new QAction(tr("&Toggle theme"), this); + m_toggleThemeAction->setShortcut( + QKeySequence(Qt::Modifier::CTRL + Qt::Key_T)); + connect(m_toggleThemeAction, &QAction::triggered, this, &MainWindow::toggleTheme); - addAction(toggleThemeAction); + addAction(m_toggleThemeAction); - aboutAction = new QAction(tr("&About"), this); - connect(aboutAction, &QAction::triggered, this, &MainWindow::showAbout); + m_aboutAction = new QAction(tr("&About"), this); + connect(m_aboutAction, &QAction::triggered, this, &MainWindow::showAbout); - quitAction = new QAction(tr("&Quit"), this); - quitAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_Q)); - connect(quitAction, &QAction::triggered, this, &MainWindow::quitApp); - addAction(quitAction); + m_quitAction = new QAction(tr("&Quit"), this); + m_quitAction->setShortcut(QKeySequence(Qt::Modifier::CTRL + Qt::Key_Q)); + connect(m_quitAction, &QAction::triggered, this, &MainWindow::quitApp); + addAction(m_quitAction); } void MainWindow::quitApp() { - settings.setValue("geometry", saveGeometry()); + SettingsManager::instance().settings().setValue("geometry", saveGeometry()); getPageTheme(); - QTimer::singleShot(500, &settings, [=]() { - settings.setValue("firstrun_tray", true); + QTimer::singleShot(500, this, [=]() { + SettingsManager::instance().settings().setValue("firstrun_tray", true); qApp->quit(); }); } void MainWindow::createTrayIcon() { - trayIconMenu = new QMenu(this); - trayIconMenu->setObjectName("trayIconMenu"); - trayIconMenu->addAction(minimizeAction); - trayIconMenu->addAction(restoreAction); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(reloadAction); - trayIconMenu->addAction(lockAction); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(openUrlAction); - trayIconMenu->addAction(toggleThemeAction); - trayIconMenu->addAction(settingsAction); - trayIconMenu->addAction(aboutAction); - trayIconMenu->addSeparator(); - trayIconMenu->addAction(quitAction); - - trayIcon = new QSystemTrayIcon(trayIconNormal, this); - trayIcon->setContextMenu(trayIconMenu); - connect(trayIconMenu, SIGNAL(aboutToShow()), this, SLOT(checkWindowState())); - - trayIcon->show(); - - connect(trayIcon, &QSystemTrayIcon::messageClicked, this, + m_trayIconMenu = new QMenu(this); + m_trayIconMenu->setObjectName("trayIconMenu"); + m_trayIconMenu->addAction(m_minimizeAction); + m_trayIconMenu->addAction(m_restoreAction); + m_trayIconMenu->addSeparator(); + m_trayIconMenu->addAction(m_reloadAction); + m_trayIconMenu->addAction(m_lockAction); + m_trayIconMenu->addSeparator(); + m_trayIconMenu->addAction(m_openUrlAction); + m_trayIconMenu->addAction(m_toggleThemeAction); + m_trayIconMenu->addAction(m_settingsAction); + m_trayIconMenu->addAction(m_aboutAction); + m_trayIconMenu->addSeparator(); + m_trayIconMenu->addAction(m_quitAction); + + m_systemTrayIcon = new QSystemTrayIcon(m_trayIconNormal, this); + m_systemTrayIcon->setContextMenu(m_trayIconMenu); + connect(m_trayIconMenu, &QMenu::aboutToShow, this, + &MainWindow::checkWindowState); + + m_systemTrayIcon->show(); + + connect(m_systemTrayIcon, &QSystemTrayIcon::messageClicked, this, &MainWindow::messageClicked); - connect(trayIcon, &QSystemTrayIcon::activated, this, + connect(m_systemTrayIcon, &QSystemTrayIcon::activated, this, &MainWindow::iconActivated); // enable show shortcuts in menu if (qApp->styleHints()->showShortcutsInContextMenus()) { - foreach (QAction *action, trayIconMenu->actions()) { + foreach (QAction *action, m_trayIconMenu->actions()) { action->setShortcutVisibleInContextMenu(true); } } @@ -663,58 +656,64 @@ void MainWindow::createTrayIcon() { void MainWindow::initLock() { - if (lockWidget == nullptr) { - lockWidget = new Lock(this); - lockWidget->setObjectName("lockWidget"); + if (m_lockWidget == nullptr) { + m_lockWidget = new Lock(this); + m_lockWidget->setObjectName("lockWidget"); - lockWidget->setWindowFlags(Qt::Widget); - lockWidget->setStyleSheet( + m_lockWidget->setWindowFlags(Qt::Widget); + m_lockWidget->setStyleSheet( "QWidget#login{background-color:palette(window)};" "QWidget#signup{background-color:palette(window)}"); - lockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + m_lockWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - connect(lockWidget, &Lock::passwordNotSet, settingsWidget, [=]() { - settings.setValue("lockscreen", false); - settingsWidget->appLockSetChecked(false); + connect(m_lockWidget, &Lock::passwordNotSet, m_settingsWidget, [=]() { + SettingsManager::instance().settings().setValue("lockscreen", false); + m_settingsWidget->appLockSetChecked(false); }); - connect(lockWidget, &Lock::unLocked, [=]() { + connect(m_lockWidget, &Lock::unLocked, [=]() { // unlock event }); - connect(lockWidget, &Lock::passwordSet, settingsWidget, [=]() { - if (settings.value("asdfg").isValid()) { - settingsWidget->setCurrentPasswordText(QByteArray::fromBase64( - settings.value("asdfg").toString().toUtf8())); + connect(m_lockWidget, &Lock::passwordSet, m_settingsWidget, [=]() { + if (SettingsManager::instance().settings().value("asdfg").isValid()) { + m_settingsWidget->setCurrentPasswordText( + QByteArray::fromBase64(SettingsManager::instance() + .settings() + .value("asdfg") + .toString() + .toUtf8())); } else { - settingsWidget->setCurrentPasswordText("Require setup"); + m_settingsWidget->setCurrentPasswordText("Require setup"); } - settingsWidget->appLockSetChecked( - settings.value("lockscreen", false).toBool()); + m_settingsWidget->appLockSetChecked(SettingsManager::instance() + .settings() + .value("lockscreen", false) + .toBool()); }); - lockWidget->applyThemeQuirks(); + m_lockWidget->applyThemeQuirks(); } - lockWidget->setGeometry(this->rect()); + m_lockWidget->setGeometry(this->rect()); - if (settings.value("lockscreen").toBool()) { - if (settings.value("asdfg").isValid()) { - lockWidget->lock_app(); + if (SettingsManager::instance().settings().value("lockscreen").toBool()) { + if (SettingsManager::instance().settings().value("asdfg").isValid()) { + m_lockWidget->lock_app(); } else { - lockWidget->signUp(); + m_lockWidget->signUp(); } - lockWidget->show(); + m_lockWidget->show(); } else { - lockWidget->hide(); + m_lockWidget->hide(); } updateWindowTheme(); } void MainWindow::changeLockPassword() { - settings.remove("asdfg"); - settingsWidget->appLockSetChecked(false); - settingsWidget->autoAppLockSetChecked(false); - settingsWidget->updateAppLockPasswordViewer(); + SettingsManager::instance().settings().remove("asdfg"); + m_settingsWidget->appLockSetChecked(false); + m_settingsWidget->autoAppLockSetChecked(false); + m_settingsWidget->updateAppLockPasswordViewer(); tryLogOut(); QTimer::singleShot(1000, this, [=]() { if (isLoggedIn()) { @@ -727,16 +726,22 @@ void MainWindow::changeLockPassword() { } void MainWindow::appAutoLockChanged() { - bool enabled = settings.value("appAutoLocking", defaultAppAutoLock).toBool(); + bool enabled = SettingsManager::instance() + .settings() + .value("appAutoLocking", defaultAppAutoLock) + .toBool(); if (enabled) { - autoLockEventFilter->setTimeoutmillis( - settings.value("autoLockDuration", defaultAppAutoLockDuration).toInt() * + m_autoLockEventFilter->setTimeoutmillis( + SettingsManager::instance() + .settings() + .value("autoLockDuration", defaultAppAutoLockDuration) + .toInt() * 1000); - qApp->installEventFilter(autoLockEventFilter); - autoLockEventFilter->resetTimer(); + qApp->installEventFilter(m_autoLockEventFilter); + m_autoLockEventFilter->resetTimer(); } else { - autoLockEventFilter->stopTimer(); - qApp->removeEventFilter(autoLockEventFilter); + m_autoLockEventFilter->stopTimer(); + qApp->removeEventFilter(m_autoLockEventFilter); } } @@ -752,7 +757,7 @@ void MainWindow::checkWindowState() { menu->actions().at(0)->setDisabled(true); menu->actions().at(1)->setDisabled(false); } - if (lockWidget && lockWidget->getIsLocked()) { + if (m_lockWidget && m_lockWidget->getIsLocked()) { menu->actions().at(4)->setDisabled(true); } else { menu->actions().at(4)->setDisabled(false); @@ -763,13 +768,21 @@ void MainWindow::checkWindowState() { void MainWindow::initGlobalWebProfile() { QWebEngineProfile *profile = QWebEngineProfile::defaultProfile(); - profile->setHttpUserAgent( - settings.value("useragent", defaultUserAgentStr).toString()); + profile->setHttpUserAgent(SettingsManager::instance() + .settings() + .value("useragent", defaultUserAgentStr) + .toString()); QStringList dict_names; - dict_names.append(settings.value("sc_dict", "en-US").toString()); - - profile->setSpellCheckEnabled(settings.value("sc_enabled", true).toBool()); + dict_names.append(SettingsManager::instance() + .settings() + .value("sc_dict", "en-US") + .toString()); + + profile->setSpellCheckEnabled(SettingsManager::instance() + .settings() + .value("sc_enabled", true) + .toBool()); profile->setSpellCheckLanguages(dict_names); auto *webSettings = profile->settings(); @@ -794,7 +807,10 @@ void MainWindow::initGlobalWebProfile() { webSettings->setAttribute(QWebEngineSettings::JavascriptCanAccessClipboard, true); webSettings->setAttribute(QWebEngineSettings::PlaybackRequiresUserGesture, - settings.value("autoPlayMedia", false).toBool()); + SettingsManager::instance() + .settings() + .value("autoPlayMedia", false) + .toBool()); } void MainWindow::createWebEngine() { @@ -806,18 +822,18 @@ void MainWindow::createWebEngine() { widgetSize.setHorizontalStretch(1); widgetSize.setVerticalStretch(1); - dictionaries = Dictionaries::GetDictionaries(); + m_dictionaries = Dictionaries::GetDictionaries(); - WebView *webEngineView = new WebView(this, dictionaries); + WebView *webEngineView = new WebView(this, m_dictionaries); setCentralWidget(webEngineView); webEngineView->setSizePolicy(widgetSize); webEngineView->show(); - this->webEngine = webEngineView; + this->m_webEngine = webEngineView; - webEngineView->addAction(minimizeAction); - webEngineView->addAction(lockAction); - webEngineView->addAction(quitAction); + webEngineView->addAction(m_minimizeAction); + webEngineView->addAction(m_lockAction); + webEngineView->addAction(m_quitAction); createWebPage(false); } @@ -834,55 +850,69 @@ const QIcon MainWindow::getTrayIcon(const int ¬ificationCount) const { } void MainWindow::createWebPage(bool offTheRecord) { - if (offTheRecord && !otrProfile) { - otrProfile.reset(new QWebEngineProfile); + if (offTheRecord && !m_otrProfile) { + m_otrProfile.reset(new QWebEngineProfile); } auto profile = - offTheRecord ? otrProfile.get() : QWebEngineProfile::defaultProfile(); + offTheRecord ? m_otrProfile.get() : QWebEngineProfile::defaultProfile(); QStringList dict_names; - dict_names.append(settings.value("sc_dict", "en-US").toString()); - - profile->setSpellCheckEnabled(settings.value("sc_enabled", true).toBool()); + dict_names.append(SettingsManager::instance() + .settings() + .value("sc_dict", "en-US") + .toString()); + + profile->setSpellCheckEnabled(SettingsManager::instance() + .settings() + .value("sc_enabled", true) + .toBool()); profile->setSpellCheckLanguages(dict_names); - profile->setHttpUserAgent( - settings.value("useragent", defaultUserAgentStr).toString()); + profile->setHttpUserAgent(SettingsManager::instance() + .settings() + .value("useragent", defaultUserAgentStr) + .toString()); setNotificationPresenter(profile); - QWebEnginePage *page = new WebEnginePage(profile, webEngine); - if (settings.value("windowTheme", "light").toString() == "dark") { + QWebEnginePage *page = new WebEnginePage(profile, m_webEngine); + if (SettingsManager::instance() + .settings() + .value("windowTheme", "light") + .toString() == "dark") { page->setBackgroundColor(QColor(17, 27, 33)); // whatsapp dark bg color } else { page->setBackgroundColor(QColor(240, 240, 240)); // whatsapp light bg color } - webEngine->setPage(page); + m_webEngine->setPage(page); // page should be set parent of profile to prevent // Release of profile requested but WebEnginePage still not deleted. Expect // troubles ! profile->setParent(page); - auto randomValue = QRandomGenerator::global()->generateDouble() * 300; + auto randomValue = QRandomGenerator::global()->generateDouble() * 300.0; page->setUrl( QUrl("https://web.whatsapp.com?v=" + QString::number(randomValue))); connect(profile, &QWebEngineProfile::downloadRequested, - &downloadManagerWidget, &DownloadManagerWidget::downloadRequested); + &m_downloadManagerWidget, &DownloadManagerWidget::downloadRequested); - connect(page, SIGNAL(fullScreenRequested(QWebEngineFullScreenRequest)), this, - SLOT(fullScreenRequested(QWebEngineFullScreenRequest))); + connect(page, &QWebEnginePage::fullScreenRequested, this, + &MainWindow::fullScreenRequested); - double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); - webEngine->page()->setZoomFactor(currentFactor); + double currentFactor = SettingsManager::instance() + .settings() + .value("zoomFactor", 1.0) + .toDouble(); + m_webEngine->page()->setZoomFactor(currentFactor); } void MainWindow::setNotificationPresenter(QWebEngineProfile *profile) { - auto *op = webEngine->findChild("engineNotifier"); + auto *op = m_webEngine->findChild("engineNotifier"); if (op != nullptr) { op->close(); op->deleteLater(); } - auto popup = new NotificationPopup(webEngine); + auto popup = new NotificationPopup(m_webEngine); popup->setObjectName("engineNotifier"); connect(popup, &NotificationPopup::notification_clicked, popup, [=]() { if (windowState().testFlag(Qt::WindowMinimized) || @@ -894,25 +924,36 @@ void MainWindow::setNotificationPresenter(QWebEngineProfile *profile) { profile->setNotificationPresenter( [=](std::unique_ptr notification) { - if (settings.value("disableNotificationPopups", false).toBool() == - true) { + if (SettingsManager::instance() + .settings() + .value("disableNotificationPopups", false) + .toBool() == true) { return; } - if (settings.value("notificationCombo", 1).toInt() == 0 && - trayIcon != nullptr) { + if (SettingsManager::instance() + .settings() + .value("notificationCombo", 1) + .toInt() == 0 && + m_systemTrayIcon != nullptr) { QIcon icon(QPixmap::fromImage(notification->icon())); - trayIcon->showMessage( - notification->title(), notification->message(), icon, - settings.value("notificationTimeOut", 9000).toInt()); - trayIcon->disconnect(trayIcon, SIGNAL(messageClicked())); - connect(trayIcon, &QSystemTrayIcon::messageClicked, trayIcon, [=]() { - if (windowState().testFlag(Qt::WindowMinimized) || - !windowState().testFlag(Qt::WindowActive) || this->isHidden()) { - this->show(); - setWindowState((windowState() & ~Qt::WindowMinimized) | - Qt::WindowActive); - } - }); + m_systemTrayIcon->showMessage(notification->title(), + notification->message(), icon, + SettingsManager::instance() + .settings() + .value("notificationTimeOut", 9000) + .toInt()); + m_systemTrayIcon->disconnect(m_systemTrayIcon, + SIGNAL(messageClicked())); + connect(m_systemTrayIcon, &QSystemTrayIcon::messageClicked, + m_systemTrayIcon, [=]() { + if (windowState().testFlag(Qt::WindowMinimized) || + !windowState().testFlag(Qt::WindowActive) || + this->isHidden()) { + this->show(); + setWindowState((windowState() & ~Qt::WindowMinimized) | + Qt::WindowActive); + } + }); } else { popup->setMinimumWidth(300); @@ -924,39 +965,39 @@ void MainWindow::setNotificationPresenter(QWebEngineProfile *profile) { void MainWindow::fullScreenRequested(QWebEngineFullScreenRequest request) { if (request.toggleOn()) { - webEngine->showFullScreen(); + m_webEngine->showFullScreen(); this->showFullScreen(); request.accept(); } else { - webEngine->showNormal(); + m_webEngine->showNormal(); this->show(); request.accept(); } } -void MainWindow::handleWebViewTitleChanged(QString title) { +void MainWindow::handleWebViewTitleChanged(const QString &title) { setWindowTitle(QApplication::applicationName() + ": " + title); - if (notificationsTitleRegExp.exactMatch(title)) { - if (notificationsTitleRegExp.capturedTexts().isEmpty() == false) { - QString capturedTitle = - notificationsTitleRegExp.capturedTexts().constFirst(); - unreadMessageCountRegExp.setMinimal(true); - if (unreadMessageCountRegExp.indexIn(capturedTitle) != -1) { - QString unreadMessageCountStr = - unreadMessageCountRegExp.capturedTexts().constLast(); - int unreadMessageCount = unreadMessageCountStr.toInt(); - - restoreAction->setText( - tr("Restore") + " | " + unreadMessageCountStr + " " + - (unreadMessageCount > 1 ? tr("messages") : tr("message"))); - trayIcon->setIcon(getTrayIcon(unreadMessageCount)); - setWindowIcon(getTrayIcon(unreadMessageCount)); - } + QRegularExpressionMatch match = m_notificationsTitleRegExp.match(title); + if (match.hasMatch()) { + QString capturedTitle = match.captured(0); + m_unreadMessageCountRegExp.setPatternOptions( + QRegularExpression::DontCaptureOption); + QRegularExpressionMatch countMatch = + m_unreadMessageCountRegExp.match(capturedTitle); + if (countMatch.hasMatch()) { + QString unreadMessageCountStr = countMatch.captured(0); + int unreadMessageCount = unreadMessageCountStr.toInt(); + + m_restoreAction->setText( + tr("Restore") + " | " + unreadMessageCountStr + " " + + (unreadMessageCount > 1 ? tr("messages") : tr("message"))); + m_systemTrayIcon->setIcon(getTrayIcon(unreadMessageCount)); + setWindowIcon(getTrayIcon(unreadMessageCount)); } } else { - trayIcon->setIcon(trayIconNormal); - setWindowIcon(trayIconNormal); + m_systemTrayIcon->setIcon(m_trayIconNormal); + setWindowIcon(m_trayIconNormal); } } @@ -966,35 +1007,38 @@ void MainWindow::handleLoadFinished(bool loaded) { checkLoadedCorrectly(); updatePageTheme(); handleZoom(); - - if (settingsWidget != nullptr) { - settingsWidget->refresh(); + if (m_settingsWidget != nullptr) { + m_settingsWidget->refresh(); } } } void MainWindow::checkLoadedCorrectly() { - if (webEngine && webEngine->page()) { + if (m_webEngine && m_webEngine->page()) { // test 1 based on the class name of body tag of the page - webEngine->page()->runJavaScript( + m_webEngine->page()->runJavaScript( "document.querySelector('body').className", [this](const QVariant &result) { if (result.toString().contains("page-version", Qt::CaseInsensitive)) { qDebug() << "Test 1 found" << result.toString(); - webEngine->page()->runJavaScript( + m_webEngine->page()->runJavaScript( "document.getElementsByTagName('body')[0].innerText = ''"); loadingQuirk("test1"); - } else if (webEngine->title().contains("Error", - Qt::CaseInsensitive)) { - utils::delete_cache(webEngine->page()->profile()->cachePath()); - utils::delete_cache( - webEngine->page()->profile()->persistentStoragePath()); - settings.setValue("useragent", defaultUserAgentStr); - utils::DisplayExceptionErrorDialog( + } else if (m_webEngine->title().contains("Error", + Qt::CaseInsensitive)) { + Utils::delete_cache(m_webEngine->page()->profile()->cachePath()); + Utils::delete_cache( + m_webEngine->page()->profile()->persistentStoragePath()); + SettingsManager::instance().settings().setValue( + "useragent", defaultUserAgentStr); + Utils::DisplayExceptionErrorDialog( "test1 handleWebViewTitleChanged(title) title: Error, " "Resetting UA, Quiting!\nUA: " + - settings.value("useragent", "DefaultUA").toString()); - quitAction->trigger(); + SettingsManager::instance() + .settings() + .value("useragent", "DefaultUA") + .toString()); + m_quitAction->trigger(); } else { qDebug() << "Test 1 loaded correctly, value:" << result.toString(); } @@ -1002,24 +1046,29 @@ void MainWindow::checkLoadedCorrectly() { } } -void MainWindow::loadingQuirk(QString test) { +void MainWindow::loadingQuirk(const QString &test) { // contains ug message apply quirk - if (correctlyLoaderRetries > -1) { + if (m_correctlyLoadedRetries > -1) { qWarning() << test << "checkLoadedCorrectly()/loadingQuirk()/doReload()" - << correctlyLoaderRetries; + << m_correctlyLoadedRetries; doReload(false, false, true); - correctlyLoaderRetries--; + m_correctlyLoadedRetries--; } else { - utils::delete_cache(webEngine->page()->profile()->cachePath()); - utils::delete_cache(webEngine->page()->profile()->persistentStoragePath()); - settings.setValue("useragent", defaultUserAgentStr); - utils::DisplayExceptionErrorDialog( + Utils::delete_cache(m_webEngine->page()->profile()->cachePath()); + Utils::delete_cache( + m_webEngine->page()->profile()->persistentStoragePath()); + SettingsManager::instance().settings().setValue("useragent", + defaultUserAgentStr); + Utils::DisplayExceptionErrorDialog( test + " checkLoadedCorrectly()/loadingQuirk() reload retries 0, Resetting " "UA, Quiting!\nUA: " + - settings.value("useragent", "DefaultUA").toString()); + SettingsManager::instance() + .settings() + .value("useragent", "DefaultUA") + .toString()); - quitAction->trigger(); + m_quitAction->trigger(); } } @@ -1027,8 +1076,10 @@ void MainWindow::loadingQuirk(QString test) { // manager void MainWindow::handleDownloadRequested(QWebEngineDownloadItem *download) { QFileDialog dialog(this); - bool usenativeFileDialog = - settings.value("useNativeFileDialog", false).toBool(); + bool usenativeFileDialog = SettingsManager::instance() + .settings() + .value("useNativeFileDialog", false) + .toBool(); if (usenativeFileDialog == false) { dialog.setOption(QFileDialog::DontUseNativeDialog, true); @@ -1046,7 +1097,10 @@ void MainWindow::handleDownloadRequested(QWebEngineDownloadItem *download) { } void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) { - if (settings.value("minimizeOnTrayIconClick", false).toBool() == false || + if (SettingsManager::instance() + .settings() + .value("minimizeOnTrayIconClick", false) + .toBool() == false || reason == QSystemTrayIcon::Context) return; if (isVisible()) { @@ -1066,8 +1120,8 @@ void MainWindow::messageClicked() { void MainWindow::doAppReload() { - if (webEngine->page()) { - webEngine->page()->disconnect(); + if (m_webEngine->page()) { + m_webEngine->page()->disconnect(); } createWebPage(false); } @@ -1083,13 +1137,13 @@ void MainWindow::newChat() { } } -void MainWindow::triggerNewChat(QString phone, QString text) { +void MainWindow::triggerNewChat(const QString &phone, const QString &text) { static QString phoneStr, textStr; - webEngine->page()->runJavaScript( + m_webEngine->page()->runJavaScript( "openNewChatWhatsieDefined()", [this, phone, text](const QVariant &result) { if (result.toString().contains("true")) { - webEngine->page()->runJavaScript( + m_webEngine->page()->runJavaScript( QString("openNewChatWhatsie(\"%1\",\"%2\")").arg(phone, text)); } else { // create send url equivalent @@ -1097,7 +1151,7 @@ void MainWindow::triggerNewChat(QString phone, QString text) { textStr = text.isEmpty() ? "" : "text=" + text; QString urlStr = "https://web.whatsapp.com/send?" + phoneStr + "&" + textStr; - webEngine->page()->load(QUrl(urlStr)); + m_webEngine->page()->load(QUrl(urlStr)); } this->alreadyRunning(); }); @@ -1106,10 +1160,10 @@ void MainWindow::triggerNewChat(QString phone, QString text) { void MainWindow::doReload(bool byPassCache, bool isAskedByCLI, bool byLoadingQuirk) { if (byLoadingQuirk) { - webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, - byPassCache); + m_webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, + byPassCache); } else { - if (lockWidget && !lockWidget->getIsLocked()) { + if (m_lockWidget && !m_lockWidget->getIsLocked()) { this->notify(QApplication::applicationName(), QObject::tr("Reloading...")); } else { @@ -1123,40 +1177,41 @@ void MainWindow::doReload(bool byPassCache, bool isAskedByCLI, this->show(); return; } - webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, - byPassCache); + m_webEngine->triggerPageAction(QWebEnginePage::ReloadAndBypassCache, + byPassCache); } } void MainWindow::toggleMute(const bool &checked) { - webEngine->page()->setAudioMuted(checked); + m_webEngine->page()->setAudioMuted(checked); } // get value of page theme when page is loaded -QString MainWindow::getPageTheme() { +QString MainWindow::getPageTheme() const { static QString theme = "web"; // implies light - if (webEngine && webEngine->page()) { - webEngine->page()->runJavaScript( + if (m_webEngine && m_webEngine->page()) { + m_webEngine->page()->runJavaScript( "document.querySelector('body').className;", - [this](const QVariant &result) { + [=](const QVariant &result) { theme = result.toString(); theme.contains("dark") ? theme = "dark" : theme = "light"; - settings.setValue("windowTheme", theme); + SettingsManager::instance().settings().setValue("windowTheme", theme); }); } return theme; } void MainWindow::tryLock() { - if (settings.value("asdfg").isValid()) { + if (SettingsManager::instance().settings().value("asdfg").isValid()) { initLock(); return; } - if (settings.value("asdfg").isValid() == false) { - settings.setValue("lockscreen", false); - settings.setValue("appAutoLocking", false); - settingsWidget->appAutoLockingSetChecked(false); - settingsWidget->appLockSetChecked(false); + if (SettingsManager::instance().settings().value("asdfg").isValid() == + false) { + SettingsManager::instance().settings().setValue("lockscreen", false); + SettingsManager::instance().settings().setValue("appAutoLocking", false); + m_settingsWidget->appAutoLockingSetChecked(false); + m_settingsWidget->appLockSetChecked(false); initLock(); } } diff --git a/src/mainwindow.h b/src/mainwindow.h index 4ca25d5..c5e2821 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -11,8 +11,6 @@ #include #include #include -#include -#include #include #include #include @@ -33,6 +31,7 @@ #include "rateapp.h" #include "requestinterceptor.h" #include "settingswidget.h" +#include "theme.h" #include "webenginepage.h" #include "webview.h" @@ -42,23 +41,25 @@ public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); + void loadSchemaUrl(const QString &arg); + void alreadyRunning(bool notify = false); + void runMinimized(); + void notify(QString title, QString message); + void doReload(bool byPassCache = false, bool isAskedByCLI = false, + bool byLoadingQuirk = false); + public slots: void updateWindowTheme(); void updatePageTheme(); - void handleWebViewTitleChanged(QString title); + void handleWebViewTitleChanged(const QString &title); void handleLoadFinished(bool loaded); void handleDownloadRequested(QWebEngineDownloadItem *download); - void loadSchemaUrl(const QString &arg); void showSettings(bool isAskedByCLI = false); void showAbout(); void lockApp(); - void runMinimized(); - void alreadyRunning(bool notify = false); - void notify(QString title, QString message); void toggleTheme(); - void doReload(bool byPassCache = false, bool isAskedByCLI = false, - bool byLoadingQuirk = false); void newChat(); + protected slots: void closeEvent(QCloseEvent *event) override; void resizeEvent(QResizeEvent *event) override; @@ -66,71 +67,67 @@ protected slots: private: const QIcon getTrayIcon(const int ¬ificationCount) const; - QPalette lightPalette, darkPalette; void createActions(); void createTrayIcon(); void createWebEngine(); - - QSettings settings; - QRegExp notificationsTitleRegExp; - QIcon trayIconNormal; - QRegExp unreadMessageCountRegExp; - - QAction *reloadAction; - QAction *minimizeAction; - QAction *restoreAction; - QAction *aboutAction; - QAction *settingsAction; - QAction *toggleThemeAction; - QAction *quitAction; - QAction *lockAction; - QAction *fullscreenAction; - QAction *openUrlAction; - - QMenu *trayIconMenu; - QSystemTrayIcon *trayIcon; - QWebEngineView *webEngine; - SettingsWidget *settingsWidget = nullptr; - DownloadManagerWidget downloadManagerWidget; - QScopedPointer otrProfile; - Lock *lockWidget = nullptr; - int correctlyLoaderRetries = 4; - QStringList dictionaries; - AutoLockEventFilter *autoLockEventFilter = nullptr; - -private slots: - - QString getPageTheme(); - void iconActivated(QSystemTrayIcon::ActivationReason reason); - void messageClicked(); + QString getPageTheme() const; void handleCookieAdded(const QNetworkCookie &cookie); - void toggleMute(const bool &checked); void doAppReload(); void askToReloadPage(); void updateSettingsUserAgentWidget(); - void fullScreenRequested(QWebEngineFullScreenRequest request); void createWebPage(bool offTheRecord = false); void initSettingWidget(); void initGlobalWebProfile(); - void checkWindowState(); - void initLock(); void tryLock(); void checkLoadedCorrectly(); - void loadingQuirk(QString test); + void loadingQuirk(const QString &test); void setNotificationPresenter(QWebEngineProfile *profile); - void quitApp(); void initRateWidget(); - void initThemes(); void handleZoomOnWindowStateChange(const QWindowStateChangeEvent *ev); void handleZoom(); - void changeLockPassword(); void forceLogOut(); - void tryLogOut(); bool isLoggedIn(); + void tryLogOut(); void initAutoLock(); - void appAutoLockChanged(); - void triggerNewChat(QString phone, QString text); + void triggerNewChat(const QString &phone, const QString &text); void restoreMainWindow(); + + QIcon m_trayIconNormal; + QRegularExpression m_notificationsTitleRegExp; + QRegularExpression m_unreadMessageCountRegExp; + DownloadManagerWidget m_downloadManagerWidget; + QScopedPointer m_otrProfile; + int m_correctlyLoadedRetries = 4; + QStringList m_dictionaries; + + QAction *m_reloadAction = nullptr; + QAction *m_minimizeAction = nullptr; + QAction *m_restoreAction = nullptr; + QAction *m_aboutAction = nullptr; + QAction *m_settingsAction = nullptr; + QAction *m_toggleThemeAction = nullptr; + QAction *m_quitAction = nullptr; + QAction *m_lockAction = nullptr; + QAction *m_fullscreenAction = nullptr; + QAction *m_openUrlAction = nullptr; + + QMenu *m_trayIconMenu = nullptr; + QSystemTrayIcon *m_systemTrayIcon = nullptr; + QWebEngineView *m_webEngine = nullptr; + SettingsWidget *m_settingsWidget = nullptr; + Lock *m_lockWidget = nullptr; + AutoLockEventFilter *m_autoLockEventFilter = nullptr; + +private slots: + void iconActivated(QSystemTrayIcon::ActivationReason reason); + void messageClicked(); + void toggleMute(const bool &checked); + void fullScreenRequested(QWebEngineFullScreenRequest request); + void checkWindowState(); + void initLock(); + void quitApp(); + void changeLockPassword(); + void appAutoLockChanged(); }; #endif // MAINWINDOW_H diff --git a/src/notificationpopup.h b/src/notificationpopup.h index 3a765e0..69aa478 100644 --- a/src/notificationpopup.h +++ b/src/notificationpopup.h @@ -1,9 +1,9 @@ #ifndef NOTIFICATIONPOPUP_H #define NOTIFICATIONPOPUP_H -#pragma once - +#include "settingsmanager.h" #include "widgets/scrolltext/scrolltext.h" + #include #include #include @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -27,7 +26,6 @@ class NotificationPopup : public QWidget { QLabel m_icon, m_title; ScrollText m_message; std::unique_ptr notification; - QSettings settings; public: NotificationPopup(QWidget *parent) : QWidget(parent) { @@ -62,7 +60,10 @@ public: image.scaledToHeight(m_icon.height(), Qt::SmoothTransformation)); this->adjustSize(); - QTimer::singleShot(settings.value("notificationTimeOut", 9000).toInt(), + QTimer::singleShot(SettingsManager::instance() + .settings() + .value("notificationTimeOut", 9000) + .toInt(), this, [=]() { onClosed(); }); animateIn(screenNumber); @@ -87,7 +88,10 @@ public: connect(notification.get(), &QWebEngineNotification::closed, this, &NotificationPopup::onClosed); - QTimer::singleShot(settings.value("notificationTimeOut", 9000).toInt(), + QTimer::singleShot(SettingsManager::instance() + .settings() + .value("notificationTimeOut", 9000) + .toInt(), notification.get(), [&]() { onClosed(); }); animateIn(screenNumber); diff --git a/src/permissiondialog.cpp b/src/permissiondialog.cpp index c0eeac6..7ca9a4d 100644 --- a/src/permissiondialog.cpp +++ b/src/permissiondialog.cpp @@ -1,9 +1,6 @@ #include "permissiondialog.h" #include "ui_permissiondialog.h" -#include -#include -#include PermissionDialog::PermissionDialog(QWidget *parent) : QWidget(parent), ui(new Ui::PermissionDialog) { @@ -41,7 +38,7 @@ void PermissionDialog::addToFeaturesTable(QWebEnginePage::Feature feature, // insertRow ui->featuresTableWidget->insertRow(nextRow); - settings.beginGroup("permissions"); + SettingsManager::instance().settings().beginGroup("permissions"); // add column for (int i = 0; i < columnData.count(); i++) { @@ -50,10 +47,10 @@ void PermissionDialog::addToFeaturesTable(QWebEnginePage::Feature feature, featureCheckBox->setStyleSheet( "border:0px;margin-left:50%; margin-right:50%;"); featureCheckBox->setChecked( - settings.value(featureName, false).toBool()); + SettingsManager::instance().settings().value(featureName, false).toBool()); connect(featureCheckBox, &QCheckBox::toggled, [=](bool checked) { // save permission - settings.setValue("permissions/" + featureName, checked); + SettingsManager::instance().settings().setValue("permissions/" + featureName, checked); emit webPageFeatureChanged(feature); }); ui->featuresTableWidget->setCellWidget(nextRow, i, featureCheckBox); @@ -65,7 +62,7 @@ void PermissionDialog::addToFeaturesTable(QWebEnginePage::Feature feature, } this->update(); } - settings.endGroup(); + SettingsManager::instance().settings().endGroup(); } } diff --git a/src/permissiondialog.h b/src/permissiondialog.h index 2460a2d..0baf406 100644 --- a/src/permissiondialog.h +++ b/src/permissiondialog.h @@ -1,10 +1,13 @@ #ifndef PERMISSIONDIALOG_H #define PERMISSIONDIALOG_H -#include +#include +#include +#include #include #include -#include + +#include "settingsmanager.h" namespace Ui { class PermissionDialog; @@ -22,13 +25,13 @@ signals: protected slots: void keyPressEvent(QKeyEvent *e); + private slots: void addToFeaturesTable(QWebEnginePage::Feature feature, QString &featureName); private: Ui::PermissionDialog *ui; - QSettings settings; }; #endif // PERMISSIONDIALOG_H diff --git a/src/rateapp.cpp b/src/rateapp.cpp index 5c370a9..c258c37 100644 --- a/src/rateapp.cpp +++ b/src/rateapp.cpp @@ -22,7 +22,7 @@ RateApp::RateApp(QWidget *parent, QString app_rating_url, int app_launch_count, showTimer = new QTimer(this); showTimer->setInterval(this->present_delay); - connect(showTimer, &QTimer::timeout, [=]() { + connect(showTimer, &QTimer::timeout, this, [=]() { qDebug() << "Rate timer timeout"; emit showRateDialog(); if (this->isVisible()) @@ -30,15 +30,26 @@ RateApp::RateApp(QWidget *parent, QString app_rating_url, int app_launch_count, }); // increase the app_launched_count by one - int app_launched = settings.value("app_launched_count", 0).toInt(); - settings.setValue("app_launched_count", app_launched + 1); + int app_launched = SettingsManager::instance() + .settings() + .value("app_launched_count", 0) + .toInt(); + SettingsManager::instance().settings().setValue("app_launched_count", + app_launched + 1); // check if app install time is set in settings - if (settings.value("app_install_time").isNull()) { - settings.setValue("app_install_time", QDateTime::currentSecsSinceEpoch()); - - } else if (settings.value("app_install_time").isValid()) { - //qDebug() << "RATEAPP should show:" << shouldShow(); + if (SettingsManager::instance() + .settings() + .value("app_install_time") + .isNull()) { + SettingsManager::instance().settings().setValue( + "app_install_time", QDateTime::currentSecsSinceEpoch()); + + } else if (SettingsManager::instance() + .settings() + .value("app_install_time") + .isValid()) { + // qDebug() << "RATEAPP should show:" << shouldShow(); if (shouldShow()) { showTimer->start(); } else { @@ -49,7 +60,10 @@ RateApp::RateApp(QWidget *parent, QString app_rating_url, int app_launch_count, } // if already reated delete this obj to free resources - if (settings.value("rated_already", false).toBool()) { + if (SettingsManager::instance() + .settings() + .value("rated_already", false) + .toBool()) { this->deleteLater(); } } @@ -70,10 +84,19 @@ void RateApp::delayShowEvent() { */ bool RateApp::shouldShow() { bool shouldShow = false; - int app_launched_count = settings.value("app_launched_count", 0).toInt(); + int app_launched_count = SettingsManager::instance() + .settings() + .value("app_launched_count", 0) + .toInt(); qint64 currentDateTime = QDateTime::currentSecsSinceEpoch(); - qint64 installed_date_time = settings.value("app_install_time").toLongLong(); - bool ratedAlready = settings.value("rated_already", false).toBool(); + qint64 installed_date_time = SettingsManager::instance() + .settings() + .value("app_install_time") + .toLongLong(); + bool ratedAlready = SettingsManager::instance() + .settings() + .value("rated_already", false) + .toBool(); if (ratedAlready) // return false if already reated; return false; @@ -99,7 +122,7 @@ void RateApp::on_rateNowBtn_clicked() { } void RateApp::on_alreadyDoneBtn_clicked() { - settings.setValue("rated_already", true); + SettingsManager::instance().settings().setValue("rated_already", true); this->close(); } @@ -109,9 +132,10 @@ void RateApp::on_laterBtn_clicked() { } void RateApp::reset() { - settings.setValue("rated_already", false); - settings.setValue("app_launched_count", 0); - settings.setValue("app_install_time", QDateTime::currentSecsSinceEpoch()); + SettingsManager::instance().settings().setValue("rated_already", false); + SettingsManager::instance().settings().setValue("app_launched_count", 0); + SettingsManager::instance().settings().setValue( + "app_install_time", QDateTime::currentSecsSinceEpoch()); } void RateApp::on_rateOnGithub_clicked() { diff --git a/src/rateapp.h b/src/rateapp.h index 50d5b98..ffb601c 100644 --- a/src/rateapp.h +++ b/src/rateapp.h @@ -1,55 +1,55 @@ #ifndef RATEAPP_H #define RATEAPP_H -#include -#include #include -#include #include #include +#include +#include + +#include "settingsmanager.h" namespace Ui { class RateApp; } -class RateApp : public QWidget -{ - Q_OBJECT +class RateApp : public QWidget { + Q_OBJECT signals: - void showRateDialog(); + void showRateDialog(); public: - explicit RateApp(QWidget *parent = nullptr , QString app_rating_url = "", - int app_launch_count = 5, int app_install_days = 5, int present_delay = 5000); - ~RateApp(); + explicit RateApp(QWidget *parent = nullptr, QString app_rating_url = "", + int app_launch_count = 5, int app_install_days = 5, + int present_delay = 5000); + ~RateApp(); public slots: - void delayShowEvent(); + void delayShowEvent(); private slots: - void on_rateNowBtn_clicked(); + void on_rateNowBtn_clicked(); - void on_alreadyDoneBtn_clicked(); + void on_alreadyDoneBtn_clicked(); - void on_laterBtn_clicked(); + void on_laterBtn_clicked(); - bool shouldShow(); - void reset(); - void on_rateOnGithub_clicked(); + bool shouldShow(); + void reset(); + void on_rateOnGithub_clicked(); - void on_donate_clicked(); + void on_donate_clicked(); - void on_donate_2_clicked(); + void on_donate_2_clicked(); private: - Ui::RateApp *ui; - QString app_rating_url; - int app_launch_count; - int app_install_days; - int present_delay; - QSettings settings; - QTimer *showTimer; + Ui::RateApp *ui; + QString app_rating_url; + int app_launch_count; + int app_install_days; + int present_delay; + QTimer *showTimer; }; #endif // RATEAPP_H diff --git a/src/requestinterceptor.h b/src/requestinterceptor.h index 95f2d48..8d8f261 100644 --- a/src/requestinterceptor.h +++ b/src/requestinterceptor.h @@ -1,41 +1,39 @@ #ifndef REQUESTINTERCEPTOR_H #define REQUESTINTERCEPTOR_H -#include + +#include #include #include -#include -#include +#include #include #include -#include +#include + +#include "settingsmanager.h" -class RequestInterceptor : public QWebEngineUrlRequestInterceptor -{ - Q_OBJECT +class RequestInterceptor : public QWebEngineUrlRequestInterceptor { + Q_OBJECT signals: - void blocked(QString adUrl); -private: - QSettings m_settings; + void blocked(QString adUrl); public: - RequestInterceptor(QObject *parent = nullptr) : QWebEngineUrlRequestInterceptor(parent) - { - } + RequestInterceptor(QObject *parent = nullptr) + : QWebEngineUrlRequestInterceptor(parent) {} - void interceptRequest(QWebEngineUrlRequestInfo &info) - { - QString reqUrlStr = info.requestUrl().toString(); + void interceptRequest(QWebEngineUrlRequestInfo &info) { + QString reqUrlStr = info.requestUrl().toString(); -// if(reqUrlStr.contains("mms-type=video")|| reqUrlStr.contains("stream/video?key")){ -// if(m_settings.value("disableVideos",false).toBool()){ -// info.block(true); -// qDebug()<<"INTERCEPTOR: Blocked video - "< + +class SettingsManager { +public: + static SettingsManager &instance() { + static SettingsManager instance; + return instance; + } + + QSettings &settings() { return m_settings; } + +private: + SettingsManager() {} + + QSettings m_settings; +}; + +#endif // SETTINGSMANAGER_H diff --git a/src/settingswidget.cpp b/src/settingswidget.cpp index 4bd213d..87f6d4c 100644 --- a/src/settingswidget.cpp +++ b/src/settingswidget.cpp @@ -23,48 +23,91 @@ SettingsWidget::SettingsWidget(QWidget *parent, int screenNumber, this->enginePersistentStoragePath = enginePersistentStoragePath; ui->zoomFactorSpinBox->setRange(0.25, 5.0); - ui->zoomFactorSpinBox->setValue(settings.value("zoomFactor", 1.0).toDouble()); + ui->zoomFactorSpinBox->setValue(SettingsManager::instance() + .settings() + .value("zoomFactor", 1.0) + .toDouble()); ui->zoomFactorSpinBoxMaximized->setRange(0.25, 5.0); ui->zoomFactorSpinBoxMaximized->setValue( - settings.value("zoomFactorMaximized", defaultZoomFactorMaximized) + SettingsManager::instance() + .settings() + .value("zoomFactorMaximized", defaultZoomFactorMaximized) .toDouble()); ui->closeButtonActionComboBox->setCurrentIndex( - settings.value("closeButtonActionCombo", 0).toInt()); + SettingsManager::instance() + .settings() + .value("closeButtonActionCombo", 0) + .toInt()); ui->notificationCheckBox->setChecked( - settings.value("disableNotificationPopups", false).toBool()); - ui->muteAudioCheckBox->setChecked( - settings.value("muteAudio", false).toBool()); - ui->autoPlayMediaCheckBox->setChecked( - settings.value("autoPlayMedia", false).toBool()); + SettingsManager::instance() + .settings() + .value("disableNotificationPopups", false) + .toBool()); + ui->muteAudioCheckBox->setChecked(SettingsManager::instance() + .settings() + .value("muteAudio", false) + .toBool()); + ui->autoPlayMediaCheckBox->setChecked(SettingsManager::instance() + .settings() + .value("autoPlayMedia", false) + .toBool()); ui->themeComboBox->setCurrentText( - utils::toCamelCase(settings.value("windowTheme", "light").toString())); - - ui->userAgentLineEdit->setText( - settings.value("useragent", defaultUserAgentStr).toString()); + Utils::toCamelCase(SettingsManager::instance() + .settings() + .value("windowTheme", "light") + .toString())); + + ui->userAgentLineEdit->setText(SettingsManager::instance() + .settings() + .value("useragent", defaultUserAgentStr) + .toString()); ui->userAgentLineEdit->home(true); ui->userAgentLineEdit->deselect(); - ui->enableSpellCheck->setChecked(settings.value("sc_enabled", true).toBool()); + ui->enableSpellCheck->setChecked(SettingsManager::instance() + .settings() + .value("sc_enabled", true) + .toBool()); ui->notificationTimeOutspinBox->setValue( - settings.value("notificationTimeOut", 9000).toInt() / 1000); - ui->notificationCombo->setCurrentIndex( - settings.value("notificationCombo", 1).toInt()); - ui->useNativeFileDialog->setChecked( - settings.value("useNativeFileDialog", false).toBool()); - ui->startMinimized->setChecked( - settings.value("startMinimized", false).toBool()); + SettingsManager::instance() + .settings() + .value("notificationTimeOut", 9000) + .toInt() / + 1000); + ui->notificationCombo->setCurrentIndex(SettingsManager::instance() + .settings() + .value("notificationCombo", 1) + .toInt()); + ui->useNativeFileDialog->setChecked(SettingsManager::instance() + .settings() + .value("useNativeFileDialog", false) + .toBool()); + ui->startMinimized->setChecked(SettingsManager::instance() + .settings() + .value("startMinimized", false) + .toBool()); this->appAutoLockingSetChecked( - settings.value("appAutoLocking", defaultAppAutoLock).toBool()); + SettingsManager::instance() + .settings() + .value("appAutoLocking", defaultAppAutoLock) + .toBool()); ui->autoLockDurationSpinbox->setValue( - settings.value("autoLockDuration", defaultAppAutoLockDuration).toInt()); + SettingsManager::instance() + .settings() + .value("autoLockDuration", defaultAppAutoLockDuration) + .toInt()); ui->minimizeOnTrayIconClick->setChecked( - settings.value("minimizeOnTrayIconClick", false).toBool()); + SettingsManager::instance() + .settings() + .value("minimizeOnTrayIconClick", false) + .toBool()); ui->defaultDownloadLocation->setText( - settings + SettingsManager::instance() + .settings() .value("defaultDownloadLocation", QStandardPaths::writableLocation( QStandardPaths::DownloadLocation) + @@ -74,23 +117,29 @@ SettingsWidget::SettingsWidget(QWidget *parent, int screenNumber, ui->styleComboBox->blockSignals(true); ui->styleComboBox->addItems(QStyleFactory::keys()); ui->styleComboBox->blockSignals(false); - ui->styleComboBox->setCurrentText( - settings.value("widgetStyle", "Fusion").toString()); + ui->styleComboBox->setCurrentText(SettingsManager::instance() + .settings() + .value("widgetStyle", "Fusion") + .toString()); ui->fullWidthViewCheckbox->blockSignals(true); - ui->fullWidthViewCheckbox->setChecked( - settings.value("fullWidthView", true).toBool()); + ui->fullWidthViewCheckbox->setChecked(SettingsManager::instance() + .settings() + .value("fullWidthView", true) + .toBool()); ui->fullWidthViewCheckbox->blockSignals(false); ui->automaticThemeCheckBox->blockSignals(true); - bool automaticThemeSwitching = - settings.value("automaticTheme", false).toBool(); + bool automaticThemeSwitching = SettingsManager::instance() + .settings() + .value("automaticTheme", false) + .toBool(); ui->automaticThemeCheckBox->setChecked(automaticThemeSwitching); ui->automaticThemeCheckBox->blockSignals(false); themeSwitchTimer = new QTimer(this); themeSwitchTimer->setInterval(60000); // 1 min - connect(themeSwitchTimer, &QTimer::timeout, &settings, + connect(themeSwitchTimer, &QTimer::timeout, this, [=]() { themeSwitchTimerTimeout(); }); // instantly call the timeout slot if automatic theme switching enabled @@ -100,7 +149,11 @@ SettingsWidget::SettingsWidget(QWidget *parent, int screenNumber, updateAutomaticTheme(); this->setCurrentPasswordText( - QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())); + QByteArray::fromBase64(SettingsManager::instance() + .settings() + .value("asdfg") + .toString() + .toUtf8())); applyThemeQuirks(); @@ -124,8 +177,11 @@ SettingsWidget::SettingsWidget(QWidget *parent, int screenNumber, ui->scrollArea->setMinimumWidth( ui->groupBox_8->sizeHint().width() + ui->scrollArea->sizeHint().width() + ui->scrollAreaWidgetContents->layout()->spacing()); - if (settings.value("settingsGeo").isValid()) { - this->restoreGeometry(settings.value("settingsGeo").toByteArray()); + if (SettingsManager::instance().settings().value("settingsGeo").isValid()) { + this->restoreGeometry(SettingsManager::instance() + .settings() + .value("settingsGeo") + .toByteArray()); QRect screenRect = QGuiApplication::screens().at(screenNumber)->geometry(); if (!screenRect.contains(this->pos())) { this->move(screenRect.center() - this->rect().center()); @@ -144,7 +200,8 @@ bool SettingsWidget::eventFilter(QObject *obj, QEvent *event) { } void SettingsWidget::closeEvent(QCloseEvent *event) { - settings.setValue("settingsGeo", this->saveGeometry()); + SettingsManager::instance().settings().setValue("settingsGeo", + this->saveGeometry()); QWidget::closeEvent(event); } @@ -161,13 +218,18 @@ inline bool inRange(unsigned low, unsigned high, unsigned x) { } void SettingsWidget::themeSwitchTimerTimeout() { - if (settings.value("automaticTheme", false).toBool()) { + if (SettingsManager::instance() + .settings() + .value("automaticTheme", false) + .toBool()) { // start time QDateTime sunrise; - sunrise.setSecsSinceEpoch(settings.value("sunrise").toLongLong()); + sunrise.setSecsSinceEpoch( + SettingsManager::instance().settings().value("sunrise").toLongLong()); // end time QDateTime sunset; - sunset.setSecsSinceEpoch(settings.value("sunset").toLongLong()); + sunset.setSecsSinceEpoch( + SettingsManager::instance().settings().value("sunset").toLongLong()); QDateTime currentTime = QDateTime::currentDateTime(); int sunsetSeconds = QTime(0, 0).secsTo(sunset.time()); @@ -185,8 +247,10 @@ void SettingsWidget::themeSwitchTimerTimeout() { } void SettingsWidget::updateAutomaticTheme() { - bool automaticThemeSwitching = - settings.value("automaticTheme", false).toBool(); + bool automaticThemeSwitching = SettingsManager::instance() + .settings() + .value("automaticTheme", false) + .toBool(); if (automaticThemeSwitching && !themeSwitchTimer->isActive()) { themeSwitchTimer->start(); } else if (!automaticThemeSwitching) { @@ -228,7 +292,10 @@ void SettingsWidget::loadDictionaries(QStringList dictionaries) { ui->dictComboBox->blockSignals(false); // load settings for spellcheck dictionary - QString dictionary_name = settings.value("sc_dict", "en-US").toString(); + QString dictionary_name = SettingsManager::instance() + .settings() + .value("sc_dict", "en-US") + .toString(); int pos = ui->dictComboBox->findText(dictionary_name); if (pos == -1) { pos = ui->dictComboBox->findText("en-US"); @@ -241,13 +308,19 @@ void SettingsWidget::loadDictionaries(QStringList dictionaries) { void SettingsWidget::refresh() { ui->themeComboBox->setCurrentText( - utils::toCamelCase(settings.value("windowTheme", "light").toString())); + Utils::toCamelCase(SettingsManager::instance() + .settings() + .value("windowTheme", "light") + .toString())); - ui->cookieSize->setText(utils::refreshCacheSize(persistentStoragePath())); + ui->cookieSize->setText(Utils::refreshCacheSize(persistentStoragePath())); // update dict settings at runtime // load settings for spellcheck dictionary - QString dictionary_name = settings.value("sc_dict", "en-US").toString(); + QString dictionary_name = SettingsManager::instance() + .settings() + .value("sc_dict", "en-US") + .toString(); int pos = ui->dictComboBox->findText(dictionary_name); if (pos == -1) { pos = ui->dictComboBox->findText("en-US"); @@ -258,8 +331,14 @@ void SettingsWidget::refresh() { ui->dictComboBox->setCurrentIndex(pos); // enable disable spell check - ui->enableSpellCheck->setChecked(settings.value("sc_enabled", true).toBool()); - emit updateFullWidthView(settings.value("fullWidthView", true).toBool()); + ui->enableSpellCheck->setChecked(SettingsManager::instance() + .settings() + .value("sc_enabled", true) + .toBool()); + emit updateFullWidthView(SettingsManager::instance() + .settings() + .value("fullWidthView", true) + .toBool()); } void SettingsWidget::updateDefaultUAButton(const QString engineUA) { @@ -301,18 +380,20 @@ void SettingsWidget::on_deletePersistentData_clicked() { } void SettingsWidget::clearAllData() { - utils::delete_cache(this->cachePath()); - utils::delete_cache(this->persistentStoragePath()); + Utils::delete_cache(this->cachePath()); + Utils::delete_cache(this->persistentStoragePath()); refresh(); } void SettingsWidget::on_notificationCheckBox_toggled(bool checked) { - settings.setValue("disableNotificationPopups", checked); + SettingsManager::instance().settings().setValue("disableNotificationPopups", + checked); } void SettingsWidget::on_themeComboBox_currentTextChanged(const QString &arg1) { applyThemeQuirks(); - settings.setValue("windowTheme", QString(arg1).toLower()); + SettingsManager::instance().settings().setValue("windowTheme", + QString(arg1).toLower()); emit updateWindowTheme(); emit updatePageTheme(); } @@ -344,12 +425,12 @@ void SettingsWidget::applyThemeQuirks() { } void SettingsWidget::on_muteAudioCheckBox_toggled(bool checked) { - settings.setValue("muteAudio", checked); + SettingsManager::instance().settings().setValue("muteAudio", checked); emit muteToggled(checked); } void SettingsWidget::on_autoPlayMediaCheckBox_toggled(bool checked) { - settings.setValue("autoPlayMedia", checked); + SettingsManager::instance().settings().setValue("autoPlayMedia", checked); emit autoPlayMediaToggled(checked); } @@ -362,10 +443,12 @@ void SettingsWidget::on_userAgentLineEdit_textChanged(const QString &arg1) { bool isDefault = QString::compare(arg1.trimmed(), defaultUserAgentStr, Qt::CaseInsensitive) == 0; bool isPrevious = - QString::compare( - arg1.trimmed(), - settings.value("useragent", defaultUserAgentStr).toString(), - Qt::CaseInsensitive) == 0; + QString::compare(arg1.trimmed(), + SettingsManager::instance() + .settings() + .value("useragent", defaultUserAgentStr) + .toString(), + Qt::CaseInsensitive) == 0; if (isDefault == false && arg1.trimmed().isEmpty() == false) { ui->defaultUserAgentButton->setEnabled(false); @@ -392,7 +475,8 @@ void SettingsWidget::on_setUserAgent_clicked() { void SettingsWidget::on_closeButtonActionComboBox_currentIndexChanged( int index) { - settings.setValue("closeButtonActionCombo", index); + SettingsManager::instance().settings().setValue("closeButtonActionCombo", + index); } void SettingsWidget::autoAppLockSetChecked(bool checked) { @@ -403,7 +487,11 @@ void SettingsWidget::autoAppLockSetChecked(bool checked) { void SettingsWidget::updateAppLockPasswordViewer() { this->setCurrentPasswordText( - QByteArray::fromBase64(settings.value("asdfg").toString().toUtf8())); + QByteArray::fromBase64(SettingsManager::instance() + .settings() + .value("asdfg") + .toString() + .toUtf8())); } void SettingsWidget::appLockSetChecked(bool checked) { @@ -420,7 +508,10 @@ void SettingsWidget::appAutoLockingSetChecked(bool checked) { void SettingsWidget::toggleTheme() { // disable automatic theme first - if (settings.value("automaticTheme", false).toBool()) { + if (SettingsManager::instance() + .settings() + .value("automaticTheme", false) + .toBool()) { emit notify(tr( "Automatic theme switching was disabled due to manual theme toggle.")); ui->automaticThemeCheckBox->setChecked(false); @@ -444,14 +535,15 @@ void SettingsWidget::setCurrentPasswordText(QString str) { } void SettingsWidget::on_applock_checkbox_toggled(bool checked) { - if (settings.value("asdfg").isValid()) { - settings.setValue("lockscreen", checked); - } else if (checked && !settings.value("asdfg").isValid()) { - settings.setValue("lockscreen", true); + if (SettingsManager::instance().settings().value("asdfg").isValid()) { + SettingsManager::instance().settings().setValue("lockscreen", checked); + } else if (checked && + !SettingsManager::instance().settings().value("asdfg").isValid()) { + SettingsManager::instance().settings().setValue("lockscreen", true); if (checked) showSetApplockPasswordDialog(); } else { - settings.setValue("lockscreen", false); + SettingsManager::instance().settings().setValue("lockscreen", false); if (checked) showSetApplockPasswordDialog(); } @@ -477,12 +569,12 @@ void SettingsWidget::showSetApplockPasswordDialog() { } void SettingsWidget::on_dictComboBox_currentIndexChanged(const QString &arg1) { - settings.setValue("sc_dict", arg1); + SettingsManager::instance().settings().setValue("sc_dict", arg1); emit dictChanged(arg1); } void SettingsWidget::on_enableSpellCheck_toggled(bool checked) { - settings.setValue("sc_enabled", checked); + SettingsManager::instance().settings().setValue("sc_enabled", checked); emit spellCheckChanged(checked); } @@ -534,12 +626,13 @@ void SettingsWidget::on_showPermissionsButton_clicked() { } void SettingsWidget::on_notificationTimeOutspinBox_valueChanged(int arg1) { - settings.setValue("notificationTimeOut", arg1 * 1000); + SettingsManager::instance().settings().setValue("notificationTimeOut", + arg1 * 1000); emit notificationPopupTimeOutChanged(); } void SettingsWidget::on_notificationCombo_currentIndexChanged(int index) { - settings.setValue("notificationCombo", index); + SettingsManager::instance().settings().setValue("notificationCombo", index); } void SettingsWidget::on_tryNotification_clicked() { @@ -555,8 +648,10 @@ void SettingsWidget::on_automaticThemeCheckBox_toggled(bool checked) { automaticTheme->setAttribute(Qt::WA_DeleteOnClose, true); connect(automaticTheme, &AutomaticTheme::destroyed, ui->automaticThemeCheckBox, [=]() { - bool automaticThemeSwitching = - settings.value("automaticTheme", false).toBool(); + bool automaticThemeSwitching = SettingsManager::instance() + .settings() + .value("automaticTheme", false) + .toBool(); ui->automaticThemeCheckBox->setChecked(automaticThemeSwitching); if (automaticThemeSwitching) themeSwitchTimerTimeout(); @@ -564,28 +659,30 @@ void SettingsWidget::on_automaticThemeCheckBox_toggled(bool checked) { }); automaticTheme->show(); } else { - settings.setValue("automaticTheme", false); + SettingsManager::instance().settings().setValue("automaticTheme", false); updateAutomaticTheme(); } } void SettingsWidget::on_useNativeFileDialog_toggled(bool checked) { - settings.setValue("useNativeFileDialog", checked); + SettingsManager::instance().settings().setValue("useNativeFileDialog", + checked); } void SettingsWidget::on_startMinimized_toggled(bool checked) { - settings.setValue("startMinimized", checked); + SettingsManager::instance().settings().setValue("startMinimized", checked); } void SettingsWidget::on_appAutoLockcheckBox_toggled(bool checked) { - if (settings.value("asdfg").isValid()) { - settings.setValue("appAutoLocking", checked); + if (SettingsManager::instance().settings().value("asdfg").isValid()) { + SettingsManager::instance().settings().setValue("appAutoLocking", checked); } else { QMessageBox::information(this, "App Lock Setup", "Please setup the App lock password first.", QMessageBox::Ok); - if (settings.value("asdfg").isValid() == false) { - settings.setValue("appAutoLocking", false); + if (SettingsManager::instance().settings().value("asdfg").isValid() == + false) { + SettingsManager::instance().settings().setValue("appAutoLocking", false); autoAppLockSetChecked(false); } } @@ -593,7 +690,7 @@ void SettingsWidget::on_appAutoLockcheckBox_toggled(bool checked) { } void SettingsWidget::on_autoLockDurationSpinbox_valueChanged(int arg1) { - settings.setValue("autoLockDuration", arg1); + SettingsManager::instance().settings().setValue("autoLockDuration", arg1); emit appAutoLockChanged(); } @@ -603,64 +700,78 @@ void SettingsWidget::on_resetAppAutoLockPushButton_clicked() { } void SettingsWidget::on_minimizeOnTrayIconClick_toggled(bool checked) { - settings.setValue("minimizeOnTrayIconClick", checked); + SettingsManager::instance().settings().setValue("minimizeOnTrayIconClick", + checked); } void SettingsWidget::on_styleComboBox_currentTextChanged(const QString &arg1) { applyThemeQuirks(); - settings.setValue("widgetStyle", arg1); + SettingsManager::instance().settings().setValue("widgetStyle", arg1); emit updateWindowTheme(); emit updatePageTheme(); } void SettingsWidget::on_zoomPlus_clicked() { - double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); + double currentFactor = SettingsManager::instance() + .settings() + .value("zoomFactor", 1.0) + .toDouble(); double newFactor = currentFactor + 0.25; ui->zoomFactorSpinBox->setValue(newFactor); - settings.setValue("zoomFactor", ui->zoomFactorSpinBox->value()); + SettingsManager::instance().settings().setValue( + "zoomFactor", ui->zoomFactorSpinBox->value()); emit zoomChanged(); } void SettingsWidget::on_zoomMinus_clicked() { - double currentFactor = settings.value("zoomFactor", 1.0).toDouble(); + double currentFactor = SettingsManager::instance() + .settings() + .value("zoomFactor", 1.0) + .toDouble(); double newFactor = currentFactor - 0.25; ui->zoomFactorSpinBox->setValue(newFactor); - settings.setValue("zoomFactor", ui->zoomFactorSpinBox->value()); + SettingsManager::instance().settings().setValue( + "zoomFactor", ui->zoomFactorSpinBox->value()); emit zoomChanged(); } void SettingsWidget::on_zoomReset_clicked() { ui->zoomFactorSpinBox->setValue(1.0); - settings.setValue("zoomFactor", ui->zoomFactorSpinBox->value()); + SettingsManager::instance().settings().setValue( + "zoomFactor", ui->zoomFactorSpinBox->value()); emit zoomChanged(); } void SettingsWidget::on_zoomResetMaximized_clicked() { ui->zoomFactorSpinBoxMaximized->setValue(defaultZoomFactorMaximized); - settings.setValue("zoomFactorMaximized", - ui->zoomFactorSpinBoxMaximized->value()); + SettingsManager::instance().settings().setValue( + "zoomFactorMaximized", ui->zoomFactorSpinBoxMaximized->value()); emit zoomMaximizedChanged(); } void SettingsWidget::on_zoomPlusMaximized_clicked() { double currentFactor = - settings.value("zoomFactorMaximized", defaultZoomFactorMaximized) + SettingsManager::instance() + .settings() + .value("zoomFactorMaximized", defaultZoomFactorMaximized) .toDouble(); double newFactor = currentFactor + 0.25; ui->zoomFactorSpinBoxMaximized->setValue(newFactor); - settings.setValue("zoomFactorMaximized", - ui->zoomFactorSpinBoxMaximized->value()); + SettingsManager::instance().settings().setValue( + "zoomFactorMaximized", ui->zoomFactorSpinBoxMaximized->value()); emit zoomMaximizedChanged(); } void SettingsWidget::on_zoomMinusMaximized_clicked() { double currentFactor = - settings.value("zoomFactorMaximized", defaultZoomFactorMaximized) + SettingsManager::instance() + .settings() + .value("zoomFactorMaximized", defaultZoomFactorMaximized) .toDouble(); double newFactor = currentFactor - 0.25; ui->zoomFactorSpinBoxMaximized->setValue(newFactor); - settings.setValue("zoomFactorMaximized", - ui->zoomFactorSpinBoxMaximized->value()); + SettingsManager::instance().settings().setValue( + "zoomFactorMaximized", ui->zoomFactorSpinBoxMaximized->value()); emit zoomMaximizedChanged(); } @@ -670,12 +781,15 @@ void SettingsWidget::on_changeDefaultDownloadLocationPb_clicked() { dialog.setOption(QFileDialog::ShowDirsOnly); QString path; - bool usenativeFileDialog = - settings.value("useNativeFileDialog", false).toBool(); + bool usenativeFileDialog = SettingsManager::instance() + .settings() + .value("useNativeFileDialog", false) + .toBool(); if (usenativeFileDialog == false) { path = QFileDialog::getExistingDirectory( this, tr("Select download directory"), - settings + SettingsManager::instance() + .settings() .value("defaultDownloadLocation", QStandardPaths::writableLocation( QStandardPaths::DownloadLocation) + @@ -685,7 +799,8 @@ void SettingsWidget::on_changeDefaultDownloadLocationPb_clicked() { } else { path = QFileDialog::getSaveFileName( this, tr("Select download directory"), - settings + SettingsManager::instance() + .settings() .value("defaultDownloadLocation", QStandardPaths::writableLocation( QStandardPaths::DownloadLocation) + @@ -695,7 +810,8 @@ void SettingsWidget::on_changeDefaultDownloadLocationPb_clicked() { if (!path.isNull() && !path.isEmpty()) { ui->defaultDownloadLocation->setText(path); - settings.setValue("defaultDownloadLocation", path); + SettingsManager::instance().settings().setValue("defaultDownloadLocation", + path); } } @@ -720,7 +836,7 @@ void SettingsWidget::on_viewPassword_clicked() { } void SettingsWidget::on_chnageCurrentPasswordPushButton_clicked() { - if (settings.value("asdfg").isValid()) { + if (SettingsManager::instance().settings().value("asdfg").isValid()) { QMessageBox msgBox; msgBox.setText("You are about to change your current app lock password!" "\n\nThis will LogOut your current session." @@ -741,20 +857,19 @@ void SettingsWidget::on_chnageCurrentPasswordPushButton_clicked() { msgBox.exec(); } else { - settings.setValue("lockscreen", true); + SettingsManager::instance().settings().setValue("lockscreen", true); showSetApplockPasswordDialog(); } } void SettingsWidget::on_fullWidthViewCheckbox_toggled(bool checked) { - settings.setValue("fullWidthView", checked); + SettingsManager::instance().settings().setValue("fullWidthView", checked); emit updateFullWidthView(checked); } -void SettingsWidget::keyPressEvent(QKeyEvent *e) -{ - if (e->key() == Qt::Key_Escape) - this->close(); +void SettingsWidget::keyPressEvent(QKeyEvent *e) { + if (e->key() == Qt::Key_Escape) + this->close(); - QWidget::keyPressEvent(e); + QWidget::keyPressEvent(e); } diff --git a/src/settingswidget.h b/src/settingswidget.h index d533343..a569d6f 100644 --- a/src/settingswidget.h +++ b/src/settingswidget.h @@ -1,12 +1,12 @@ #ifndef SETTINGSWIDGET_H #define SETTINGSWIDGET_H +#include + #include "permissiondialog.h" +#include "settingsmanager.h" #include "utils.h" -#include -#include - namespace Ui { class SettingsWidget; } @@ -102,7 +102,6 @@ private slots: private: Ui::SettingsWidget *ui; QString engineCachePath, enginePersistentStoragePath; - QSettings settings; QTimer *themeSwitchTimer; }; diff --git a/src/theme.cpp b/src/theme.cpp new file mode 100644 index 0000000..742e59d --- /dev/null +++ b/src/theme.cpp @@ -0,0 +1,69 @@ +#include "theme.h" + +QPalette Theme::initLightPalette() { + QPalette lightPalette; + lightPalette.setColor(QPalette::Window, QColor(240, 240, 240)); + lightPalette.setColor(QPalette::WindowText, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::Button, QColor(240, 240, 240)); + lightPalette.setColor(QPalette::Light, QColor(180, 180, 180)); + lightPalette.setColor(QPalette::Midlight, QColor(200, 200, 200)); + lightPalette.setColor(QPalette::Dark, QColor(225, 225, 225)); + lightPalette.setColor(QPalette::Text, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::BrightText, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::ButtonText, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::Base, QColor(237, 237, 237)); + lightPalette.setColor(QPalette::Shadow, QColor(20, 20, 20)); + lightPalette.setColor(QPalette::Highlight, QColor(76, 163, 224)); + lightPalette.setColor(QPalette::HighlightedText, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::Link, QColor(0, 162, 232)); + lightPalette.setColor(QPalette::AlternateBase, QColor(225, 225, 225)); + lightPalette.setColor(QPalette::ToolTipBase, QColor(240, 240, 240)); + lightPalette.setColor(QPalette::ToolTipText, QColor(0, 0, 0)); + lightPalette.setColor(QPalette::LinkVisited, QColor(222, 222, 222)); + lightPalette.setColor(QPalette::Disabled, QPalette::WindowText, + QColor(115, 115, 115)); + lightPalette.setColor(QPalette::Disabled, QPalette::Text, + QColor(115, 115, 115)); + lightPalette.setColor(QPalette::Disabled, QPalette::ButtonText, + QColor(115, 115, 115)); + lightPalette.setColor(QPalette::Disabled, QPalette::Highlight, + QColor(190, 190, 190)); + lightPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, + QColor(115, 115, 115)); + + return lightPalette; +} + +QPalette Theme::initDarkPalette() { + QPalette darkPalette; + darkPalette.setColor(QPalette::Window, QColor(17, 27, 33)); + darkPalette.setColor(QPalette::Text, Qt::white); + darkPalette.setColor(QPalette::WindowText, Qt::white); + darkPalette.setColor(QPalette::Base, QColor(32, 44, 51)); + darkPalette.setColor(QPalette::AlternateBase, QColor(95, 108, 115)); + darkPalette.setColor(QPalette::ToolTipBase, QColor(66, 66, 66)); + darkPalette.setColor(QPalette::ToolTipText, QColor(192, 192, 192)); + darkPalette.setColor(QPalette::Dark, QColor(35, 35, 35)); + darkPalette.setColor(QPalette::Shadow, QColor(20, 20, 20)); + darkPalette.setColor(QPalette::Button, QColor(17, 27, 33)); + darkPalette.setColor(QPalette::ButtonText, Qt::white); + darkPalette.setColor(QPalette::BrightText, Qt::red); + darkPalette.setColor(QPalette::Link, QColor(42, 130, 218)); + darkPalette.setColor(QPalette::Highlight, QColor(38, 140, 196)); + darkPalette.setColor(QPalette::HighlightedText, Qt::white); + darkPalette.setColor(QPalette::Disabled, QPalette::HighlightedText, + QColor(127, 127, 127)); + darkPalette.setColor(QPalette::Disabled, QPalette::Window, + QColor(65, 65, 67)); + darkPalette.setColor(QPalette::Disabled, QPalette::Highlight, + QColor(80, 80, 80)); + darkPalette.setColor(QPalette::Disabled, QPalette::ButtonText, + QColor(127, 127, 127)); + darkPalette.setColor(QPalette::Disabled, QPalette::Text, + QColor(127, 127, 127)); + return darkPalette; +} + +QPalette &Theme::getLightPalette() { return lightPalette(); } + +QPalette &Theme::getDarkPalette() { return darkPalette(); } diff --git a/src/theme.h b/src/theme.h new file mode 100644 index 0000000..71b7306 --- /dev/null +++ b/src/theme.h @@ -0,0 +1,27 @@ +#ifndef THEME_H +#define THEME_H + +#include +#include +#include + +class Theme { +public: + static QPalette &getLightPalette(); + static QPalette &getDarkPalette(); + +private: + static QPalette &lightPalette() { + static QPalette palette = initLightPalette(); + return palette; + } + static QPalette &darkPalette() { + static QPalette palette = initDarkPalette(); + return palette; + } + + static QPalette initLightPalette(); + static QPalette initDarkPalette(); +}; + +#endif // THEME_H diff --git a/src/utils.cpp b/src/utils.cpp index c00b25d..46365e7 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -2,12 +2,12 @@ #include "def.h" #include -utils::utils(QObject *parent) : QObject(parent) { setParent(parent); } +Utils::Utils(QObject *parent) : QObject(parent) { setParent(parent); } -utils::~utils() { this->deleteLater(); } +Utils::~Utils() { this->deleteLater(); } // calculate dir size -quint64 utils::dir_size(const QString &directory) { +quint64 Utils::dir_size(const QString &directory) { quint64 sizex = 0; QFileInfo str_info(directory); if (str_info.isDir()) { @@ -28,7 +28,7 @@ quint64 utils::dir_size(const QString &directory) { } // get the size of cache folder in human readble format -QString utils::refreshCacheSize(const QString cache_dir) { +QString Utils::refreshCacheSize(const QString cache_dir) { qint64 cache_size = dir_size(cache_dir); QString cache_unit; if (cache_size > 1024 * 1024 * 1024) { @@ -47,25 +47,25 @@ QString utils::refreshCacheSize(const QString cache_dir) { return QString::number(cache_size) + cache_unit; } -bool utils::delete_cache(const QString cache_dir) { +bool Utils::delete_cache(const QString cache_dir) { bool deleted = QDir(cache_dir).removeRecursively(); QDir(cache_dir).mkpath(cache_dir); return deleted; } // returns string with first letter capitalized -QString utils::toCamelCase(const QString &s) { +QString Utils::toCamelCase(const QString &s) { QStringList parts = s.split(' ', Qt::SkipEmptyParts); for (int i = 0; i < parts.size(); ++i) parts[i].replace(0, 1, parts[i][0].toUpper()); return parts.join(" "); } -QString utils::generateRandomId(int length) { +QString Utils::generateRandomId(int length) { return genRand(length, false, true, false); } -QString utils::genRand(int length, bool useUpper, bool useLower, +QString Utils::genRand(int length, bool useUpper, bool useLower, bool useDigits) { QString possibleCharacters; if (useUpper) { @@ -93,7 +93,7 @@ QString utils::genRand(int length, bool useUpper, bool useLower, return QString::fromLatin1(randomBytes); } -QString utils::convertSectoDay(qint64 secs) { +QString Utils::convertSectoDay(qint64 secs) { int day = secs / (24 * 3600); secs = secs % (24 * 3600); @@ -111,9 +111,28 @@ QString utils::convertSectoDay(qint64 secs) { return days; } -// static on demand path maker +/** + * @brief Returns the full path for a given file or directory name within a + * specified location. + * + * The method constructs the full path by concatenating the specified `pathname` + * with the provided `standardLocation`. If `standardLocation` is not provided, + * the default value is obtained from + * `QStandardPaths::writableLocation(QStandardPaths::DataLocation)`. + * + * @param pathname The name of the file or directory within the specified + * location. + * @param standardLocation (optional) The base directory to prepend to + * `pathname`. Default value: + * QStandardPaths::writableLocation(QStandardPaths::DataLocation). + * + * @return The full path, including the `pathname` and the `standardLocation`, + * separated by the appropriate directory separator. If the specified location + * does not exist, the method creates it using QDir::mkpath. The returned path + * ends with a directory separator. + */ QString -utils::returnPath(QString pathname, +Utils::returnPath(QString pathname, QString standardLocation = QStandardPaths::writableLocation( QStandardPaths::DataLocation)) { QChar sepe = QDir::separator(); @@ -122,10 +141,24 @@ utils::returnPath(QString pathname, return standardLocation + sepe + pathname + sepe; } -QString utils::EncodeXML(const QString &encodeMe) { - +/** + * @brief Encodes XML special characters in a given string and returns the + * encoded version. + * + * The method iterates over each character in the input `encodeMe` string and + * replaces XML special characters + * ('&', '\'', '"', '<', and '>') with their corresponding XML entities + * ('&', ''', '"', '<', and '>'). The encoded string is then + * returned. + * + * @param encodeMe The string to be encoded. + * @return The encoded version of the input string, where XML special characters + * are replaced with their corresponding entities. + */ +QString Utils::encodeXML(const QString &encodeMe) { QString temp; int length = encodeMe.size(); + for (int index = 0; index < length; index++) { QChar character(encodeMe.at(index)); @@ -159,8 +192,20 @@ QString utils::EncodeXML(const QString &encodeMe) { return temp; } -QString utils::DecodeXML(const QString &decodeMe) { - +/** + * @brief Decodes XML entities in a given string and returns the decoded + * version. + * + * The method creates a copy of the input `decodeMe` string and replaces XML + * entities + * ('&', ''', '"', '<', and '>') with their corresponding + * characters. The decoded string is then returned. + * + * @param decodeMe The string to be decoded. + * @return The decoded version of the input string, where XML entities are + * replaced with their corresponding characters. + */ +QString Utils::decodeXML(const QString &decodeMe) { QString temp(decodeMe); temp.replace("&", "&"); @@ -172,45 +217,96 @@ QString utils::DecodeXML(const QString &decodeMe) { return temp; } -QString utils::htmlToPlainText(const QString &str) { - QString out; - QTextDocument text; - text.setHtml(str); - out = text.toPlainText(); - text.deleteLater(); - return out.replace("\\\"", "'") - .replace("&", "&") - .replace(">", ">") - .replace("<", "<") - .replace("'", "'"); +/** + * @brief Retrieves the installation type based on the environment variables and + * heuristics. + * + * The method retrieves the value of the "INSTALL_TYPE" environment variable + * using QProcessEnvironment. If the "INSTALL_TYPE" variable is empty, the + * method performs heuristics to determine the installation type. It checks if + * the "SNAP" environment variable is set, in which case the installation type + * is considered as "snap". If the "SNAP" variable is not set, it checks if the + * "FLATPAK_ID" environment variable is not empty, in which case the + * installation type is considered as "flatpak". + * + * @return The installation type as a QString. It can be "snap", "flatpak", or + * an empty string if the installation type could not be determined. + */ +QString Utils::getInstallType() { + QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); + + // Retrieve the value of "INSTALL_TYPE" environment variable + QString installType = env.value("INSTALL_TYPE"); + + // Try guessing if it is empty + if (installType.isEmpty()) { + if (env.contains("SNAP")) { + installType = "snap"; + } else if (env.value("FLATPAK_ID").trimmed().isEmpty() == false) { + installType = "flatpak"; + } + } + + return installType.trimmed(); } -QString utils::appDebugInfo() { +/** + * @brief Retrieves debug information about the application. + * + * The method generates a formatted string containing various debug information + * about the application. It includes information such as the application name, + * version, source branch, commit hash, build datetime, Qt runtime version, Qt + * compiled version, system information, and installation mode. + * + * @return A QString containing the debug information about the application. + */ +QString Utils::appDebugInfo() { + QString installType = Utils::getInstallType(); + installType = + "
  • " + QObject::tr("Install mode") + ": " + + QString(installType.trimmed().isEmpty() ? "Unknown" : installType) + + "
  • "; + + QString applicationName = QApplication::applicationName(); + QString version = QString(VERSIONSTR); + QString sourceBranch = QString(GIT_BRANCH); + QString commitHash = QString(GIT_HASH); + QString buildDatetime = QString::fromLatin1(BUILD_TIMESTAMP); + QString qtRuntimeVersion = QString(qVersion()); + QString qtCompiledVersion = QString(QT_VERSION_STR); + QString systemInfo = QSysInfo::prettyProductName(); + QString architecture = QSysInfo::currentCpuArchitecture(); + QString installMode = Utils::getInstallType(); QStringList debugInfo; - debugInfo << "

    " + QApplication::applicationName() + "

    " + debugInfo << "

    " + applicationName + "

    " << "
      " << "
    • " + QObject::tr("Version") + ": " + - QString(VERSIONSTR) + "
    • " + version + "" << "
    • " + QObject::tr("Source Branch") + ": " + - QString(GIT_BRANCH) + "
    • " + sourceBranch + "" << "
    • " + QObject::tr("Commit Hash") + ": " + - QString(GIT_HASH) + "
    • " + commitHash + "" << "
    • " + QObject::tr("Build Datetime") + ": " + - QString::fromLatin1(BUILD_TIMESTAMP) + "
    • " + buildDatetime + "" << "
    • " + QObject::tr("Qt Runtime Version") + ": " + - QString(qVersion()) + "
    • " + qtRuntimeVersion + "" << "
    • " + QObject::tr("Qt Compiled Version") + ": " + - QString(QT_VERSION_STR) + "
    • " + qtCompiledVersion + "" << "
    • " + QObject::tr("System") + ": " + - QSysInfo::prettyProductName() + "
    • " + systemInfo + "" << "
    • " + QObject::tr("Architecture") + ": " + - QSysInfo::currentCpuArchitecture() + "
    • "; - debugInfo << "
    "; + architecture + "" + << "
  • " + QObject::tr("Install mode") + ": " + + QString(installMode.trimmed().isEmpty() ? "Unknown" + : installMode) + + "
  • " + << ""; + return debugInfo.join("\n"); } -void utils::DisplayExceptionErrorDialog(const QString &error_info) { +void Utils::DisplayExceptionErrorDialog(const QString &error_info) { QMessageBox message_box(QApplication::activeWindow()); message_box.setAttribute(Qt::WA_DeleteOnClose, true); message_box.setWindowFlags(Qt::Window | Qt::WindowStaysOnTopHint); @@ -235,19 +331,31 @@ void utils::DisplayExceptionErrorDialog(const QString &error_info) { << "\nQt Runtime Version: " + QString(qVersion()) << "\nQt Compiled Version: " + QString(QT_VERSION_STR) << "\nSystem: " + QSysInfo::prettyProductName() - << "\nArchitecture: " + QSysInfo::currentCpuArchitecture(); + << "\nArchitecture: " + QSysInfo::currentCpuArchitecture() + << "\nInstall type: " + Utils::getInstallType(); message_box.setDetailedText(detailed_text.join("\n")); message_box.exec(); } -// Returns the same number, but rounded to one decimal place -float utils::RoundToOneDecimal(float number) { +/** + * Returns the same number, but rounded to one decimal place + * + * @brief Utils::RoundToOneDecimal + * @param number + * @return + */ +float Utils::RoundToOneDecimal(float number) { return QString::number(number, 'f', 1).toFloat(); } -// Returns a value for the environment variable name passed; -// if the env var isn't set, it returns an empty string -QString utils::GetEnvironmentVar(const QString &variable_name) { +/** + * Returns a value for the environment variable name passed; + * if the env var isn't set, it returns an empty string + * @brief Utils::GetEnvironmentVar + * @param variable_name + * @return + */ +QString Utils::GetEnvironmentVar(const QString &variable_name) { #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) // The only time this might fall down is on Linux when an // environment variable holds bytedata. Don't use this @@ -261,14 +369,24 @@ QString utils::GetEnvironmentVar(const QString &variable_name) { #endif } -void utils::desktopOpenUrl(const QString &str) { +/** + * @brief Opens the specified URL in the default desktop application. + * + * The method attempts to open the URL using the `xdg-open` command-line tool. + * If the `xdg-open` process fails to start within 1 second, it falls back to + * using `QDesktopServices` to open the URL. If both methods fail, a warning + * message is printed to the console. + * + * @param str The URL to be opened. + */ +void Utils::desktopOpenUrl(const QString &str) { QProcess *xdg_open = new QProcess(0); xdg_open->start("xdg-open", QStringList() << str); if (xdg_open->waitForStarted(1000) == false) { - // try using QdesktopServices + // Try using QDesktopServices bool opened = QDesktopServices::openUrl(QUrl(str)); if (opened == false) { - qWarning() << "failed to open url" << str; + qWarning() << "Failed to open URL:" << str; } } connect(xdg_open, @@ -282,7 +400,7 @@ void utils::desktopOpenUrl(const QString &str) { }); } -bool utils::isPhoneNumber(const QString &phoneNumber) { +bool Utils::isPhoneNumber(const QString &phoneNumber) { const QString phone = "^\\+(((\\d{2}))\\s?)?((\\d{2})|(\\((\\d{2})\\))\\s?)?(" "\\d{3,15})(\\-(\\d{3,15}))?$"; static QRegularExpression reg(phone); diff --git a/src/utils.h b/src/utils.h index c972ba4..76e8043 100644 --- a/src/utils.h +++ b/src/utils.h @@ -17,22 +17,21 @@ #include #include -class utils : public QObject { +class Utils : public QObject { Q_OBJECT public: - utils(QObject *parent = 0); - virtual ~utils(); -public slots: + Utils(QObject *parent = 0); + virtual ~Utils(); + static QString getInstallType(); static QString refreshCacheSize(const QString cache_dir); static bool delete_cache(const QString cache_dir); static QString toCamelCase(const QString &s); static QString generateRandomId(int length); static QString convertSectoDay(qint64 secs); static QString returnPath(QString pathname, QString standardLocation); - static QString EncodeXML(const QString &encodeMe); - static QString DecodeXML(const QString &decodeMe); - static QString htmlToPlainText(const QString &str); + static QString encodeXML(const QString &encodeMe); + static QString decodeXML(const QString &decodeMe); static QString GetEnvironmentVar(const QString &variable_name); static float RoundToOneDecimal(float number); static void DisplayExceptionErrorDialog(const QString &error_info); diff --git a/src/webenginepage.cpp b/src/webenginepage.cpp index c7b7086..7ff4d9c 100644 --- a/src/webenginepage.cpp +++ b/src/webenginepage.cpp @@ -1,9 +1,5 @@ #include "webenginepage.h" -#include -#include -#include - WebEnginePage::WebEnginePage(QWebEngineProfile *profile, QObject *parent) : QWebEnginePage(profile, parent) { @@ -75,8 +71,11 @@ inline QString questionForFeature(QWebEnginePage::Feature feature) { void WebEnginePage::handleFeaturePermissionRequested(const QUrl &securityOrigin, Feature feature) { bool autoPlay = true; - if (settings.value("autoPlayMedia").isValid()) - autoPlay = settings.value("autoPlayMedia", false).toBool(); + if (SettingsManager::instance().settings().value("autoPlayMedia").isValid()) + autoPlay = SettingsManager::instance() + .settings() + .value("autoPlayMedia", false) + .toBool(); if (autoPlay && (feature == QWebEnginePage::MediaVideoCapture || feature == QWebEnginePage::MediaAudioVideoCapture)) { QWebEngineProfile *defProfile = QWebEngineProfile::defaultProfile(); @@ -92,8 +91,11 @@ void WebEnginePage::handleFeaturePermissionRequested(const QUrl &securityOrigin, QString question = questionForFeature(feature).arg(securityOrigin.host()); QString featureStr = QVariant::fromValue(feature).toString(); - settings.beginGroup("permissions"); - if (settings.value(featureStr, false).toBool()) { + SettingsManager::instance().settings().beginGroup("permissions"); + if (SettingsManager::instance() + .settings() + .value(featureStr, false) + .toBool()) { setFeaturePermission( securityOrigin, feature, QWebEnginePage::PermissionPolicy::PermissionGrantedByUser); @@ -104,29 +106,35 @@ void WebEnginePage::handleFeaturePermissionRequested(const QUrl &securityOrigin, setFeaturePermission( securityOrigin, feature, QWebEnginePage::PermissionPolicy::PermissionGrantedByUser); - settings.setValue(featureStr, true); + SettingsManager::instance().settings().setValue(featureStr, true); } else { setFeaturePermission( securityOrigin, feature, QWebEnginePage::PermissionPolicy::PermissionDeniedByUser); - settings.setValue(featureStr, false); + SettingsManager::instance().settings().setValue(featureStr, false); } } - settings.endGroup(); + SettingsManager::instance().settings().endGroup(); } void WebEnginePage::handleLoadFinished(bool ok) { // turn on Notification settings by default - if (settings.value("permissions/Notifications").isValid() == false) { - settings.beginGroup("permissions"); - settings.setValue("Notifications", true); + if (SettingsManager::instance() + .settings() + .value("permissions/Notifications") + .isValid() == false) { + SettingsManager::instance().settings().beginGroup("permissions"); + SettingsManager::instance().settings().setValue("Notifications", true); setFeaturePermission( QUrl("https://web.whatsapp.com/"), QWebEnginePage::Feature::Notifications, QWebEnginePage::PermissionPolicy::PermissionGrantedByUser); - settings.endGroup(); - } else if (settings.value("permissions/Notifications", true).toBool()) { + SettingsManager::instance().settings().endGroup(); + } else if (SettingsManager::instance() + .settings() + .value("permissions/Notifications", true) + .toBool()) { setFeaturePermission( QUrl("https://web.whatsapp.com/"), QWebEnginePage::Feature::Notifications, @@ -159,8 +167,10 @@ QStringList WebEnginePage::chooseFiles(QWebEnginePage::FileSelectionMode mode, } QFileDialog *dialog = new QFileDialog(); - bool usenativeFileDialog = - settings.value("useNativeFileDialog", false).toBool(); + bool usenativeFileDialog = SettingsManager::instance() + .settings() + .value("useNativeFileDialog", false) + .toBool(); if (usenativeFileDialog == false) { dialog->setOption(QFileDialog::DontUseNativeDialog, true); @@ -387,7 +397,10 @@ void WebEnginePage::injectMutationObserver() { } void WebEnginePage::injectFullWidthJavaScript() { - if (!settings.value("fullWidthView", true).toBool()) + if (!SettingsManager::instance() + .settings() + .value("fullWidthView", true) + .toBool()) return; QString js = R"(function updateFullWidthView(element) { diff --git a/src/webenginepage.h b/src/webenginepage.h index d039288..8f05e44 100644 --- a/src/webenginepage.h +++ b/src/webenginepage.h @@ -1,22 +1,22 @@ #ifndef WEBENGINEPAGE_H #define WEBENGINEPAGE_H -#include -#include -#include -#include - #include #include +#include +#include #include #include +#include #include -#include - #include +#include +#include +#include #include +#include -#include +#include "settingsmanager.h" #include "ui_certificateerrordialog.h" #include "ui_passworddialog.h" @@ -26,9 +26,6 @@ class WebEnginePage : public QWebEnginePage { public: WebEnginePage(QWebEngineProfile *profile, QObject *parent = nullptr); -private: - QSettings settings; - protected: bool acceptNavigationRequest(const QUrl &url, QWebEnginePage::NavigationType type, @@ -36,7 +33,7 @@ protected: QWebEnginePage *createWindow(QWebEnginePage::WebWindowType type) override; bool certificateError(const QWebEngineCertificateError &error) override; QStringList chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, - const QStringList &acceptedMimeTypes); + const QStringList &acceptedMimeTypes) override; public slots: void handleFeaturePermissionRequested(const QUrl &securityOrigin, @@ -47,7 +44,7 @@ protected slots: void javaScriptConsoleMessage(WebEnginePage::JavaScriptConsoleMessageLevel level, const QString &message, int lineId, - const QString &sourceId); + const QString &sourceId) override; private slots: void handleAuthenticationRequired(const QUrl &requestUrl, QAuthenticator *auth); diff --git a/src/webview.cpp b/src/webview.cpp index 8029ffd..035fb4b 100644 --- a/src/webview.cpp +++ b/src/webview.cpp @@ -7,8 +7,7 @@ #include WebView::WebView(QWidget *parent, QStringList dictionaries) - : QWebEngineView(parent) { - dictionaries = dictionaries; + : QWebEngineView(parent), m_dictionaries(dictionaries) { QObject *parentMainWindow = this->parent(); while (!parentMainWindow->objectName().contains("MainWindow")) { @@ -99,22 +98,24 @@ void WebView::contextMenuEvent(QContextMenuEvent *event) { spellcheckAction->setCheckable(true); spellcheckAction->setChecked(pageWebengineProfile->isSpellCheckEnabled()); connect(spellcheckAction, &QAction::toggled, this, - [pageWebengineProfile, this](bool toogled) { + [pageWebengineProfile](bool toogled) { pageWebengineProfile->setSpellCheckEnabled(toogled); - settings.setValue("sc_enabled", toogled); + SettingsManager::instance().settings().setValue("sc_enabled", + toogled); }); menu->addAction(spellcheckAction); if (pageWebengineProfile->isSpellCheckEnabled()) { auto subMenu = menu->addMenu(tr("Select Language")); - for (const QString &dict : qAsConst(dictionaries)) { + for (const QString &dict : qAsConst(m_dictionaries)) { auto action = subMenu->addAction(dict); action->setCheckable(true); action->setChecked(languages.contains(dict)); - connect(action, &QAction::triggered, this, [pageWebengineProfile, dict, this]() { - pageWebengineProfile->setSpellCheckLanguages(QStringList() << dict); - settings.setValue("sc_dict", dict); - }); + connect( + action, &QAction::triggered, this, [pageWebengineProfile, dict]() { + pageWebengineProfile->setSpellCheckLanguages(QStringList() << dict); + SettingsManager::instance().settings().setValue("sc_dict", dict); + }); } } connect(menu, &QMenu::aboutToHide, menu, &QObject::deleteLater); diff --git a/src/webview.h b/src/webview.h index e03fa49..058341d 100644 --- a/src/webview.h +++ b/src/webview.h @@ -1,9 +1,10 @@ #ifndef WEBVIEW_H #define WEBVIEW_H -#include -#include #include +#include + +#include "settingsmanager.h" class WebView : public QWebEngineView { Q_OBJECT @@ -13,13 +14,10 @@ public: protected: void contextMenuEvent(QContextMenuEvent *event) override; - -protected slots: - void wheelEvent(QWheelEvent *event); + void wheelEvent(QWheelEvent *event) override; private: - QStringList dictionaries; - QSettings settings; + QStringList m_dictionaries; }; #endif // WEBVIEW_H diff --git a/src/widgets/MoreApps/moreapps.cpp b/src/widgets/MoreApps/moreapps.cpp index b8e8c17..c333751 100644 --- a/src/widgets/MoreApps/moreapps.cpp +++ b/src/widgets/MoreApps/moreapps.cpp @@ -11,6 +11,7 @@ #include #include #include +#include MoreApps::MoreApps(QWidget *parent, QNetworkAccessManager *nam, const QString &publisherName, const QUrl &remoteFilterUrl, @@ -217,7 +218,7 @@ void MoreApps::setRemoteIcon(const QUrl &iconUrl, QLabel *lb) { auto replyBytes = reply->readAll(); QPixmap pixmap; pixmap.loadFromData(replyBytes); - //qDebug() << "after load" << lb->size(); + // qDebug() << "after load" << lb->size(); lb->setPixmap(pixmap.scaled(lb->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); } @@ -239,11 +240,10 @@ void MoreApps::showApps() { qDebug() << "showing apps..."; - std::srand(unsigned(std::time(0))); - // rand generator - auto rand = [](auto i) { return std::rand() % i; }; - // shuffle appList before adding - std::random_shuffle(mAppList.begin(), mAppList.end(), rand); + std::random_device rd; + std::mt19937 rng(rd()); + + std::shuffle(mAppList.begin(), mAppList.end(), rng); auto fallbackIconUrl = QUrl("https://dashboard.snapcraft.io/site_media/appmedia/" @@ -254,7 +254,7 @@ void MoreApps::showApps() { setRemoteIcon(fallbackIconUrl, nullptr); foreach (auto a, mAppList) { auto iconUrl = a.getIconUrl(); - //qDebug() << "pre-caching icon for" << a.getName(); + // qDebug() << "pre-caching icon for" << a.getName(); setRemoteIcon(iconUrl, nullptr); } } diff --git a/src/widgets/scrolltext/scrolltext.cpp b/src/widgets/scrolltext/scrolltext.cpp index b03b761..cac212f 100644 --- a/src/widgets/scrolltext/scrolltext.cpp +++ b/src/widgets/scrolltext/scrolltext.cpp @@ -15,7 +15,7 @@ ScrollText::ScrollText(QWidget *parent) : QWidget(parent), scrollPos(0) { setSeparator(" "); - connect(&timer, SIGNAL(timeout()), this, SLOT(timer_timeout())); + connect(&timer, &QTimer::timeout, this, &ScrollText::timer_timeout); timer.setInterval(50); } -- cgit v1.2.3