Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/keepassxreboot/keepassxc.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan White <support@dmapps.us>2021-05-15 16:47:09 +0300
committerJonathan White <support@dmapps.us>2021-05-30 15:44:09 +0300
commit7941d59f4a2e2753842643306abb0958772860d4 (patch)
tree19a1240489f15ff6182b8c74ca42f19a43178487
parent1fdfc153bede248f82fd652b005e31179b3cd68b (diff)
Show search bar when toolbar is hidden or overflow
* Fix #505 - always show the search bar when the search keyboard shortcut is pressed. If the toolbar is in overflow, the toolbar will be expanded automatically and search focused. If the toolbar is hidden it will be shown and expanded if necessary. When searching is canceled or the down arrow is pressed (to select the first entry) the toolbar will be set back to it's previous configuration.
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/gui/DatabaseWidget.cpp3
-rw-r--r--src/gui/MainWindow.cpp29
-rw-r--r--src/gui/MainWindow.h1
-rw-r--r--src/gui/MainWindow.ui7
-rw-r--r--src/gui/SearchWidget.cpp21
-rw-r--r--src/gui/SearchWidget.h5
-rw-r--r--src/gui/widgets/KPToolBar.cpp75
-rw-r--r--src/gui/widgets/KPToolBar.h52
9 files changed, 180 insertions, 14 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 0ceccdd9a..a441b475b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -173,6 +173,7 @@ set(keepassx_SOURCES
gui/osutils/OSUtilsBase.cpp
gui/settings/SettingsWidget.cpp
gui/widgets/ElidedLabel.cpp
+ gui/widgets/KPToolBar.cpp
gui/widgets/PopupHelpWidget.cpp
gui/wizard/NewDatabaseWizard.cpp
gui/wizard/NewDatabaseWizardPage.cpp
diff --git a/src/gui/DatabaseWidget.cpp b/src/gui/DatabaseWidget.cpp
index bb0a6ec41..a91d15b3b 100644
--- a/src/gui/DatabaseWidget.cpp
+++ b/src/gui/DatabaseWidget.cpp
@@ -1391,9 +1391,8 @@ void DatabaseWidget::onGroupChanged()
// Intercept group changes if in search mode
if (isSearchActive() && m_searchLimitGroup) {
search(m_lastSearchText);
- } else if (isSearchActive()) {
- endSearch();
} else {
+ endSearch();
m_entryView->displayGroup(group);
}
diff --git a/src/gui/MainWindow.cpp b/src/gui/MainWindow.cpp
index 7a53f144d..659ac8457 100644
--- a/src/gui/MainWindow.cpp
+++ b/src/gui/MainWindow.cpp
@@ -118,6 +118,17 @@ MainWindow::MainWindow()
m_searchWidgetAction = m_ui->toolBar->addWidget(m_searchWidget);
m_searchWidgetAction->setEnabled(false);
+ new QShortcut(QKeySequence::Find, this, SLOT(focusSearchWidget()));
+
+ connect(m_searchWidget, &SearchWidget::searchCanceled, this, [this] {
+ m_ui->toolBar->setExpanded(false);
+ m_ui->toolBar->setVisible(!config()->get(Config::GUI_HideToolbar).toBool());
+ });
+ connect(m_searchWidget, &SearchWidget::lostFocus, this, [this] {
+ m_ui->toolBar->setExpanded(false);
+ m_ui->toolBar->setVisible(!config()->get(Config::GUI_HideToolbar).toBool());
+ });
+
m_countDefaultAttributes = m_ui->menuEntryCopyAttribute->actions().size();
m_entryContextMenu = new QMenu(this);
@@ -1227,7 +1238,10 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
dbWidget->focusOnEntries(true);
return;
} else if (event->key() == Qt::Key_F3) {
- m_searchWidget->searchFocus();
+ focusSearchWidget();
+ return;
+ } else if (event->key() == Qt::Key_Escape && dbWidget->isSearchActive()) {
+ m_searchWidget->clearSearch();
return;
}
}
@@ -1248,13 +1262,13 @@ bool MainWindow::focusNextPrevChild(bool next)
} else if (m_ui->tabWidget->hasFocus()) {
dbWidget->setFocus(Qt::TabFocusReason);
} else {
- m_searchWidget->setFocus(Qt::TabFocusReason);
+ focusSearchWidget();
}
} else {
if (m_searchWidget->hasFocus()) {
dbWidget->setFocus(Qt::BacktabFocusReason);
} else if (m_ui->tabWidget->hasFocus()) {
- m_searchWidget->setFocus(Qt::BacktabFocusReason);
+ focusSearchWidget();
} else {
m_ui->tabWidget->setFocus(Qt::BacktabFocusReason);
}
@@ -1266,6 +1280,15 @@ bool MainWindow::focusNextPrevChild(bool next)
return QMainWindow::focusNextPrevChild(next);
}
+void MainWindow::focusSearchWidget()
+{
+ if (m_searchWidgetAction->isEnabled()) {
+ m_ui->toolBar->setVisible(true);
+ m_ui->toolBar->setExpanded(true);
+ m_searchWidget->focusSearch();
+ }
+}
+
void MainWindow::saveWindowInformation()
{
if (isVisible()) {
diff --git a/src/gui/MainWindow.h b/src/gui/MainWindow.h
index 8a99d4432..a80346dfe 100644
--- a/src/gui/MainWindow.h
+++ b/src/gui/MainWindow.h
@@ -143,6 +143,7 @@ private slots:
private slots:
void updateTrayIcon();
void updateProgressBar(int percentage, QString message);
+ void focusSearchWidget();
private:
static void setShortcut(QAction* action, QKeySequence::StandardKey standard, int fallback = 0);
diff --git a/src/gui/MainWindow.ui b/src/gui/MainWindow.ui
index 62d6cdd93..679578f1b 100644
--- a/src/gui/MainWindow.ui
+++ b/src/gui/MainWindow.ui
@@ -394,7 +394,7 @@
<addaction name="menuView"/>
<addaction name="menuHelp"/>
</widget>
- <widget class="QToolBar" name="toolBar">
+ <widget class="KPToolBar" name="toolBar">
<property name="contextMenuPolicy">
<enum>Qt::PreventContextMenu</enum>
</property>
@@ -1043,6 +1043,11 @@
<header>gui/WelcomeWidget.h</header>
<container>1</container>
</customwidget>
+ <customwidget>
+ <class>KPToolBar</class>
+ <extends>QToolBar</extends>
+ <header>gui/widgets/KPToolBar.h</header>
+ </customwidget>
</customwidgets>
<resources/>
<connections/>
diff --git a/src/gui/SearchWidget.cpp b/src/gui/SearchWidget.cpp
index 6ade47e2e..4cf53a9ac 100644
--- a/src/gui/SearchWidget.cpp
+++ b/src/gui/SearchWidget.cpp
@@ -48,8 +48,8 @@ SearchWidget::SearchWidget(QWidget* parent)
connect(m_ui->helpIcon, SIGNAL(triggered()), SLOT(toggleHelp()));
connect(m_ui->searchIcon, SIGNAL(triggered()), SLOT(showSearchMenu()));
connect(m_searchTimer, SIGNAL(timeout()), SLOT(startSearch()));
- connect(m_clearSearchTimer, SIGNAL(timeout()), m_ui->searchEdit, SLOT(clear()));
- connect(this, SIGNAL(escapePressed()), m_ui->searchEdit, SLOT(clear()));
+ connect(m_clearSearchTimer, SIGNAL(timeout()), SLOT(clearSearch()));
+ connect(this, SIGNAL(escapePressed()), SLOT(clearSearch()));
new QShortcut(QKeySequence::Find, this, SLOT(searchFocus()), nullptr, Qt::ApplicationShortcut);
new QShortcut(Qt::Key_Escape, m_ui->searchEdit, SLOT(clear()), nullptr, Qt::ApplicationShortcut);
@@ -109,7 +109,7 @@ bool SearchWidget::eventFilter(QObject* obj, QEvent* event)
return true;
}
}
- } else if (event->type() == QEvent::FocusOut && !m_ui->searchEdit->text().isEmpty()) {
+ } else if (event->type() == QEvent::FocusOut) {
if (config()->get(Config::Security_ClearSearch).toBool()) {
int timeout = config()->get(Config::Security_ClearSearchTimeout).toInt();
if (timeout > 0) {
@@ -117,6 +117,7 @@ bool SearchWidget::eventFilter(QObject* obj, QEvent* event)
m_clearSearchTimer->start(timeout * 60000); // 60 sec * 1000 ms
}
}
+ emit lostFocus();
} else if (event->type() == QEvent::FocusIn) {
// Never clear the search if we are using it
m_clearSearchTimer->stop();
@@ -133,10 +134,10 @@ void SearchWidget::connectSignals(SignalMultiplexer& mx)
mx.connect(this, SIGNAL(limitGroupChanged(bool)), SLOT(setSearchLimitGroup(bool)));
mx.connect(this, SIGNAL(copyPressed()), SLOT(copyPassword()));
mx.connect(this, SIGNAL(downPressed()), SLOT(focusOnEntries()));
- mx.connect(SIGNAL(clearSearch()), m_ui->searchEdit, SLOT(clear()));
+ mx.connect(SIGNAL(clearSearch()), this, SLOT(clearSearch()));
mx.connect(SIGNAL(entrySelectionChanged()), this, SLOT(resetSearchClearTimer()));
mx.connect(SIGNAL(currentModeChanged(DatabaseWidget::Mode)), this, SLOT(resetSearchClearTimer()));
- mx.connect(SIGNAL(databaseUnlocked()), this, SLOT(searchFocus()));
+ mx.connect(SIGNAL(databaseUnlocked()), this, SLOT(focusSearch()));
mx.connect(m_ui->searchEdit, SIGNAL(returnPressed()), SLOT(switchToEntryEdit()));
}
@@ -149,7 +150,7 @@ void SearchWidget::databaseChanged(DatabaseWidget* dbWidget)
emit caseSensitiveChanged(m_actionCaseSensitive->isChecked());
emit limitGroupChanged(m_actionLimitGroup->isChecked());
} else {
- m_ui->searchEdit->clear();
+ clearSearch();
}
}
@@ -201,12 +202,18 @@ void SearchWidget::setLimitGroup(bool state)
updateLimitGroup();
}
-void SearchWidget::searchFocus()
+void SearchWidget::focusSearch()
{
m_ui->searchEdit->setFocus();
m_ui->searchEdit->selectAll();
}
+void SearchWidget::clearSearch()
+{
+ m_ui->searchEdit->clear();
+ emit searchCanceled();
+}
+
void SearchWidget::toggleHelp()
{
if (m_helpWidget->isVisible()) {
diff --git a/src/gui/SearchWidget.h b/src/gui/SearchWidget.h
index eefdff6ee..b2192f54d 100644
--- a/src/gui/SearchWidget.h
+++ b/src/gui/SearchWidget.h
@@ -52,16 +52,19 @@ protected:
signals:
void search(const QString& text);
+ void searchCanceled();
void caseSensitiveChanged(bool state);
void limitGroupChanged(bool state);
void escapePressed();
void copyPressed();
void downPressed();
void enterPressed();
+ void lostFocus();
public slots:
void databaseChanged(DatabaseWidget* dbWidget = nullptr);
- void searchFocus();
+ void focusSearch();
+ void clearSearch();
private slots:
void startSearchTimer();
diff --git a/src/gui/widgets/KPToolBar.cpp b/src/gui/widgets/KPToolBar.cpp
new file mode 100644
index 000000000..88b75b9b1
--- /dev/null
+++ b/src/gui/widgets/KPToolBar.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "KPToolBar.h"
+
+#include <QAbstractButton>
+#include <QEvent>
+#include <QLayout>
+
+KPToolBar::KPToolBar(const QString& title, QWidget* parent)
+ : QToolBar(title, parent)
+{
+ init();
+}
+
+KPToolBar::KPToolBar(QWidget* parent)
+ : QToolBar(parent)
+{
+ init();
+}
+
+void KPToolBar::init()
+{
+ m_expandButton = findChild<QAbstractButton*>("qt_toolbar_ext_button");
+ m_expandTimer.setSingleShot(true);
+ connect(&m_expandTimer, &QTimer::timeout, this, [this] { setExpanded(false); });
+}
+
+bool KPToolBar::isExpanded()
+{
+ return !canExpand() || (canExpand() && m_expandButton->isChecked());
+}
+
+bool KPToolBar::canExpand()
+{
+ return m_expandButton && m_expandButton->isVisible();
+}
+
+void KPToolBar::setExpanded(bool state)
+{
+ if (canExpand() && !QMetaObject::invokeMethod(layout(), "setExpanded", Q_ARG(bool, state))) {
+ qWarning("Toolbar: Cannot invoke setExpanded!");
+ }
+}
+
+bool KPToolBar::event(QEvent* event)
+{
+ // Override events handled by the base class for better UX when using an expandable toolbar.
+ switch (event->type()) {
+ case QEvent::Leave:
+ // Hide the toolbar after 2 seconds of mouse exit
+ m_expandTimer.start(2000);
+ return true;
+ case QEvent::Enter:
+ // Mouse came back in, stop hiding timer
+ m_expandTimer.stop();
+ return true;
+ default:
+ return QToolBar::event(event);
+ }
+}
diff --git a/src/gui/widgets/KPToolBar.h b/src/gui/widgets/KPToolBar.h
new file mode 100644
index 000000000..8883982bd
--- /dev/null
+++ b/src/gui/widgets/KPToolBar.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2021 KeePassXC Team <team@keepassxc.org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 or (at your option)
+ * version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef KEEPASSXC_KPTOOLBAR_H
+#define KEEPASSXC_KPTOOLBAR_H
+
+#include <QPointer>
+#include <QTimer>
+#include <QToolBar>
+
+class QAbstractButton;
+
+class KPToolBar : public QToolBar
+{
+ Q_OBJECT
+
+public:
+ explicit KPToolBar(const QString& title, QWidget* parent = nullptr);
+ explicit KPToolBar(QWidget* parent = nullptr);
+ ~KPToolBar() override = default;
+
+ bool isExpanded();
+ bool canExpand();
+
+public slots:
+ void setExpanded(bool state);
+
+protected:
+ bool event(QEvent* event) override;
+
+private:
+ void init();
+
+ QTimer m_expandTimer;
+ QPointer<QAbstractButton> m_expandButton;
+};
+
+#endif // KEEPASSXC_KPTOOLBAR_H