]> cloud.milkyroute.net Git - dolphin.git/blob - src/search/dolphinsearchoptionsconfigurator.cpp
Use Nepomuk::Query::Query for global search queries, as it does not only return files...
[dolphin.git] / src / search / dolphinsearchoptionsconfigurator.cpp
1 /***************************************************************************
2 * Copyright (C) 2009 by Peter Penz <peter.penz@gmx.at> *
3 * *
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. *
8 * *
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. *
13 * *
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 ***************************************************************************/
19
20 #include "dolphinsearchoptionsconfigurator.h"
21
22 #include "dolphin_searchsettings.h"
23 #include <settings/dolphinsettings.h>
24
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>
32
33 #include "nfo.h"
34
35 #include <kcombobox.h>
36 #include <kdialog.h>
37 #include <kfileplacesmodel.h>
38 #include <kicon.h>
39 #include <klineedit.h>
40 #include <klocale.h>
41 #include <kseparator.h>
42
43 #include "searchcriterionselector.h"
44 #include "searchoptiondialogbox.h"
45
46 #include <QButtonGroup>
47 #include <QHBoxLayout>
48 #include <QLabel>
49 #include <QPushButton>
50 #include <QShowEvent>
51 #include <QVBoxLayout>
52
53 struct SettingsItem
54 {
55 const char* settingsName;
56 const char* text;
57 };
58
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")}
64 };
65
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")}
73 };
74
75 struct CriterionItem
76 {
77 const char* settingsName;
78 SearchCriterionSelector::Type type;
79 };
80
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}
88 };
89
90 DolphinSearchOptionsConfigurator::DolphinSearchOptionsConfigurator(QWidget* parent) :
91 QWidget(parent),
92 m_initialized(false),
93 m_directory(),
94 m_locationBox(0),
95 m_whatBox(0),
96 m_addSelectorButton(0),
97 m_searchButton(0),
98 m_saveButton(0),
99 m_vBoxLayout(0),
100 m_criteria(),
101 m_customSearchQuery()
102 {
103 m_vBoxLayout = new QVBoxLayout(this);
104
105 // add "search" configuration
106 QLabel* searchLabel = new QLabel(i18nc("@label", "Search:"));
107
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);
111 }
112
113 // add "what" configuration
114 QLabel* whatLabel = new QLabel(i18nc("@label", "What:"));
115
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);
119 }
120 connect(m_whatBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateButtons()));
121
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()));
128
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()));
136
137 // add button "Save"
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()));
144
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()));
151
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);
162
163 m_vBoxLayout->addWidget(new KSeparator(this));
164 m_vBoxLayout->addLayout(topLineLayout);
165 m_vBoxLayout->addWidget(new KSeparator(this));
166 }
167
168 DolphinSearchOptionsConfigurator::~DolphinSearchOptionsConfigurator()
169 {
170 // store the UI configuration
171 const int locationIndex = m_locationBox->currentIndex();
172 SearchSettings::setLocation(g_locationItems[locationIndex].settingsName);
173
174 const int whatIndex = m_whatBox->currentIndex();
175 SearchSettings::setWhat(g_whatItems[whatIndex].settingsName);
176
177 QString criteriaString;
178 foreach(const SearchCriterionSelector* criterion, m_criteria) {
179 if (!criteriaString.isEmpty()) {
180 criteriaString += ',';
181 }
182 const int index = static_cast<int>(criterion->type());
183 criteriaString += g_criterionItems[index].settingsName;
184 }
185 SearchSettings::setCriteria(criteriaString);
186
187 SearchSettings::self()->writeConfig();
188 }
189
190 QString DolphinSearchOptionsConfigurator::customSearchQuery() const
191 {
192 return m_customSearchQuery;
193 }
194
195
196 KUrl DolphinSearchOptionsConfigurator::directory() const
197 {
198 return m_directory;
199 }
200
201 KUrl DolphinSearchOptionsConfigurator::nepomukSearchUrl() const
202 {
203 const Nepomuk::Query::Query query = nepomukQuery();
204 return query.isValid() ? query.toSearchUrl() : KUrl();
205 }
206
207 void DolphinSearchOptionsConfigurator::setCustomSearchQuery(const QString& searchQuery)
208 {
209 m_customSearchQuery = searchQuery.simplified();
210 updateButtons();
211 }
212
213 void DolphinSearchOptionsConfigurator::setDirectory(const KUrl& dir)
214 {
215 if (dir.protocol() != QString::fromLatin1("nepomuksearch")) {
216 m_directory = dir;
217 }
218 }
219
220 void DolphinSearchOptionsConfigurator::showEvent(QShowEvent* event)
221 {
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);
228 break;
229 }
230 }
231
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);
236 break;
237 }
238 }
239
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));
247 break;
248 }
249 }
250 }
251
252 m_initialized = true;
253 }
254 QWidget::showEvent(event);
255 }
256
257 void DolphinSearchOptionsConfigurator::slotAddSelectorButtonClicked()
258 {
259 SearchCriterionSelector* selector = new SearchCriterionSelector(SearchCriterionSelector::Date, this);
260 addCriterion(selector);
261 }
262
263 void DolphinSearchOptionsConfigurator::removeCriterion()
264 {
265 SearchCriterionSelector* criterion = qobject_cast<SearchCriterionSelector*>(sender());
266 Q_ASSERT(criterion != 0);
267 m_vBoxLayout->removeWidget(criterion);
268
269 const int index = m_criteria.indexOf(criterion);
270 m_criteria.removeAt(index);
271
272 criterion->deleteLater();
273
274 updateButtons();
275 }
276
277 void DolphinSearchOptionsConfigurator::saveQuery()
278 {
279 QPointer<SearchOptionDialogBox> dialog = new SearchOptionDialogBox( 0 );
280
281 if (dialog->exec() == QDialog::Accepted) {
282 KFilePlacesModel* model = DolphinSettings::instance().placesModel();
283 model->addPlace(dialog->text(), nepomukSearchUrl());
284 }
285 delete dialog;
286 }
287
288 void DolphinSearchOptionsConfigurator::updateButtons()
289 {
290 const bool enable = nepomukQuery().isValid();
291 m_searchButton->setEnabled(enable);
292 m_saveButton->setEnabled(enable);
293
294 const int selectors = m_vBoxLayout->count() - 1;
295 m_addSelectorButton->setEnabled(selectors < 10);
296 }
297
298 void DolphinSearchOptionsConfigurator::addCriterion(SearchCriterionSelector* criterion)
299 {
300 connect(criterion, SIGNAL(removeCriterion()), this, SLOT(removeCriterion()));
301 connect(criterion, SIGNAL(criterionChanged()), this, SLOT(updateButtons()));
302
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);
306 updateButtons();
307
308 m_criteria.append(criterion);
309 }
310
311 Nepomuk::Query::Query DolphinSearchOptionsConfigurator::nepomukQuery() const
312 {
313 Nepomuk::Query::AndTerm andTerm;
314
315 // add search criterion terms
316 foreach (const SearchCriterionSelector* criterion, m_criteria) {
317 const Nepomuk::Query::Term term = criterion->queryTerm();
318 andTerm.addSubTerm(term);
319 }
320
321 bool addCustomQuery = true;
322
323 // filter result by the "What" filter
324 switch (m_whatBox->currentIndex()) {
325 case 1: {
326 // Image
327 const Nepomuk::Query::ResourceTypeTerm image(Nepomuk::Vocabulary::NFO::Image());
328 andTerm.addSubTerm(image);
329 break;
330 }
331 case 2: {
332 // Text
333 const Nepomuk::Query::ResourceTypeTerm textDocument(Nepomuk::Vocabulary::NFO::TextDocument());
334 andTerm.addSubTerm(textDocument);
335 break;
336 }
337 case 3: {
338 // Filenames
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;
346 }
347 default: break;
348 }
349
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());
355 }
356 }
357
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);
362 return fileQuery;
363 }
364
365 Nepomuk::Query::Query query;
366 query.setTerm(andTerm);
367 return query;
368 }
369
370 #include "dolphinsearchoptionsconfigurator.moc"