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>
47 #include <QFutureWatcher>
49 #include "../../include/CommonDictInterface.h"
50 #include "../../include/settings.h"
51 #include "../../include/translation.h"
52 #include "../../include/History.h"
53 #include "../../include/Notify.h"
54 #include "ConfigGenerator.h"
55 #include "Bookmarks.h"
58 /*! Inner part of dictionary - glues together GUI and plugins, also kind of
59 GoF facade (for GUI) cover few classes \see Bookmarks \see History
61 Backbone is responsible for managing plugins and dictionaries, starting
62 new searches and threads, merging search results from multiple dictionaries.
64 Each plugin may live in multiple instances - each with its own dictionary,
65 backbone must provide a way to create them at start (with specific Settings) and
66 distinguish each ditionary.
68 Backbone also manages bookmarks and history: providing interface to GUI.
70 Backbone is also responsible for saving and spawning session via configs
71 file (stored in ~/.mdictionary) -> configs are kind of tricky because
72 mDictionary is delivered with two simple dicts -> it's necessary to separate default
73 configs from user configs (updating/reinstalling app results in overwritten
74 default config file), moreover config file there is general mdictionary
75 configuration (apart from dictionaries and plugin ones).
77 Other modules may set some internal backbone behaviour via \see setSettings():
78 Settings object with options given:
79 * history_size - int, size of stored searches
80 * search_limit - int, how many different words each dictionary may return
81 * search_dictionaries - true/false, whether search in dictionaries
82 * search_bookmarks - true/false, whether search in bookmarks
85 At first GUI should ask for a list of words matching a given pattern,
86 then each Translation object is capable of finding its own final translation
89 - GUI calls search(...)
90 - Backbone calls plugins searchWordList(...) in idealThreadCount()+1 threads
91 - Backbone sets the FutureWatcher to be notified when plugins are done
92 - Backbone fetches results from Future<..> and formats it for GUI, then
97 - GUI calls searchXml()
98 - Backbone starts toXml for each translation object in separate threads
99 - Backbone sets FutureWatcher to be notified after last toXml returns
100 - Backbone fetches translation from Future<...> objects and calls
102 - Gui calls xmlResult()
105 class Backbone : public QObject
110 /*! \param pluginPath path to plugins (leave blank for default)
111 \param configPath path to folder with configuration files
112 \param dry dry run is mode without paying attention to configuration etc
115 Backbone(QString pluginPath="", QString configPath="",
116 bool dry = 0, QObject *parent = 0);
118 Backbone(const Backbone& b);
120 //! \return all loaded dictionaries with activity state flag
121 QHash<CommonDictInterface*, bool> getDictionaries();
123 //! \return all loaded plugins
124 QList<CommonDictInterface*> getPlugins();
126 //! \return history of performed searches
129 //! \return search fesult
130 QMultiHash<QString, Translation*> result();
132 //! \return maximum number of words that plugin could find
133 int searchLimit() const;
135 //! \return final translation (after searching for xml)
138 /*! maximum number of translations that each plugin may return; it must be
139 public static because of QtConcurent::mapped restrictions about
140 what kind of function may be used there see Qt docs */
141 static int _searchLimit;
143 void addBookmarkFuture(QList<Translation*> translations);
146 //! stops all current searches and emits searchCanceled signal
147 void stopSearching();
149 /*! searches for a word translation
150 \param word word to be translated
152 void search(QString word);
154 /*! sets active dictionaries (searches are performed only in active dicts)
155 \param List of dictionaries to be activated
157 void selectedDictionaries(QList<CommonDictInterface*>);
159 /*! adds a new dictionary and activates it
160 \param dict dictionary to be added
161 \param active decides whether searches are perfomed in given dictionaries
163 void addDictionary(CommonDictInterface* dict, bool active = 1);
166 //! stops all current activity - emitting signal \see closeOk
170 /*! Fired by FutureWatcher when a list of words is ready (after calling search),
171 fetch Future<...> to final result
173 void translationReady();
175 /*! Fired by FutureWatcher when search result is ready, fetch Future to
178 void xmlTranslationReady();
180 /*! Removes a given dictionary
181 \param dict dictionary to be deleted
183 void removeDictionary(CommonDictInterface* dict);
185 /*! Saves plugins new state/configuration after each change */
188 /*! Performs search for final translation (xml) form
189 \param list of Translation* to be searched for
191 void searchXml(QList<Translation*>);
194 /*! adds bookmarks to given translations (translation object is fetched and
195 added to bookmarks data base (key and translation stored in db))
196 \param translations list of Translation objects to be stored in db
198 void addBookmark(QList<Translation*> translations);
201 /*! Removes bookmarks to given translations
202 \param translations remove bookmark to these translations
204 void removeBookmark(QList<Translation*> translations) {
205 foreach(Translation* translation, translations)
206 _bookmarks.remove(translation);
211 /*! Removes all bookmarks
213 void removeAllBookmarks(){
218 /*! Searching a list of bookmarks may take some time, so it's moved to a
219 new thread (to avoid GUI blocking), further it's consistent with ordinary
220 searching a list of words (\see search)
222 void fetchBookmarks() {
229 _innerBookmarks = QtConcurrent::run(_bookmarks,
231 _bookmarkSearchWatcher.setFuture(_innerBookmarks);
234 /*! Sets settings for backbone: history_size, search_limit,
235 searching backends (search_bookmarks, search_dictionaries)
236 \param settings settings object with options set
238 void setSettings(Settings* settings);
240 /*! \return corresponding settings object with history_size, search_limit,
241 searching backends (search_bookmarks, search_dictionaries)
243 Settings* settings();
245 void bookmarkReadyFuture();
250 /*! emitted when backbone is ready to close - after getting stop signal it
251 should kill all threads and so on */
254 //! emitted when there are search results ready to fetch
257 //! emitted when xml result is ready to fetch
260 //! thrown when searches are stopped
261 void searchCanceled();
263 //! emitted when bookmark list is ready to fetch
264 void bookmarksReady();
266 /*! emitted by direct connection to plugins notifying signals
267 \param Notify::NotifyType GUI may decide to show different types in
269 \param text of the notification
271 void notify(Notify::NotifyType, QString);
273 void bookmarkReady();
276 void bookmarksListReady();
280 QHash<CommonDictInterface*, bool> _dicts; // List of dictionaries
281 QList<CommonDictInterface*> _plugins; // List of plugins
284 QFuture<QList<Translation*> > _innerResult; //Res of concurrent word search
285 QFuture<QString> _innerXmlResult; // Result of xml search
286 QFuture<QList<Translation*> > _innerBookmarks; //Res of search in bookmarks
287 QFuture<QList<Translation*> > _innerListBookmarks; //Res of search in bookmarks
288 QFuture<QStringList> _innerXmlBookmarks; //Xml result of bookmarks search
289 QFuture<void> _innerTranslationsList;
292 QMultiHash<QString, Translation*> _result; //Final result of word search
293 QStringList _xmlResult; // Final result of xml search
294 QList<Translation*> _bookmarksResult; // Final result of search in bookmarks
297 // Keeps track of concurent computations
298 QFutureWatcher<QList<Translation*> > _resultWatcher;
299 QFutureWatcher<QList<Translation*> > _bookmarkWatcher;
300 QFutureWatcher<QList<Translation*> > _bookmarkSearchWatcher;
301 QFutureWatcher<QString> _xmlResultWatcher;
302 QFutureWatcher<void> _translationsListWatcher;
311 bool dryRun; // mainly for testing - when true then doesn't bother configs etc
312 bool stopped; // true when user stops searching/fetching
313 bool bookmarkFin, dictFin; // informs whether given search type is ready
314 bool _searchDicts, _searchBookmarks; // whether search performed in given source
316 Bookmarks _bookmarks;
321 QStringList getFilesFromDir(QString dir, QStringList nameFilter);
322 void loadPlugins(); //< locate and load plugins
323 void loadPrefs(QString fileName);
324 void loadDicts(QString fileName);
326 void saveState(QSettings*, Settings*, bool, uint);
327 void addInternalDictionary(CommonDictInterface*, bool);
328 void savePrefs(QSettings*);
330 CommonDictInterface* plugin(QString type); // searches for plugin of a given type
331 QList<CommonDictInterface*> activeDicts();
332 bool containsDict(uint hash) const;
337 friend class BackboneTest;