mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2025-02-26 09:21:21 -05:00
Merge pull request #141 from keepassxreboot/feature/searchui-enhance
Enhanced search ui keypress actions Also resolves #163: icons gone when running release-compiled binary from the build directory
This commit is contained in:
commit
de69ecc35f
@ -211,6 +211,9 @@ FilePath::FilePath()
|
|||||||
else if (testSetDir(appDirPath + "/share")) {
|
else if (testSetDir(appDirPath + "/share")) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
// Last ditch test when running in the build directory (mainly for travis tests)
|
||||||
|
else if (testSetDir(QString(KEEPASSX_SOURCE_DIR) + "/share")) {
|
||||||
|
}
|
||||||
|
|
||||||
if (m_dataPath.isEmpty()) {
|
if (m_dataPath.isEmpty()) {
|
||||||
qWarning("FilePath::DataPath: can't find data dir");
|
qWarning("FilePath::DataPath: can't find data dir");
|
||||||
|
@ -34,12 +34,13 @@ SearchWidget::SearchWidget(QWidget *parent)
|
|||||||
m_searchTimer->setSingleShot(true);
|
m_searchTimer->setSingleShot(true);
|
||||||
|
|
||||||
connect(m_ui->searchEdit, SIGNAL(textChanged(QString)), SLOT(startSearchTimer()));
|
connect(m_ui->searchEdit, SIGNAL(textChanged(QString)), SLOT(startSearchTimer()));
|
||||||
connect(m_ui->searchEdit, SIGNAL(returnPressed()), SLOT(startSearch()));
|
connect(m_ui->searchIcon, SIGNAL(pressed()), m_ui->searchEdit, SLOT(setFocus()));
|
||||||
connect(m_ui->searchIcon, SIGNAL(triggered(QAction*)), m_ui->searchEdit, SLOT(setFocus()));
|
connect(m_ui->clearIcon, SIGNAL(pressed()), m_ui->searchEdit, SLOT(clear()));
|
||||||
|
connect(m_ui->clearIcon, SIGNAL(pressed()), m_ui->searchEdit, SLOT(setFocus()));
|
||||||
connect(m_searchTimer, SIGNAL(timeout()), this, SLOT(startSearch()));
|
connect(m_searchTimer, SIGNAL(timeout()), this, SLOT(startSearch()));
|
||||||
connect(this, SIGNAL(escapePressed()), m_ui->searchEdit, SLOT(clear()));
|
connect(this, SIGNAL(escapePressed()), m_ui->searchEdit, SLOT(clear()));
|
||||||
|
|
||||||
new QShortcut(Qt::CTRL + Qt::Key_F, m_ui->searchEdit, SLOT(setFocus()), nullptr, Qt::ApplicationShortcut);
|
new QShortcut(Qt::CTRL + Qt::Key_F, this, SLOT(searchFocus()), nullptr, Qt::ApplicationShortcut);
|
||||||
|
|
||||||
m_ui->searchEdit->installEventFilter(this);
|
m_ui->searchEdit->installEventFilter(this);
|
||||||
|
|
||||||
@ -51,6 +52,9 @@ SearchWidget::SearchWidget(QWidget *parent)
|
|||||||
m_ui->searchIcon->setIcon(filePath()->icon("actions", "system-search"));
|
m_ui->searchIcon->setIcon(filePath()->icon("actions", "system-search"));
|
||||||
m_ui->searchIcon->setMenu(searchMenu);
|
m_ui->searchIcon->setMenu(searchMenu);
|
||||||
m_ui->searchIcon->setPopupMode(QToolButton::MenuButtonPopup);
|
m_ui->searchIcon->setPopupMode(QToolButton::MenuButtonPopup);
|
||||||
|
|
||||||
|
m_ui->clearIcon->setIcon(filePath()->icon("actions", "edit-clear-locationbar-rtl"));
|
||||||
|
m_ui->clearIcon->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
SearchWidget::~SearchWidget()
|
SearchWidget::~SearchWidget()
|
||||||
@ -67,23 +71,24 @@ bool SearchWidget::eventFilter(QObject *obj, QEvent *event)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (keyEvent->matches(QKeySequence::Copy)) {
|
else if (keyEvent->matches(QKeySequence::Copy)) {
|
||||||
// If Control+C is pressed in the search edit when no
|
// If Control+C is pressed in the search edit when no text
|
||||||
// text is selected, copy the password of the current
|
// is selected, copy the password of the current entry
|
||||||
// entry.
|
|
||||||
if (!m_ui->searchEdit->hasSelectedText()) {
|
if (!m_ui->searchEdit->hasSelectedText()) {
|
||||||
emit copyPressed();
|
emit copyPressed();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (keyEvent->matches(QKeySequence::MoveToNextLine)) {
|
else if (keyEvent->matches(QKeySequence::MoveToNextLine)) {
|
||||||
// If Down is pressed at EOL in the search edit, move
|
if (m_ui->searchEdit->cursorPosition() == m_ui->searchEdit->text().length()) {
|
||||||
// the focus to the entry view.
|
// If down is pressed at EOL, move the focus to the entry view
|
||||||
QLineEdit* searchEdit = m_ui->searchEdit;
|
|
||||||
if (!searchEdit->hasSelectedText() &&
|
|
||||||
searchEdit->cursorPosition() == searchEdit->text().length()) {
|
|
||||||
emit downPressed();
|
emit downPressed();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// Otherwise move the cursor to EOL
|
||||||
|
m_ui->searchEdit->setCursorPosition(m_ui->searchEdit->text().length());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +101,7 @@ void SearchWidget::connectSignals(SignalMultiplexer& mx)
|
|||||||
mx.connect(this, SIGNAL(caseSensitiveChanged(bool)), SLOT(setSearchCaseSensitive(bool)));
|
mx.connect(this, SIGNAL(caseSensitiveChanged(bool)), SLOT(setSearchCaseSensitive(bool)));
|
||||||
mx.connect(this, SIGNAL(copyPressed()), SLOT(copyPassword()));
|
mx.connect(this, SIGNAL(copyPressed()), SLOT(copyPassword()));
|
||||||
mx.connect(this, SIGNAL(downPressed()), SLOT(setFocus()));
|
mx.connect(this, SIGNAL(downPressed()), SLOT(setFocus()));
|
||||||
|
mx.connect(m_ui->searchEdit, SIGNAL(returnPressed()), SLOT(switchToEntryEdit()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchWidget::databaseChanged(DatabaseWidget *dbWidget)
|
void SearchWidget::databaseChanged(DatabaseWidget *dbWidget)
|
||||||
@ -125,6 +131,9 @@ void SearchWidget::startSearch()
|
|||||||
m_searchTimer->stop();
|
m_searchTimer->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasText = m_ui->searchEdit->text().length() > 0;
|
||||||
|
m_ui->clearIcon->setEnabled(hasText);
|
||||||
|
|
||||||
search(m_ui->searchEdit->text());
|
search(m_ui->searchEdit->text());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,3 +147,9 @@ void SearchWidget::setCaseSensitive(bool state)
|
|||||||
m_actionCaseSensitive->setChecked(state);
|
m_actionCaseSensitive->setChecked(state);
|
||||||
updateCaseSensitive();
|
updateCaseSensitive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SearchWidget::searchFocus()
|
||||||
|
{
|
||||||
|
m_ui->searchEdit->setFocus();
|
||||||
|
m_ui->searchEdit->selectAll();
|
||||||
|
}
|
||||||
|
@ -48,6 +48,7 @@ signals:
|
|||||||
void escapePressed();
|
void escapePressed();
|
||||||
void copyPressed();
|
void copyPressed();
|
||||||
void downPressed();
|
void downPressed();
|
||||||
|
void enterPressed();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void databaseChanged(DatabaseWidget* dbWidget);
|
void databaseChanged(DatabaseWidget* dbWidget);
|
||||||
@ -56,6 +57,7 @@ private slots:
|
|||||||
void startSearchTimer();
|
void startSearchTimer();
|
||||||
void startSearch();
|
void startSearch();
|
||||||
void updateCaseSensitive();
|
void updateCaseSensitive();
|
||||||
|
void searchFocus();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QScopedPointer<Ui::SearchWidget> m_ui;
|
const QScopedPointer<Ui::SearchWidget> m_ui;
|
||||||
|
@ -10,26 +10,33 @@
|
|||||||
<height>34</height>
|
<height>34</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="gridLayout">
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<property name="leftMargin">
|
<property name="leftMargin">
|
||||||
<number>0</number>
|
<number>3</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="topMargin">
|
<property name="topMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="rightMargin">
|
<property name="rightMargin">
|
||||||
<number>0</number>
|
<number>7</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QToolButton" name="searchIcon">
|
<widget class="QToolButton" name="searchIcon">
|
||||||
<property name="focusPolicy">
|
<property name="focusPolicy">
|
||||||
<enum>Qt::ClickFocus</enum>
|
<enum>Qt::ClickFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Search</string>
|
||||||
|
</property>
|
||||||
<property name="toolButtonStyle">
|
<property name="toolButtonStyle">
|
||||||
<enum>Qt::ToolButtonIconOnly</enum>
|
<enum>Qt::ToolButtonIconOnly</enum>
|
||||||
</property>
|
</property>
|
||||||
@ -39,16 +46,33 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLineEdit" name="searchEdit">
|
||||||
<property name="text">
|
<property name="styleSheet">
|
||||||
<string>Find:</string>
|
<string notr="true">padding:3px</string>
|
||||||
|
</property>
|
||||||
|
<property name="placeholderText">
|
||||||
|
<string>Find</string>
|
||||||
|
</property>
|
||||||
|
<property name="clearButtonEnabled">
|
||||||
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
<item>
|
||||||
</item>
|
<widget class="QToolButton" name="clearIcon">
|
||||||
<item row="0" column="1">
|
<property name="focusPolicy">
|
||||||
<widget class="QLineEdit" name="searchEdit"/>
|
<enum>Qt::ClickFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolButtonStyle">
|
||||||
|
<enum>Qt::ToolButtonIconOnly</enum>
|
||||||
|
</property>
|
||||||
|
<property name="autoRaise">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -401,7 +401,13 @@ void TestGui::testSearch()
|
|||||||
QTRY_COMPARE(searchTextEdit->text(), QString("ZZZ"));
|
QTRY_COMPARE(searchTextEdit->text(), QString("ZZZ"));
|
||||||
QTRY_VERIFY(m_dbWidget->isInSearchMode());
|
QTRY_VERIFY(m_dbWidget->isInSearchMode());
|
||||||
QTRY_COMPARE(entryView->model()->rowCount(), 0);
|
QTRY_COMPARE(entryView->model()->rowCount(), 0);
|
||||||
|
// Press the search clear button
|
||||||
|
QToolButton* clearButton = searchWidget->findChild<QToolButton*>("clearIcon");
|
||||||
|
QTest::mouseClick(clearButton, Qt::LeftButton);
|
||||||
|
QTRY_VERIFY(searchTextEdit->text().isEmpty());
|
||||||
|
QTRY_VERIFY(searchTextEdit->hasFocus());
|
||||||
// Escape clears searchedit and retains focus
|
// Escape clears searchedit and retains focus
|
||||||
|
QTest::keyClicks(searchTextEdit, "ZZZ");
|
||||||
QTest::keyClick(searchTextEdit, Qt::Key_Escape);
|
QTest::keyClick(searchTextEdit, Qt::Key_Escape);
|
||||||
QTRY_VERIFY(searchTextEdit->text().isEmpty());
|
QTRY_VERIFY(searchTextEdit->text().isEmpty());
|
||||||
QTRY_VERIFY(searchTextEdit->hasFocus());
|
QTRY_VERIFY(searchTextEdit->hasFocus());
|
||||||
@ -413,19 +419,26 @@ void TestGui::testSearch()
|
|||||||
// Search for "someTHING"
|
// Search for "someTHING"
|
||||||
QTest::keyClicks(searchTextEdit, "THING");
|
QTest::keyClicks(searchTextEdit, "THING");
|
||||||
QTRY_COMPARE(entryView->model()->rowCount(), 2);
|
QTRY_COMPARE(entryView->model()->rowCount(), 2);
|
||||||
// Press Down to focus on the entry view if at EOL
|
// Press Down to focus on the entry view
|
||||||
QTest::keyClick(searchTextEdit, Qt::Key_Right, Qt::ControlModifier);
|
QTest::keyClick(searchTextEdit, Qt::Key_Right, Qt::ControlModifier);
|
||||||
QTRY_VERIFY(searchTextEdit->hasFocus());
|
QTRY_VERIFY(searchTextEdit->hasFocus());
|
||||||
QTest::keyClick(searchTextEdit, Qt::Key_Down);
|
QTest::keyClick(searchTextEdit, Qt::Key_Down);
|
||||||
QTRY_VERIFY(entryView->hasFocus());
|
QTRY_VERIFY(entryView->hasFocus());
|
||||||
// Test clipboard
|
// Restore focus and search text selection
|
||||||
|
QTest::keyClick(m_mainWindow, Qt::Key_F, Qt::ControlModifier);
|
||||||
|
QTRY_COMPARE(searchTextEdit->selectedText(), QString("someTHING"));
|
||||||
|
// Ensure Down focuses on entry view when search text is selected
|
||||||
|
QTest::keyClick(searchTextEdit, Qt::Key_Down);
|
||||||
|
QTRY_VERIFY(entryView->hasFocus());
|
||||||
|
// Refocus back to search edit
|
||||||
|
QTest::mouseClick(searchTextEdit, Qt::LeftButton);
|
||||||
|
QTRY_VERIFY(searchTextEdit->hasFocus());
|
||||||
|
// Test password copy
|
||||||
QClipboard *clipboard = QApplication::clipboard();
|
QClipboard *clipboard = QApplication::clipboard();
|
||||||
QTest::keyClick(entryView, Qt::Key_C, Qt::ControlModifier);
|
QTest::keyClick(searchTextEdit, Qt::Key_C, Qt::ControlModifier);
|
||||||
QModelIndex searchedItem = entryView->model()->index(0, 1);
|
QModelIndex searchedItem = entryView->model()->index(0, 1);
|
||||||
Entry* searchedEntry = entryView->entryFromIndex(searchedItem);
|
Entry* searchedEntry = entryView->entryFromIndex(searchedItem);
|
||||||
QTRY_COMPARE(searchedEntry->password(), clipboard->text());
|
QTRY_COMPARE(searchedEntry->password(), clipboard->text());
|
||||||
// Restore focus
|
|
||||||
QTest::mouseClick(searchTextEdit, Qt::LeftButton);
|
|
||||||
|
|
||||||
// Test case sensitive search
|
// Test case sensitive search
|
||||||
searchWidget->setCaseSensitive(true);
|
searchWidget->setCaseSensitive(true);
|
||||||
@ -445,16 +458,14 @@ void TestGui::testSearch()
|
|||||||
QCOMPARE(groupView->currentGroup(), m_db->rootGroup());
|
QCOMPARE(groupView->currentGroup(), m_db->rootGroup());
|
||||||
|
|
||||||
// Try to edit the first entry from the search view
|
// Try to edit the first entry from the search view
|
||||||
|
// Refocus back to search edit
|
||||||
|
QTest::mouseClick(searchTextEdit, Qt::LeftButton);
|
||||||
|
QTRY_VERIFY(searchTextEdit->hasFocus());
|
||||||
|
QVERIFY(m_dbWidget->isInSearchMode());
|
||||||
|
|
||||||
QModelIndex item = entryView->model()->index(0, 1);
|
QModelIndex item = entryView->model()->index(0, 1);
|
||||||
Entry* entry = entryView->entryFromIndex(item);
|
Entry* entry = entryView->entryFromIndex(item);
|
||||||
QVERIFY(m_dbWidget->isInSearchMode());
|
QTest::keyClick(searchTextEdit, Qt::Key_Return);
|
||||||
clickIndex(item, entryView, Qt::LeftButton);
|
|
||||||
QAction* entryEditAction = m_mainWindow->findChild<QAction*>("actionEntryEdit");
|
|
||||||
QVERIFY(entryEditAction->isEnabled());
|
|
||||||
QWidget* entryEditWidget = toolBar->widgetForAction(entryEditAction);
|
|
||||||
QVERIFY(entryEditWidget->isVisible());
|
|
||||||
QVERIFY(entryEditWidget->isEnabled());
|
|
||||||
QTest::mouseClick(entryEditWidget, Qt::LeftButton);
|
|
||||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
|
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::EditMode);
|
||||||
|
|
||||||
// Perform the edit and save it
|
// Perform the edit and save it
|
||||||
@ -465,7 +476,7 @@ void TestGui::testSearch()
|
|||||||
QDialogButtonBox* editEntryWidgetButtonBox = editEntryWidget->findChild<QDialogButtonBox*>("buttonBox");
|
QDialogButtonBox* editEntryWidgetButtonBox = editEntryWidget->findChild<QDialogButtonBox*>("buttonBox");
|
||||||
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
|
QTest::mouseClick(editEntryWidgetButtonBox->button(QDialogButtonBox::Ok), Qt::LeftButton);
|
||||||
|
|
||||||
// Confirm the edit was made and we are back in view mode
|
// Confirm the edit was made and we are back in search mode
|
||||||
QTRY_VERIFY(m_dbWidget->isInSearchMode());
|
QTRY_VERIFY(m_dbWidget->isInSearchMode());
|
||||||
QCOMPARE(entry->title(), origTitle.append("_edited"));
|
QCOMPARE(entry->title(), origTitle.append("_edited"));
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user