]> cloud.milkyroute.net Git - dolphin.git/blob - src/search/dolphinsearchoptionsconfigurator.cpp
Fix context for action name "Delete (using shortcut for Trash)"
[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 if ( query.isValid() ) {
205 KUrl url = query.toSearchUrl();
206 url.addQueryItem( QLatin1String( "userquery" ), customSearchQuery() );
207 return url;
208 }
209 else {
210 return KUrl();
211 }
212 }
213
214 void DolphinSearchOptionsConfigurator::setCustomSearchQuery(const QString& searchQuery)
215 {
216 m_customSearchQuery = searchQuery.simplified();
217 updateButtons();
218 }
219
220 void DolphinSearchOptionsConfigurator::setDirectory(const KUrl& dir)
221 {
222 if (dir.protocol() != QString::fromLatin1("nepomuksearch")) {
223 m_directory = dir;
224 }
225 }
226
227 void DolphinSearchOptionsConfigurator::showEvent(QShowEvent* event)
228 {
229 if (!event->spontaneous() && !m_initialized) {
230 // restore the UI layout of the last session
231 const QString location = SearchSettings::location();
232 for (unsigned int i = 0; i < sizeof(g_locationItems) / sizeof(SettingsItem); ++i) {
233 if (g_locationItems[i].settingsName == location) {
234 m_locationBox->setCurrentIndex(i);
235 break;
236 }
237 }
238
239 const QString what = SearchSettings::what();
240 for (unsigned int i = 0; i < sizeof(g_whatItems) / sizeof(SettingsItem); ++i) {
241 if (g_whatItems[i].settingsName == what) {
242 m_whatBox->setCurrentIndex(i);
243 break;
244 }
245 }
246
247 const QString criteria = SearchSettings::criteria();
248 QStringList criteriaList = criteria.split(',');
249 foreach (const QString& criterionName, criteriaList) {
250 for (unsigned int i = 0; i < sizeof(g_criterionItems) / sizeof(CriterionItem); ++i) {
251 if (g_criterionItems[i].settingsName == criterionName) {
252 const SearchCriterionSelector::Type type = g_criterionItems[i].type;
253 addCriterion(new SearchCriterionSelector(type, this));
254 break;
255 }
256 }
257 }
258
259 m_initialized = true;
260 }
261 QWidget::showEvent(event);
262 }
263
264 void DolphinSearchOptionsConfigurator::slotAddSelectorButtonClicked()
265 {
266 SearchCriterionSelector* selector = new SearchCriterionSelector(SearchCriterionSelector::Date, this);
267 addCriterion(selector);
268 }
269
270 void DolphinSearchOptionsConfigurator::removeCriterion()
271 {
272 SearchCriterionSelector* criterion = qobject_cast<SearchCriterionSelector*>(sender());
273 Q_ASSERT(criterion != 0);
274 m_vBoxLayout->removeWidget(criterion);
275
276 const int index = m_criteria.indexOf(criterion);
277 m_criteria.removeAt(index);
278
279 criterion->deleteLater();
280
281 updateButtons();
282 }
283
284 void DolphinSearchOptionsConfigurator::saveQuery()
285 {
286 QPointer<SearchOptionDialogBox> dialog = new SearchOptionDialogBox( 0 );
287
288 if (dialog->exec() == QDialog::Accepted) {
289 KFilePlacesModel* model = DolphinSettings::instance().placesModel();
290 model->addPlace(dialog->text(), nepomukSearchUrl());
291 }
292 delete dialog;
293 }
294
295 void DolphinSearchOptionsConfigurator::updateButtons()
296 {
297 const bool enable = nepomukQuery().isValid();
298 m_searchButton->setEnabled(enable);
299 m_saveButton->setEnabled(enable);
300
301 const int selectors = m_vBoxLayout->count() - 1;
302 m_addSelectorButton->setEnabled(selectors < 10);
303 }
304
305 void DolphinSearchOptionsConfigurator::addCriterion(SearchCriterionSelector* criterion)
306 {
307 connect(criterion, SIGNAL(removeCriterion()), this, SLOT(removeCriterion()));
308 connect(criterion, SIGNAL(criterionChanged()), this, SLOT(updateButtons()));
309
310 // insert the new selector before the KSeparator at the bottom
311 const int index = m_vBoxLayout->count() - 1;
312 m_vBoxLayout->insertWidget(index, criterion);
313 updateButtons();
314
315 m_criteria.append(criterion);
316 }
317
318 Nepomuk::Query::Query DolphinSearchOptionsConfigurator::nepomukQuery() const
319 {
320 Nepomuk::Query::AndTerm andTerm;
321
322 // add search criterion terms
323 foreach (const SearchCriterionSelector* criterion, m_criteria) {
324 const Nepomuk::Query::Term term = criterion->queryTerm();
325 andTerm.addSubTerm(term);
326 }
327
328 bool addCustomQuery = true;
329
330 // filter result by the "What" filter
331 switch (m_whatBox->currentIndex()) {
332 case 1: {
333 // Image
334 const Nepomuk::Query::ResourceTypeTerm image(Nepomuk::Vocabulary::NFO::Image());
335 andTerm.addSubTerm(image);
336 break;
337 }
338 case 2: {
339 // Text
340 const Nepomuk::Query::ResourceTypeTerm textDocument(Nepomuk::Vocabulary::NFO::TextDocument());
341 andTerm.addSubTerm(textDocument);
342 break;
343 }
344 case 3: {
345 // Filenames
346 // trueg: Restriction to filename differs a bit from restriction to a type of file since it does not add a condition
347 // on the query but influences the text edited in the search bar directly.
348 // This is a bit tricky as we need to use the search bar text as plain text value for filename searches
349 // We do it the ugly way assuming the user only entered a literal value.
350 Nepomuk::Query::ComparisonTerm filenameTerm(Nepomuk::Vocabulary::NFO::fileName(), Nepomuk::Query::LiteralTerm(m_customSearchQuery));
351 andTerm.addSubTerm(filenameTerm);
352 addCustomQuery = false;
353 }
354 default: break;
355 }
356
357 if (addCustomQuery) {
358 // add custom query term from the searchbar
359 const Nepomuk::Query::Query customQuery = Nepomuk::Query::QueryParser::parseQuery(m_customSearchQuery);
360 if (customQuery.isValid()) {
361 andTerm.addSubTerm(customQuery.term());
362 }
363 }
364
365 if ((m_locationBox->currentIndex() == 1) && m_directory.isValid()) {
366 // "From Here" is selected as location filter
367 Nepomuk::Query::FileQuery fileQuery;
368 fileQuery.addIncludeFolder(m_directory);
369 fileQuery.setTerm(andTerm);
370 return fileQuery;
371 }
372
373 Nepomuk::Query::Query query;
374 query.setTerm(andTerm);
375 return query;
376 }
377
378 #include "dolphinsearchoptionsconfigurator.moc"