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>
48 #include "../../include/CommonDictInterface.h"
49 #include "../../include/settings.h"
50 #include "../../include/translation.h"
51 #include "../../include/History.h"
52 #include "../../include/Notify.h"
53 #include "ConfigGenerator.h"
54 #include "Bookmarks.h"
57 /*! Inner part of dictionary - glues together GUI and plugins, also kind of
58 GoF facade (for GUI) cover few classes \see Bookmarks \see History
60 Backbone is responsible for managing plugins and dictionaries, starting
61 new searches and threads, merging search results from multiple dictionaries.
63 Each plugin may live in multiple instances - each with its own dictionary,
64 backbone must provide a way to create them at start (with specific Settings) and
65 distinguish each ditionary.
67 Backbone also manages bookmarks and history: providing interface to GUI.
69 Backbone is also responsible for saving and spawning session via configs
70 file (stored in ~/.mdictionary) -> configs are kind of tricky because
71 mDictionary is delivered with two simple dicts -> it's necessary to separate default
72 configs from user configs (updating/reinstalling app results in overwritten
73 default config file), moreover config file there is general mdictionary
74 configuration (apart from dictionaries and plugin ones).
76 Other modules may set some internal backbone behaviour via \see setSettings():
77 Settings object with options given:
78 * history_size - int, size of stored searches
79 * search_limit - int, how many different words each dictionary may return
80 * search_dictionaries - true/false, whether search in dictionaries
81 * search_bookmarks - true/false, whether search in bookmarks
84 At first GUI should ask for a list of words matching a given pattern,
85 then each Translation object is capable of finding its own final translation
88 - GUI calls search(...)
89 - Backbone calls plugins searchWordList(...) in idealThreadCount()+1 threads
90 - Backbone sets the FutureWatcher to be notified when plugins are done
91 - Backbone fetches results from Future<..> and formats it for GUI, then
96 - GUI calls searchXml()
97 - Backbone starts toXml for each translation object in separate threads
98 - Backbone sets FutureWatcher to be notified after last toXml returns
99 - Backbone fetches translation from Future<...> objects and calls
101 - Gui calls xmlResult()
104 class Backbone : public QObject
109 /*! \param pluginPath path to plugins (leave blank for default)
110 \param configPath path to folder with configuration files
111 \param dry dry run is mode without paying attention to configuration etc
114 Backbone(QString pluginPath="", QString configPath="",
115 bool dry = 0, QObject *parent = 0);
117 Backbone(const Backbone& b);
119 //! \return all loaded dictionaries with activity state flag
120 QHash<CommonDictInterface*, bool> getDictionaries();
122 //! \return all loaded plugins
123 QList<CommonDictInterface*> getPlugins();
125 //! \return history of performed searches
128 //! \return search fesult
129 QMultiHash<QString, Translation*> result();
131 //! \return maximum number of words that plugin could find
132 int searchLimit() const;
134 //! \return final translation (after searching for xml)
137 /*! maximum number of translations that each plugin may return; it must be
138 public static because of QtConcurent::mapped restrictions about
139 what kind of function may be used there see Qt docs */
140 static int _searchLimit;
145 //! stops all current searches and emits searchCanceled signal
146 void stopSearching();
148 /*! searches for a word translation
149 \param word word to be translated
151 void search(QString word);
153 /*! sets active dictionaries (searches are performed only in active dicts)
154 \param List of dictionaries to be activated
156 void selectedDictionaries(QList<CommonDictInterface*>);
158 /*! adds a new dictionary and activates it
159 \param dict dictionary to be added
160 \param active decides whether searches are perfomed in given dictionaries
162 void addDictionary(CommonDictInterface* dict, bool active = 1);
165 //! stops all current activity - emitting signal \see closeOk
169 /*! Fired by FutureWatcher when a list of words is ready (after calling search),
170 fetch Future<...> to final result
172 void translationReady();
174 /*! Fired by FutureWatcher when search result is ready, fetch Future to
177 void xmlTranslationReady();
179 /*! Removes a given dictionary
180 \param dict dictionary to be deleted
182 void removeDictionary(CommonDictInterface* dict);
184 /*! Saves plugins new state/configuration after each change */
187 /*! Performs search for final translation (xml) form
188 \param list of Translation* to be searched for
190 void searchXml(QList<Translation*>);
193 /*! adds bookmarks to given translations (translation object is fetched and
194 added to bookmarks data base (key and translation stored in db))
195 \param translations list of Translation objects to be stored in db
197 void addBookmark(QList<Translation*> translations) {
198 Translation* translation;
199 foreach(translation, translations)
200 _bookmarks.add(translation);
204 /*! Removes bookmarks to given translations
205 \param translations remove bookmark to these translations
207 void removeBookmark(QList<Translation*> translations) {
208 foreach(Translation* translation, translations)
209 _bookmarks.remove(translation);
214 /*! Removes all bookmarks
216 void removeAllBookmarks(){
221 /*! Searching a list of bookmarks may take some time, so it's moved to a
222 new thread (to avoid GUI blocking), further it's consistent with ordinary
223 searching a list of words (\see search)
225 void fetchBookmarks() {
232 _innerBookmarks = QtConcurrent::run(_bookmarks,
234 _bookmarkSearchWatcher.setFuture(_innerBookmarks);
239 /*! Sets settings for backbone: history_size, search_limit,
240 searching backends (search_bookmarks, search_dictionaries)
241 \param settings settings object with options set
243 void setSettings(Settings* settings);
246 /*! \return corresponding settings object with history_size, search_limit,
247 searching backends (search_bookmarks, search_dictionaries)
249 Settings* settings();
257 /*! emitted when backbone is ready to close - after getting stop signal it
258 should kill all threads and so on */
261 //! emitted when there are search results ready to fetch
264 //! emitted when xml result is ready to fetch
267 //! thrown when searches are stopped
268 void searchCanceled();
270 //! emitted when bookmark list is ready to fetch
271 void bookmarksReady();
273 /*! emitted by direct connection to plugins notifying signals
274 \param Notify::NotifyType GUI may decide to show different types in
276 \param text of the notification
278 void notify(Notify::NotifyType, QString);
281 void bookmarksListReady();
285 QHash<CommonDictInterface*, bool> _dicts; // List of dictionaries
286 QList<CommonDictInterface*> _plugins; // List of plugins
289 QFuture<QList<Translation*> > _innerResult; //Res of concurrent word search
290 QFuture<QString> _innerXmlResult; // Result of xml search
291 QFuture<QList<Translation*> > _innerBookmarks; //Res of search in bookmarks
292 QFuture<QList<Translation*> > _innerListBookmarks; //Res of search in bookmarks
293 QFuture<QStringList> _innerXmlBookmarks; //Xml result of bookmarks search
295 QMultiHash<QString, Translation*> _result; //Final result of word search
296 QStringList _xmlResult; // Final result of xml search
297 QList<Translation*> _bookmarksResult; // Final result of search in bookmarks
300 // Keeps track of concurent computations
301 QFutureWatcher<QList<Translation*> > _resultWatcher;
302 QFutureWatcher<QList<Translation*> > _bookmarkWatcher;
303 QFutureWatcher<QList<Translation*> > _bookmarkSearchWatcher;
304 QFutureWatcher<QString> _xmlResultWatcher;
313 bool dryRun; // mainly for testing - when true then doesn't bother configs etc
314 bool stopped; // true when user stops searching/fetching
315 bool bookmarkFin, dictFin; // informs whether given search type is ready
316 bool _searchDicts, _searchBookmarks; // whether search performed in given source
318 Bookmarks _bookmarks;
323 QStringList getFilesFromDir(QString dir, QStringList nameFilter);
324 void loadPlugins(); //< locate and load plugins
325 void loadPrefs(QString fileName);
326 void loadDicts(QString fileName);
328 void saveState(QSettings*, Settings*, bool, uint);
329 void addInternalDictionary(CommonDictInterface*, bool);
330 void savePrefs(QSettings*);
332 CommonDictInterface* plugin(QString type); // searches for plugin of a given type
333 QList<CommonDictInterface*> activeDicts();
334 bool containsDict(uint hash) const;
339 friend class BackboneTest;