1 /*******************************************************************************
3 This file is part of mDictionary.
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.
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.
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/>.
18 Copyright 2010 Comarch S.A.
20 *******************************************************************************/
22 /*! \file backbone.cpp
23 \brief Backbone/core main header \see Backbone
26 \author Bartosz Szatkowski <bulislaw@linux.com>
36 #include <QPluginLoader>
38 #include <QtConcurrentRun>
39 #include <QtConcurrentMap>
40 #include <QFutureIterator>
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"
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
59 Backbone is responsible for managing plugins and dictionaries, starting
60 new searches and threads, merging search results from multiple dictionaries.
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.
66 Backbone also manages bookmarks and history: providing interface to GUI.
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).
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
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
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
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
100 - Gui calls htmlResult()
103 class Backbone : public QObject
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
113 Backbone(QString pluginPath="", QString configPath="",
114 bool dry = 0, QObject *parent = 0);
116 Backbone(const Backbone& b);
118 //! \return all loaded dictionaries with activity state flag
119 QHash<CommonDictInterface*, bool> getDictionaries();
121 //! \return all loaded plugins
122 QList<CommonDictInterface*> getPlugins();
124 //! \return history of performed searches
127 //! \return return search fesult
128 QMultiHash<QString, Translation*> result();
130 //! \return maximum number of words that plugin could find
131 int searchLimit() const;
133 //! \return final translation (after searching for html)
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;
144 //! stops all current searches and emits searchCanceled signal
145 void stopSearching();
147 /*! searches for a word translation
148 \param word to be translated
150 void search(QString word);
152 /*! sets active dictionaries (searches are performed only in active dicts
153 \param List of dictionaries to be activated
155 void selectedDictionaries(QList<CommonDictInterface* >);
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
161 void addDictionary(CommonDictInterface* dict, bool active = 1);
164 //! stops all current activity - emitting signal \see closeOk
168 /*! Fired by FutureWatcher when list of words is ready (after calling search)
169 fetch Future<...> to final result
171 void translationReady();
173 /*! Fired by FutureWatcher when search result is ready, fetch Future to
176 void htmlTranslationReady();
178 /*! Removes given dictionary
179 \param dict dictionary to be deleted
181 void removeDictionary(CommonDictInterface* dict);
183 /*! Saves plugins new state/configuration after each change */
186 /*! Performs search for final translation (html/xml) form
187 \param list of Translation* to be searched for
189 void searchHtml(QList<Translation*>);
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
196 void addBookmark(QList<Translation*> translations) {
197 foreach(Translation* translation, translations)
198 //_bookmarks.add(translation);
199 QtConcurrent::run(_bookmarks, &Bookmarks::add, translation);
203 /*! Removes bookmarks to given translations
204 \param translation remove bookmark to this translation
206 void removeBookmark(QList<Translation*> translations) {
207 foreach(Translation* translation, translations)
208 _bookmarks.remove(translation);
213 /*! Removes all bookmarks
215 void removeAllBookmarks(){
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)
224 void fetchBookmarks() {
231 _innerBookmarks = QtConcurrent::run(_bookmarks,
233 _bookmarkSearchWatcher.setFuture(_innerBookmarks);
238 /*! Sets settings for backbone: history_size, search_limit,
239 searching backends (search_bookmarks, search_dictionaries)
240 \param settings settings object with options set
242 void setSettings(Settings* settings);
245 /*! \return corresponding settings object with history_size, search_limit,
246 searching backends (search_bookmarks, search_dictionaries)
248 Settings* settings();
256 /*! emitted when backbone is ready to close - after getting stop signal it
257 should kill all threads and so on */
260 //! emitted when there are search results ready to fetch
263 //! emitted when html result is ready to fetch
266 //! thrown when searches are stopped
267 void searchCanceled();
269 //! emitted when bookmark list is ready to fetch
270 void bookmarksReady();
272 /*! emitted by direct connection to plugins notifying signals
273 \param Notify::NotifyType GUI may decide to show different types in
275 \param QString text of the notification
277 void notify(Notify::NotifyType, QString);
280 void bookmarksListReady();
284 QHash<CommonDictInterface*, bool> _dicts; // List of dictionaries
285 QList<CommonDictInterface*> _plugins; // List of plugins
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
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
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;
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
317 Bookmarks _bookmarks;
322 QStringList getFilesFromDir(QString dir, QStringList nameFilter);
323 void loadPlugins(); //< locate and load plugins
324 void loadPrefs(QString fileName);
325 void loadDicts(QString fileName);
327 void saveState(QSettings*, Settings*, bool, uint);
328 void addInternalDictionary(CommonDictInterface*, bool);
329 void savePrefs(QSettings*);
331 CommonDictInterface* plugin(QString type); // searches for plugin of given type
332 QList<CommonDictInterface*> activeDicts();
333 bool containsDict(uint hash) const;
338 friend class BackboneTest;