439641cd93a46fa9c2fbebd7d9a6c00c290dd176
[mverbiste] / mainwindow.cpp
1 #include "mainwindow.h"
2 #include "ui_mainwindow.h"
3 #include "gui/conjugation.h"
4
5 #include <QtCore/QCoreApplication>
6
7 MainWindow::MainWindow(QWidget *parent)
8     : QMainWindow(parent), ui(new Ui::MainWindow)
9 {
10 #ifdef Q_WS_MAEMO_5
11     this->setAttribute(Qt::WA_Maemo5StackedWindow);
12     this->setWindowFlags(Qt::Window);
13 #endif
14     ui->setupUi(this);
15     setupcodedUI();
16 }
17
18 void MainWindow::setupcodedUI()
19 {
20     cent = centralWidget();
21     mlayout = new QVBoxLayout;
22     btlayout = new QHBoxLayout;
23
24     resultPages = new QTabWidget;
25     resultPages->setTabPosition(QTabWidget::West);
26     mlayout->addWidget(resultPages);
27
28     btnClear = new QPushButton;
29     btnClear->setIcon(QIcon("/usr/share/icons/hicolor/64x64/hildon/general_delete.png"));
30     wordinput = new QLineEdit;
31     btlayout->addWidget(btnClear);
32     btlayout->addWidget(wordinput);
33     btnLookup = new QPushButton;  // Lookup button
34     btnLookup->setIcon(QIcon("/usr/share/icons/hicolor/64x64/hildon/general_search.png"));
35     btlayout->addWidget(btnLookup);
36
37     mlayout->addLayout(btlayout);
38     cent->setLayout(mlayout);
39
40     // Clear the word input when Clear button is tapped
41     connect(btnClear, SIGNAL(clicked()), this, SLOT(startAgain()));
42
43     connect(wordinput, SIGNAL(returnPressed()), this, SLOT(startLookup()));
44     connect(btnLookup, SIGNAL(clicked()), this, SLOT(startLookup()));
45 }
46
47 MainWindow::~MainWindow()
48 {
49     delete ui;
50     delete freVerbDic;
51 }
52
53 void MainWindow::setOrientation(ScreenOrientation orientation)
54 {
55 #if defined(Q_OS_SYMBIAN)
56     // If the version of Qt on the device is < 4.7.2, that attribute won't work
57     if (orientation != ScreenOrientationAuto) {
58         const QStringList v = QString::fromAscii(qVersion()).split(QLatin1Char('.'));
59         if (v.count() == 3 && (v.at(0).toInt() << 16 | v.at(1).toInt() << 8 | v.at(2).toInt()) < 0x040702) {
60             qWarning("Screen orientation locking only supported with Qt 4.7.2 and above");
61             return;
62         }
63     }
64 #endif // Q_OS_SYMBIAN
65
66     Qt::WidgetAttribute attribute;
67     switch (orientation) {
68 #if QT_VERSION < 0x040702
69     // Qt < 4.7.2 does not yet have the Qt::WA_*Orientation attributes
70     case ScreenOrientationLockPortrait:
71         attribute = static_cast<Qt::WidgetAttribute>(128);
72         break;
73     case ScreenOrientationLockLandscape:
74         attribute = static_cast<Qt::WidgetAttribute>(129);
75         break;
76     default:
77     case ScreenOrientationAuto:
78         attribute = static_cast<Qt::WidgetAttribute>(130);
79         break;
80 #else // QT_VERSION < 0x040702
81     case ScreenOrientationLockPortrait:
82         attribute = Qt::WA_LockPortraitOrientation;
83         break;
84     case ScreenOrientationLockLandscape:
85         attribute = Qt::WA_LockLandscapeOrientation;
86         break;
87     default:
88     case ScreenOrientationAuto:
89         attribute = Qt::WA_AutoOrientation;
90         break;
91 #endif // QT_VERSION < 0x040702
92     };
93     setAttribute(attribute, true);
94 }
95
96 void MainWindow::showExpanded()
97 {
98 #if defined(Q_OS_SYMBIAN) || defined(Q_WS_SIMULATOR)
99     showFullScreen();
100 #elif defined(Q_WS_MAEMO_5)
101     showMaximized();
102 #else
103     show();
104 #endif
105     wordinput->setFocus();
106     initverbiste();
107 }
108
109 void  MainWindow::initverbiste()
110 {
111     langCode = "fr";
112
113     FrenchVerbDictionary::Language lang = FrenchVerbDictionary::parseLanguageCode(langCode);
114     if (lang != FrenchVerbDictionary::FRENCH)
115     {
116         // TODO: If lang code is not supported?
117     }
118
119     /* Create verb dictionary, accept non-accent input */
120     freVerbDic = new FrenchVerbDictionary(true);
121 }
122
123 void MainWindow::startLookup()
124 {
125     QString input = wordinput->text().trimmed();
126     if (input.isEmpty()) {
127         return;
128     }
129
130     btnLookup->setText(tr("Please wait..."));
131     btnLookup->setEnabled(false);
132     clearResults();
133     /* Pending the lookup job to the next event loop (redraw the button right now) */
134     QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
135
136     /* Get input word to look up */
137     const std::string word = input.toLower().toUtf8().constData();
138
139     /*
140      *  For each possible deconjugation, take the infinitive form and
141      *  obtain its complete conjugation.
142      */
143     std::vector<InflectionDesc> infles;
144     bool includePronouns = FALSE;    // TODO: Will get this value from external
145     bool isItalian = FALSE;          // TODO: Will get this value from external
146
147 #ifndef QT_NO_DEBUG
148     timer.start();
149     qDebug() << "Start " << timer.elapsed();
150 #endif
151     freVerbDic->deconjugate(word, infles);
152
153     resultPages->setUpdatesEnabled(false);
154     std::string prevUTF8Infinitive, prevTemplateName; /* Remember found word
155     to avoid conjugating again */
156
157     for (std::vector<InflectionDesc>::const_iterator it = infles.begin();
158          it != infles.end(); it++)
159     {
160         const InflectionDesc &d = *it;
161
162 #ifndef QT_NO_DEBUG
163         qDebug() << ">> Infinitive " << d.infinitive.c_str();
164         qDebug() << "   Template " << d.templateName.c_str();
165 #endif
166         /* If this infinitive has been conjugated, we skip to the next infinitive */
167         if (d.infinitive == prevUTF8Infinitive && d.templateName == prevTemplateName) {
168             continue;
169         }
170         /* FIXME:
171          * In original source (Verbiste), this checking is done later,
172          * after getConjugation(). I place it here to avoid calling again
173          * multitimes getConjugation(), which is very slow.
174          * We need to test more to see which place is more correct.
175          */
176
177         VVVS conjug;
178 #ifndef QT_NO_DEBUG
179         qDebug() << "   START getConjugation " << timer.elapsed();
180 #endif
181         getConjugation(freVerbDic, d.infinitive, d.templateName, conjug,
182                #ifndef QT_NO_DEBUG
183                        timer,
184                #endif
185                        includePronouns);
186
187 #ifndef QT_NO_DEBUG
188         qDebug() << "   getConjugation() returns: " << timer.elapsed();
189 #endif
190
191         if (conjug.size() == 0           // if no tenses
192             || conjug[0].size() == 0     // if no infinitive tense
193             || conjug[0][0].size() == 0  // if no person in inf. tense
194             || conjug[0][0][0].empty())  // if infinitive string empty
195         {
196             continue;
197         }
198
199         std::string utf8Infinitive = conjug[0][0][0];
200 #ifndef QT_NO_DEBUG
201         qDebug() << "     Infinitive " << utf8Infinitive.c_str();
202         qDebug() << "     Template " << d.templateName.c_str();
203 #endif
204
205         /* Add result to GUI (not show yet) */
206         ResultPage *rsp = addResultPage(utf8Infinitive);
207
208         /* Get modes and tenses of the verb */
209         int i = 0;
210         for (VVVS::const_iterator t = conjug.begin();
211              t != conjug.end(); t++, i++) {
212             if (i == 1)
213                 i = 4;
214             else if (i == 11)
215                 i = 12;
216             assert(i >= 0 && i < 16);
217
218             int row = i / 4;
219             int col = i % 4;
220
221             std::string utf8TenseName = getTenseNameForTableCell(row, col, isItalian);
222             if (utf8TenseName.empty())
223                 continue;
224
225             QVBoxLayout *cell = makeResultCell(*t, utf8TenseName, word, freVerbDic);
226             rsp->grid->addLayout(cell, row, col);
227         }
228
229         /* Show the result on GUI */
230         rsp->packContent();
231         prevUTF8Infinitive = utf8Infinitive;
232         prevTemplateName = d.templateName;
233     }
234
235     /* Enable the button again */
236     btnLookup->setEnabled(true);
237     btnLookup->setText("");
238     resultPages->setUpdatesEnabled(true);
239 }
240
241 ResultPage* MainWindow::addResultPage(const std::string &labelText)
242 {
243     ResultPage *rp = new ResultPage();
244     QString label = QString::fromUtf8(labelText.c_str());
245     resultPages->addTab(rp->page, label);
246     return rp;
247 }
248
249 void MainWindow::clearResults()
250 {
251     while (resultPages->count()) {
252         int lastIndex = resultPages->count() - 1;
253         resultPages->widget(lastIndex)->deleteLater();
254         resultPages->removeTab(lastIndex);
255     }
256 }
257
258 void MainWindow::startAgain()
259 {
260     wordinput->clear();
261     clearResults();
262     wordinput->setFocus();
263     btnLookup->setEnabled(true);
264 }
265
266 QVBoxLayout* MainWindow::makeResultCell(const VVS &tenseIterator,
267                                         const std::string &tenseName,
268                                         const std::string &inputWord,
269                                         FrenchVerbDictionary *verbDict)
270 {
271     /* Mode & Tense name */
272     QLabel *tenseLabel = new QLabel();
273     tenseLabel->setText(QString::fromUtf8(tenseName.c_str()));
274     tenseLabel->setStyleSheet("QLabel {background-color: #44A51C; "
275                               "padding-left: 10px; padding-right: 10px}");
276
277     /* Conjugaison */
278     QVBoxLayout *vbox = new QVBoxLayout();
279     vbox->addWidget(tenseLabel);
280     QVector<QString> persons = qgetConjugates(*verbDict, tenseIterator,inputWord,
281                                               "<font color='#D20020'>", "</font>");
282     for (int i = 0; i < persons.size(); ++i) {
283         QLabel *lb = new QLabel(persons.at(i));
284         lb->setMargin(4);
285         vbox->addWidget(lb, 1);
286     }
287     return vbox;
288 }
289
290 /**** For ResultPage class ****/
291 ResultPage::ResultPage()
292     : page(new QScrollArea),
293       grid(new QGridLayout)
294 {
295 }
296
297 void ResultPage::packContent()
298 {
299     QWidget *immediate = new QWidget();
300     immediate->setLayout(grid);
301     page->setWidget(immediate);
302 }
303