X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/ae488b13186a4cb5d0bc5d7f23b07467d6638979..0a6257bce3de877e4ae869f974df645c428d32c9:/src/search/dolphinsearchbox.cpp diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp index c4270d383..050ae394d 100644 --- a/src/search/dolphinsearchbox.cpp +++ b/src/search/dolphinsearchbox.cpp @@ -20,51 +20,48 @@ #include "dolphinsearchbox.h" #include "dolphin_searchsettings.h" -#include "dolphinsearchinformation.h" +#include "dolphinfacetswidget.h" -#include +#include #include -#include +#include #include #include #include #include -#include #include #include #include -#include #include #include #include #include -#include -#ifdef HAVE_NEPOMUK - #include - #include - #include - #include - #include - #include - #include - #include - #include +#ifdef HAVE_BALOO + #include + #include + #include + #include + #include #endif +#include DolphinSearchBox::DolphinSearchBox(QWidget* parent) : QWidget(parent), m_startedSearching(false), - m_readOnly(false), + m_active(true), m_topLayout(0), + m_searchLabel(0), m_searchInput(0), + m_optionsScrollArea(0), m_fileNameButton(0), m_contentButton(0), m_separator(0), m_fromHereButton(0), m_everywhereButton(0), - m_infoLabel(0), + m_facetsToggleButton(0), + m_facetsWidget(0), m_searchPath(), m_startSearchTimer(0) { @@ -90,7 +87,7 @@ void DolphinSearchBox::setSearchPath(const KUrl& url) m_searchPath = url; QFontMetrics metrics(m_fromHereButton->font()); - const int maxWidth = metrics.averageCharWidth() * 15; + const int maxWidth = metrics.height() * 8; QString location = url.fileName(); if (location.isEmpty()) { @@ -104,10 +101,17 @@ void DolphinSearchBox::setSearchPath(const KUrl& url) const QString elidedLocation = metrics.elidedText(location, Qt::ElideMiddle, maxWidth); m_fromHereButton->setText(i18nc("action:button", "From Here (%1)", elidedLocation)); - const bool showSearchFromButtons = url.isLocalFile() && !m_readOnly; + const bool showSearchFromButtons = url.isLocalFile(); m_separator->setVisible(showSearchFromButtons); m_fromHereButton->setVisible(showSearchFromButtons); m_everywhereButton->setVisible(showSearchFromButtons); + + bool hasFacetsSupport = false; +#ifdef HAVE_BALOO + const Baloo::IndexerConfig searchInfo; + hasFacetsSupport = searchInfo.fileIndexingEnabled() && searchInfo.shouldBeIndexed(m_searchPath.toLocalFile()); +#endif + m_facetsWidget->setEnabled(hasFacetsSupport); } KUrl DolphinSearchBox::searchPath() const @@ -118,9 +122,13 @@ KUrl DolphinSearchBox::searchPath() const KUrl DolphinSearchBox::urlForSearching() const { KUrl url; - const DolphinSearchInformation& searchInfo = DolphinSearchInformation::instance(); - if (searchInfo.isIndexingEnabled() && searchInfo.isPathIndexed(m_searchPath)) { - url = nepomukUrlForSearching(); + bool useBalooSearch = false; +#ifdef HAVE_BALOO + const Baloo::IndexerConfig searchInfo; + useBalooSearch = searchInfo.fileIndexingEnabled() && searchInfo.shouldBeIndexed(m_searchPath.toLocalFile()); +#endif + if (useBalooSearch) { + url = balooUrlForSearching(); } else { url.setProtocol("filenamesearch"); url.addQueryItem("search", m_searchInput->text()); @@ -143,22 +151,40 @@ KUrl DolphinSearchBox::urlForSearching() const return url; } +void DolphinSearchBox::fromSearchUrl(const KUrl& url) +{ + if (url.protocol() == "baloosearch") { + fromBalooSearchUrl(url); + } else if (url.protocol() == "filenamesearch") { + const QMap& queryItems = url.queryItems(); + setText(queryItems.value("search")); + setSearchPath(queryItems.value("url")); + m_contentButton->setChecked(queryItems.value("checkContent") == "yes"); + } else { + setText(QString()); + setSearchPath(url); + } +} + void DolphinSearchBox::selectAll() { m_searchInput->selectAll(); } -void DolphinSearchBox::setReadOnly(bool readOnly) +void DolphinSearchBox::setActive(bool active) { - if (m_readOnly != readOnly) { - m_readOnly = readOnly; - applyReadOnlyState(); + if (active != m_active) { + m_active = active; + + if (active) { + emit activated(); + } } } -bool DolphinSearchBox::isReadOnly() const +bool DolphinSearchBox::isActive() const { - return m_readOnly; + return m_active; } bool DolphinSearchBox::event(QEvent* event) @@ -189,49 +215,89 @@ void DolphinSearchBox::keyReleaseEvent(QKeyEvent* event) } } -void DolphinSearchBox::emitSearchSignal() +bool DolphinSearchBox::eventFilter(QObject* obj, QEvent* event) { - m_startSearchTimer->stop(); - m_startedSearching = true; - emit search(m_searchInput->text()); + switch (event->type()) { + case QEvent::FocusIn: + setActive(true); + setFocus(); + break; + + default: + break; + } + + return QObject::eventFilter(obj, event); } -void DolphinSearchBox::slotSearchLocationChanged() +void DolphinSearchBox::emitSearchRequest() { - emit searchLocationChanged(m_fromHereButton->isChecked() ? SearchFromHere : SearchEverywhere); + m_startSearchTimer->stop(); + m_startedSearching = true; + emit searchRequest(); } -void DolphinSearchBox::slotSearchContextChanged() +void DolphinSearchBox::emitCloseRequest() { - emit searchContextChanged(m_fileNameButton->isChecked() ? SearchFileName : SearchContent); + m_startSearchTimer->stop(); + m_startedSearching = false; + emit closeRequest(); } void DolphinSearchBox::slotConfigurationChanged() { saveSettings(); if (m_startedSearching) { - emitSearchSignal(); + emitSearchRequest(); } } -void DolphinSearchBox::slotSearchTextChanged(const QString& text) +void DolphinSearchBox::slotSearchTextChanged() { - m_startSearchTimer->start(); + const QString text = m_searchInput->text(); + + if (text.isEmpty()) { + m_startSearchTimer->stop(); + } else { + m_startSearchTimer->start(); + } emit searchTextChanged(text); } -void DolphinSearchBox::slotReturnPressed(const QString& text) +void DolphinSearchBox::slotReturnPressed() +{ + emitSearchRequest(); + emit returnPressed(m_searchInput->text()); +} + +void DolphinSearchBox::updateSearchInputParsing() +{ +#ifdef HAVE_BALOO + m_searchInput->setParsingEnabled(m_contentButton->isChecked()); +#endif +} + +void DolphinSearchBox::slotFacetsButtonToggled() +{ + const bool facetsIsVisible = !m_facetsWidget->isVisible(); + m_facetsWidget->setVisible(facetsIsVisible); + updateFacetsToggleButton(); +} + +void DolphinSearchBox::slotFacetChanged() { - emitSearchSignal(); - emit returnPressed(text); + m_startedSearching = true; + m_startSearchTimer->stop(); + emit searchRequest(); } -void DolphinSearchBox::initButton(QPushButton* button) +void DolphinSearchBox::initButton(QToolButton* button) { + button->installEventFilter(this); button->setAutoExclusive(true); - button->setFlat(true); + button->setAutoRaise(true); button->setCheckable(true); - connect(button, SIGNAL(clicked(bool)), this, SLOT(slotConfigurationChanged())); + connect(button, &QToolButton::clicked, this, &DolphinSearchBox::slotConfigurationChanged); } void DolphinSearchBox::loadSettings() @@ -247,13 +313,17 @@ void DolphinSearchBox::loadSettings() } else { m_fileNameButton->setChecked(true); } + + m_facetsWidget->setVisible(SearchSettings::showFacetsWidget()); + updateSearchInputParsing(); } void DolphinSearchBox::saveSettings() { SearchSettings::setLocation(m_fromHereButton->isChecked() ? "FromHere" : "Everywhere"); SearchSettings::setWhat(m_fileNameButton->isChecked() ? "FileName" : "Content"); - SearchSettings::self()->writeConfig(); + SearchSettings::setShowFacetsWidget(m_facetsToggleButton->isChecked()); + SearchSettings::self()->save(); } void DolphinSearchBox::init() @@ -261,65 +331,80 @@ void DolphinSearchBox::init() // Create close button QToolButton* closeButton = new QToolButton(this); closeButton->setAutoRaise(true); - closeButton->setIcon(KIcon("dialog-close")); + closeButton->setIcon(QIcon::fromTheme("dialog-close")); closeButton->setToolTip(i18nc("@info:tooltip", "Quit searching")); - connect(closeButton, SIGNAL(clicked()), SIGNAL(closeRequest())); + connect(closeButton, &QToolButton::clicked, this, &DolphinSearchBox::emitCloseRequest); // Create search label - QLabel* searchLabel = new QLabel(i18nc("@label:textbox", "Find:"), this); + m_searchLabel = new QLabel(this); // Create search box +#ifdef HAVE_BALOO + m_queryParser.reset(new Baloo::NaturalFileQueryParser); + m_searchInput = new Baloo::QueryBuilder(m_queryParser.data(), this); + connect(m_searchInput, &Baloo::QueryBuilder::editingFinished, + this, &DolphinSearchBox::slotReturnPressed); + connect(m_searchInput, &Baloo::QueryBuilder::textChanged, + this, &DolphinSearchBox::slotSearchTextChanged); +#else m_searchInput = new KLineEdit(this); + m_searchInput->installEventFilter(this); m_searchInput->setClearButtonShown(true); - m_searchInput->setFont(KGlobalSettings::generalFont()); + m_searchInput->setFont(QFontDatabase::systemFont(QFontDatabase::GeneralFont)); + connect(m_searchInput, &KLineEdit::returnPressed, + this, &DolphinSearchBox::slotReturnPressed); + connect(m_searchInput, &KLineEdit::textChanged, + this, &DolphinSearchBox::slotSearchTextChanged); +#endif setFocusProxy(m_searchInput); - connect(m_searchInput, SIGNAL(returnPressed(QString)), - this, SLOT(slotReturnPressed(QString))); - connect(m_searchInput, SIGNAL(textChanged(QString)), - this, SLOT(slotSearchTextChanged(QString))); - - // Create information label - m_infoLabel = new QLabel("TODO: Provide information about the current query", this); // Apply layout for the search input QHBoxLayout* searchInputLayout = new QHBoxLayout(); searchInputLayout->setMargin(0); searchInputLayout->addWidget(closeButton); - searchInputLayout->addWidget(searchLabel); + searchInputLayout->addWidget(m_searchLabel); searchInputLayout->addWidget(m_searchInput); - searchInputLayout->addWidget(m_infoLabel); // Create "Filename" and "Content" button - m_fileNameButton = new QPushButton(this); + m_fileNameButton = new QToolButton(this); m_fileNameButton->setText(i18nc("action:button", "Filename")); initButton(m_fileNameButton); - m_contentButton = new QPushButton(); + m_contentButton = new QToolButton(); m_contentButton->setText(i18nc("action:button", "Content")); - initButton(m_contentButton);; + initButton(m_contentButton); QButtonGroup* searchWhatGroup = new QButtonGroup(this); searchWhatGroup->addButton(m_fileNameButton); searchWhatGroup->addButton(m_contentButton); - connect(m_fileNameButton, SIGNAL(clicked()), this, SLOT(slotSearchContextChanged())); - connect(m_contentButton, SIGNAL(clicked()), this, SLOT(slotSearchContextChanged())); + connect(searchWhatGroup, static_cast(&QButtonGroup::buttonClicked), + this, &DolphinSearchBox::updateSearchInputParsing); m_separator = new KSeparator(Qt::Vertical, this); // Create "From Here" and "Everywhere"button - m_fromHereButton = new QPushButton(this); + m_fromHereButton = new QToolButton(this); m_fromHereButton->setText(i18nc("action:button", "From Here")); initButton(m_fromHereButton); - m_everywhereButton = new QPushButton(this); + m_everywhereButton = new QToolButton(this); m_everywhereButton->setText(i18nc("action:button", "Everywhere")); initButton(m_everywhereButton); QButtonGroup* searchLocationGroup = new QButtonGroup(this); searchLocationGroup->addButton(m_fromHereButton); searchLocationGroup->addButton(m_everywhereButton); - connect(m_fromHereButton, SIGNAL(clicked()), this, SLOT(slotSearchLocationChanged())); - connect(m_everywhereButton, SIGNAL(clicked()), this, SLOT(slotSearchLocationChanged())); + + // Create "Facets" widgets + m_facetsToggleButton = new QToolButton(this); + m_facetsToggleButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + initButton(m_facetsToggleButton); + connect(m_facetsToggleButton, &QToolButton::clicked, this, &DolphinSearchBox::slotFacetsButtonToggled); + + m_facetsWidget = new DolphinFacetsWidget(this); + m_facetsWidget->installEventFilter(this); + m_facetsWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum); + connect(m_facetsWidget, &DolphinFacetsWidget::facetChanged, this, &DolphinSearchBox::slotFacetChanged); // Apply layout for the options QHBoxLayout* optionsLayout = new QHBoxLayout(); @@ -330,25 +415,28 @@ void DolphinSearchBox::init() optionsLayout->addWidget(m_fromHereButton); optionsLayout->addWidget(m_everywhereButton); optionsLayout->addStretch(1); + optionsLayout->addWidget(m_facetsToggleButton); // 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); optionsContainer->setLayout(optionsLayout); - QScrollArea* optionsScrollArea = new QScrollArea(this); - optionsScrollArea->setFrameShape(QFrame::NoFrame); - optionsScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - optionsScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - optionsScrollArea->setMaximumHeight(optionsContainer->sizeHint().height()); - optionsScrollArea->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); - optionsScrollArea->setWidget(optionsContainer); - optionsScrollArea->setWidgetResizable(true); + + m_optionsScrollArea = new QScrollArea(this); + m_optionsScrollArea->setFrameShape(QFrame::NoFrame); + m_optionsScrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_optionsScrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + m_optionsScrollArea->setMaximumHeight(optionsContainer->sizeHint().height()); + m_optionsScrollArea->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + m_optionsScrollArea->setWidget(optionsContainer); + m_optionsScrollArea->setWidgetResizable(true); m_topLayout = new QVBoxLayout(this); + m_topLayout->setMargin(0); m_topLayout->addLayout(searchInputLayout); - m_topLayout->addWidget(optionsScrollArea); + m_topLayout->addWidget(m_optionsScrollArea); + m_topLayout->addWidget(m_facetsWidget); - searchLabel->setBuddy(m_searchInput); loadSettings(); // The searching should be started automatically after the user did not change @@ -356,62 +444,96 @@ void DolphinSearchBox::init() m_startSearchTimer = new QTimer(this); m_startSearchTimer->setSingleShot(true); m_startSearchTimer->setInterval(1000); - connect(m_startSearchTimer, SIGNAL(timeout()), this, SLOT(emitSearchSignal())); + connect(m_startSearchTimer, &QTimer::timeout, this, &DolphinSearchBox::emitSearchRequest); - applyReadOnlyState(); + updateFacetsToggleButton(); } -KUrl DolphinSearchBox::nepomukUrlForSearching() const +KUrl DolphinSearchBox::balooUrlForSearching() const { -#ifdef HAVE_NEPOMUK - Nepomuk::Query::OrTerm orTerm; - +#ifdef HAVE_BALOO const QString text = m_searchInput->text(); - // Search the text in the filename in any case - QString regex = QRegExp::escape(text); - regex.replace("\\*", QLatin1String(".*")); - regex.replace("\\?", QLatin1String(".")); - regex.replace("\\", "\\\\"); - orTerm.addSubTerm(Nepomuk::Query::ComparisonTerm( - Nepomuk::Vocabulary::NFO::fileName(), - Nepomuk::Query::LiteralTerm(regex), - Nepomuk::Query::ComparisonTerm::Regexp)); + Baloo::Query query; if (m_contentButton->isChecked()) { - // Search the text also in the content of the files - const Nepomuk::Query::Query customQuery = Nepomuk::Query::QueryParser::parseQuery(text, Nepomuk::Query::QueryParser::DetectFilenamePattern); - if (customQuery.isValid()) { - orTerm.addSubTerm(customQuery.term()); - } + query = m_queryParser->parse(text, Baloo::NaturalQueryParser::DetectFilenamePattern); + } else { + query.setTerm(Baloo::Term(QLatin1String("filename"), text)); + } + + // Configure the query so that it returns files and takes the rating into account + query.addType("File"); + query.addType(m_facetsWidget->facetType()); + + Baloo::Term term(Baloo::Term::And); + Baloo::Term ratingTerm = m_facetsWidget->ratingTerm(); + + if (ratingTerm.isValid()) { + term.addSubTerm(query.term()); + term.addSubTerm(ratingTerm); + + query.setTerm(term); } - Nepomuk::Query::FileQuery fileQuery; - fileQuery.setFileMode(Nepomuk::Query::FileQuery::QueryFilesAndFolders); - fileQuery.setTerm(orTerm); if (m_fromHereButton->isChecked()) { - const bool recursive = true; - fileQuery.addIncludeFolder(m_searchPath, recursive); + query.setIncludeFolder(m_searchPath.toLocalFile()); } - return fileQuery.toSearchUrl(i18nc("@title UDS_DISPLAY_NAME for a KIO directory listing. %1 is the query the user entered.", - "Query Results from '%1'", - text)); + return query.toSearchUrl(i18nc("@title UDS_DISPLAY_NAME for a KIO directory listing. %1 is the query the user entered.", + "Query Results from '%1'", text)); #else return KUrl(); #endif } -void DolphinSearchBox::applyReadOnlyState() +void DolphinSearchBox::fromBalooSearchUrl(const KUrl& url) +{ +#ifdef HAVE_BALOO + const Baloo::Query query = Baloo::Query::fromSearchUrl(url); + const Baloo::Term term = query.term(); + + // Block all signals to avoid unnecessary "searchRequest" signals + // while we adjust the search text and the facet widget. + blockSignals(true); + + const QString customDir = query.includeFolder(); + if (!customDir.isEmpty()) { + setSearchPath(customDir); + } else { + setSearchPath(QDir::homePath()); + } + + if (!query.searchString().isEmpty()) { + setText(query.searchString()); + } + + QStringList types = query.types(); + types.removeOne("File"); // We are only interested in facet widget types + if (!types.isEmpty()) { + m_facetsWidget->setFacetType(types.first()); + } + + foreach (const Baloo::Term& subTerm, term.subTerms()) { + const QString property = subTerm.property(); + + if (property == QLatin1String("filename")) { + setText(subTerm.value().toString()); + } else if (m_facetsWidget->isRatingTerm(subTerm)) { + m_facetsWidget->setRatingTerm(subTerm); + } + } + + m_startSearchTimer->stop(); + blockSignals(false); +#endif +} + +void DolphinSearchBox::updateFacetsToggleButton() { - // TODO: This is just an early draft to indicate that a state change - // has been done - m_searchInput->setVisible(!m_readOnly); - m_infoLabel->setVisible(m_readOnly); - m_fileNameButton->setVisible(!m_readOnly); - m_contentButton->setVisible(!m_readOnly); - m_fromHereButton->setVisible(!m_readOnly); - m_everywhereButton->setVisible(!m_readOnly); + const bool facetsIsVisible = SearchSettings::showFacetsWidget(); + m_facetsToggleButton->setChecked(facetsIsVisible ? true : false); + m_facetsToggleButton->setIcon(QIcon::fromTheme(facetsIsVisible ? "arrow-up-double" : "arrow-down-double")); + m_facetsToggleButton->setText(facetsIsVisible ? i18nc("action:button", "Fewer Options") : i18nc("action:button", "More Options")); } -#include "dolphinsearchbox.moc"