Changed changelog, copyright. Support for sorting checked items to bottom.
[easylist] / src / mainwindow.cpp
1 /*\r
2  *  Copyright (c) 2010 Willem Liu\r
3  *\r
4  *  Permission is hereby granted, free of charge, to any person obtaining a copy\r
5  *  of this software and associated documentation files (the "Software"), to deal\r
6  *  in the Software without restriction, including without limitation the rights\r
7  *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
8  *  copies of the Software, and to permit persons to whom the Software is\r
9  *  furnished to do so, subject to the following conditions:\r
10  *\r
11  *  The above copyright notice and this permission notice shall be included in\r
12  *  all copies or substantial portions of the Software.\r
13  *\r
14  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
15  *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
16  *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
17  *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
18  *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
19  *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
20  *  THE SOFTWARE.\r
21  */\r
22 \r
23 #include "mainwindow.h"\r
24 #include "ui_mainwindow.h"\r
25 #include "ui_listwindow.h"\r
26 \r
27 /**\r
28  * Constructor.\r
29  * Settings are initialised here.\r
30  * Landscape mode is set to true.\r
31  * List window is loaded.\r
32  * @fn MainWindow\r
33  * @param parent - The parent widget.\r
34  */\r
35 MainWindow::MainWindow(QWidget *parent) :\r
36     QMainWindow(parent),\r
37     editUi(new Ui::EditWindow),\r
38     listUi(new Ui::ListWindow)\r
39 {\r
40     // Connect to DBUS of keyboard slider.\r
41     QDBusConnection::systemBus().connect(QString("org.freedesktop.Hal"),\r
42                                          DBUS_KEYBOARD_SLIDE,\r
43                                          QString("org.freedesktop.Hal.Device"),\r
44                                          QString("PropertyModified"),\r
45                                          this, SLOT(slotKeyboardSlide()));\r
46     // Initialise the settings.\r
47     settings = new QSettings(WILLEM_LIU, EASY_LIST);\r
48 \r
49     // Set a default value for CHECKED_ITEMS_TO_BOTTOM\r
50     if(settings->contains(CHECKED_ITEMS_TO_BOTTOM) == false)\r
51     {\r
52         settings->setValue(CHECKED_ITEMS_TO_BOTTOM, false);\r
53     }\r
54 \r
55     // We always start in landscape mode.\r
56     landscape = settings->value(LANDSCAPE).toBool();\r
57     if(settings->contains(LANDSCAPE))\r
58     {\r
59         landscape = settings->value(LANDSCAPE).toBool();\r
60     }\r
61     settings->setValue(LANDSCAPE, landscape);\r
62     // If keyboard is opened at start. We do landscape mode.\r
63     // Otherwise we do what's read from the QSettings.\r
64     if(isKeyboardClosed() == false)\r
65     {\r
66         setLandscapeMode(true);\r
67     }\r
68     else\r
69     {\r
70         setLandscapeMode(landscape);\r
71     }\r
72     // Auto-detect portrait/landscape mode. Only works on top widget.\r
73 //    setAttribute(Qt::WA_Maemo5AutoOrientation, true);\r
74 \r
75     showListWindow();\r
76 }\r
77 \r
78 /**\r
79  * Destructor.\r
80  * User interface pointers are deleted here.\r
81  *\r
82  * @fn ~MainWindow\r
83  */\r
84 MainWindow::~MainWindow()\r
85 {\r
86     delete editUi;\r
87     delete listUi;\r
88 }\r
89 \r
90 /**\r
91  * Check the DBUS property to see if the keyboard is closed or opened.\r
92  */\r
93 bool MainWindow::isKeyboardClosed()\r
94 {\r
95     QDBusInterface propertyInterface("org.freedesktop.Hal",\r
96                     DBUS_KEYBOARD_SLIDE,\r
97                     "org.freedesktop.Hal.Device",\r
98                     QDBusConnection::systemBus());\r
99     bool result = propertyInterface.call("GetProperty", "button.state.value").arguments().at(0).toBool();\r
100     qDebug() << "Keyboard is closed:" << result;\r
101     return result;\r
102 }\r
103 \r
104 /**\r
105  * Slot is called when a DBUS event has been received caused by opening/closing the keyboard.\r
106  */\r
107 void MainWindow::slotKeyboardSlide()\r
108 {\r
109     // When keyboard is opened.\r
110     if(isKeyboardClosed() == false)\r
111     {\r
112         setLandscapeMode(true);\r
113     }\r
114     else\r
115     {\r
116         setLandscapeMode(landscape);\r
117     }\r
118 }\r
119 \r
120 /**\r
121  * Slot for action from Edit list button in de the list window.\r
122  *\r
123  * @fn slotListWindowEdit\r
124  */\r
125 void MainWindow::slotListWindowEdit()\r
126 {\r
127     qDebug() << "Edit list";\r
128     showEditWindow();\r
129 }\r
130 \r
131 /**\r
132  * Slot for action from Cancel button in de the edit window.\r
133  *\r
134  * @fn slotEditWindowCancel\r
135  */\r
136 void MainWindow::slotEditWindowCancel()\r
137 {\r
138     qDebug() << "Cancel";\r
139     showListWindow();\r
140 }\r
141 \r
142 /**\r
143  * Slot for action from Save button in de the edit window.\r
144  *\r
145  * @fn slotEditWindowSave\r
146  */\r
147 void MainWindow::slotEditWindowSave()\r
148 {\r
149     qDebug() << "Save";\r
150     settings->setValue(LIST_TEXT, editUi->textEdit->toPlainText());\r
151     showListWindow();\r
152 }\r
153 \r
154 /**\r
155  * Slot for action from Clear selected button in de the list window.\r
156  * It clears all QCheckBoxes from the layout, removes all checked items from\r
157  * the list text and finally calls generateList().\r
158  *\r
159  * @fn slotListWindowClearSelected\r
160  */\r
161 void MainWindow::slotListWindowClearSelected()\r
162 {\r
163     qDebug() << "Clear selected";\r
164     QString listText("");\r
165     foreach(QCheckBox * cb, checkBoxes)\r
166     {\r
167         cb->deleteLater();\r
168         if(cb->isChecked() == false)\r
169         {\r
170             listText.append(cb->text());\r
171             listText.append("\n");\r
172         }\r
173     }\r
174 \r
175     settings->setValue(LIST_TEXT, listText);\r
176     generateList();\r
177 }\r
178 \r
179 /**\r
180  * Prefix all checked items with ! in the list text and save it to QSettings.\r
181  */\r
182 void MainWindow::slotListWindowSaveChecked()\r
183 {\r
184     qDebug() << "Save selected";\r
185     QString listText("");\r
186     foreach(QCheckBox * cb, checkBoxes)\r
187     {\r
188         QString item(cb->text());\r
189         if(cb->isChecked() == true)\r
190         {\r
191             if(item.startsWith("!") == false)\r
192             {\r
193                 item.push_front("!");\r
194             }\r
195             listText.append(item);\r
196         }\r
197         else\r
198         {\r
199             if(item.startsWith("!") == true)\r
200             {\r
201                 item = item.replace("!", "");\r
202             }\r
203             listText.append(item);\r
204         }\r
205         listText.append("\n");\r
206     }\r
207 \r
208     settings->setValue(LIST_TEXT, listText);\r
209 }\r
210 \r
211 /**\r
212  * Is called when a checkbox has been clicked.\r
213  *\r
214  * @fn slotActionCheckBox\r
215  * @param bool checked - true if checkbox is checked.\r
216  */\r
217 void MainWindow::slotActionCheckBox(bool checked)\r
218 {\r
219     qDebug() << "CheckBox checked=" << checked;\r
220     slotListWindowSaveChecked();\r
221     if(settings->value(CHECKED_ITEMS_TO_BOTTOM).toBool())\r
222     {\r
223         slotSortCheckedBottom();\r
224         // Remove all the checkboxes from the screen.\r
225         foreach(QCheckBox * cb, checkBoxes)\r
226         {\r
227             cb->deleteLater();\r
228         }\r
229         generateList();\r
230     }\r
231     else\r
232     {\r
233         qDebug() << "No need to sort items to bottom";\r
234     }\r
235 }\r
236 \r
237 /**\r
238  * Sort checked items to bottom of the list text and returns the new list text.\r
239  *\r
240  * @fn slotSortCheckedBottom\r
241  *\r
242  * @return QString - the new list text.\r
243  */\r
244 QString MainWindow::slotSortCheckedBottom()\r
245 {\r
246     QString result(settings->value(LIST_TEXT).toString());\r
247     if(settings->value(CHECKED_ITEMS_TO_BOTTOM).toBool())\r
248     {\r
249         QStringList list = result.split("\n");\r
250         QString listText("");\r
251         QString checkedListText("");\r
252         foreach(QString item, list)\r
253         {\r
254             if(item.length() > 0)\r
255             {\r
256                 if(item.startsWith("!"))\r
257                 {\r
258                     checkedListText.append(item);\r
259                     checkedListText.append("\n");\r
260                 }\r
261                 else\r
262                 {\r
263                     listText.append(item);\r
264                     listText.append("\n");\r
265                 }\r
266             }\r
267         }\r
268         listText.append(checkedListText);\r
269         qDebug() << "Sort checked items to bottom";\r
270         settings->setValue(LIST_TEXT, listText);\r
271         result = listText;\r
272     }\r
273     return result;\r
274 }\r
275 \r
276 /**\r
277  * Show the edit window.\r
278  *\r
279  * @fn showEditWindow\r
280  */\r
281 void MainWindow::showEditWindow()\r
282 {\r
283     slotListWindowSaveChecked();\r
284     editUi->setupUi(this);\r
285     editUi->textEdit->setText(settings->value(LIST_TEXT).toString());\r
286     connect(editUi->savePushButton, SIGNAL(clicked()), this, SLOT(slotEditWindowSave()));\r
287     connect(editUi->cancelPushButton, SIGNAL(clicked()), this, SLOT(slotEditWindowCancel()));\r
288 }\r
289 \r
290 /**\r
291  * Show the list window.\r
292  *\r
293  * @fn showListWindow\r
294  */\r
295 void MainWindow::showListWindow()\r
296 {\r
297     listUi->setupUi(this);\r
298     listUi->listVerticalLayout->setAlignment(Qt::AlignTop);\r
299     listUi->actionChecked_Bottom->setChecked(settings->value(CHECKED_ITEMS_TO_BOTTOM).toBool());\r
300     slotSortCheckedBottom();\r
301     generateList();\r
302     connect(listUi->editListPushButton, SIGNAL(clicked()), this, SLOT(slotListWindowEdit()));\r
303     connect(listUi->clearSelectedPushButton, SIGNAL(clicked()), this, SLOT(slotListWindowClearSelected()));\r
304     connect(listUi->menuChecked_Bottom, SIGNAL(triggered(QAction*)), this, SLOT(slotActionCheckedBottom(QAction*)));\r
305     connect(listUi->menuAbout, SIGNAL(triggered(QAction*)), this, SLOT(slotActionAbout(QAction*)));\r
306     connect(listUi->menuRotate, SIGNAL(triggered(QAction*)), this, SLOT(slotActionRotate(QAction*)));\r
307 }\r
308 \r
309 /**\r
310  * Generate the list of checkboxes. A pointer to such a checkbox will be stored\r
311  * in a container for later use.\r
312  *\r
313  * @fn generateList\r
314  */\r
315 void MainWindow::generateList()\r
316 {\r
317     qDebug() << "Generate List";\r
318 \r
319     checkBoxes.clear();\r
320     QString text = settings->value(LIST_TEXT).toString();\r
321     QStringList list = text.split("\n");\r
322 \r
323     foreach(QString item, list)\r
324     {\r
325         if(item.length() > 0)\r
326         {\r
327             QCheckBox * cb = new QCheckBox(item);\r
328             connect(cb, SIGNAL(clicked(bool)), this, SLOT(slotActionCheckBox(bool)));\r
329             if(item.startsWith("!"))\r
330             {\r
331                 QString itemName(item.right(item.length()-1));\r
332                 cb->setText(itemName);\r
333                 cb->setChecked(true);\r
334             }\r
335             checkBoxes.append(cb);\r
336             listUi->listVerticalLayout->addWidget(cb);\r
337         }\r
338     }\r
339 }\r
340 \r
341 /**\r
342  * Is called when the application terminates.\r
343  *\r
344  * @fn closeEvent\r
345  * @param event - the QCloseEvent.\r
346  */\r
347 void MainWindow::closeEvent(QCloseEvent *event)\r
348 {\r
349     qDebug() << "Closed";\r
350     slotListWindowSaveChecked();\r
351     event->accept();\r
352 }\r
353 \r
354 /**\r
355  * Is called when the Rotate menu item is triggered. Display orientation is saved in the QSettings.\r
356  *\r
357  * @fn slotActionRotate\r
358  * @param QAction* action - the action.\r
359  */\r
360 void MainWindow::slotActionRotate(QAction* action)\r
361 {\r
362     qDebug() << "Rotate" << action->text();\r
363 \r
364     landscape = !tempLandscapeMode;\r
365     settings->setValue(LANDSCAPE, landscape);\r
366     setLandscapeMode(landscape);\r
367 }\r
368 \r
369 /**\r
370  * Set landscape/portrait mode.\r
371  */\r
372 void MainWindow::setLandscapeMode(bool landscape)\r
373 {\r
374     if(landscape)\r
375     {\r
376         tempLandscapeMode = true;\r
377         qDebug() << LANDSCAPE;\r
378         setAttribute(Qt::WA_Maemo5LandscapeOrientation, true);\r
379         setAttribute(Qt::WA_Maemo5PortraitOrientation, false);\r
380     }\r
381     else\r
382     {\r
383         tempLandscapeMode = false;\r
384         qDebug() << PORTRAIT;\r
385         setAttribute(Qt::WA_Maemo5PortraitOrientation, true);\r
386         setAttribute(Qt::WA_Maemo5LandscapeOrientation, false);\r
387     }\r
388 }\r
389 \r
390 /**\r
391  * Is called when the About menu item is triggered.\r
392  *\r
393  * @fn slotActionAbout\r
394  * @param QAction* action - the action.\r
395  */\r
396 void MainWindow::slotActionAbout(QAction* action)\r
397 {\r
398     qDebug() << "About" << action->text();\r
399     QString aboutText;\r
400     aboutText.append("EasyList (c) 2010\n\n");\r
401     aboutText.append("Created by Willem Liu.\n");\r
402     aboutText.append("Created with QtCreator.\n");\r
403     QMessageBox::about(this, "EasyList", aboutText);\r
404 }\r
405 \r
406 /**\r
407  * Is called when the Checked Bottom menu item is triggered.\r
408  * The menu item is a checkable item. So we need to check if it's checked or not.\r
409  *\r
410  * @fn slotActionCheckedBottom\r
411  * @param QAction* action - the action.\r
412  */\r
413 void MainWindow::slotActionCheckedBottom(QAction* action)\r
414 {\r
415     qDebug() << "Checked Bottom" << action->text() << listUi->actionChecked_Bottom->isChecked();\r
416     settings->setValue(CHECKED_ITEMS_TO_BOTTOM, listUi->actionChecked_Bottom->isChecked());\r
417 }\r