]> cloud.milkyroute.net Git - dolphin.git/blob - src/search/dolphinsearchoptionsconfigurator.cpp
SVN_SILENT made messages (.desktop file)
[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/term.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
45 #include <QButtonGroup>
46 #include <QHBoxLayout>
47 #include <QLabel>
48 #include <QPushButton>
49 #include <QShowEvent>
50 #include <QVBoxLayout>
51
52 struct SettingsItem
53 {
54 const char* settingsName;
55 const char* text;
56 };
57
58 // Contains the settings names and translated texts
59 // for each item of the location-combo-box.
60 static const SettingsItem g_locationItems[] = {
61 {"Everywhere", I18N_NOOP2("@label", "Everywhere")},
62 {"From Here", I18N_NOOP2("@label", "From Here")}
63 };
64
65 // Contains the settings names and translated texts
66 // for each item of the what-combobox.
67 static const SettingsItem g_whatItems[] = {
68 {"All", I18N_NOOP2("@label", "All")},
69 {"Images", I18N_NOOP2("@label", "Images")},
70 {"Text", I18N_NOOP2("@label", "Text")},
71 {"Filenames", I18N_NOOP2("@label", "Filenames")}
72 };
73
74 struct CriterionItem
75 {
76 const char* settingsName;
77 SearchCriterionSelector::Type type;
78 };
79
80 // Contains the settings names for type
81 // of availabe search criterion.
82 static const CriterionItem g_criterionItems[] = {
83 {"Date", SearchCriterionSelector::Date},
84 {"Size", SearchCriterionSelector::Size},
85 {"Tag", SearchCriterionSelector::Tag},
86 {"Raging", SearchCriterionSelector::Rating}
87 };
88
89 DolphinSearchOptionsConfigurator::DolphinSearchOptionsConfigurator(QWidget* parent) :
90 QWidget(parent),
91 m_initialized(false),
92 m_directory(),
93 m_locationBox(0),
94 m_whatBox(0),
95 m_addSelectorButton(0),
96 m_searchButton(0),
97 m_saveButton(0),
98 m_vBoxLayout(0),
99 m_criteria(),
100 m_customSearchQuery()
101 {
102 m_vBoxLayout = new QVBoxLayout(this);
103
104 // add "search" configuration
105 QLabel* searchLabel = new QLabel(i18nc("@label", "Search:"));
106
107 m_locationBox = new KComboBox(this);
108 for (unsigned int i = 0; i < sizeof(g_locationItems) / sizeof(SettingsItem); ++i) {
109 m_locationBox->addItem(g_locationItems[i].text);
110 }
111
112 // add "what" configuration
113 QLabel* whatLabel = new QLabel(i18nc("@label", "What:"));
114
115 m_whatBox = new KComboBox(this);
116 for (unsigned int i = 0; i < sizeof(g_whatItems) / sizeof(SettingsItem); ++i) {
117 m_whatBox->addItem(g_whatItems[i].text);
118 }
119 connect(m_whatBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updateButtons()));
120
121 // add "Add selector" button
122 m_addSelectorButton = new QPushButton(this);
123 m_addSelectorButton->setIcon(KIcon("list-add"));
124 m_addSelectorButton->setToolTip(i18nc("@info", "Add search option"));
125 m_addSelectorButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
126 connect(m_addSelectorButton, SIGNAL(clicked()), this, SLOT(slotAddSelectorButtonClicked()));
127
128 // add button "Search"
129 m_searchButton = new QPushButton(this);
130 m_searchButton->setIcon(KIcon("edit-find"));
131 m_searchButton->setText(i18nc("@action:button", "Search"));
132 m_searchButton->setToolTip(i18nc("@info", "Start searching"));
133 m_searchButton->setEnabled(false);
134 connect(m_searchButton, SIGNAL(clicked()), this, SIGNAL(searchOptionsChanged()));
135
136 // add button "Save"
137 m_saveButton = new QPushButton(this);
138 m_saveButton->setIcon(KIcon("document-save"));
139 m_saveButton->setText(i18nc("@action:button", "Save"));
140 m_saveButton->setToolTip(i18nc("@info", "Save search options"));
141 m_saveButton->setEnabled(false);
142 connect(m_saveButton, SIGNAL(clicked()), this, SLOT(saveQuery()));
143
144 // add button "Close"
145 QPushButton* closeButton = new QPushButton(this);
146 closeButton->setIcon(KIcon("dialog-close"));
147 closeButton->setText(i18nc("@action:button", "Close"));
148 closeButton->setToolTip(i18nc("@info", "Close search options"));
149 connect(closeButton, SIGNAL(clicked()), this, SLOT(hide()));
150
151 QHBoxLayout* topLineLayout = new QHBoxLayout();
152 topLineLayout->addWidget(m_addSelectorButton);
153 topLineLayout->addWidget(searchLabel);
154 topLineLayout->addWidget(m_locationBox);
155 topLineLayout->addWidget(whatLabel);
156 topLineLayout->addWidget(m_whatBox);
157 topLineLayout->addWidget(new QWidget(this), 1); // filler
158 topLineLayout->addWidget(m_searchButton);
159 topLineLayout->addWidget(m_saveButton);
160 topLineLayout->addWidget(closeButton);
161
162 m_vBoxLayout->addWidget(new KSeparator(this));
163 m_vBoxLayout->addLayout(topLineLayout);
164 m_vBoxLayout->addWidget(new KSeparator(this));
165 }
166
167 DolphinSearchOptionsConfigurator::~DolphinSearchOptionsConfigurator()
168 {
169 // store the UI configuration
170 const int locationIndex = m_locationBox->currentIndex();
171 SearchSettings::setLocation(g_locationItems[locationIndex].settingsName);
172
173 const int whatIndex = m_whatBox->currentIndex();
174 SearchSettings::setWhat(g_whatItems[whatIndex].settingsName);
175
176 QString criteriaString;
177 foreach(const SearchCriterionSelector* criterion, m_criteria) {
178 if (!criteriaString.isEmpty()) {
179 criteriaString += ',';
180 }
181 const int index = static_cast<int>(criterion->type());
182 criteriaString += g_criterionItems[index].settingsName;
183 }
184 SearchSettings::setCriteria(criteriaString);
185
186 SearchSettings::self()->writeConfig();
187 }
188
189 QString DolphinSearchOptionsConfigurator::customSearchQuery() const
190 {
191 return m_customSearchQuery;
192 }
193
194
195 KUrl DolphinSearchOptionsConfigurator::directory() const
196 {
197 return m_directory;
198 }
199
200 KUrl DolphinSearchOptionsConfigurator::nepomukSearchUrl() const
201 {
202 const Nepomuk::Query::Query query = nepomukQuery();
203 return query.isValid() ? query.toSearchUrl() : KUrl();
204 }
205
206 void DolphinSearchOptionsConfigurator::setCustomSearchQuery(const QString& searchQuery)
207 {
208 m_customSearchQuery = searchQuery.simplified();
209 updateButtons();
210 }
211
212 void DolphinSearchOptionsConfigurator::setDirectory(const KUrl& dir)
213 {
214 if (dir.protocol() != QString::fromLatin1("nepomuksearch")) {
215 m_directory = dir;
216 }
217 }
218
219 void DolphinSearchOptionsConfigurator::showEvent(QShowEvent* event)
220 {
221 if (!event->spontaneous() && !m_initialized) {
222 // restore the UI layout of the last session
223 const QString location = SearchSettings::location();
224 for (unsigned int i = 0; i < sizeof(g_locationItems) / sizeof(SettingsItem); ++i) {
225 if (g_locationItems[i].settingsName == location) {
226 m_locationBox->setCurrentIndex(i);
227 break;
228 }
229 }
230
231 const QString what = SearchSettings::what();
232 for (unsigned int i = 0; i < sizeof(g_whatItems) / sizeof(SettingsItem); ++i) {
233 if (g_whatItems[i].settingsName == what) {
234 m_whatBox->setCurrentIndex(i);
235 break;
236 }
237 }
238
239 const QString criteria = SearchSettings::criteria();
240 QStringList criteriaList = criteria.split(',');
241 foreach (const QString& criterionName, criteriaList) {
242 for (unsigned int i = 0; i < sizeof(g_criterionItems) / sizeof(CriterionItem); ++i) {
243 if (g_criterionItems[i].settingsName == criterionName) {
244 const SearchCriterionSelector::Type type = g_criterionItems[i].type;
245 addCriterion(new SearchCriterionSelector(type, this));
246 break;
247 }
248 }
249 }
250
251 m_initialized = true;
252 }
253 QWidget::showEvent(event);
254 }
255
256 void DolphinSearchOptionsConfigurator::slotAddSelectorButtonClicked()
257 {
258 SearchCriterionSelector* selector = new SearchCriterionSelector(SearchCriterionSelector::Date, this);
259 addCriterion(selector);
260 }
261
262 void DolphinSearchOptionsConfigurator::removeCriterion()
263 {
264 SearchCriterionSelector* criterion = qobject_cast<SearchCriterionSelector*>(sender());
265 Q_ASSERT(criterion != 0);
266 m_vBoxLayout->removeWidget(criterion);
267
268 const int index = m_criteria.indexOf(criterion);
269 m_criteria.removeAt(index);
270
271 criterion->deleteLater();
272
273 updateButtons();
274 }
275
276 void DolphinSearchOptionsConfigurator::saveQuery()
277 {
278 // TODO: provide a custom dialog class for KDE 4.5, which
279 // enables/disables the OK button depend on whether a text
280 // has been entered.
281 QPointer<KDialog> dialog = new KDialog(0, Qt::Dialog);
282
283 QWidget* container = new QWidget(dialog);
284
285 QLabel* label = new QLabel(i18nc("@label", "Name:"), container);
286 KLineEdit* lineEdit = new KLineEdit(container);
287 lineEdit->setMinimumWidth(250);
288
289 QHBoxLayout* layout = new QHBoxLayout(container);
290 layout->addWidget(label, Qt::AlignRight);
291 layout->addWidget(lineEdit);
292
293 dialog->setMainWidget(container);
294 dialog->setCaption(i18nc("@title:window", "Save Search Options"));
295 dialog->setButtons(KDialog::Ok | KDialog::Cancel);
296 dialog->setDefaultButton(KDialog::Ok);
297 dialog->setButtonText(KDialog::Ok, i18nc("@action:button", "Save"));
298
299 KConfigGroup dialogConfig(KSharedConfig::openConfig("dolphinrc"),
300 "SaveSearchOptionsDialog");
301 dialog->restoreDialogSize(dialogConfig);
302 if ((dialog->exec() == QDialog::Accepted) && !lineEdit->text().isEmpty()) {
303 KFilePlacesModel* model = DolphinSettings::instance().placesModel();
304 model->addPlace(lineEdit->text(), nepomukSearchUrl());
305 }
306 delete dialog;
307 }
308
309 void DolphinSearchOptionsConfigurator::updateButtons()
310 {
311 const bool enable = nepomukQuery().isValid();
312 m_searchButton->setEnabled(enable);
313 m_saveButton->setEnabled(enable);
314
315 const int selectors = m_vBoxLayout->count() - 1;
316 m_addSelectorButton->setEnabled(selectors < 10);
317 }
318
319 void DolphinSearchOptionsConfigurator::addCriterion(SearchCriterionSelector* criterion)
320 {
321 connect(criterion, SIGNAL(removeCriterion()), this, SLOT(removeCriterion()));
322 connect(criterion, SIGNAL(criterionChanged()), this, SLOT(updateButtons()));
323
324 // insert the new selector before the KSeparator at the bottom
325 const int index = m_vBoxLayout->count() - 1;
326 m_vBoxLayout->insertWidget(index, criterion);
327 updateButtons();
328
329 m_criteria.append(criterion);
330 }
331
332 Nepomuk::Query::Query DolphinSearchOptionsConfigurator::nepomukQuery() const
333 {
334 Nepomuk::Query::AndTerm andTerm;
335
336 // add search criterion terms
337 foreach (const SearchCriterionSelector* criterion, m_criteria) {
338 const Nepomuk::Query::Term term = criterion->queryTerm();
339 andTerm.addSubTerm(term);
340 }
341
342 // add custom query term from the searchbar
343 const Nepomuk::Query::Query customQuery = Nepomuk::Query::QueryParser::parseQuery(m_customSearchQuery);
344 if (customQuery.isValid()) {
345 andTerm.addSubTerm(customQuery.term());
346 }
347
348 // filter result by the "What" filter
349 switch (m_whatBox->currentIndex()) {
350 case 1: {
351 // Image
352 const Nepomuk::Query::ResourceTypeTerm image(Nepomuk::Vocabulary::NFO::Image());
353 andTerm.addSubTerm(image);
354 break;
355 }
356 case 2: {
357 // Text
358 const Nepomuk::Query::ResourceTypeTerm textDocument(Nepomuk::Vocabulary::NFO::TextDocument());
359 andTerm.addSubTerm(textDocument);
360 break;
361 }
362 default: break;
363 }
364
365 Nepomuk::Query::FileQuery fileQuery;
366 if ((m_locationBox->currentIndex() == 1) && m_directory.isValid()) {
367 // "From Here" is selected as location filter
368 fileQuery.addIncludeFolder(m_directory);
369 }
370 fileQuery.setTerm(andTerm);
371 return fileQuery;
372 }
373
374 #include "dolphinsearchoptionsconfigurator.moc"