Introduce View Menu

* Move user interface settings from the settings widget into the view menu.
* Add auto-restart prompt to make theme changes easy
This commit is contained in:
Jonathan White 2020-06-28 10:01:24 -04:00
parent 1dd758c66a
commit 4bf6d8d94d
10 changed files with 206 additions and 137 deletions

View File

@ -315,3 +315,15 @@ bool Application::isDarkTheme() const
{
return m_darkTheme;
}
void Application::restart()
{
// Disable single instance
m_lockServer.close();
if (m_lockFile) {
m_lockFile->unlock();
delete m_lockFile;
}
exit(RESTART_EXITCODE);
}

View File

@ -31,6 +31,8 @@ class OSEventFilter;
class QLockFile;
class QSocketNotifier;
constexpr int RESTART_EXITCODE = -1;
class Application : public QApplication
{
Q_OBJECT
@ -47,6 +49,8 @@ public:
bool sendFileNamesToRunningInstance(const QStringList& fileNames);
void restart();
signals:
void openFile(const QString& filename);
void anotherInstanceStarted();

View File

@ -106,7 +106,6 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent)
connect(m_generalUi->autoSaveAfterEveryChangeCheckBox, SIGNAL(toggled(bool)), SLOT(autoSaveToggled(bool)));
connect(m_generalUi->hideWindowOnCopyCheckBox, SIGNAL(toggled(bool)), SLOT(hideWindowOnCopyCheckBoxToggled(bool)));
connect(m_generalUi->systrayShowCheckBox, SIGNAL(toggled(bool)), SLOT(systrayToggled(bool)));
connect(m_generalUi->toolbarHideCheckBox, SIGNAL(toggled(bool)), SLOT(toolbarSettingsToggled(bool)));
connect(m_generalUi->rememberLastDatabasesCheckBox, SIGNAL(toggled(bool)), SLOT(rememberDatabasesToggled(bool)));
connect(m_generalUi->resetSettingsButton, SIGNAL(clicked()), SLOT(resetSettings()));
@ -126,7 +125,6 @@ ApplicationSettingsWidget::ApplicationSettingsWidget(QWidget* parent)
m_generalUi->faviconTimeoutSpinBox->installEventFilter(mouseWheelFilter);
m_generalUi->toolButtonStyleComboBox->installEventFilter(mouseWheelFilter);
m_generalUi->languageComboBox->installEventFilter(mouseWheelFilter);
m_generalUi->appThemeSelection->installEventFilter(mouseWheelFilter);
#ifdef WITH_XC_UPDATECHECK
connect(m_generalUi->checkForUpdatesOnStartupCheckBox, SIGNAL(toggled(bool)), SLOT(checkUpdatesToggled(bool)));
@ -210,20 +208,9 @@ void ApplicationSettingsWidget::loadSettings()
m_generalUi->languageComboBox->setCurrentIndex(defaultIndex);
}
m_generalUi->previewHideCheckBox->setChecked(config()->get(Config::GUI_HidePreviewPanel).toBool());
m_generalUi->toolbarHideCheckBox->setChecked(config()->get(Config::GUI_HideToolbar).toBool());
toolbarSettingsToggled(m_generalUi->toolbarHideCheckBox->isChecked());
m_generalUi->toolbarMovableCheckBox->setChecked(config()->get(Config::GUI_MovableToolbar).toBool());
m_generalUi->monospaceNotesCheckBox->setChecked(config()->get(Config::GUI_MonospaceNotes).toBool());
m_generalUi->appThemeSelection->clear();
m_generalUi->appThemeSelection->addItem(tr("Automatic"), "auto");
m_generalUi->appThemeSelection->addItem(tr("Light"), "light");
m_generalUi->appThemeSelection->addItem(tr("Dark"), "dark");
m_generalUi->appThemeSelection->addItem(tr("Classic (Platform-native)"), "classic");
m_generalUi->appThemeSelection->setCurrentIndex(
m_generalUi->appThemeSelection->findData(config()->get(Config::GUI_ApplicationTheme).toString()));
m_generalUi->toolButtonStyleComboBox->clear();
m_generalUi->toolButtonStyleComboBox->addItem(tr("Icon only"), Qt::ToolButtonIconOnly);
m_generalUi->toolButtonStyleComboBox->addItem(tr("Text only"), Qt::ToolButtonTextOnly);
@ -338,14 +325,9 @@ void ApplicationSettingsWidget::saveSettings()
config()->set(Config::FaviconDownloadTimeout, m_generalUi->faviconTimeoutSpinBox->value());
config()->set(Config::GUI_Language, m_generalUi->languageComboBox->currentData().toString());
config()->set(Config::GUI_HidePreviewPanel, m_generalUi->previewHideCheckBox->isChecked());
config()->set(Config::GUI_HideToolbar, m_generalUi->toolbarHideCheckBox->isChecked());
config()->set(Config::GUI_MovableToolbar, m_generalUi->toolbarMovableCheckBox->isChecked());
config()->set(Config::GUI_MonospaceNotes, m_generalUi->monospaceNotesCheckBox->isChecked());
QString theme = m_generalUi->appThemeSelection->currentData().toString();
config()->set(Config::GUI_ApplicationTheme, theme);
config()->set(Config::GUI_ToolButtonStyle, m_generalUi->toolButtonStyleComboBox->currentData().toString());
config()->set(Config::GUI_ShowTrayIcon, m_generalUi->systrayShowCheckBox->isChecked());
@ -481,13 +463,6 @@ void ApplicationSettingsWidget::systrayToggled(bool checked)
m_generalUi->systrayMinimizeToTrayCheckBox->setEnabled(checked);
}
void ApplicationSettingsWidget::toolbarSettingsToggled(bool checked)
{
m_generalUi->toolbarMovableCheckBox->setEnabled(!checked);
m_generalUi->toolButtonStyleComboBox->setEnabled(!checked);
m_generalUi->toolButtonStyleLabel->setEnabled(!checked);
}
void ApplicationSettingsWidget::rememberDatabasesToggled(bool checked)
{
if (!checked) {

View File

@ -60,7 +60,6 @@ private slots:
void autoSaveToggled(bool checked);
void hideWindowOnCopyCheckBoxToggled(bool checked);
void systrayToggled(bool checked);
void toolbarSettingsToggled(bool checked);
void rememberDatabasesToggled(bool checked);
void checkUpdatesToggled(bool checked);

View File

@ -307,13 +307,6 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="previewHideCheckBox">
<property name="text">
<string>Hide the entry preview panel</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="minimizeOnOpenUrlCheckBox">
<property name="text">
@ -460,8 +453,8 @@
<property name="horizontalSpacing">
<number>10</number>
</property>
<item row="0" column="1">
<widget class="QComboBox" name="appThemeSelection">
<item row="1" column="1">
<widget class="QComboBox" name="toolButtonStyleComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
@ -472,51 +465,30 @@
<enum>Qt::StrongFocus</enum>
</property>
<property name="accessibleName">
<string>Application Theme Selection</string>
<string>Toolbar button style</string>
</property>
</widget>
</item>
<item row="0" column="3">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label">
<property name="text">
<string>(restart program to activate)</string>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="languageLabel_3">
<widget class="QCheckBox" name="toolbarMovableCheckBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>(restart program to activate)</string>
<string>Movable toolbar</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="appThemeLabel">
<property name="text">
<string>Application theme:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>appThemeSelection</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="0" column="1">
<widget class="QComboBox" name="languageComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
@ -532,7 +504,7 @@
</property>
</widget>
</item>
<item row="1" column="0">
<item row="0" column="0">
<widget class="QLabel" name="languageLabel_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
@ -551,7 +523,27 @@
</property>
</widget>
</item>
<item row="2" column="0">
<item row="0" column="2">
<widget class="QLabel" name="languageLabel_3">
<property name="text">
<string>(restart program to activate)</string>
</property>
</widget>
</item>
<item row="0" column="3">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<widget class="QLabel" name="toolButtonStyleLabel">
<property name="enabled">
<bool>true</bool>
@ -576,66 +568,8 @@
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="toolButtonStyleComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="focusPolicy">
<enum>Qt::StrongFocus</enum>
</property>
<property name="accessibleName">
<string>Toolbar button style</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="toolbarHideCheckBox">
<property name="text">
<string>Hide toolbar</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="toolbarMovableCheckBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Movable toolbar</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="monospaceNotesCheckBox">
<property name="text">
@ -1102,20 +1036,18 @@
<tabstop>autoReloadOnChangeCheckBox</tabstop>
<tabstop>useAtomicSavesCheckBox</tabstop>
<tabstop>useGroupIconOnEntryCreationCheckBox</tabstop>
<tabstop>previewHideCheckBox</tabstop>
<tabstop>minimizeOnOpenUrlCheckBox</tabstop>
<tabstop>hideWindowOnCopyCheckBox</tabstop>
<tabstop>minimizeOnCopyRadioButton</tabstop>
<tabstop>dropToBackgroundOnCopyRadioButton</tabstop>
<tabstop>faviconTimeoutSpinBox</tabstop>
<tabstop>appThemeSelection</tabstop>
<tabstop>languageComboBox</tabstop>
<tabstop>toolButtonStyleComboBox</tabstop>
<tabstop>toolbarHideCheckBox</tabstop>
<tabstop>toolbarMovableCheckBox</tabstop>
<tabstop>monospaceNotesCheckBox</tabstop>
<tabstop>toolbarMovableCheckBox</tabstop>
<tabstop>minimizeOnCloseCheckBox</tabstop>
<tabstop>systrayShowCheckBox</tabstop>
<tabstop>trayIconAppearance</tabstop>
<tabstop>systrayMinimizeToTrayCheckBox</tabstop>
<tabstop>resetSettingsButton</tabstop>
<tabstop>autoTypeEntryTitleMatchCheckBox</tabstop>

View File

@ -77,6 +77,12 @@ EntryPreviewWidget::EntryPreviewWidget(QWidget* parent)
connect(m_ui->entryTabWidget, SIGNAL(tabBarClicked(int)), SLOT(updateTabIndexes()), Qt::QueuedConnection);
connect(&m_totpTimer, SIGNAL(timeout()), SLOT(updateTotpLabel()));
connect(config(), &Config::changed, this, [this](Config::ConfigKey key) {
if (key == Config::GUI_HidePreviewPanel) {
setVisible(!config()->get(Config::GUI_HidePreviewPanel).toBool());
}
});
// Group
m_ui->groupCloseButton->setIcon(resources()->icon("dialog-close"));
connect(m_ui->groupCloseButton, SIGNAL(clicked()), SLOT(hide()));

View File

@ -37,6 +37,7 @@
#include "core/Tools.h"
#include "gui/AboutDialog.h"
#include "gui/DatabaseWidget.h"
#include "gui/MessageBox.h"
#include "gui/SearchWidget.h"
#include "keys/CompositeKey.h"
#include "keys/FileKey.h"
@ -50,7 +51,6 @@
#endif
#ifdef WITH_XC_UPDATECHECK
#include "gui/MessageBox.h"
#include "gui/UpdateCheckDialog.h"
#include "updatecheck/UpdateChecker.h"
#endif
@ -167,6 +167,8 @@ MainWindow::MainWindow()
m_ui->actionEntryAddToAgent->setVisible(false);
m_ui->actionEntryRemoveFromAgent->setVisible(false);
initViewMenu();
#if defined(WITH_XC_KEESHARE)
KeeShare::init(this);
m_ui->settingsWidget->addSettingsPage(new SettingsPageKeeShare(m_ui->tabWidget));
@ -1132,11 +1134,12 @@ void MainWindow::closeEvent(QCloseEvent* event)
if (m_appExiting) {
saveWindowInformation();
event->accept();
QApplication::quit();
m_restartRequested ? kpxcApp->restart() : QApplication::quit();
return;
}
m_appExitCalled = false;
m_restartRequested = false;
event->ignore();
}
@ -1639,3 +1642,56 @@ void MainWindow::displayDesktopNotification(const QString& msg, QString title, i
m_trayIcon->showMessage(title, msg, QSystemTrayIcon::Information, msTimeoutHint);
#endif
}
void MainWindow::restartApp(const QString& message)
{
auto ans = MessageBox::question(
this, tr("Restart Application?"), message, MessageBox::Yes | MessageBox::No, MessageBox::Yes);
if (ans == MessageBox::Yes) {
m_appExitCalled = true;
m_restartRequested = true;
close();
} else {
m_restartRequested = false;
}
}
void MainWindow::initViewMenu()
{
m_ui->actionThemeAuto->setData("auto");
m_ui->actionThemeLight->setData("light");
m_ui->actionThemeDark->setData("dark");
m_ui->actionThemeClassic->setData("classic");
auto themeActions = new QActionGroup(this);
themeActions->addAction(m_ui->actionThemeAuto);
themeActions->addAction(m_ui->actionThemeLight);
themeActions->addAction(m_ui->actionThemeDark);
themeActions->addAction(m_ui->actionThemeClassic);
auto theme = config()->get(Config::GUI_ApplicationTheme).toString();
for (auto action : themeActions->actions()) {
if (action->data() == theme) {
action->setChecked(true);
break;
}
}
connect(themeActions, &QActionGroup::triggered, this, [this](QAction* action) {
if (action->data() != config()->get(Config::GUI_ApplicationTheme)) {
config()->set(Config::GUI_ApplicationTheme, action->data());
restartApp(tr("You must restart the application to apply this setting. Would you like to restart now?"));
}
});
m_ui->actionShowToolbar->setChecked(!config()->get(Config::GUI_HideToolbar).toBool());
connect(m_ui->actionShowToolbar, &QAction::toggled, this, [this](bool checked) {
config()->set(Config::GUI_HideToolbar, !checked);
applySettingsChanges();
});
m_ui->actionShowPreviewPanel->setChecked(!config()->get(Config::GUI_HidePreviewPanel).toBool());
connect(m_ui->actionShowPreviewPanel, &QAction::toggled, this, [](bool checked) {
config()->set(Config::GUI_HidePreviewPanel, !checked);
});
}

View File

@ -81,6 +81,7 @@ public slots:
void closeAllDatabases();
void lockAllDatabases();
void displayDesktopNotification(const QString& msg, QString title = "", int msTimeoutHint = 10000);
void restartApp(const QString& message);
protected:
void closeEvent(QCloseEvent* event) override;
@ -152,6 +153,8 @@ private:
void dragEnterEvent(QDragEnterEvent* event) override;
void dropEvent(QDropEvent* event) override;
void initViewMenu();
const QScopedPointer<Ui::MainWindow> m_ui;
SignalMultiplexer m_actionMultiplexer;
QPointer<QAction> m_clearHistoryAction;
@ -171,6 +174,7 @@ private:
bool m_appExitCalled = false;
bool m_appExiting = false;
bool m_restartRequested = false;
bool m_contextMenuFocusLock = false;
bool m_showToolbarSeparator = false;
qint64 m_lastFocusOutTime = 0;

View File

@ -353,10 +353,28 @@
<addaction name="actionPasswordGenerator"/>
<addaction name="actionSettings"/>
</widget>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
<widget class="QMenu" name="menuTheme">
<property name="title">
<string>Theme</string>
</property>
<addaction name="actionThemeAuto"/>
<addaction name="actionThemeLight"/>
<addaction name="actionThemeDark"/>
<addaction name="actionThemeClassic"/>
</widget>
<addaction name="menuTheme"/>
<addaction name="actionShowPreviewPanel"/>
<addaction name="actionShowToolbar"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEntries"/>
<addaction name="menuGroups"/>
<addaction name="menuTools"/>
<addaction name="menuView"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QToolBar" name="toolBar">
@ -843,6 +861,63 @@
<string>Remove key from SSH Agent</string>
</property>
</action>
<action name="actionThemeAuto">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Automatic</string>
</property>
</action>
<action name="actionThemeLight">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Light</string>
</property>
</action>
<action name="actionThemeDark">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Dark</string>
</property>
</action>
<action name="actionThemeClassic">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Classic (Platform-native)</string>
</property>
</action>
<action name="actionShowToolbar">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Show Toolbar</string>
</property>
</action>
<action name="actionShowPreviewPanel">
<property name="checkable">
<bool>true</bool>
</property>
<property name="checked">
<bool>true</bool>
</property>
<property name="text">
<string>Show Preview Panel</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@ -155,6 +155,12 @@ int main(int argc, char** argv)
int exitCode = Application::exec();
// Check if restart was requested
if (exitCode == RESTART_EXITCODE) {
QProcess* proc = new QProcess();
proc->start(QCoreApplication::applicationFilePath());
}
#if defined(WITH_ASAN) && defined(WITH_LSAN)
// do leak check here to prevent massive tail of end-of-process leak errors from third-party libraries
__lsan_do_leak_check();