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>
35 #include <QPluginLoader>
37 #include <QtConcurrentRun>
38 #include <QtConcurrentMap>
39 #include <QFutureIterator>
45 #include <QFutureWatcher>
46 #include "../../includes/CommonDictInterface.h"
47 #include "../../includes/settings.h"
48 #include "../../includes/translation.h"
49 #include "../../includes/History.h"
50 #include "../../includes/Notify.h"
51 #include "Bookmarks.h"
54 /*! Inner part of dictionary - glues together GUI and plugins, also kind of
55 GoF facade (for GUI) cover few classes \see Bookmarks \see History
57 Backbone is responsible for managing plugins and dictionaries, starting
58 new searches and threads, merging search results from multiple dictionaries.
60 Each plugin may live in multiple instances - each with its own dictionary,
61 backbone must provide way to create them at start (with specific Settings) and
62 distinguich each ditionary.
64 Backbone also manage bookmarks and history: providing interface to gui
66 Backbone is also responsible for saving and spawning session via configs
67 file (stored in ~/.mdictionary) -> configs are kind of tricky because
68 mDictionary is delivered with two simple dicts -> its necessary to separate default
69 configs from user configs (updating/reinstaling app results in overwriten
70 default config file), moreover config file there is general mdictionary
71 configuration (aparto from dictionaries and plugin ones).
73 Other modules may set some internal backbone behaviour via \see setSettings():
74 Settings object with option given:
75 * history_size - int, size of stored searches
76 * search_limit - int, how many different word may each dictionary returns
77 * search_dictionaries - true/false, whether search in dictionaries
78 * search_bookmarks - true/false, whether search in bookmarks
81 First GUI should ask for list of words matching given pattern
82 then eatch Translation object is capable of finging it own final translation
85 - Gui call search(...)
86 - Backbone call plugins searchWordList(...) in idealThreadCount()+1 threads
87 - Backbone sets the FutureWatcher to be notifed when plugins are done
88 - Backbone fetch results from Future<..> and formats it for gui then
93 - Gui call searchHtml()
94 - Backbone starts for eatch translation object toHtml in separate threads
95 - Backbone sets FutureWatcher to be notified after last toHtml returns
96 - Backbone fetch translation from Future<...> objects and calls
98 - gui calls htmlResult()
101 class Backbone : public QObject
106 /*!\param pluginPath path to plugins (leave blank for default)
107 \param configPath path to folder with configuration files
108 \param dry dry run is mode without paying attention to configuration etc
111 Backbone(QString pluginPath="", QString configPath="",
112 bool dry = 0, QObject *parent = 0);
114 Backbone(const Backbone& b);
116 //! \return all loadded dictionaries with activity state flag
117 QHash<CommonDictInterface*, bool> getDictionaries();
119 //! \return all loadded plugins
120 QList<CommonDictInterface*> getPlugins();
122 //! \return history of performed searches
125 //! \return return search fesult
126 QMultiHash<QString, Translation*> result();
128 //! \return maximum number of word that plugin could find
129 int searchLimit() const;
131 //! \return final translation (after searching for html)
134 /*! maximum number of translation that each plugin may return; it must be
135 public static becouse of QtConcurent::mapped restrictions about
136 what kind of function may be used there see Qt docs */
137 static int _searchLimit;
142 //! stops all current searches and emiting searchCanceled signal
143 void stopSearching();
145 /*! search for a word translation
146 \param word to be translated
148 void search(QString word);
150 /*! sets active dictionaries (searches are performed only in active dicts
151 \param List of dictionaris to be activated
153 void selectedDictionaries(QList<CommonDictInterface* >);
155 /*! adds new dictionary and activate it
156 \param dict dictionary to be added
157 \param active decides whether searches are perfomed in given dictionaries
159 void addDictionary(CommonDictInterface* dict, bool active = 1);
162 //! stops all current activity - emiting signal \see closeOk
166 /*! Fired by FutureWatcher when list of words is ready (after calling search)
167 fetch Future<...> to final result
169 void translationReady();
171 /*! Fired by FutureWatcher when search result is ready, fetch Future to
174 void htmlTranslationReady();
176 /*! Removes given dictionary
177 \param dict dictionary to be deleted
179 void removeDictionary(CommonDictInterface* dict);
181 /*! saves plugins new state/configuration after each change */
184 /*! Performs search for final translation (html/xml) form
185 \param list of Translation* to be searched for
187 void searchHtml(QList<Translation*>);
190 /*! add bookmarks to given translations (translation object is fetched and
191 added to bookmarks data base (key and translation stored in db)
192 \param translation translation object to be stored in db
194 void addBookmark(QList<Translation*> translations) {
195 foreach(Translation* translation, translations)
196 //_bookmarks.add(translation);
197 QtConcurrent::run(_bookmarks, &Bookmarks::add, translation);
201 /*! Remove bookmarks to given translatios
202 \param translation remove bookmark to this translation
204 void removeBookmark(QList<Translation*> translations) {
205 foreach(Translation* translation, translations)
206 _bookmarks.remove(translation);
211 /*! Remove all bookmarks
213 void removeAllBookmarks(){
218 /*! Searching for list of bookmarks may take some time, so i moved it to
219 new thread (to avoid gui blocking), futher its consistent with ordinary
220 searching for list of word (\see search)
222 void fetchBookmarks() {
229 if(_searchBookmarks) {
230 _innerBookmarks = QtConcurrent::run(_bookmarks,
231 &Bookmarks::searchWordList, QString("*"));
232 _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 opitons set
242 void setSettings(Settings* settings);
245 /*! \return coresponding settings object with history_size, search_limit,
246 searching backends (search_bookmarks, search_dictionaries)
248 Settings* settings();
256 /*! emmited 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 result ready to fetch
263 //! emitted when html result is ready to fetch
266 //! throwed when searches are stopped
267 void searchCanceled();
269 //! emmited when bookmark list is ready to fetch
270 void bookmarksReady();
272 /*! emited by direct connection to plugins notifying signals
273 \param Notify::NotifyType gui my dacide to show different typet 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 concurent 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;
306 QString _pluginPath, _defaultPluginPath;
308 QString _defaultConfigPath;
309 int _defaultSearchLimit;
310 int _historyLen, _defaultHistoryLen;
312 bool dryRun; // mainly for testing - when true then dosent bother configs etc
313 bool stopped; // true when user stops searching/fetching
314 bool bookmarkFin, dictFin; // inform whether givent search type is ready
315 bool _searchDicts, _searchBookmarks; // whether perform search 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, bool _default=false);
327 void saveState(QSettings*, Settings*, bool, uint);
328 void addInternalDictionary(CommonDictInterface*, bool);
329 void savePrefs(QSettings*);
330 void saveDefaultPrefs(QSettings*);
332 CommonDictInterface* plugin(QString type); // search for given type plugin
333 QList<CommonDictInterface*> activeDicts();
334 bool containsDict(uint hash) const;
339 friend class BackboneTest;