1 | /* This file is part of Strigi Desktop Search |
2 | * |
3 | * Copyright (C) 2006 Jos van den Oever <jos@vandenoever.info> |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Library General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2 of the License, or (at your option) any later version. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Library General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Library General Public License |
16 | * along with this library; see the file COPYING.LIB. If not, write to |
17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | * Boston, MA 02110-1301, USA. |
19 | */ |
20 | #include "simplesearchgui.h" |
21 | #include "dlgfilters.h" |
22 | #include "dlglistindexedfiles.h" |
23 | #include "searchtabs.h" |
24 | #include "histogram.h" |
25 | #include "searchview.h" |
26 | #include <QtGui/QListWidget> |
27 | #include <QtGui/QListWidgetItem> |
28 | #include <QtGui/QLineEdit> |
29 | #include <QtGui/QVBoxLayout> |
30 | #include <QtGui/QStackedWidget> |
31 | #include <QtGui/QLabel> |
32 | #include <QtGui/QDockWidget> |
33 | #include <QtGui/QPushButton> |
34 | #include <QtGui/QToolButton> |
35 | #include <QtGui/QFileDialog> |
36 | #include <QtGui/QComboBox> |
37 | #include <QtGui/QMenu> |
38 | #include <QtGui/QMenuBar> |
39 | #include <QtGui/QAction> |
40 | #include <QtCore/QString> |
41 | #include <QtCore/QDebug> |
42 | #include <QtCore/QCoreApplication> |
43 | #include <QtCore/QProcess> |
44 | #include <QtCore/QTimer> |
45 | #include <string> |
46 | #include <map> |
47 | #include <vector> |
48 | using namespace std; |
49 | |
50 | SimpleSearchGui::SimpleSearchGui (QWidget * parent, Qt::WFlags flags) |
51 | : QMainWindow (parent, flags) |
52 | { |
53 | mainview = new QStackedWidget(); |
54 | |
55 | QWidget* statuswidget = new QWidget(); |
56 | QVBoxLayout *statuslayout = new QVBoxLayout; |
57 | statuslayout->setMargin(0); |
58 | statusview = new QLabel(); |
59 | statusview->setAlignment(Qt::AlignTop); |
60 | statusview->setMargin(25); |
61 | indexing = false; |
62 | running = false; |
63 | starting = true; |
64 | indexeddirs = new QListWidget(); |
65 | indexeddirs->setSelectionMode(QAbstractItemView::ExtendedSelection); |
66 | adddir = new QPushButton(tr("add directory" )); |
67 | removedir = new QPushButton(tr("remove directory" )); |
68 | toggleindexing = new QPushButton(tr("start indexing" )); |
69 | toggledaemon = new QPushButton(tr("stop daemon" )); |
70 | statuslayout->addWidget(statusview); |
71 | QHBoxLayout *hlayout = new QHBoxLayout; |
72 | hlayout->addWidget(toggledaemon); |
73 | hlayout->addWidget(toggleindexing); |
74 | statuslayout->addLayout(hlayout); |
75 | |
76 | histogram = new Histogram(); |
77 | histogram->setOrientation(Qt::Vertical); |
78 | fieldnames = new QComboBox(); |
79 | fieldnames->addItems(strigi.getFieldNames()); |
80 | fieldnames->setCurrentIndex(fieldnames->findText("system.last_modified_time" )); |
81 | histogram->setFieldName("system.last_modified_time" ); |
82 | refreshHistogram = new QPushButton(tr("refresh histogram" )); |
83 | refreshHistogram->setEnabled(false); |
84 | |
85 | /* vector<string> backends = ClientInterface::getBackEnds(); |
86 | if (backends.size() > 1) { |
87 | backendsList = new QComboBox(); |
88 | for (uint i = 0; i< backends.size(); ++i) { |
89 | QString backend = backends[i].c_str(); |
90 | backendsList->insertItem(i, backend); |
91 | } |
92 | statuslayout->addWidget(backendsList); |
93 | } else {*/ |
94 | backendsList = 0; |
95 | // } |
96 | statuslayout->addWidget(indexeddirs); |
97 | hlayout = new QHBoxLayout; |
98 | hlayout->addWidget(adddir); |
99 | hlayout->addWidget(removedir); |
100 | statuslayout->addLayout(hlayout); |
101 | statuswidget->setLayout(statuslayout); |
102 | |
103 | tabs = new SearchTabs(); |
104 | tabs->addTab("kde" , "kde" ); |
105 | tabs->addTab("msg" , "content.mime_type:message/*" ); |
106 | tabs->addTab("irc" , "system.location:*konversation*log" ); |
107 | tabs->addTab("mail" , "content.mime_type:text/x-mail" ); |
108 | tabs->addTab("audio" , "content.mime_type:audio/*" ); |
109 | tabs->addTab("other" , |
110 | "-kde -system.location:*konversation*log -content.mime_type:message/* -content.mime_type:text/x-mail -content.mime_type:audio/*" ); |
111 | tabs->addTab("all" , "" ); |
112 | mainview->addWidget(tabs); |
113 | mainview->addWidget(statuswidget); |
114 | asyncstrigi.updateStatus(); |
115 | mainview->setCurrentIndex(1); |
116 | |
117 | queryfield = new QLineEdit(); |
118 | QVBoxLayout *layout = new QVBoxLayout; |
119 | layout->addWidget(mainview); |
120 | layout->addWidget(queryfield); |
121 | |
122 | /* The histogram widget is temporarily disabled |
123 | QVBoxLayout* histlayout = new QVBoxLayout(); |
124 | QDockWidget* histwidget = new QDockWidget(); |
125 | histwidget->setFeatures(QDockWidget::NoDockWidgetFeatures); |
126 | QWidget* histw = new QWidget(); |
127 | histw->setLayout(histlayout); |
128 | histwidget->setWidget(histw); |
129 | histlayout->addWidget(fieldnames); |
130 | histlayout->addWidget(histogram); |
131 | histlayout->addWidget(refreshHistogram); |
132 | addDockWidget(Qt::LeftDockWidgetArea, histwidget);*/ |
133 | |
134 | centralview = new QWidget(); |
135 | centralview->setLayout(layout); |
136 | setCentralWidget(centralview); |
137 | |
138 | createActions(); |
139 | createMenus(); |
140 | |
141 | connect(queryfield, SIGNAL(textChanged(const QString&)), |
142 | this, SLOT(query(const QString&))); |
143 | connect(toggleindexing, SIGNAL(clicked()), |
144 | this, SLOT(toggleIndexing())); |
145 | connect(toggledaemon, SIGNAL(clicked()), |
146 | this, SLOT(toggleDaemon())); |
147 | connect(adddir, SIGNAL(clicked()), |
148 | this, SLOT(addDirectory())); |
149 | connect(removedir, SIGNAL(clicked()), |
150 | this, SLOT(removeDirectory())); |
151 | queryfield->setFocus(Qt::ActiveWindowFocusReason); |
152 | |
153 | connect(&asyncstrigi,SIGNAL(statusUpdated(const QMap<QString, QString>& )), |
154 | this, SLOT(updateStatus(const QMap<QString, QString>& ))); |
155 | // connect(tabs->getSearchView(), SIGNAL(gotHits(const QString&)), |
156 | // histogram, SLOT(setQuery(const QString&))); |
157 | connect(refreshHistogram, SIGNAL(clicked()), |
158 | this, SLOT(refresh())); |
159 | connect(fieldnames, SIGNAL(currentIndexChanged(const QString&)), |
160 | histogram, SLOT(setFieldName(const QString&))); |
161 | |
162 | QTimer *timer = new QTimer(this); |
163 | connect(timer, SIGNAL(timeout()), this, SLOT(updateStatus())); |
164 | timer->start(2000); |
165 | asyncstrigi.updateStatus(); |
166 | } |
167 | void |
168 | SimpleSearchGui::refresh() { |
169 | histogram->setQuery(queryfield->text()); |
170 | } |
171 | void |
172 | SimpleSearchGui::() { |
173 | fileMenu = menuBar()->addMenu(tr("&File" )); |
174 | fileMenu->addAction(fileExitAct); |
175 | |
176 | editMenu = menuBar()->addMenu(tr("&Edit" )); |
177 | editMenu->addAction(editFiltersAct); |
178 | editMenu->addAction(editListIndexedFilesAct); |
179 | } |
180 | void |
181 | SimpleSearchGui::createActions() { |
182 | fileExitAct = new QAction(tr("&Exit" ), this); |
183 | fileExitAct->setShortcut(tr("Ctrl+Q" )); |
184 | fileExitAct->setStatusTip(tr("Quit the program" )); |
185 | connect(fileExitAct, SIGNAL(triggered()), this, SLOT(close())); |
186 | |
187 | editFiltersAct = new QAction(tr("Edit Filters" ), this); |
188 | editFiltersAct->setStatusTip(tr("Edit filename filters" )); |
189 | connect(editFiltersAct, SIGNAL(triggered()), this, SLOT(editFilters())); |
190 | |
191 | editListIndexedFilesAct = new QAction(tr("List indexed files" ), this); |
192 | editListIndexedFilesAct->setStatusTip(tr("Show files indexed by strigi" )); |
193 | connect(editListIndexedFilesAct, SIGNAL(triggered()), this, SLOT(editListIndexedFiles())); |
194 | } |
195 | void |
196 | SimpleSearchGui::query(const QString& item) { |
197 | QString query = item.trimmed(); |
198 | if (query.length() == 0) { |
199 | tabs->setQuery(QString()); |
200 | asyncstrigi.updateStatus(); |
201 | mainview->setCurrentIndex(1); |
202 | } else { |
203 | mainview->setCurrentIndex(0); |
204 | tabs->setQuery(query); |
205 | } |
206 | refreshHistogram->setEnabled(query.length()); |
207 | } |
208 | void |
209 | SimpleSearchGui::updateStatus() { |
210 | if (statusview->isVisible()) { |
211 | asyncstrigi.updateStatus(); |
212 | } |
213 | if (fieldnames->count() == 0) { |
214 | fieldnames->addItems(strigi.getFieldNames()); |
215 | fieldnames->setCurrentIndex( |
216 | fieldnames->findText("system.last_modified_time" )); |
217 | } |
218 | } |
219 | void |
220 | SimpleSearchGui::updateStatus(const QMap<QString, QString>& s) { |
221 | // static bool first = true; |
222 | static bool attemptedstart = false; |
223 | // if (!first && !statusview->isVisible()) return; |
224 | // first = false; |
225 | QMap<QString, QString> status (s); |
226 | if (status.size() == 0) { |
227 | running = false; |
228 | editFiltersAct->setEnabled(false); |
229 | editListIndexedFilesAct->setEnabled(false); |
230 | status["Status" ] = "Daemon is not running" ; |
231 | } else { |
232 | attemptedstart = true; |
233 | starting = false; |
234 | running = true; |
235 | editFiltersAct->setEnabled(true); |
236 | editListIndexedFilesAct->setEnabled(true); |
237 | if (indexeddirs->count() == 0) { |
238 | updateDirectories(); |
239 | } |
240 | } |
241 | toggleindexing->setEnabled(running); |
242 | adddir->setEnabled(running); |
243 | removedir->setEnabled(running); |
244 | queryfield->setEnabled(running); |
245 | toggledaemon->setText((running)?tr("stop daemon" ):tr("start daemon" )); |
246 | toggledaemon->setEnabled(true); |
247 | if (backendsList) { |
248 | backendsList->setEnabled(!running); |
249 | } |
250 | bool idxng = status["Status" ] == "indexing" ; |
251 | if (idxng != indexing) { |
252 | indexing = idxng; |
253 | toggleindexing->setText((indexing)?tr("stop indexing" ):tr("start indexing" )); |
254 | } |
255 | |
256 | QMap<QString,QString>::const_iterator i; |
257 | QString text; |
258 | for (i = status.constBegin(); i != status.constEnd(); ++i) { |
259 | text += i.key(); |
260 | text += ":\t" ; |
261 | text += i.value(); |
262 | text += '\n'; |
263 | } |
264 | statusview->setText(text); |
265 | } |
266 | void |
267 | SimpleSearchGui::startDaemon() { |
268 | toggledaemon->setEnabled(false); |
269 | starting = true; |
270 | // try to start the daemon |
271 | QFileInfo exe = QCoreApplication::applicationDirPath() |
272 | + "/../../daemon/strigidaemon" ; |
273 | QStringList args; |
274 | if (backendsList) { |
275 | args += backendsList->currentText(); |
276 | } |
277 | if (exe.exists()) { |
278 | // start not installed version |
279 | QProcess::startDetached(exe.absoluteFilePath(), args); |
280 | } else { |
281 | exe = QCoreApplication::applicationDirPath()+"/strigidaemon" ; |
282 | if (exe.exists()) { |
283 | QProcess::startDetached(exe.absoluteFilePath(), args); |
284 | } else { |
285 | // start installed version |
286 | QProcess::startDetached("strigidaemon" ); |
287 | } |
288 | } |
289 | } |
290 | void |
291 | SimpleSearchGui::toggleDaemon() { |
292 | if (running) { |
293 | strigi.stopDaemon(); |
294 | indexeddirs->clear(); |
295 | } else { |
296 | startDaemon(); |
297 | } |
298 | } |
299 | void |
300 | SimpleSearchGui::toggleIndexing() { |
301 | if (indexing) { |
302 | strigi.stopIndexing(); |
303 | } else { |
304 | strigi.startIndexing(); |
305 | } |
306 | } |
307 | void |
308 | SimpleSearchGui::addDirectory() { |
309 | // open file dialog |
310 | QString dir = QFileDialog::getExistingDirectory (this); |
311 | if (dir.size() <= 0) return; |
312 | for (int i=0; i<indexeddirs->count(); ++i) { |
313 | QString text = indexeddirs->item(i)->text(); |
314 | if (dir.startsWith(text)) { |
315 | return; |
316 | } |
317 | if (text.startsWith(dir)) { |
318 | indexeddirs->takeItem(i); |
319 | i = 0; |
320 | } |
321 | } |
322 | indexeddirs->addItem(dir); |
323 | setDirectories(); |
324 | } |
325 | void |
326 | SimpleSearchGui::removeDirectory() { |
327 | QList<QListWidgetItem*> items = indexeddirs->selectedItems(); |
328 | |
329 | if (items.size() == 0) |
330 | return; |
331 | |
332 | for (QList<QListWidgetItem*>::iterator iter = items.begin(); iter != items.end(); ++iter) |
333 | { |
334 | int row = indexeddirs->row (*iter); |
335 | indexeddirs->takeItem (row); |
336 | } |
337 | setDirectories(); |
338 | } |
339 | void |
340 | SimpleSearchGui::setDirectories() { |
341 | QStringList s; |
342 | for (int i=0; i<indexeddirs->count(); ++i) { |
343 | QString text = indexeddirs->item(i)->text(); |
344 | s.append(text); |
345 | } |
346 | strigi.setIndexedDirectories(s); |
347 | updateDirectories(); |
348 | } |
349 | void |
350 | SimpleSearchGui::updateDirectories() { |
351 | indexeddirs->clear(); |
352 | indexeddirs->addItems(strigi.getIndexedDirectories()); |
353 | } |
354 | void |
355 | SimpleSearchGui::editFilters() { |
356 | QList<QPair<bool,QString> > filters; |
357 | filters = strigi.getFilters(); |
358 | |
359 | DlgFilters dlg(filters); |
360 | if (dlg.exec() && filters != dlg.getFilters()) { |
361 | strigi.setFilters(dlg.getFilters()); |
362 | } |
363 | } |
364 | void |
365 | SimpleSearchGui::editListIndexedFiles() { |
366 | QStringList files = strigi.getIndexedFiles(); |
367 | DlgListIndexedFiles dlg(files); |
368 | dlg.exec(); |
369 | } |
370 | |