mirror of
https://github.com/keepassxreboot/keepassxc.git
synced 2024-12-25 15:29:44 -05:00
Search scopes to currently selected group (and children) (#118)
* Added test cases for case sensitive and group search
This commit is contained in:
parent
9261d8ae9d
commit
791a749c2f
@ -142,9 +142,8 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
|
|||||||
|
|
||||||
connect(m_splitter, SIGNAL(splitterMoved(int,int)), SIGNAL(splitterSizesChanged()));
|
connect(m_splitter, SIGNAL(splitterMoved(int,int)), SIGNAL(splitterSizesChanged()));
|
||||||
connect(m_entryView->header(), SIGNAL(sectionResized(int,int,int)), SIGNAL(entryColumnSizesChanged()));
|
connect(m_entryView->header(), SIGNAL(sectionResized(int,int,int)), SIGNAL(entryColumnSizesChanged()));
|
||||||
connect(m_groupView, SIGNAL(groupChanged(Group*)), this, SLOT(clearLastGroup(Group*)));
|
connect(m_groupView, SIGNAL(groupChanged(Group*)), this, SLOT(onGroupChanged(Group*)));
|
||||||
connect(m_groupView, SIGNAL(groupChanged(Group*)), SIGNAL(groupChanged()));
|
connect(m_groupView, SIGNAL(groupChanged(Group*)), SIGNAL(groupChanged()));
|
||||||
connect(m_groupView, SIGNAL(groupChanged(Group*)), m_entryView, SLOT(setGroup(Group*)));
|
|
||||||
connect(m_entryView, SIGNAL(entryActivated(Entry*, EntryModel::ModelColumn)),
|
connect(m_entryView, SIGNAL(entryActivated(Entry*, EntryModel::ModelColumn)),
|
||||||
SLOT(entryActivationSignalReceived(Entry*, EntryModel::ModelColumn)));
|
SLOT(entryActivationSignalReceived(Entry*, EntryModel::ModelColumn)));
|
||||||
connect(m_entryView, SIGNAL(entrySelectionChanged()), SIGNAL(entrySelectionChanged()));
|
connect(m_entryView, SIGNAL(entrySelectionChanged()), SIGNAL(entrySelectionChanged()));
|
||||||
@ -171,7 +170,6 @@ DatabaseWidget::DatabaseWidget(Database* db, QWidget* parent)
|
|||||||
m_ignoreNextAutoreload = false;
|
m_ignoreNextAutoreload = false;
|
||||||
|
|
||||||
m_searchCaseSensitive = false;
|
m_searchCaseSensitive = false;
|
||||||
m_searchCurrentGroup = false;
|
|
||||||
|
|
||||||
setCurrentWidget(m_mainWidget);
|
setCurrentWidget(m_mainWidget);
|
||||||
}
|
}
|
||||||
@ -624,11 +622,7 @@ void DatabaseWidget::switchToEntryEdit(Entry* entry)
|
|||||||
|
|
||||||
void DatabaseWidget::switchToEntryEdit(Entry* entry, bool create)
|
void DatabaseWidget::switchToEntryEdit(Entry* entry, bool create)
|
||||||
{
|
{
|
||||||
Group* group = m_groupView->currentGroup();
|
Group* group = currentGroup();
|
||||||
if (!group) {
|
|
||||||
Q_ASSERT(m_entryView->inEntryListMode());
|
|
||||||
group = m_lastGroup;
|
|
||||||
}
|
|
||||||
Q_ASSERT(group);
|
Q_ASSERT(group);
|
||||||
|
|
||||||
m_editEntryWidget->loadEntry(entry, create, false, group->name(), m_db);
|
m_editEntryWidget->loadEntry(entry, create, false, group->name(), m_db);
|
||||||
@ -842,16 +836,9 @@ void DatabaseWidget::search(const QString& searchtext)
|
|||||||
|
|
||||||
Q_EMIT searchModeAboutToActivate();
|
Q_EMIT searchModeAboutToActivate();
|
||||||
|
|
||||||
if (!isInSearchMode())
|
Qt::CaseSensitivity caseSensitive = m_searchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
|
||||||
{
|
|
||||||
m_lastGroup = m_groupView->currentGroup();
|
|
||||||
Q_ASSERT(m_lastGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
Group* searchGroup = m_searchCurrentGroup ? m_lastGroup : m_db->rootGroup();
|
QList<Entry*> searchResult = EntrySearcher().search(searchtext, currentGroup(), caseSensitive);
|
||||||
Qt::CaseSensitivity sensitivity = m_searchCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive;
|
|
||||||
|
|
||||||
QList<Entry*> searchResult = EntrySearcher().search(searchtext, searchGroup, sensitivity);
|
|
||||||
|
|
||||||
m_entryView->setEntryList(searchResult);
|
m_entryView->setEntryList(searchResult);
|
||||||
m_lastSearchText = searchtext;
|
m_lastSearchText = searchtext;
|
||||||
@ -877,12 +864,13 @@ void DatabaseWidget::setSearchCaseSensitive(bool state)
|
|||||||
search(m_lastSearchText);
|
search(m_lastSearchText);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseWidget::setSearchCurrentGroup(bool state)
|
void DatabaseWidget::onGroupChanged(Group* group)
|
||||||
{
|
{
|
||||||
m_searchCurrentGroup = state;
|
// Intercept group changes if in search mode
|
||||||
|
|
||||||
if (isInSearchMode())
|
if (isInSearchMode())
|
||||||
search(m_lastSearchText);
|
search(m_lastSearchText);
|
||||||
|
else
|
||||||
|
m_entryView->setGroup(group);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DatabaseWidget::getCurrentSearch()
|
QString DatabaseWidget::getCurrentSearch()
|
||||||
@ -894,12 +882,10 @@ void DatabaseWidget::endSearch()
|
|||||||
{
|
{
|
||||||
if (isInSearchMode())
|
if (isInSearchMode())
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_lastGroup);
|
|
||||||
|
|
||||||
Q_EMIT listModeAboutToActivate();
|
Q_EMIT listModeAboutToActivate();
|
||||||
|
|
||||||
m_groupView->setCurrentGroup(m_lastGroup);
|
// Show the normal entry view of the current group
|
||||||
m_entryView->setGroup(m_lastGroup);
|
m_entryView->setGroup(currentGroup());
|
||||||
|
|
||||||
Q_EMIT listModeActivated();
|
Q_EMIT listModeActivated();
|
||||||
}
|
}
|
||||||
@ -938,15 +924,7 @@ bool DatabaseWidget::isInSearchMode() const
|
|||||||
|
|
||||||
Group* DatabaseWidget::currentGroup() const
|
Group* DatabaseWidget::currentGroup() const
|
||||||
{
|
{
|
||||||
return isInSearchMode() ? m_lastGroup
|
return m_groupView->currentGroup();
|
||||||
: m_groupView->currentGroup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DatabaseWidget::clearLastGroup(Group* group)
|
|
||||||
{
|
|
||||||
if (group) {
|
|
||||||
m_lastGroup = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DatabaseWidget::lock()
|
void DatabaseWidget::lock()
|
||||||
|
@ -127,6 +127,7 @@ public Q_SLOTS:
|
|||||||
void openUrlForEntry(Entry* entry);
|
void openUrlForEntry(Entry* entry);
|
||||||
void createGroup();
|
void createGroup();
|
||||||
void deleteGroup();
|
void deleteGroup();
|
||||||
|
void onGroupChanged(Group* group);
|
||||||
void switchToView(bool accepted);
|
void switchToView(bool accepted);
|
||||||
void switchToEntryEdit();
|
void switchToEntryEdit();
|
||||||
void switchToGroupEdit();
|
void switchToGroupEdit();
|
||||||
@ -142,7 +143,6 @@ public Q_SLOTS:
|
|||||||
// Search related slots
|
// Search related slots
|
||||||
void search(const QString& searchtext);
|
void search(const QString& searchtext);
|
||||||
void setSearchCaseSensitive(bool state);
|
void setSearchCaseSensitive(bool state);
|
||||||
void setSearchCurrentGroup(bool state);
|
|
||||||
void endSearch();
|
void endSearch();
|
||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
@ -159,7 +159,6 @@ private Q_SLOTS:
|
|||||||
void mergeDatabase(bool accepted);
|
void mergeDatabase(bool accepted);
|
||||||
void unlockDatabase(bool accepted);
|
void unlockDatabase(bool accepted);
|
||||||
void emitCurrentModeChanged();
|
void emitCurrentModeChanged();
|
||||||
void clearLastGroup(Group* group);
|
|
||||||
// Database autoreload slots
|
// Database autoreload slots
|
||||||
void onWatchedFileChanged();
|
void onWatchedFileChanged();
|
||||||
void reloadDatabaseFile();
|
void reloadDatabaseFile();
|
||||||
@ -188,14 +187,12 @@ private:
|
|||||||
Group* m_newGroup;
|
Group* m_newGroup;
|
||||||
Entry* m_newEntry;
|
Entry* m_newEntry;
|
||||||
Group* m_newParent;
|
Group* m_newParent;
|
||||||
Group* m_lastGroup;
|
|
||||||
QString m_filename;
|
QString m_filename;
|
||||||
Uuid m_groupBeforeLock;
|
Uuid m_groupBeforeLock;
|
||||||
|
|
||||||
// Search state
|
// Search state
|
||||||
QString m_lastSearchText;
|
QString m_lastSearchText;
|
||||||
bool m_searchCaseSensitive;
|
bool m_searchCaseSensitive;
|
||||||
bool m_searchCurrentGroup;
|
|
||||||
|
|
||||||
// Autoreload
|
// Autoreload
|
||||||
QFileSystemWatcher m_fileWatcher;
|
QFileSystemWatcher m_fileWatcher;
|
||||||
|
@ -59,11 +59,9 @@ SearchWidget::SearchWidget(QWidget *parent)
|
|||||||
|
|
||||||
QMenu *searchMenu = new QMenu();
|
QMenu *searchMenu = new QMenu();
|
||||||
m_actionCaseSensitive = searchMenu->addAction(tr("Case Sensitive"), this, SLOT(updateCaseSensitive()));
|
m_actionCaseSensitive = searchMenu->addAction(tr("Case Sensitive"), this, SLOT(updateCaseSensitive()));
|
||||||
|
m_actionCaseSensitive->setObjectName("actionSearchCaseSensitive");
|
||||||
m_actionCaseSensitive->setCheckable(true);
|
m_actionCaseSensitive->setCheckable(true);
|
||||||
|
|
||||||
m_actionGroupSearch = searchMenu->addAction(tr("Search Current Group"), this, SLOT(updateGroupSearch()));
|
|
||||||
m_actionGroupSearch->setCheckable(true);
|
|
||||||
|
|
||||||
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);
|
||||||
@ -77,9 +75,7 @@ SearchWidget::~SearchWidget()
|
|||||||
void SearchWidget::connectSignals(SignalMultiplexer& mx)
|
void SearchWidget::connectSignals(SignalMultiplexer& mx)
|
||||||
{
|
{
|
||||||
mx.connect(this, SIGNAL(search(QString)), SLOT(search(QString)));
|
mx.connect(this, SIGNAL(search(QString)), SLOT(search(QString)));
|
||||||
mx.connect(this, SIGNAL(setCaseSensitive(bool)), SLOT(setSearchCaseSensitive(bool)));
|
mx.connect(this, SIGNAL(caseSensitiveChanged(bool)), SLOT(setSearchCaseSensitive(bool)));
|
||||||
mx.connect(this, SIGNAL(setGroupSearch(bool)), SLOT(setSearchCurrentGroup(bool)));
|
|
||||||
mx.connect(SIGNAL(groupChanged()), m_ui->searchEdit, SLOT(clear()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchWidget::databaseChanged(DatabaseWidget *dbWidget)
|
void SearchWidget::databaseChanged(DatabaseWidget *dbWidget)
|
||||||
@ -89,8 +85,7 @@ void SearchWidget::databaseChanged(DatabaseWidget *dbWidget)
|
|||||||
m_ui->searchEdit->setText(dbWidget->getCurrentSearch());
|
m_ui->searchEdit->setText(dbWidget->getCurrentSearch());
|
||||||
|
|
||||||
// Enforce search policy
|
// Enforce search policy
|
||||||
emit setCaseSensitive(m_actionCaseSensitive->isChecked());
|
emit caseSensitiveChanged(m_actionCaseSensitive->isChecked());
|
||||||
emit setGroupSearch(m_actionGroupSearch->isChecked());
|
|
||||||
} else {
|
} else {
|
||||||
m_ui->searchEdit->clear();
|
m_ui->searchEdit->clear();
|
||||||
}
|
}
|
||||||
@ -115,10 +110,11 @@ void SearchWidget::startSearch()
|
|||||||
|
|
||||||
void SearchWidget::updateCaseSensitive()
|
void SearchWidget::updateCaseSensitive()
|
||||||
{
|
{
|
||||||
emit setCaseSensitive(m_actionCaseSensitive->isChecked());
|
emit caseSensitiveChanged(m_actionCaseSensitive->isChecked());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SearchWidget::updateGroupSearch()
|
void SearchWidget::setCaseSensitive(bool state)
|
||||||
{
|
{
|
||||||
emit setGroupSearch(m_actionGroupSearch->isChecked());
|
m_actionCaseSensitive->setChecked(state);
|
||||||
|
updateCaseSensitive();
|
||||||
}
|
}
|
||||||
|
@ -48,11 +48,11 @@ public:
|
|||||||
~SearchWidget();
|
~SearchWidget();
|
||||||
|
|
||||||
void connectSignals(SignalMultiplexer& mx);
|
void connectSignals(SignalMultiplexer& mx);
|
||||||
|
void setCaseSensitive(bool state);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void search(const QString &text);
|
void search(const QString &text);
|
||||||
void setCaseSensitive(bool state);
|
void caseSensitiveChanged(bool state);
|
||||||
void setGroupSearch(bool state);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void databaseChanged(DatabaseWidget* dbWidget);
|
void databaseChanged(DatabaseWidget* dbWidget);
|
||||||
@ -61,7 +61,6 @@ private slots:
|
|||||||
void startSearchTimer();
|
void startSearchTimer();
|
||||||
void startSearch();
|
void startSearch();
|
||||||
void updateCaseSensitive();
|
void updateCaseSensitive();
|
||||||
void updateGroupSearch();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QScopedPointer<Ui::SearchWidget> m_ui;
|
const QScopedPointer<Ui::SearchWidget> m_ui;
|
||||||
@ -69,7 +68,6 @@ private:
|
|||||||
SearchEventFilter m_searchEventFilter;
|
SearchEventFilter m_searchEventFilter;
|
||||||
|
|
||||||
QAction *m_actionCaseSensitive;
|
QAction *m_actionCaseSensitive;
|
||||||
QAction *m_actionGroupSearch;
|
|
||||||
|
|
||||||
Q_DISABLE_COPY(SearchWidget)
|
Q_DISABLE_COPY(SearchWidget)
|
||||||
};
|
};
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
#include "gui/FileDialog.h"
|
#include "gui/FileDialog.h"
|
||||||
#include "gui/MainWindow.h"
|
#include "gui/MainWindow.h"
|
||||||
#include "gui/MessageBox.h"
|
#include "gui/MessageBox.h"
|
||||||
|
#include "gui/SearchWidget.h"
|
||||||
#include "gui/entry/EditEntryWidget.h"
|
#include "gui/entry/EditEntryWidget.h"
|
||||||
#include "gui/entry/EntryView.h"
|
#include "gui/entry/EntryView.h"
|
||||||
#include "gui/group/GroupModel.h"
|
#include "gui/group/GroupModel.h"
|
||||||
@ -378,36 +379,50 @@ void TestGui::testSearch()
|
|||||||
|
|
||||||
QToolBar* toolBar = m_mainWindow->findChild<QToolBar*>("toolBar");
|
QToolBar* toolBar = m_mainWindow->findChild<QToolBar*>("toolBar");
|
||||||
|
|
||||||
QWidget* searchActionWidget = toolBar->findChild<QWidget*>("SearchWidget");
|
SearchWidget* searchWidget = toolBar->findChild<SearchWidget*>("SearchWidget");
|
||||||
QVERIFY(searchActionWidget->isEnabled());
|
QVERIFY(searchWidget->isEnabled());
|
||||||
QLineEdit* searchEdit = searchActionWidget->findChild<QLineEdit*>("searchEdit");
|
QLineEdit* searchTextEdit = searchWidget->findChild<QLineEdit*>("searchEdit");
|
||||||
|
|
||||||
EntryView* entryView = m_dbWidget->findChild<EntryView*>("entryView");
|
EntryView* entryView = m_dbWidget->findChild<EntryView*>("entryView");
|
||||||
QVERIFY(entryView->isVisible());
|
QVERIFY(entryView->isVisible());
|
||||||
|
|
||||||
// Enter search
|
// Enter search
|
||||||
QTest::mouseClick(searchEdit, Qt::LeftButton);
|
QTest::mouseClick(searchTextEdit, Qt::LeftButton);
|
||||||
QTRY_VERIFY(searchEdit->hasFocus());
|
QTRY_VERIFY(searchTextEdit->hasFocus());
|
||||||
// Search for "ZZZ"
|
// Search for "ZZZ"
|
||||||
QTest::keyClicks(searchEdit, "ZZZ");
|
QTest::keyClicks(searchTextEdit, "ZZZ");
|
||||||
QTRY_COMPARE(searchEdit->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);
|
||||||
// Escape clears searchedit and retains focus
|
// Escape clears searchedit and retains focus
|
||||||
QTest::keyClick(searchEdit, Qt::Key_Escape);
|
QTest::keyClick(searchTextEdit, Qt::Key_Escape);
|
||||||
QTRY_VERIFY(searchEdit->text().isEmpty());
|
QTRY_VERIFY(searchTextEdit->text().isEmpty());
|
||||||
QTRY_VERIFY(searchEdit->hasFocus());
|
QTRY_VERIFY(searchTextEdit->hasFocus());
|
||||||
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
|
QCOMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
|
||||||
// Search for "some"
|
// Search for "some"
|
||||||
QTest::keyClicks(searchEdit, "some");
|
QTest::keyClicks(searchTextEdit, "some");
|
||||||
QTRY_VERIFY(m_dbWidget->isInSearchMode());
|
QTRY_VERIFY(m_dbWidget->isInSearchMode());
|
||||||
QTRY_COMPARE(entryView->model()->rowCount(), 3);
|
QTRY_COMPARE(entryView->model()->rowCount(), 3);
|
||||||
// Press Down to focus on the entry view
|
// Search for "someTHING"
|
||||||
QTest::keyClicks(searchEdit, "thing");
|
QTest::keyClicks(searchTextEdit, "THING");
|
||||||
QTRY_COMPARE(entryView->model()->rowCount(), 2);
|
QTRY_COMPARE(entryView->model()->rowCount(), 2);
|
||||||
//QVERIFY(!entryView->hasFocus());
|
|
||||||
//QTest::keyClick(searchEdit, Qt::Key_Down);
|
// Test case sensitive search
|
||||||
//QVERIFY(entryView->hasFocus());
|
searchWidget->setCaseSensitive(true);
|
||||||
|
QTRY_COMPARE(entryView->model()->rowCount(), 0);
|
||||||
|
searchWidget->setCaseSensitive(false);
|
||||||
|
QTRY_COMPARE(entryView->model()->rowCount(), 2);
|
||||||
|
|
||||||
|
// Test group search
|
||||||
|
GroupView* groupView = m_dbWidget->findChild<GroupView*>("groupView");
|
||||||
|
QCOMPARE(groupView->currentGroup(), m_db->rootGroup());
|
||||||
|
QModelIndex rootGroupIndex = groupView->model()->index(0, 0);
|
||||||
|
clickIndex(groupView->model()->index(0, 0, rootGroupIndex), groupView, Qt::LeftButton);
|
||||||
|
QCOMPARE(groupView->currentGroup()->name(), QString("General"));
|
||||||
|
QTRY_COMPARE(entryView->model()->rowCount(), 0);
|
||||||
|
// reset
|
||||||
|
clickIndex(rootGroupIndex, groupView, Qt::LeftButton);
|
||||||
|
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
|
||||||
QModelIndex item = entryView->model()->index(0, 1);
|
QModelIndex item = entryView->model()->index(0, 1);
|
||||||
@ -435,12 +450,9 @@ void TestGui::testSearch()
|
|||||||
QCOMPARE(entry->title(), origTitle.append("_edited"));
|
QCOMPARE(entry->title(), origTitle.append("_edited"));
|
||||||
|
|
||||||
// Cancel search, should return to normal view
|
// Cancel search, should return to normal view
|
||||||
QTest::mouseClick(searchEdit, Qt::LeftButton);
|
QTest::mouseClick(searchTextEdit, Qt::LeftButton);
|
||||||
QTest::keyClick(searchEdit, Qt::Key_Escape);
|
QTest::keyClick(searchTextEdit, Qt::Key_Escape);
|
||||||
QTRY_COMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
|
QTRY_COMPARE(m_dbWidget->currentMode(), DatabaseWidget::ViewMode);
|
||||||
//QCOMPARE(entryView->model()->rowCount(), 4);
|
|
||||||
|
|
||||||
// TODO: add tests to confirm case sensitive and group search
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestGui::testDeleteEntry()
|
void TestGui::testDeleteEntry()
|
||||||
|
Loading…
Reference in New Issue
Block a user