mirror of
https://github.com/tnodir/fort
synced 2024-11-15 14:16:30 +00:00
UI: Add (un)locking of password.
This commit is contained in:
parent
1d4ae8ac91
commit
7ef6df2307
@ -1,4 +1,4 @@
|
||||
INCLUDEPATH *= $$PWD
|
||||
|
||||
# Windows
|
||||
LIBS *= -lfwpuclnt -ladvapi32 -lkernel32 -luser32 -luuid -lversion -lws2_32
|
||||
LIBS *= -lfwpuclnt -ladvapi32 -lkernel32 -luser32 -luuid -lversion -lws2_32 -lwtsapi32
|
||||
|
@ -76,17 +76,24 @@ QPushButton *ControlUtil::createLinkButton(
|
||||
return c;
|
||||
}
|
||||
|
||||
QPushButton *ControlUtil::createSplitterButton(
|
||||
QPushButton *ControlUtil::createFlatButton(
|
||||
const QString &iconPath, const std::function<void()> &onClicked)
|
||||
{
|
||||
auto c = createButton(iconPath, onClicked);
|
||||
c->setFixedSize(32, 32);
|
||||
c->setFlat(true);
|
||||
c->setCursor(Qt::PointingHandCursor);
|
||||
c->setFocusPolicy(Qt::NoFocus);
|
||||
return c;
|
||||
}
|
||||
|
||||
QPushButton *ControlUtil::createSplitterButton(
|
||||
const QString &iconPath, const std::function<void()> &onClicked)
|
||||
{
|
||||
auto c = createFlatButton(iconPath, onClicked);
|
||||
c->setFixedSize(32, 32);
|
||||
return c;
|
||||
}
|
||||
|
||||
QLabel *ControlUtil::createLabel(const QString &text)
|
||||
{
|
||||
auto c = new QLabel(text);
|
||||
|
@ -31,6 +31,8 @@ public:
|
||||
const QString &iconPath, const std::function<void()> &onClicked);
|
||||
static QPushButton *createLinkButton(const QString &iconPath,
|
||||
const QString &linkPath = QString(), const QString &toolTip = QString());
|
||||
static QPushButton *createFlatButton(
|
||||
const QString &iconPath, const std::function<void()> &onClicked);
|
||||
static QPushButton *createSplitterButton(
|
||||
const QString &iconPath, const std::function<void()> &onClicked);
|
||||
static QLabel *createLabel(const QString &text = QString());
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "passworddialog.h"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
@ -19,12 +20,24 @@ void PasswordDialog::retranslateUi()
|
||||
{
|
||||
m_labelPassword->setText(tr("Please enter the password:"));
|
||||
|
||||
m_labelUnlock->setText(tr("Unlock till:"));
|
||||
retranslateComboUnlock();
|
||||
|
||||
m_buttonBox->button(QDialogButtonBox::Ok)->setText(tr("OK"));
|
||||
m_buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Cancel"));
|
||||
|
||||
this->setWindowTitle(tr("Password input"));
|
||||
}
|
||||
|
||||
void PasswordDialog::retranslateComboUnlock()
|
||||
{
|
||||
const QStringList list = { tr("Disabled"), tr("Session lockout"), tr("Program exit") };
|
||||
|
||||
m_comboUnlock->clear();
|
||||
m_comboUnlock->addItems(list);
|
||||
m_comboUnlock->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void PasswordDialog::setupUi()
|
||||
{
|
||||
// Password Row
|
||||
@ -33,9 +46,13 @@ void PasswordDialog::setupUi()
|
||||
// Button Box
|
||||
setupButtonBox();
|
||||
|
||||
// Unlock Row
|
||||
auto unlockLayout = setupUnlockLayout();
|
||||
|
||||
// Main layout
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->addLayout(passwordLayout);
|
||||
layout->addLayout(unlockLayout);
|
||||
layout->addStretch();
|
||||
layout->addWidget(ControlUtil::createSeparator());
|
||||
layout->addWidget(m_buttonBox);
|
||||
@ -64,6 +81,22 @@ QLayout *PasswordDialog::setupPasswordLayout()
|
||||
return layout;
|
||||
}
|
||||
|
||||
QLayout *PasswordDialog::setupUnlockLayout()
|
||||
{
|
||||
auto layout = new QHBoxLayout();
|
||||
layout->setSpacing(6);
|
||||
|
||||
m_labelUnlock = ControlUtil::createLabel();
|
||||
|
||||
m_comboUnlock = new QComboBox();
|
||||
m_comboUnlock->setMinimumWidth(150);
|
||||
|
||||
layout->addWidget(m_labelUnlock);
|
||||
layout->addWidget(m_comboUnlock);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
void PasswordDialog::setupButtonBox()
|
||||
{
|
||||
m_buttonBox =
|
||||
@ -72,8 +105,13 @@ void PasswordDialog::setupButtonBox()
|
||||
QObject::connect(m_buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
|
||||
}
|
||||
|
||||
QString PasswordDialog::getPassword(QWidget *parent)
|
||||
bool PasswordDialog::getPassword(QString &password, UnlockType &unlock, QWidget *parent)
|
||||
{
|
||||
PasswordDialog dialog(parent);
|
||||
return dialog.exec() == 1 ? dialog.m_editPassword->text() : QString();
|
||||
if (dialog.exec() == 0)
|
||||
return false;
|
||||
|
||||
password = dialog.m_editPassword->text();
|
||||
unlock = static_cast<UnlockType>(dialog.m_comboUnlock->currentIndex());
|
||||
return true;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QComboBox)
|
||||
QT_FORWARD_DECLARE_CLASS(QDialogButtonBox)
|
||||
QT_FORWARD_DECLARE_CLASS(QLabel)
|
||||
QT_FORWARD_DECLARE_CLASS(QLineEdit)
|
||||
@ -12,21 +13,31 @@ class PasswordDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum UnlockType {
|
||||
UnlockDisabled = 0,
|
||||
UnlockTillSessionLock,
|
||||
UnlockTillAppExit,
|
||||
};
|
||||
|
||||
explicit PasswordDialog(QWidget *parent = nullptr);
|
||||
|
||||
static QString getPassword(QWidget *parent = nullptr);
|
||||
static bool getPassword(QString &password, UnlockType &unlock, QWidget *parent = nullptr);
|
||||
|
||||
private:
|
||||
void retranslateUi();
|
||||
void retranslateComboUnlock();
|
||||
|
||||
void setupUi();
|
||||
QLayout *setupPasswordLayout();
|
||||
QLayout *setupUnlockLayout();
|
||||
void setupButtonBox();
|
||||
|
||||
private:
|
||||
QLabel *m_labelPassword = nullptr;
|
||||
QLineEdit *m_editPassword = nullptr;
|
||||
QDialogButtonBox *m_buttonBox = nullptr;
|
||||
QLabel *m_labelUnlock = nullptr;
|
||||
QComboBox *m_comboUnlock = nullptr;
|
||||
};
|
||||
|
||||
#endif // PASSWORDDIALOG_H
|
||||
|
@ -70,9 +70,11 @@ void OptionsPage::onSaved()
|
||||
const auto password = m_editPassword->text();
|
||||
settings()->setPasswordHash(StringUtil::cryptoHash(password));
|
||||
m_editPassword->clear();
|
||||
}
|
||||
|
||||
settings()->setPasswordCheckOnce(m_cbPasswordCheckOnce->isChecked());
|
||||
if (password.isEmpty() && m_btPasswordLock->isVisible()) {
|
||||
m_btPasswordLock->click(); // Reset unlocked password
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsPage::onRetranslateUi()
|
||||
@ -98,7 +100,7 @@ void OptionsPage::onRetranslateUi()
|
||||
|
||||
m_cbPassword->setText(tr("Password:"));
|
||||
retranslateEditPassword();
|
||||
m_cbPasswordCheckOnce->setText(tr("Check password only once"));
|
||||
m_btPasswordLock->setText(tr("Lock the password"));
|
||||
|
||||
m_labelLanguage->setText(tr("Language:"));
|
||||
|
||||
@ -277,7 +279,7 @@ void OptionsPage::setupGlobalBox()
|
||||
auto layout = new QVBoxLayout();
|
||||
layout->addWidget(m_cbHotKeys);
|
||||
layout->addLayout(passwordLayout);
|
||||
layout->addWidget(m_cbPasswordCheckOnce);
|
||||
layout->addWidget(m_btPasswordLock);
|
||||
layout->addLayout(langLayout);
|
||||
|
||||
m_gbGlobal = new QGroupBox(this);
|
||||
@ -297,8 +299,11 @@ QLayout *OptionsPage::setupPasswordLayout()
|
||||
|
||||
setIniEdited(true);
|
||||
});
|
||||
m_cbPasswordCheckOnce = ControlUtil::createCheckBox(
|
||||
settings()->passwordCheckOnce(), [&](bool) { setIniEdited(true); });
|
||||
|
||||
m_btPasswordLock = ControlUtil::createFlatButton(":/icons/lock-open.png", [&] {
|
||||
settings()->resetCheckedPassword();
|
||||
m_btPasswordLock->hide();
|
||||
});
|
||||
|
||||
setupEditPassword();
|
||||
|
||||
@ -316,10 +321,12 @@ void OptionsPage::setupEditPassword()
|
||||
m_editPassword->setFixedWidth(200);
|
||||
|
||||
const auto refreshEditPassword = [&] {
|
||||
m_editPassword->setReadOnly(settings()->hasPassword() || !m_cbPassword->isChecked());
|
||||
const bool hasPassword = settings()->hasPassword();
|
||||
|
||||
m_editPassword->setReadOnly(hasPassword || !m_cbPassword->isChecked());
|
||||
retranslateEditPassword();
|
||||
|
||||
m_cbPasswordCheckOnce->setEnabled(m_cbPassword->isChecked());
|
||||
m_btPasswordLock->setVisible(hasPassword && !settings()->isPasswordRequired());
|
||||
};
|
||||
|
||||
refreshEditPassword();
|
||||
|
@ -60,7 +60,7 @@ private:
|
||||
QCheckBox *m_cbHotKeys = nullptr;
|
||||
QCheckBox *m_cbPassword = nullptr;
|
||||
QLineEdit *m_editPassword = nullptr;
|
||||
QCheckBox *m_cbPasswordCheckOnce = nullptr;
|
||||
QPushButton *m_btPasswordLock = nullptr;
|
||||
QLabel *m_labelLanguage = nullptr;
|
||||
QComboBox *m_comboLanguage = nullptr;
|
||||
QLabel *m_iconDriver = nullptr;
|
||||
|
@ -19,6 +19,7 @@
|
||||
<file>icons/home.png</file>
|
||||
<file>icons/key.png</file>
|
||||
<file>icons/line-graph.png</file>
|
||||
<file>icons/lock-open.png</file>
|
||||
<file>icons/map-map-marker.png</file>
|
||||
<file>icons/map-marker.png</file>
|
||||
<file>icons/pencil.png</file>
|
||||
|
@ -56,23 +56,17 @@
|
||||
#include "util/window/widgetwindowstatewatcher.h"
|
||||
|
||||
FortManager::FortManager(FortSettings *settings, EnvManager *envManager, QObject *parent) :
|
||||
QObject(parent),
|
||||
m_trayTriggered(false),
|
||||
m_passwordChecked(false),
|
||||
m_settings(settings),
|
||||
m_envManager(envManager)
|
||||
QObject(parent), m_trayTriggered(false), m_settings(settings), m_envManager(envManager)
|
||||
{
|
||||
}
|
||||
|
||||
FortManager::~FortManager()
|
||||
{
|
||||
closeEventFilter();
|
||||
closeMainWindow();
|
||||
|
||||
closeDriver();
|
||||
closeLogManager();
|
||||
|
||||
delete m_mainWindow;
|
||||
|
||||
OsUtil::closeMutex(m_instanceMutex);
|
||||
}
|
||||
|
||||
@ -234,12 +228,6 @@ void FortManager::setupEventFilter()
|
||||
m_nativeEventFilter = new NativeEventFilter(this);
|
||||
}
|
||||
|
||||
void FortManager::closeEventFilter()
|
||||
{
|
||||
m_nativeEventFilter->unregisterHotKeys();
|
||||
m_nativeEventFilter->unregisterSessionNotification();
|
||||
}
|
||||
|
||||
void FortManager::setupEnvManager()
|
||||
{
|
||||
connect(m_nativeEventFilter, &NativeEventFilter::environmentChanged, envManager(),
|
||||
@ -284,6 +272,22 @@ void FortManager::setupTaskManager()
|
||||
void FortManager::setupMainWindow()
|
||||
{
|
||||
m_mainWindow = new MainWindow();
|
||||
|
||||
m_nativeEventFilter->registerSessionNotification(m_mainWindow->winId());
|
||||
|
||||
connect(m_nativeEventFilter, &NativeEventFilter::sessionLocked, this,
|
||||
[&] { settings()->resetCheckedPassword(PasswordDialog::UnlockTillSessionLock); });
|
||||
}
|
||||
|
||||
void FortManager::closeMainWindow()
|
||||
{
|
||||
if (!m_mainWindow)
|
||||
return;
|
||||
|
||||
m_nativeEventFilter->unregisterHotKeys();
|
||||
m_nativeEventFilter->unregisterSessionNotification(m_mainWindow->winId());
|
||||
|
||||
delete m_mainWindow;
|
||||
}
|
||||
|
||||
void FortManager::setupHotKeyManager()
|
||||
@ -616,7 +620,7 @@ bool FortManager::checkPassword()
|
||||
{
|
||||
static bool g_passwordDialogOpened = false;
|
||||
|
||||
if (!isPasswordRequired())
|
||||
if (!settings()->isPasswordRequired())
|
||||
return true;
|
||||
|
||||
if (g_passwordDialogOpened) {
|
||||
@ -629,18 +633,18 @@ bool FortManager::checkPassword()
|
||||
|
||||
g_passwordDialogOpened = true;
|
||||
|
||||
const QString password = PasswordDialog::getPassword(m_mainWindow);
|
||||
QString password;
|
||||
PasswordDialog::UnlockType unlocked = PasswordDialog::UnlockDisabled;
|
||||
const bool ok = PasswordDialog::getPassword(password, unlocked, m_mainWindow);
|
||||
|
||||
g_passwordDialogOpened = false;
|
||||
|
||||
m_passwordChecked =
|
||||
!password.isEmpty() && StringUtil::cryptoHash(password) == settings()->passwordHash();
|
||||
return m_passwordChecked;
|
||||
}
|
||||
const bool checked = ok && !password.isEmpty()
|
||||
&& StringUtil::cryptoHash(password) == settings()->passwordHash();
|
||||
|
||||
bool FortManager::isPasswordRequired()
|
||||
{
|
||||
return settings()->hasPassword() && !(settings()->passwordCheckOnce() && m_passwordChecked);
|
||||
settings()->setPasswordChecked(checked, checked ? unlocked : PasswordDialog::UnlockDisabled);
|
||||
|
||||
return checked;
|
||||
}
|
||||
|
||||
void FortManager::showErrorBox(const QString &text, const QString &title)
|
||||
@ -944,7 +948,7 @@ void FortManager::createTrayMenu()
|
||||
|
||||
void FortManager::updateTrayMenuFlags()
|
||||
{
|
||||
const bool editEnabled = (!isPasswordRequired() && !m_optWindow);
|
||||
const bool editEnabled = (!settings()->isPasswordRequired() && !m_optWindow);
|
||||
|
||||
m_filterEnabledAction->setEnabled(editEnabled);
|
||||
m_stopTrafficAction->setEnabled(editEnabled);
|
||||
|
@ -114,7 +114,6 @@ public slots:
|
||||
void quitByCheckPassword();
|
||||
|
||||
bool checkPassword();
|
||||
bool isPasswordRequired();
|
||||
|
||||
void showErrorBox(const QString &text, const QString &title = QString());
|
||||
void showInfoBox(const QString &text, const QString &title = QString());
|
||||
@ -146,8 +145,6 @@ private:
|
||||
void closeLogManager();
|
||||
|
||||
void setupEventFilter();
|
||||
void closeEventFilter();
|
||||
|
||||
void setupEnvManager();
|
||||
void setupStatManager();
|
||||
void setupConfManager();
|
||||
@ -156,6 +153,8 @@ private:
|
||||
void setupTaskManager();
|
||||
|
||||
void setupMainWindow();
|
||||
void closeMainWindow();
|
||||
|
||||
void setupHotKeyManager();
|
||||
void setupTrayIcon();
|
||||
|
||||
@ -214,7 +213,6 @@ private:
|
||||
|
||||
private:
|
||||
bool m_trayTriggered : 1;
|
||||
bool m_passwordChecked : 1;
|
||||
|
||||
TrayMessageType m_lastMessageType = MessageOptions;
|
||||
|
||||
|
@ -35,6 +35,8 @@ FortSettings::FortSettings(QObject *parent) :
|
||||
m_isService(false),
|
||||
m_hasService(false),
|
||||
m_isWindowControl(false),
|
||||
m_passwordChecked(false),
|
||||
m_passwordUnlocked(0),
|
||||
m_bulkUpdating(false),
|
||||
m_bulkIniChanged(false)
|
||||
{
|
||||
@ -223,6 +225,30 @@ QString FortSettings::confFilePath() const
|
||||
return profilePath() + (APP_BASE ".config");
|
||||
}
|
||||
|
||||
void FortSettings::setPasswordChecked(bool checked, bool unlocked)
|
||||
{
|
||||
if (m_passwordChecked == checked)
|
||||
return;
|
||||
|
||||
m_passwordChecked = checked;
|
||||
m_passwordUnlocked = unlocked;
|
||||
|
||||
emit iniChanged();
|
||||
}
|
||||
|
||||
void FortSettings::resetCheckedPassword(int unlocked)
|
||||
{
|
||||
if (unlocked != 0 && unlocked != m_passwordUnlocked)
|
||||
return;
|
||||
|
||||
setPasswordChecked(false, 0);
|
||||
}
|
||||
|
||||
bool FortSettings::isPasswordRequired()
|
||||
{
|
||||
return hasPassword() && !(m_passwordUnlocked != 0 && m_passwordChecked);
|
||||
}
|
||||
|
||||
void FortSettings::readConfIni(FirewallConf &conf) const
|
||||
{
|
||||
m_ini->beginGroup("confFlags");
|
||||
|
@ -33,9 +33,6 @@ public:
|
||||
QString passwordHash() const { return iniText("base/passwordHash"); }
|
||||
void setPasswordHash(const QString &v) { setIniValue("base/passwordHash", v); }
|
||||
|
||||
bool passwordCheckOnce() const { return iniBool("base/passwordCheckOnce"); }
|
||||
void setPasswordCheckOnce(bool on) { setIniValue("base/passwordCheckOnce", on); }
|
||||
|
||||
QString appUpdatesUrl() const;
|
||||
int appVersion() const;
|
||||
|
||||
@ -225,6 +222,13 @@ public:
|
||||
|
||||
QString errorMessage() const { return m_errorMessage; }
|
||||
|
||||
bool passwordChecked() const { return m_passwordChecked; }
|
||||
bool passwordUnlocked() const { return m_passwordUnlocked; }
|
||||
void setPasswordChecked(bool checked, bool unlocked);
|
||||
|
||||
void resetCheckedPassword(int unlocked = 0);
|
||||
bool isPasswordRequired();
|
||||
|
||||
bool confMigrated() const;
|
||||
bool confCanMigrate(QString &viaVersion) const;
|
||||
|
||||
@ -280,14 +284,17 @@ private:
|
||||
static QString startupShortcutPath();
|
||||
|
||||
private:
|
||||
bool m_iniExists : 1;
|
||||
bool m_noCache : 1;
|
||||
bool m_isService : 1;
|
||||
bool m_hasService : 1;
|
||||
bool m_isWindowControl : 1;
|
||||
uint m_iniExists : 1;
|
||||
uint m_noCache : 1;
|
||||
uint m_isService : 1;
|
||||
uint m_hasService : 1;
|
||||
uint m_isWindowControl : 1;
|
||||
|
||||
bool m_bulkUpdating : 1;
|
||||
bool m_bulkIniChanged : 1;
|
||||
uint m_passwordChecked : 1;
|
||||
uint m_passwordUnlocked : 3;
|
||||
|
||||
uint m_bulkUpdating : 1;
|
||||
uint m_bulkIniChanged : 1;
|
||||
|
||||
QString m_defaultLanguage;
|
||||
QString m_profilePath;
|
||||
|
BIN
src/ui/icons/lock-open.png
Normal file
BIN
src/ui/icons/lock-open.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 657 B |
@ -4,6 +4,7 @@
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <qt_windows.h>
|
||||
#include <wtsapi32.h>
|
||||
|
||||
NativeEventFilter::NativeEventFilter(QObject *parent) : QObject(parent)
|
||||
{
|
||||
@ -56,6 +57,16 @@ void NativeEventFilter::unregisterHotKeys()
|
||||
m_keyIdMap.clear();
|
||||
}
|
||||
|
||||
bool NativeEventFilter::registerSessionNotification(quintptr winId)
|
||||
{
|
||||
return WTSRegisterSessionNotification((HWND) winId, NOTIFY_FOR_THIS_SESSION);
|
||||
}
|
||||
|
||||
void NativeEventFilter::unregisterSessionNotification(quintptr winId)
|
||||
{
|
||||
WTSUnRegisterSessionNotification((HWND) winId);
|
||||
}
|
||||
|
||||
void NativeEventFilter::setKeyId(int hotKeyId, quint32 nativeMod, quint32 nativeKey)
|
||||
{
|
||||
const quint32 nativeKeyMod = nativeMod | (nativeKey << 16);
|
||||
@ -103,6 +114,11 @@ bool NativeEventFilter::nativeEventFilter(const QByteArray &eventType, void *mes
|
||||
emit environmentChanged();
|
||||
}
|
||||
} break;
|
||||
case WM_WTSSESSION_CHANGE: {
|
||||
if (msg->wParam == WTS_SESSION_LOCK) {
|
||||
emit sessionLocked();
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -29,9 +29,13 @@ public:
|
||||
void unregisterHotKey(int hotKeyId);
|
||||
void unregisterHotKeys();
|
||||
|
||||
bool registerSessionNotification(quintptr winId);
|
||||
void unregisterSessionNotification(quintptr winId);
|
||||
|
||||
signals:
|
||||
void hotKeyPressed(int hotKeyId);
|
||||
void environmentChanged();
|
||||
void sessionLocked();
|
||||
|
||||
public slots:
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user