1 /***************************************************************************
2 * Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
18 ***************************************************************************/
20 #include "dolphinsearchoptionsconfigurator.h"
22 #include "dolphin_searchsettings.h"
23 #include <settings/dolphinsettings.h>
25 #define DISABLE_NEPOMUK_LEGACY
26 #include <nepomuk/andterm.h>
27 #include <nepomuk/filequery.h>
28 #include <nepomuk/orterm.h>
29 #include <nepomuk/queryparser.h>
30 #include <nepomuk/resourcetypeterm.h>
31 #include <nepomuk/literalterm.h>
35 #include <kcombobox.h>
37 #include <kfileplacesmodel.h>
39 #include <klineedit.h>
41 #include <kseparator.h>
43 #include "searchcriterionselector.h"
44 #include "searchoptiondialogbox.h"
46 #include <QButtonGroup>
47 #include <QHBoxLayout>
49 #include <QPushButton>
51 #include <QVBoxLayout>
55 const char* settingsName
;
59 // Contains the settings names and translated texts
60 // for each item of the location-combo-box.
61 static const SettingsItem g_locationItems
[] = {
62 {"Everywhere", I18N_NOOP2("@label", "Everywhere")},
63 {"From Here", I18N_NOOP2("@label", "From Here")}
66 // Contains the settings names and translated texts
67 // for each item of the what-combobox.
68 static const SettingsItem g_whatItems
[] = {
69 {"All", I18N_NOOP2("@label", "All")},
70 {"Images", I18N_NOOP2("@label", "Images")},
71 {"Text", I18N_NOOP2("@label", "Text")},
72 {"Filenames", I18N_NOOP2("@label", "Filenames")}
77 const char* settingsName
;
78 SearchCriterionSelector::Type type
;
81 // Contains the settings names for type
82 // of availabe search criterion.
83 static const CriterionItem g_criterionItems
[] = {
84 {"Date", SearchCriterionSelector::Date
},
85 {"Size", SearchCriterionSelector::Size
},
86 {"Tag", SearchCriterionSelector::Tag
},
87 {"Raging", SearchCriterionSelector::Rating
}
90 DolphinSearchOptionsConfigurator::DolphinSearchOptionsConfigurator(QWidget
* parent
) :
96 m_addSelectorButton(0),
101 m_customSearchQuery()
103 m_vBoxLayout
= new QVBoxLayout(this);
105 // add "search" configuration
106 QLabel
* searchLabel
= new QLabel(i18nc("@label", "Search:"));
108 m_locationBox
= new KComboBox(this);
109 for (unsigned int i
= 0; i
< sizeof(g_locationItems
) / sizeof(SettingsItem
); ++i
) {
110 m_locationBox
->addItem(g_locationItems
[i
].text
);
113 // add "what" configuration
114 QLabel
* whatLabel
= new QLabel(i18nc("@label", "What:"));
116 m_whatBox
= new KComboBox(this);
117 for (unsigned int i
= 0; i
< sizeof(g_whatItems
) / sizeof(SettingsItem
); ++i
) {
118 m_whatBox
->addItem(g_whatItems
[i
].text
);
120 connect(m_whatBox
, SIGNAL(currentIndexChanged(int)), this, SLOT(updateButtons()));
122 // add "Add selector" button
123 m_addSelectorButton
= new QPushButton(this);
124 m_addSelectorButton
->setIcon(KIcon("list-add"));
125 m_addSelectorButton
->setToolTip(i18nc("@info", "Add search option"));
126 m_addSelectorButton
->setSizePolicy(QSizePolicy::Fixed
, QSizePolicy::Fixed
);
127 connect(m_addSelectorButton
, SIGNAL(clicked()), this, SLOT(slotAddSelectorButtonClicked()));
129 // add button "Search"
130 m_searchButton
= new QPushButton(this);
131 m_searchButton
->setIcon(KIcon("edit-find"));
132 m_searchButton
->setText(i18nc("@action:button", "Search"));
133 m_searchButton
->setToolTip(i18nc("@info", "Start searching"));
134 m_searchButton
->setEnabled(false);
135 connect(m_searchButton
, SIGNAL(clicked()), this, SIGNAL(searchOptionsChanged()));
138 m_saveButton
= new QPushButton(this);
139 m_saveButton
->setIcon(KIcon("document-save"));
140 m_saveButton
->setText(i18nc("@action:button", "Save"));
141 m_saveButton
->setToolTip(i18nc("@info", "Save search options"));
142 m_saveButton
->setEnabled(false);
143 connect(m_saveButton
, SIGNAL(clicked()), this, SLOT(saveQuery()));
145 // add button "Close"
146 QPushButton
* closeButton
= new QPushButton(this);
147 closeButton
->setIcon(KIcon("dialog-close"));
148 closeButton
->setText(i18nc("@action:button", "Close"));
149 closeButton
->setToolTip(i18nc("@info", "Close search options"));
150 connect(closeButton
, SIGNAL(clicked()), this, SLOT(hide()));
152 QHBoxLayout
* topLineLayout
= new QHBoxLayout();
153 topLineLayout
->addWidget(m_addSelectorButton
);
154 topLineLayout
->addWidget(searchLabel
);
155 topLineLayout
->addWidget(m_locationBox
);
156 topLineLayout
->addWidget(whatLabel
);
157 topLineLayout
->addWidget(m_whatBox
);
158 topLineLayout
->addWidget(new QWidget(this), 1); // filler
159 topLineLayout
->addWidget(m_searchButton
);
160 topLineLayout
->addWidget(m_saveButton
);
161 topLineLayout
->addWidget(closeButton
);
163 m_vBoxLayout
->addWidget(new KSeparator(this));
164 m_vBoxLayout
->addLayout(topLineLayout
);
165 m_vBoxLayout
->addWidget(new KSeparator(this));
168 DolphinSearchOptionsConfigurator::~DolphinSearchOptionsConfigurator()
170 // store the UI configuration
171 const int locationIndex
= m_locationBox
->currentIndex();
172 SearchSettings::setLocation(g_locationItems
[locationIndex
].settingsName
);
174 const int whatIndex
= m_whatBox
->currentIndex();
175 SearchSettings::setWhat(g_whatItems
[whatIndex
].settingsName
);
177 QString criteriaString
;
178 foreach(const SearchCriterionSelector
* criterion
, m_criteria
) {
179 if (!criteriaString
.isEmpty()) {
180 criteriaString
+= ',';
182 const int index
= static_cast<int>(criterion
->type());
183 criteriaString
+= g_criterionItems
[index
].settingsName
;
185 SearchSettings::setCriteria(criteriaString
);
187 SearchSettings::self()->writeConfig();
190 QString
DolphinSearchOptionsConfigurator::customSearchQuery() const
192 return m_customSearchQuery
;
196 KUrl
DolphinSearchOptionsConfigurator::directory() const
201 KUrl
DolphinSearchOptionsConfigurator::nepomukSearchUrl() const
203 const Nepomuk::Query::Query query
= nepomukQuery();
204 return query
.isValid() ? query
.toSearchUrl() : KUrl();
207 void DolphinSearchOptionsConfigurator::setCustomSearchQuery(const QString
& searchQuery
)
209 m_customSearchQuery
= searchQuery
.simplified();
213 void DolphinSearchOptionsConfigurator::setDirectory(const KUrl
& dir
)
215 if (dir
.protocol() != QString::fromLatin1("nepomuksearch")) {
220 void DolphinSearchOptionsConfigurator::showEvent(QShowEvent
* event
)
222 if (!event
->spontaneous() && !m_initialized
) {
223 // restore the UI layout of the last session
224 const QString location
= SearchSettings::location();
225 for (unsigned int i
= 0; i
< sizeof(g_locationItems
) / sizeof(SettingsItem
); ++i
) {
226 if (g_locationItems
[i
].settingsName
== location
) {
227 m_locationBox
->setCurrentIndex(i
);
232 const QString what
= SearchSettings::what();
233 for (unsigned int i
= 0; i
< sizeof(g_whatItems
) / sizeof(SettingsItem
); ++i
) {
234 if (g_whatItems
[i
].settingsName
== what
) {
235 m_whatBox
->setCurrentIndex(i
);
240 const QString criteria
= SearchSettings::criteria();
241 QStringList criteriaList
= criteria
.split(',');
242 foreach (const QString
& criterionName
, criteriaList
) {
243 for (unsigned int i
= 0; i
< sizeof(g_criterionItems
) / sizeof(CriterionItem
); ++i
) {
244 if (g_criterionItems
[i
].settingsName
== criterionName
) {
245 const SearchCriterionSelector::Type type
= g_criterionItems
[i
].type
;
246 addCriterion(new SearchCriterionSelector(type
, this));
252 m_initialized
= true;
254 QWidget::showEvent(event
);
257 void DolphinSearchOptionsConfigurator::slotAddSelectorButtonClicked()
259 SearchCriterionSelector
* selector
= new SearchCriterionSelector(SearchCriterionSelector::Date
, this);
260 addCriterion(selector
);
263 void DolphinSearchOptionsConfigurator::removeCriterion()
265 SearchCriterionSelector
* criterion
= qobject_cast
<SearchCriterionSelector
*>(sender());
266 Q_ASSERT(criterion
!= 0);
267 m_vBoxLayout
->removeWidget(criterion
);
269 const int index
= m_criteria
.indexOf(criterion
);
270 m_criteria
.removeAt(index
);
272 criterion
->deleteLater();
277 void DolphinSearchOptionsConfigurator::saveQuery()
279 QPointer
<SearchOptionDialogBox
> dialog
= new SearchOptionDialogBox( 0 );
281 if (dialog
->exec() == QDialog::Accepted
) {
282 KFilePlacesModel
* model
= DolphinSettings::instance().placesModel();
283 model
->addPlace(dialog
->text(), nepomukSearchUrl());
288 void DolphinSearchOptionsConfigurator::updateButtons()
290 const bool enable
= nepomukQuery().isValid();
291 m_searchButton
->setEnabled(enable
);
292 m_saveButton
->setEnabled(enable
);
294 const int selectors
= m_vBoxLayout
->count() - 1;
295 m_addSelectorButton
->setEnabled(selectors
< 10);
298 void DolphinSearchOptionsConfigurator::addCriterion(SearchCriterionSelector
* criterion
)
300 connect(criterion
, SIGNAL(removeCriterion()), this, SLOT(removeCriterion()));
301 connect(criterion
, SIGNAL(criterionChanged()), this, SLOT(updateButtons()));
303 // insert the new selector before the KSeparator at the bottom
304 const int index
= m_vBoxLayout
->count() - 1;
305 m_vBoxLayout
->insertWidget(index
, criterion
);
308 m_criteria
.append(criterion
);
311 Nepomuk::Query::Query
DolphinSearchOptionsConfigurator::nepomukQuery() const
313 Nepomuk::Query::AndTerm andTerm
;
315 // add search criterion terms
316 foreach (const SearchCriterionSelector
* criterion
, m_criteria
) {
317 const Nepomuk::Query::Term term
= criterion
->queryTerm();
318 andTerm
.addSubTerm(term
);
321 bool addCustomQuery
= true;
323 // filter result by the "What" filter
324 switch (m_whatBox
->currentIndex()) {
327 const Nepomuk::Query::ResourceTypeTerm
image(Nepomuk::Vocabulary::NFO::Image());
328 andTerm
.addSubTerm(image
);
333 const Nepomuk::Query::ResourceTypeTerm
textDocument(Nepomuk::Vocabulary::NFO::TextDocument());
334 andTerm
.addSubTerm(textDocument
);
339 // trueg: Restriction to filename differs a bit from restriction to a type of file since it does not add a condition
340 // on the query but influences the text edited in the search bar directly.
341 // This is a bit tricky as we need to use the search bar text as plain text value for filename searches
342 // We do it the ugly way assuming the user only entered a literal value.
343 Nepomuk::Query::ComparisonTerm
filenameTerm(Nepomuk::Vocabulary::NFO::fileName(), Nepomuk::Query::LiteralTerm(m_customSearchQuery
));
344 andTerm
.addSubTerm(filenameTerm
);
345 addCustomQuery
= false;
350 if (addCustomQuery
) {
351 // add custom query term from the searchbar
352 const Nepomuk::Query::Query customQuery
= Nepomuk::Query::QueryParser::parseQuery(m_customSearchQuery
);
353 if (customQuery
.isValid()) {
354 andTerm
.addSubTerm(customQuery
.term());
358 if ((m_locationBox
->currentIndex() == 1) && m_directory
.isValid()) {
359 // "From Here" is selected as location filter
360 Nepomuk::Query::FileQuery fileQuery
;
361 fileQuery
.addIncludeFolder(m_directory
);
365 Nepomuk::Query::Query query
;
366 query
.setTerm(andTerm
);
370 #include "dolphinsearchoptionsconfigurator.moc"