OPT added to MAkefile; KanjiView::Cell constructor: fg,bg changed to int (Fl_Color...
[aoi.git] / src / aoi.hxx
blob35ecae0f77b6ade516e589937b4372568ed1098c
1 /*
2 Copyright 2013 Karel Matas
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef _AOI_HXX
18 #define _AOI_HXX
20 /* \file aoi.hxx
21 * Contains App - the main class of the application.
24 #include <cmath>
25 #include <vector>
26 #include <string>
27 #include <set>
29 #include "logger.hxx"
30 #include "datatypes.hxx"
31 #include "utils.hxx"
32 #include "romanization.hxx"
33 #include "config.hxx"
34 #include "sqlite3.hxx"
35 #include "gui.hxx"
36 #include "parsers.hxx"
37 #include "gui_dicview.hxx"
38 #include "gui_kanjiview.hxx"
41 using std::vector;
42 using std::string;
43 using std::set;
45 namespace aoi_ui {
46 class GUI;
49 namespace aoi {
51 /*!
52 * \sa cb_kanji_search
54 enum KANJI_SORT_MODE {
55 SORT_FREQ_ASC = 0,
56 SORT_FREQ_DESC = 1,
57 SORT_STROKES_ASC = 2,
58 SORT_STROKES_DESC = 3
62 /*!
63 * One item (line) in listview (dictionary results).
64 * \sa cb_filter_listview()
66 struct DicViewItem {
67 int did;
68 set<string> pos;
69 // vector<string> flags;
70 string reading;
71 string kanji;
72 string sense;
73 DicViewItem( int id, const set<string> &p, const string &r,
74 const string &k, const string &s )
75 : did(id), pos(p), reading(r), kanji(k), sense(s) {};
80 /*!
81 * Main class of the program. <b>Singleton</b>. Manages database, logger,
82 * config and UI. Provides functions for UI's callbacks.
83 * \note This should be only class to call query()
84 * \todo when calling ui_* functions check whether the ui_ pointer is valid
86 class App
88 private:
89 class SQLite3::SQLite3 *db_;
90 class Romanization *rmn_;
91 class aoi_ui::GUI *ui_;
92 class aoi_config::Config *cfg_;
93 class Logger logger_;
94 vector<DicViewItem> listview_items_;
95 map<string,int> components_; //!< component: stroke_count
96 std::multimap<int,string> curr_components_; //!< frequency:component
97 // singleton
98 App();
99 App& operator=(App const&) = delete;
100 static App* instance_;
102 /*!
103 * Returns part of the SQL query for DicView.
104 * \param id database id (did) of the searched word
105 * \sa parse_dic_input()
107 inline string q_reading ( const string &id="")
109 string s1 = id.empty() ? "":"(select ";
110 string s2 = id.empty() ? "":(" from d_reading where d_reading.did="+id+") ");
111 return s1 + "group_concat("\
112 "(case freq when 1 then '<reading_freq>'||reading||'</reading_freq>' "\
113 "else '<reading>'||reading||'</reading>' end)||"\
114 "'<rinf>'||inf||'</rinf>',"\
115 "\"<br/>\")" + s2 + "as reading, ";
118 /*!
119 * Returns part of the SQL query for DicView.
120 * \param id database id (did) of the searched word
121 * \sa parse_dic_input()
123 inline string q_kanji ( const string &id="" )
125 string s1 = id.empty() ? "":"(select ";
126 string s2 = id.empty() ? "":(" from d_kanji where d_kanji.did="+id+") ");
127 return s1 + "group_concat("\
128 "(case freq when 1 then '<kanji_freq>'||kanji||'</kanji_freq>' "\
129 "else '<kanji>'||kanji||'</kanji>' end)||"\
130 "'<kinf>'||inf||'</kinf>',"\
131 "\"<br/>\")" + s2 + "as kanji, ";
134 /*!
135 * Returns part of the SQL query for DicView.
136 * \param id database id (did) of the searched word
137 * \sa parse_dic_input()
139 inline string q_sense ( const string &id="" )
141 string s1 = id.empty() ? "":"(select ";
142 string s2 = id.empty() ? "":(" from d_sense where d_sense.did="+id+") ");
143 return s1 + "group_concat("\
144 "(case pos when '' then '' else '<pos>'||pos||'</pos>' end)||"\
145 "(case misc when '' then '' else '<misc>'||misc||'</misc>' end)||"\
146 "gloss||"\
147 "(case field when '' then '' else '<field>'||field||'</field>' end)||"\
148 "(case dial when '' then '' else '<dial>'||dial||'</dial>' end),"\
149 "'<sep/>') " + s2 + " as sense ";
152 public:
153 ~App();
155 //! Returns instance of App.
156 static inline App *get (){
157 if ( !instance_)
158 instance_ = new App();
159 return instance_;
162 //! Returns pointer to Romanization.
163 inline Romanization *rmn () const { return rmn_; };
165 //! Opens the main database and attach the user database.
166 void open_database ();
168 //! Log message.
169 inline void log ( const string &s ) { logger_.msg(s); };
170 //! Log error.
171 inline void log_e ( const string &s ) { logger_.msg(s,Logger::MSG_ERROR); };
172 //! Log warning.
173 inline void log_w ( const string &s ) { logger_.msg(s,Logger::MSG_WARNING); };
174 //! Log debug message.
175 inline void log_d ( const string &s ) { logger_.msg(s,Logger::MSG_DEBUG); };
176 //! Log message.
177 inline void log ( const std::stringstream &s ) { logger_.msg(s); };
178 //! Log error.
179 inline void log_e ( const std::stringstream &s )
180 { logger_.msg(s,Logger::MSG_ERROR); };
181 //! Log warning.
182 inline void log_w ( const std::stringstream &s )
183 { logger_.msg(s,Logger::MSG_WARNING); };
184 //! Log debug message.
185 inline void log_d ( const std::stringstream &s )
186 { logger_.msg(s,Logger::MSG_DEBUG); };
188 //! Returns pointer to UI.
189 inline aoi_ui::GUI *ui() const { return ui_; };
191 //! Call UI::run(), which calls Fl::run()
192 int run ( int argc, char **argv );
195 * Performs database query q.
196 * \param q SQLite query
197 * \param log_query true: q will be logged as debug message
198 * \param replace_separator true: parsers::SEPARATOR_SQL ('|')
199 * will be replaced by ", "
200 * \sa SQLite3::query()
201 * \returns data in same format as SQLite3::query()
203 vector<string> query ( const char *q, bool log_query=true,
204 bool replace_separator = true );
206 //! Gets one kanji from database.
207 Kanji db_get_kanji ( const string &kanji );
209 //! Gets one word(record) from database
210 DicWord db_get_word( int did );
212 //! Returns whole config as map.
213 inline std::map<string,aoi_config::Config::Value> get_config_map ()
214 { return cfg_->get_map(); };
215 //! Returns default config map.
216 inline std::map<string,aoi_config::Config::Value> get_config_map_default ()
217 { return cfg_->get_default_map(); };
218 /*!
219 * Sets one key=value config pair.
220 * \sa apply_config()
222 inline void set_config ( const string &key, const string &val )
223 { cfg_->set( key, val ); };
226 * Overrides one config option. Overidden option cant be changed until restart
227 * of the program.
228 * \sa Config::set_override()
230 inline void config_override ( const string &key, const string &val ) {
231 try{
232 cfg_->set_override(key,val);
234 catch ( const std::exception &e ) {
235 log_e("Unknown config: " + key);
240 * Load color from database (string 0xRRGGBB00) and converts it to Fl_Color
241 * (unsigned int);
243 inline Fl_Color get_color ( const string &color ){
244 string s = cfg_->get<string>("color/"+color);
245 std::stringstream ss;
246 ss << std::hex << s.substr(2);
247 Fl_Color c;
248 ss >> c;
249 return c;
253 * Applies config - sets colors, loglevel, fonts, ... Redraws UI.
254 * \sa set_config()
256 void apply_config ();
257 /*!
258 * Gets one config item
259 * \exception std::runtime_error when key does not exist
261 template<class T=string> inline T get_config( const string &s )
262 { return cfg_->get<T>(s); }
264 * Writes current config to database. Calls set_config() for each
265 * item in config map. After that calls init_dicview()
266 * \sa get_config_map()
267 * \sa set_config()
268 * \sa init_dicview()
269 * \todo check new keys
271 void save_config ( const std::map<string,aoi_config::Config::Value> &newmap={});
273 /*!
274 * Loads config from database.
275 * \todo Compare loaded and default config. Drop keys which exists in loaded
276 * but dont in default (i.e. keys from previous versions).
278 void load_config ();
281 * Initializes and sets styles in DicView.
282 * \sa DicView
283 * \sa TextStyle
284 * \sa GUI::register_tag_dicview()
286 void init_dicview ();
288 //! Shows alert/error window.
289 void alert ( const string &msg, const string &desc="" );
292 * Checks tables in database. Creates missing.
293 * \sa aoi_config::db_tables
295 void check_tables ();
297 * Checks indexes in database. Creates missing indexes and runs
298 * VACUUM if neccessary.
299 * \sa aoi_config::db_tables
301 void check_indexes ();
304 * Loads database stored as SQLite script. File may be GZipped.
306 void load_dbscript ( const char *fname );
307 inline void load_dbscript ( const string &fname ){ load_dbscript(fname.c_str());};
310 * Calls input parser. Resets GUI (pos chekboxes).
312 void cb_dic_input ();
314 // void on_dic_selected ( int id );
317 * Shows dialog which allows editing of the currently selected word
318 * (i.e. row in DicView)
320 void cb_edit_word ();
323 * Parses the content of dic_input_, builds and performs the query
324 * to the database.
325 * \see DictionaryInputParser
326 * \see q_sense(), q_reading(), q_kanji()
328 void parse_dic_input ( const char *str );
331 * Gets kanji from database and calls GUI::popup_kanji()
333 void cb_popup_kanji ( const string &kanji );
334 void cb_kanji_search ();
337 * Sets contents of the listview and listview_items_.
338 * \parameter v preformatted text (output from query()) to be used
339 * in aoi_ui::DicView
340 * \todo nokanji
342 void set_listview ( const vector<string> &v );
345 * Shows a context menu that contains kanji which appears in the selected
346 * word and items: Examples, Notes and Edit word.
347 * \see GUI::dicview_menu()
349 void cb_dicview_rightclick ( int did );
352 * Shows a dialog with example sentences. Sentances marked as good example
353 * for the word are displayed first and in the color.
355 void cb_examples ();
358 * Shows a dialog that allows managing the DB and downloading one.
360 void cb_manage_db ();
363 * Filters visible rows in the listview according to selected checkboxes.
365 void cb_filter_listview ();
368 * Builds a histogram of the components in currently visible kanjis and
369 * sets the content of ComponentView.
371 void cb_set_components ();
374 * Downloads prebuilt (gzipped) database from aoi.souko.cz.
376 void cb_download_db();
379 * Used as callback for download button in aoi_ui::ManageDBDialog::cb_download()
380 * \see cb_manage_db() (here it is set as callback)
381 * \see cb_download_db()
383 inline static void scb_download_db ( Fl_Widget *w, void *p )
384 { ((App*)p)->cb_download_db(); }
385 //! See cb_examples()
386 inline static void scb_examples ( Fl_Widget *w, void *p )
387 { ((App*)p)->cb_examples(); }
388 //! See cb_dic_input()
389 inline static void scb_dic_input ( Fl_Widget *w, void *p )
390 { ((App*)p)->cb_dic_input(); }
391 //! See cb_filter_listview()
392 inline static void scb_filter_listview ( Fl_Widget *w, void *p )
393 { ((App*)p)->cb_filter_listview(); }
394 //! See cb_manage_db()
395 inline static void scb_manage_db ( Fl_Widget *w, void *p )
396 { ((App*)p)->cb_manage_db(); }
397 //! See cb_kanji_search()
398 inline static void scb_kanji_search ( Fl_Widget *w, void *p )
399 { ((App*)p)->cb_kanji_search(); }
402 * \todo siplify and unite with GUI::popup_kanji
403 * \todo change to direct kanjisearch
405 inline static void scb_kanjiview_select ( Fl_Widget *w, void *p ){
406 aoi_ui::KanjiView *v = (aoi_ui::KanjiView*)w;
407 aoi_ui::KanjiView::Cell *c = v->selected();
408 if ( c ){
409 ((App*)p)->cb_popup_kanji( c->str );
410 // copy to selection buffer (middle mouse)
411 Fl::copy(c->str.c_str(), strlen(c->str.c_str()), 0);
415 * Static callback for doubleclick in dicview.
416 * \see cb_edit_word()
418 inline static void scb_dicview_doubleclick ( Fl_Widget *w, void *p ){
419 ((App*)p)->cb_edit_word(); }
421 * \see cb_edit_word()
423 inline static void scb_edit_word ( Fl_Widget *w, void *p ){
424 ((App*)p)->cb_edit_word(); }
427 * Calls back DicViews' callback for rightclick.
428 * \todo simplify, clarify
430 inline static void scb_dicview_rightclick ( Fl_Widget *w, void *p ){
431 aoi_ui::DicView *v = (aoi_ui::DicView*)w;
432 ((App*)p)->cb_dicview_rightclick( v->selected_row_id() );
434 //! See cb_set_components()
435 inline static void scb_set_components ( Fl_Widget *w, void *p )
436 { ((App*)p)->cb_set_components(); }
441 * Parses string in the dictionary's input fiels.
442 * Breaks the input string into the parts ( parts_ ) and build query.
443 * Part = content of one {}, [] or ().
444 * \see App:parse_dic_input()
446 class DictionaryInputParser
448 public:
449 enum PartType { STRING, WORD, KANJI };
450 private:
451 vector<std::pair<string,PartType>> parts_;
452 std::stringstream buffer_;
453 PartType type_ = STRING;
454 bool warning_ = false;
457 * Adds content of the buffer_ to parts_ and sets its type (called after
458 * encountering the start of a new part or end of string).
459 * \see parse()
461 inline void add () {
462 if ( buffer_.str().empty() ) return;
463 parts_.push_back( { buffer_.str(), type_ } );
464 buffer_.str("");
468 * Performs a kanji query, extracts all kanji from the result to the new set
469 * and intersects it with the set <i>current</i>. Called by find_kanji().
470 * \returns result of the intersection
472 set<string> intersection ( const string &query, const set<string> &current );
474 public:
475 DictionaryInputParser(){};
476 ~DictionaryInputParser(){};
478 /*!
479 * Returns whether the caller should display a warning about too broad search.
480 * \see check_warning(), Config::"dic/input_parser_warning"
482 inline bool warning () const { return warning_; };
485 * Parses the text in [] or (). Does some db queries (based on SKIP,
486 * reading of the word or on/kun).
487 * \param from_words If true then [] else ().
488 * \see intersect()
489 * \returns string consisting from all the matching kanji
491 string find_kanji ( const string &s, bool from_words=true );
494 * Checks whether the flag warning_ should be set.
495 * \see warning_()
497 void check_warning ( const string &s, const string &previous );
500 * Splits the input string into parts, identifies their types and
501 * \return list of matching kanji in the curly brackets (GLOB like)
503 string parse ( const char *s );
506 } // namespace aoi
507 #endif // _AOI_HXX