Changed include folder name
[mdictionary] / src / mdictionary / backbone / backbone.h
1 /*******************************************************************************
2
3     This file is part of mDictionary.
4
5     mDictionary is free software: you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation, either version 3 of the License, or
8     (at your option) any later version.
9
10     mDictionary 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
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with mDictionary.  If not, see <http://www.gnu.org/licenses/>.
17
18     Copyright 2010 Comarch S.A.
19
20 *******************************************************************************/
21
22 /*! \file backbone.cpp
23 \brief Backbone/core main header \see Backbone
24
25
26 \author Bartosz Szatkowski <bulislaw@linux.com>
27 */
28
29 #ifndef BACKBONE_H
30 #define BACKBONE_H
31
32 #include <QObject>
33 #include <QList>
34 #include <QHash>
35 #include <QSet>
36 #include <QPluginLoader>
37 #include <QFuture>
38 #include <QtConcurrentRun>
39 #include <QtConcurrentMap>
40 #include <QFutureIterator>
41 #include <QTimer>
42 #include <QTime>
43 #include <QDir>
44 #include <QThread>
45 #include <QSettings>
46 #include <QFutureWatcher>
47 #include "../../include/CommonDictInterface.h"
48 #include "../../include/settings.h"
49 #include "../../include/translation.h"
50 #include "../../include/History.h"
51 #include "../../include/Notify.h"
52 #include "ConfigGenerator.h"
53 #include "Bookmarks.h"
54
55
56 /*! Inner part of dictionary - glues together GUI and plugins, also kind of
57     GoF facade (for GUI) cover few classes \see Bookmarks \see History
58
59   Backbone is responsible for managing plugins and dictionaries, starting
60   new searches and threads, merging search results from multiple dictionaries.
61
62   Each plugin may live in multiple instances - each with its own dictionary,
63   backbone must provide way to create them at start (with specific Settings) and
64   distinguish each ditionary.
65
66   Backbone also manages bookmarks and history: providing interface to GUI.
67
68   Backbone is also responsible for saving and spawning session via configs
69   file (stored in ~/.mdictionary) -> configs are kind of tricky because
70   mDictionary is delivered with two simple dicts -> it's necessary to separate default
71   configs from user configs (updating/reinstalling app results in overwritten
72   default config file), moreover config file there is general mdictionary
73   configuration (apart from dictionaries and plugin ones).
74
75   Other modules may set some internal backbone behaviour via \see setSettings():
76   Settings object with options given:
77      * history_size - int, size of stored searches
78      * search_limit - int, how many different words each dictionary may return
79      * search_dictionaries - true/false, whether search in dictionaries
80      * search_bookmarks - true/false, whether search in bookmarks
81
82     Searching schema:
83         At first GUI should ask for list of words matching given pattern,
84         then each Translation object is capable of finding its own final translation
85
86       List of words:
87         - GUI calls search(...)
88         - Backbone calls plugins searchWordList(...) in idealThreadCount()+1 threads
89         - Backbone sets the FutureWatcher to be notified when plugins are done
90         - Backbone fetches results from Future<..> and formats it for GUI, then
91            emits ready()
92         - GUI calls result()
93
94       Final translation:
95          - GUI calls searchHtml()
96          - Backbone starts toHtml for each translation object in separate threads
97          - Backbone sets FutureWatcher to be notified after last toHtml returns
98          - Backbone fetches translation from Future<...> objects and calls
99              htmlReady()
100          - Gui calls htmlResult()
101
102 */
103 class Backbone : public QObject
104 {
105     Q_OBJECT
106
107 public:
108     /*!\param pluginPath path to plugins (leave blank for default)
109       \param configPath path to folder with configuration files
110       \param dry dry run is mode without paying attention to configuration etc
111           mainly for testing
112       */
113     Backbone(QString pluginPath="", QString configPath="",
114              bool dry = 0, QObject *parent = 0);
115     ~Backbone();
116     Backbone(const Backbone& b);
117
118     //! \return all loaded dictionaries with activity state flag
119     QHash<CommonDictInterface*, bool> getDictionaries();
120
121     //! \return all loaded plugins
122     QList<CommonDictInterface*> getPlugins();
123
124     //! \return history of performed searches
125     History* history();
126
127     //! \return return search fesult
128     QMultiHash<QString, Translation*> result();
129
130     //! \return maximum number of words that plugin could find
131     int searchLimit() const;
132
133     //! \return final translation (after searching for html)
134     QStringList htmls();
135
136     /*! maximum number of translations that each plugin may return; it must be
137         public static because of QtConcurent::mapped restrictions about
138         what kind of function may be used there see Qt docs */
139     static int _searchLimit;
140
141
142
143 public Q_SLOTS:
144     //! stops all current searches and emits searchCanceled signal
145     void stopSearching();
146
147     /*! searches for a word translation
148        \param word to be translated
149       */
150     void search(QString word);
151
152     /*! sets active dictionaries (searches are performed only in active dicts
153        \param List of dictionaries to be activated
154       */
155     void selectedDictionaries(QList<CommonDictInterface* >);
156
157     /*! adds new dictionary and activates it
158       \param dict dictionary to be added
159       \param active decides whether searches are perfomed in given dictionaries
160       */
161     void addDictionary(CommonDictInterface* dict, bool active = 1);
162
163
164     //! stops all current activity - emitting signal \see closeOk
165     void quit();
166
167
168     /*! Fired by FutureWatcher when list of words is ready (after calling search)
169         fetch Future<...> to final result
170       */
171     void translationReady();
172
173     /*! Fired by FutureWatcher when search result is ready, fetch Future to
174         final result
175       */
176     void htmlTranslationReady();
177
178     /*! Removes given dictionary
179         \param dict dictionary to be deleted
180       */
181     void removeDictionary(CommonDictInterface* dict);
182
183     /*! Saves plugins new state/configuration after each change */
184     void dictUpdated();
185
186     /*! Performs search for final translation (html/xml) form
187       \param list of Translation* to be searched for
188       */
189     void searchHtml(QList<Translation*>);
190
191
192     /*! adds bookmarks to given translations (translation object is fetched and
193       added to bookmarks data base (key and translation stored in db))
194       \param translation translation object to be stored in db
195       */
196     void addBookmark(QList<Translation*> translations) {
197         foreach(Translation* translation, translations)
198             //_bookmarks.add(translation);
199             QtConcurrent::run(_bookmarks, &Bookmarks::add, translation);
200     }
201
202
203     /*! Removes bookmarks to given translations
204       \param translation remove bookmark to this translation
205       */
206     void removeBookmark(QList<Translation*> translations) {
207         foreach(Translation* translation, translations)
208             _bookmarks.remove(translation);
209     }
210
211
212
213     /*! Removes all bookmarks
214       */
215     void removeAllBookmarks(){
216         _bookmarks.clear();
217     }
218
219
220    /*! Searching for list of bookmarks may take some time, so I moved it to
221        new thread (to avoid GUI blocking), further it's consistent with ordinary
222        searching for list of words (\see search)
223        */
224    void fetchBookmarks() {
225         _result.clear();
226
227         stopped = false;
228         dictFin = 1;
229         bookmarkFin = 0;
230
231         _innerBookmarks = QtConcurrent::run(_bookmarks,
232                 &Bookmarks::list);
233         _bookmarkSearchWatcher.setFuture(_innerBookmarks);
234    }
235
236
237
238    /*! Sets settings for backbone: history_size, search_limit,
239        searching backends (search_bookmarks, search_dictionaries)
240        \param settings settings object with options set
241        */
242     void setSettings(Settings* settings);
243
244
245     /*! \return corresponding settings object with history_size, search_limit,
246        searching backends (search_bookmarks, search_dictionaries)
247        */
248     Settings* settings();
249
250
251
252
253
254
255 Q_SIGNALS:
256     /*! emitted when backbone is ready to close - after getting stop signal it
257         should kill all threads and so on */
258     void closeOk();
259
260     //! emitted when there are search results ready to fetch
261     void ready();
262
263     //! emitted when html result is ready to fetch
264     void htmlReady();
265
266     //! thrown when searches are stopped
267     void searchCanceled();
268
269     //! emitted when bookmark list is ready to fetch
270     void bookmarksReady();
271
272     /*! emitted by direct connection to plugins notifying signals
273         \param Notify::NotifyType GUI may decide to show different types in
274             different ways
275         \param QString text of the notification
276     */
277     void notify(Notify::NotifyType, QString);
278
279 private Q_SLOTS:
280     void bookmarksListReady();
281
282
283 private:
284     QHash<CommonDictInterface*, bool> _dicts; // List of dictionaries
285     QList<CommonDictInterface*> _plugins;  // List of plugins
286
287
288     QFuture<QList<Translation*> > _innerResult; //Res of concurrent word search
289     QFuture<QString> _innerHtmlResult;  // Result of html search
290     QFuture<QList<Translation*> > _innerBookmarks; //Res of search in bookmarks
291     QFuture<QList<Translation*> > _innerListBookmarks; //Res of search in bookmarks
292     QFuture<QStringList> _innerHtmlBookmarks; //Html result of bookmarks search
293
294     QMultiHash<QString, Translation*> _result; //Final result of word search
295     QStringList _htmlResult; // Final result of html search
296     QList<Translation*> _bookmarksResult; // Final result of search in bookmarks
297
298
299     // Keeps track of concurent computations
300     QFutureWatcher<QList<Translation*> > _resultWatcher;
301     QFutureWatcher<QList<Translation*> > _bookmarkWatcher;
302     QFutureWatcher<QList<Translation*> > _bookmarkSearchWatcher;
303     QFutureWatcher<QString> _htmlResultWatcher;
304
305
306     QString _pluginPath;
307     QString _configPath;
308     QString _dir;
309     int _historyLen;
310     qreal _zoom;
311
312     bool dryRun; // mainly for testing - when true then doesn't bother configs etc
313     bool stopped; // true when user stops searching/fetching
314     bool bookmarkFin, dictFin; // informs whether given search type is ready
315     bool _searchDicts, _searchBookmarks; // whether search performed in given source
316
317     Bookmarks _bookmarks;
318
319
320     void init();
321
322     QStringList getFilesFromDir(QString dir, QStringList nameFilter);
323     void loadPlugins(); //< locate and load plugins
324     void loadPrefs(QString fileName);
325     void loadDicts(QString fileName);
326
327     void saveState(QSettings*, Settings*, bool, uint);
328     void addInternalDictionary(CommonDictInterface*, bool);
329     void savePrefs(QSettings*);
330
331     CommonDictInterface* plugin(QString type); // searches for plugin of given type
332     QList<CommonDictInterface*> activeDicts();
333     bool containsDict(uint hash) const;
334     int _dictNum;
335
336     History* _history;
337
338     friend class BackboneTest;
339
340 };
341
342 #endif // BACKBONE_H