X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/ed2d352c42a6d517d4f29b3582c0e00aa34fe647..7e10da6e2e0171fa30a1162e5767be2b95937c21:/src/search/dolphinsearchbox.cpp diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp index 9df417c4f..ee425501d 100644 --- a/src/search/dolphinsearchbox.cpp +++ b/src/search/dolphinsearchbox.cpp @@ -13,9 +13,10 @@ #include "dolphinquery.h" #include "config-dolphin.h" +#include #include -#include #include +#include #if HAVE_BALOO #include #include @@ -35,7 +36,7 @@ #include DolphinSearchBox::DolphinSearchBox(QWidget *parent) - : QWidget(parent) + : AnimatedHeightWidget(parent) , m_startedSearching(false) , m_active(true) , m_topLayout(nullptr) @@ -50,6 +51,7 @@ DolphinSearchBox::DolphinSearchBox(QWidget *parent) , m_facetsWidget(nullptr) , m_searchPath() , m_startSearchTimer(nullptr) + , m_initialized(false) { } @@ -60,7 +62,9 @@ DolphinSearchBox::~DolphinSearchBox() void DolphinSearchBox::setText(const QString &text) { - m_searchInput->setText(text); + if (m_searchInput->text() != text) { + m_searchInput->setText(text); + } } QString DolphinSearchBox::text() const @@ -70,7 +74,7 @@ QString DolphinSearchBox::text() const void DolphinSearchBox::setSearchPath(const QUrl &url) { - if (url == m_searchPath) { + if (url == m_searchPath || !m_initialized) { return; } @@ -116,13 +120,13 @@ QUrl DolphinSearchBox::urlForSearching() const url.setScheme(QStringLiteral("filenamesearch")); QUrlQuery query; - query.addQueryItem(QStringLiteral("search"), m_searchInput->text()); + query.addQueryItem(QStringLiteral("search"), QUrl::toPercentEncoding(m_searchInput->text())); if (m_contentButton->isChecked()) { query.addQueryItem(QStringLiteral("checkContent"), QStringLiteral("yes")); } - query.addQueryItem(QStringLiteral("url"), searchPath().url()); - query.addQueryItem(QStringLiteral("title"), queryTitle(m_searchInput->text())); + query.addQueryItem(QStringLiteral("url"), QUrl::toPercentEncoding(searchPath().url())); + query.addQueryItem(QStringLiteral("title"), QUrl::toPercentEncoding(queryTitle(m_searchInput->text()))); url.setQuery(query); } @@ -137,11 +141,11 @@ void DolphinSearchBox::fromSearchUrl(const QUrl &url) updateFromQuery(query); } else if (url.scheme() == QLatin1String("filenamesearch")) { const QUrlQuery query(url); - setText(query.queryItemValue(QStringLiteral("search"))); + setText(query.queryItemValue(QStringLiteral("search"), QUrl::FullyDecoded)); if (m_searchPath.scheme() != url.scheme()) { m_searchPath = QUrl(); } - setSearchPath(QUrl::fromUserInput(query.queryItemValue(QStringLiteral("url")), QString(), QUrl::AssumeLocalFile)); + setSearchPath(QUrl::fromUserInput(query.queryItemValue(QStringLiteral("url"), QUrl::FullyDecoded), QString(), QUrl::AssumeLocalFile)); m_contentButton->setChecked(query.queryItemValue(QStringLiteral("checkContent")) == QLatin1String("yes")); } else { setText(QString()); @@ -173,12 +177,12 @@ bool DolphinSearchBox::isActive() const return m_active; } -bool DolphinSearchBox::event(QEvent *event) +void DolphinSearchBox::setVisible(bool visible, Animated animated) { - if (event->type() == QEvent::Polish) { + if (visible) { init(); } - return QWidget::event(event); + AnimatedHeightWidget::setVisible(visible, animated); } void DolphinSearchBox::showEvent(QShowEvent *event) @@ -193,7 +197,9 @@ void DolphinSearchBox::hideEvent(QHideEvent *event) { Q_UNUSED(event) m_startedSearching = false; - m_startSearchTimer->stop(); + if (m_startSearchTimer) { + m_startSearchTimer->stop(); + } } void DolphinSearchBox::keyReleaseEvent(QKeyEvent *event) @@ -201,7 +207,7 @@ void DolphinSearchBox::keyReleaseEvent(QKeyEvent *event) QWidget::keyReleaseEvent(event); if (event->key() == Qt::Key_Escape) { if (m_searchInput->text().isEmpty()) { - Q_EMIT closeRequest(); + emitCloseRequest(); } else { m_searchInput->clear(); } @@ -261,7 +267,9 @@ void DolphinSearchBox::slotConfigurationChanged() void DolphinSearchBox::slotSearchTextChanged(const QString &text) { if (text.isEmpty()) { - m_startSearchTimer->stop(); + // Restore URL when search box is cleared by closing and reopening the box. + emitCloseRequest(); + Q_EMIT openRequest(); } else { m_startSearchTimer->start(); } @@ -270,6 +278,10 @@ void DolphinSearchBox::slotSearchTextChanged(const QString &text) void DolphinSearchBox::slotReturnPressed() { + if (m_searchInput->text().isEmpty()) { + return; + } + emitSearchRequest(); Q_EMIT focusViewRequest(); } @@ -318,15 +330,23 @@ void DolphinSearchBox::loadSettings() void DolphinSearchBox::saveSettings() { - SearchSettings::setLocation(m_fromHereButton->isChecked() ? QStringLiteral("FromHere") : QStringLiteral("Everywhere")); - SearchSettings::setWhat(m_fileNameButton->isChecked() ? QStringLiteral("FileName") : QStringLiteral("Content")); - SearchSettings::self()->save(); + if (m_initialized) { + SearchSettings::setLocation(m_fromHereButton->isChecked() ? QStringLiteral("FromHere") : QStringLiteral("Everywhere")); + SearchSettings::setWhat(m_fileNameButton->isChecked() ? QStringLiteral("FileName") : QStringLiteral("Content")); + SearchSettings::self()->save(); + } } void DolphinSearchBox::init() { + if (m_initialized) { + return; // This object is already initialised. + } + + QWidget *contentsContainer = prepareContentsContainer(); + // Create search box - m_searchInput = new QLineEdit(this); + m_searchInput = new QLineEdit(contentsContainer); m_searchInput->setPlaceholderText(i18n("Search…")); m_searchInput->installEventFilter(this); m_searchInput->setClearButtonEnabled(true); @@ -344,7 +364,7 @@ void DolphinSearchBox::init() connect(m_saveSearchAction, &QAction::triggered, this, &DolphinSearchBox::slotSearchSaved); // Create close button - QToolButton *closeButton = new QToolButton(this); + QToolButton *closeButton = new QToolButton(contentsContainer); closeButton->setAutoRaise(true); closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); closeButton->setToolTip(i18nc("@info:tooltip", "Quit searching")); @@ -357,7 +377,7 @@ void DolphinSearchBox::init() searchInputLayout->addWidget(closeButton); // Create "Filename" and "Content" button - m_fileNameButton = new QToolButton(this); + m_fileNameButton = new QToolButton(contentsContainer); m_fileNameButton->setText(i18nc("action:button", "Filename")); initButton(m_fileNameButton); @@ -365,43 +385,49 @@ void DolphinSearchBox::init() m_contentButton->setText(i18nc("action:button", "Content")); initButton(m_contentButton); - QButtonGroup *searchWhatGroup = new QButtonGroup(this); + QButtonGroup *searchWhatGroup = new QButtonGroup(contentsContainer); searchWhatGroup->addButton(m_fileNameButton); searchWhatGroup->addButton(m_contentButton); - m_separator = new KSeparator(Qt::Vertical, this); + m_separator = new KSeparator(Qt::Vertical, contentsContainer); // Create "From Here" and "Your files" buttons - m_fromHereButton = new QToolButton(this); + m_fromHereButton = new QToolButton(contentsContainer); m_fromHereButton->setText(i18nc("action:button", "From Here")); initButton(m_fromHereButton); - m_everywhereButton = new QToolButton(this); + m_everywhereButton = new QToolButton(contentsContainer); m_everywhereButton->setText(i18nc("action:button", "Your files")); m_everywhereButton->setToolTip(i18nc("action:button", "Search in your home directory")); m_everywhereButton->setIcon(QIcon::fromTheme(QStringLiteral("user-home"))); m_everywhereButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); initButton(m_everywhereButton); - QButtonGroup *searchLocationGroup = new QButtonGroup(this); + QButtonGroup *searchLocationGroup = new QButtonGroup(contentsContainer); searchLocationGroup->addButton(m_fromHereButton); searchLocationGroup->addButton(m_everywhereButton); - auto moreSearchToolsButton = new QToolButton(this); - moreSearchToolsButton->setAutoRaise(true); - moreSearchToolsButton->setPopupMode(QToolButton::InstantPopup); - moreSearchToolsButton->setIcon(QIcon::fromTheme("arrow-down-double")); - moreSearchToolsButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - moreSearchToolsButton->setText(i18n("More Search Tools")); - moreSearchToolsButton->setMenu(new QMenu(this)); - connect(moreSearchToolsButton->menu(), &QMenu::aboutToShow, moreSearchToolsButton->menu(), [this, moreSearchToolsButton]() { - m_menuFactory.reset(new KMoreToolsMenuFactory("dolphin/search-tools")); - moreSearchToolsButton->menu()->clear(); - m_menuFactory->fillMenuFromGroupingNames(moreSearchToolsButton->menu(), {"files-find"}, this->m_searchPath); - }); + KService::Ptr kfind = KService::serviceByDesktopName(QStringLiteral("org.kde.kfind")); + + QToolButton *kfindToolsButton = nullptr; + if (kfind) { + kfindToolsButton = new QToolButton(contentsContainer); + kfindToolsButton->setAutoRaise(true); + kfindToolsButton->setPopupMode(QToolButton::InstantPopup); + kfindToolsButton->setIcon(QIcon::fromTheme("arrow-down-double")); + kfindToolsButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + kfindToolsButton->setText(i18n("Open %1", kfind->name())); + kfindToolsButton->setIcon(QIcon::fromTheme(kfind->icon())); + + connect(kfindToolsButton, &QToolButton::clicked, this, [this, kfind] { + auto *job = new KIO::ApplicationLauncherJob(kfind); + job->setUrls({m_searchPath}); + job->start(); + }); + } // Create "Facets" widget - m_facetsWidget = new DolphinFacetsWidget(this); + m_facetsWidget = new DolphinFacetsWidget(contentsContainer); m_facetsWidget->installEventFilter(this); m_facetsWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); m_facetsWidget->layout()->setSpacing(Dolphin::LAYOUT_SPACING_SMALL); @@ -409,7 +435,7 @@ void DolphinSearchBox::init() // Put the options into a QScrollArea. This prevents increasing the view width // in case that not enough width for the options is available. - QWidget *optionsContainer = new QWidget(this); + QWidget *optionsContainer = new QWidget(contentsContainer); // Apply layout for the options QHBoxLayout *optionsLayout = new QHBoxLayout(optionsContainer); @@ -420,11 +446,13 @@ void DolphinSearchBox::init() optionsLayout->addWidget(m_separator); optionsLayout->addWidget(m_fromHereButton); optionsLayout->addWidget(m_everywhereButton); - optionsLayout->addWidget(new KSeparator(Qt::Vertical, this)); - optionsLayout->addWidget(moreSearchToolsButton); + optionsLayout->addWidget(new KSeparator(Qt::Vertical, contentsContainer)); + if (kfindToolsButton) { + optionsLayout->addWidget(kfindToolsButton); + } optionsLayout->addStretch(1); - m_optionsScrollArea = new QScrollArea(this); + m_optionsScrollArea = new QScrollArea(contentsContainer); m_optionsScrollArea->setFrameShape(QFrame::NoFrame); m_optionsScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_optionsScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -433,7 +461,7 @@ void DolphinSearchBox::init() m_optionsScrollArea->setWidget(optionsContainer); m_optionsScrollArea->setWidgetResizable(true); - m_topLayout = new QVBoxLayout(this); + m_topLayout = new QVBoxLayout(contentsContainer); m_topLayout->setContentsMargins(0, Dolphin::LAYOUT_SPACING_SMALL, 0, 0); m_topLayout->setSpacing(Dolphin::LAYOUT_SPACING_SMALL); m_topLayout->addLayout(searchInputLayout); @@ -443,11 +471,13 @@ void DolphinSearchBox::init() loadSettings(); // The searching should be started automatically after the user did not change - // the text within one second + // the text for a while m_startSearchTimer = new QTimer(this); m_startSearchTimer->setSingleShot(true); - m_startSearchTimer->setInterval(1000); + m_startSearchTimer->setInterval(500); connect(m_startSearchTimer, &QTimer::timeout, this, &DolphinSearchBox::emitSearchRequest); + + m_initialized = true; } QString DolphinSearchBox::queryTitle(const QString &text) const @@ -496,10 +526,7 @@ void DolphinSearchBox::updateFromQuery(const DolphinQuery &query) setSearchPath(QUrl::fromLocalFile(QDir::homePath())); } - // If the input box has focus, do not update to avoid messing with user typing - if (!m_searchInput->hasFocus()) { - setText(query.text()); - } + setText(query.text()); if (query.hasContentSearch()) { m_contentButton->setChecked(true); @@ -523,6 +550,11 @@ void DolphinSearchBox::updateFacetsVisible() const bool indexingEnabled = isIndexingEnabled(); m_facetsWidget->setEnabled(indexingEnabled); m_facetsWidget->setVisible(indexingEnabled); + + // The m_facetsWidget might have changed visibility. We smoothly animate towards the updated height. + if (isVisible() && isEnabled()) { + setVisible(true, WithAnimation); + } } bool DolphinSearchBox::isIndexingEnabled() const @@ -535,4 +567,9 @@ bool DolphinSearchBox::isIndexingEnabled() const #endif } +int DolphinSearchBox::preferredHeight() const +{ + return m_initialized ? m_topLayout->sizeHint().height() : 0; +} + #include "moc_dolphinsearchbox.cpp"