Added some error checks for sanity
[biaweb_qt.git] / main_window.py
1 # BiaWeb Website content manager (c) 2010 V.Harishankar
2 # Main Window class
3
4 import PyQt4
5 import sys
6
7 import ui_main_window
8 import site_configuration_dialog as scd
9 import category_dialog as catd
10 import article_dialog as artd
11 import templates_dialog as tpld
12 import generate_dialog as gend
13 import biaweb_db
14
15 class MainWindow (PyQt4.QtGui.QMainWindow, ui_main_window.Ui_MainWindow):
16 def __init__ (self):
17 PyQt4.QtGui.QMainWindow.__init__ (self)
18 self.setupUi (self)
19 self.current_db = None
20
21 # refresh the category list
22 def repopulate_categories (self):
23 recs = biaweb_db.get_categories (self.current_db)
24
25 # check with False because None is returned when no records exist
26 if recs == False:
27 PyQt4.QtGui.QMessageBox.critical (self, "Error", "SQLite 3 error in getting the categories")
28 return False
29
30 self.categories.clear ()
31 for (id, name, desc, stub) in recs:
32 qrow = PyQt4.QtGui.QTreeWidgetItem ([str(id), str(name)])
33 self.categories.addTopLevelItem (qrow)
34
35 # return true when successful
36 return True
37
38 # refresh the articles list
39 def repopulate_articles (self, catid=None):
40 recs = biaweb_db.get_articles (self.current_db, catid)
41
42 # check with False because None is returned when no records exist
43 if recs == False:
44 PyQt4.QtGui.QMessageBox.critical (self, "Error", "SQLite 3 error in getting the articles")
45 return False
46
47 self.articles.clear ()
48 for item in recs:
49 qrow = PyQt4.QtGui.QTreeWidgetItem ([str(item[0]), str(item[1])])
50 self.articles.addTopLevelItem (qrow)
51 # return true when successful
52
53 # when the view is refreshed
54 def onViewRefresh (self):
55 if self.current_db is not None:
56 self.repopulate_categories ()
57 self.repopulate_articles ()
58
59 # when add article is triggered
60 def onArticleAdd (self):
61 if self.current_db is None:
62 PyQt4.QtGui.QMessageBox.critical (self, "Error",
63 "Cannot create article. You need to create or open a website first")
64 else:
65 catid = self.get_selected_item_id (self.categories)
66 # if no category is selected
67 if catid is None:
68 PyQt4.QtGui.QMessageBox.critical (self, "Error", "No category selected for article")
69 return
70 artdlg = artd.ArticleDialog (self)
71 cats = biaweb_db.get_categories (self.current_db)
72
73 artdlg.populate_categories (cats, catid)
74
75 # if OK is pressed
76 if artdlg.exec_ () == PyQt4.QtGui.QDialog.Accepted:
77 title = str (artdlg.article_title.text ()).strip ()
78 keywords = str (artdlg.keywords.text ()).strip ()
79 summary = str (artdlg.summary.toPlainText ()).strip ()
80 content = str (artdlg.content.toPlainText ()).strip ()
81 cid, ok = artdlg.category.itemData (artdlg.category.currentIndex ()).toInt ()
82 # if catid is not an integer then abort
83 if not ok:
84 return
85 rating = artdlg.rating.value ()
86 stub = str (artdlg.stub.text ()).strip ()
87
88 ret = biaweb_db.create_article (self.current_db, title, summary, keywords, content, cid,
89 stub, rating)
90 if ret:
91 PyQt4.QtGui.QMessageBox.information (self, "Success", "Article successfully created")
92 self.repopulate_categories ()
93 self.repopulate_articles (catid)
94 else:
95 PyQt4.QtGui.QMessageBox.critical (self, "Error", "SQLite 3 error in creating article")
96
97 # when edit article is triggered
98 def onArticleEdit (self):
99 if self.current_db is None:
100 PyQt4.QtGui.QMessageBox.critical (self, "Error",
101 "Cannot edit article. You need to create or open a website first")
102 else:
103 # get the selected article
104 artid = self.get_selected_item_id (self.articles)
105 catid = self.get_selected_item_id (self.categories)
106
107 # no article is selected
108 if artid is None:
109 PyQt4.QtGui.QMessageBox.critical (self, "Error", "No article selected")
110 return
111 article = biaweb_db.get_article (self.current_db, artid)
112 # if article cannot be read
113 if not article:
114 PyQt4.QtGui.QMessageBox.critical (self, "Error", "SQLite 3 error in reading article")
115 return
116 artdlg = artd.ArticleDialog (self)
117
118 artdlg.article_title.setText (article[1])
119 artdlg.summary.setPlainText (article[2])
120 artdlg.keywords.setText (article[3])
121 artdlg.content.setPlainText (article[4])
122 # populate category combo box and set active category to the article's category
123 cats = biaweb_db.get_categories (self.current_db)
124 artdlg.populate_categories (cats, article[7])
125 artdlg.stub.setText (article[8])
126 artdlg.rating.setValue (article[9])
127
128 # ok is pressed
129 if artdlg.exec_ () == PyQt4.QtGui.QDialog.Accepted:
130 title = str (artdlg.article_title.text ()).strip ()
131 summary = str (artdlg.summary.toPlainText ()).strip ()
132 keywords = str (artdlg.keywords.text ()).strip ()
133 content = str (artdlg.content.toPlainText ()).strip ()
134 cid, ok = artdlg.category.itemData (artdlg.category.currentIndex()).toInt ()
135 # if cat id is not an integer
136 if not ok:
137 return
138 rating = artdlg.rating.value ()
139 stub = str (artdlg.stub.text ()).strip ()
140 ret = biaweb_db.update_article (self.current_db, artid, title,
141 summary, keywords, content, cid, stub, rating)
142 if ret:
143 PyQt4.QtGui.QMessageBox.information (self, "Success", "Article successfully updated")
144 self.repopulate_articles (catid)
145 else:
146 PyQt4.QtGui.QMessageBox.critical (self, "Error", "SQLite 3 error in updating article")
147
148 # when delete article is triggered
149 def onArticleDelete (self):
150 if self.current_db is None:
151 PyQt4.QtGui.QMessageBox.critical (self, "Error",
152 "Cannot delete article. You need to create or open a website first")
153 else:
154 # get the selected article
155 artid = self.get_selected_item_id (self.articles)
156 catid = self.get_selected_item_id (self.categories)
157 if artid is None:
158 PyQt4.QtGui.QMessageBox.critical (self, "Error", "No article selected")
159 return
160 # get confirmation on delete
161 flag = PyQt4.QtGui.QMessageBox.question (self, "Confirm",
162 "Are you sure you wish to delete the selected article?",
163 PyQt4.QtGui.QMessageBox.Yes, PyQt4.QtGui.QMessageBox.No)
164 # confirmed
165 if flag == PyQt4.QtGui.QMessageBox.Yes:
166 ret = biaweb_db.delete_article (self.current_db, artid)
167 if not ret:
168 PyQt4.QtGui.QMessageBox.critical (self, "Error", "SQLite 3 error in deleting article")
169 else:
170 self.repopulate_articles (catid)
171
172 # when category item is activated
173 def onCategoryItemActivated (self):
174 self.onCategoryEdit ()
175
176 # when article item is activated
177 def onArticleItemActivated (self):
178 self.onArticleEdit ()
179
180 # when item selection is changed in categories tree widget
181 def onCategorySelectionChanged (self):
182 if self.current_db is not None:
183 catid = self.get_selected_item_id (self.categories)
184 self.repopulate_articles (catid)
185
186 # when configuration menu is triggered
187 def onConfiguration (self):
188 if self.current_db is None:
189 PyQt4.QtGui.QMessageBox.critical (self, "Error",
190 "Cannot edit configuration. You need to create or open a website first")
191 else:
192 dlg = scd.SiteConfigDialog (self)
193 configs = biaweb_db.get_configuration (self.current_db)
194
195 if not configs:
196 PyQt4.QtGui.QMessageBox.critical (self, "Error", "SQLite 3 error in reading configuration")
197 return
198
199 # set the data
200 dlg.site_url.setText (configs[0])
201 dlg.site_title.setText (configs[1])
202 dlg.keywords.setText (configs[2])
203 dlg.description.setPlainText (configs[3])
204 dlg.num_rss_items.setValue (configs[4])
205 dlg.destination.setText (configs[5])
206 dlg.copyright.setText (configs[6])
207
208 if (dlg.exec_ () == PyQt4.QtGui.QDialog.Accepted):
209 # if accepted, get the data and store in database
210 site_title = str (dlg.site_title.text ()).strip ()
211 site_url = str (dlg.site_url.text ()).strip ()
212 keywords = str (dlg.keywords.text ()).strip ()
213 destination = str (dlg.destination.text ()).strip ()
214 description = str (dlg.description.toPlainText ()).strip ()
215 num_rss = dlg.num_rss_items.value ()
216 copyright = str (dlg.copyright.text ()).strip ()
217 # database update
218 flag = biaweb_db.set_configuration (self.current_db, site_title, site_url, keywords, description,
219 copyright, num_rss, destination)
220 if not flag:
221 PyQt4.QtGui.QMessageBox.critical (self, "Error",
222 "SQLite 3 error in updating configuration")
223
224 # when templates menu is triggered
225 def onTemplates (self):
226 if self.current_db is None:
227 PyQt4.QtGui.QMessageBox.critical (self, "Error",
228 "Cannot edit templates. You need to create or open a website first")
229 else:
230 tdlg = tpld.TemplatesDialog (self, self.current_db)
231 tdlg.exec_ ()
232
233 # function to get the category or article ID from current selected item in a tree widget
234 def get_selected_item_id (self, twidget):
235 selitems = twidget.selectedItems ()
236 if selitems:
237 # get the first column data as integer
238 selindex = selitems[0].data(0, 0).toInt ()[0]
239 return selindex
240 else:
241 return None
242
243 # category edit action
244 def onCategoryEdit (self):
245 # if no database is open
246 if self.current_db is None:
247 PyQt4.QtGui.QMessageBox.critical (self, "Error",
248 "Cannot edit category. You need to create or open a website first")
249 # database is open
250 else:
251 catid = self.get_selected_item_id (self.categories)
252 # if no category is selected, display an error
253 if catid is None:
254 PyQt4.QtGui.QMessageBox.critical (self, "Error", "No category selected")
255 # category is selected
256 else:
257 cat = biaweb_db.get_category (self.current_db, catid)
258 # if the category cannot be retrieved from database
259 if not cat:
260 PyQt4.QtGui.QMessageBox.critical (self, "Error", "SQLite 3 error in reading category")
261 return
262
263 # set the data in the dialog
264 dlg = catd.CategoryDialog (self)
265 dlg.category_name.setText (cat[1])
266 dlg.category_desc.setText (cat[2])
267 dlg.category_stub.setText (cat[3])
268
269 # if accepted
270 if dlg.exec_ () == PyQt4.QtGui.QDialog.Accepted:
271 category_name = str (dlg.category_name.text ()).strip ()
272 category_desc = str (dlg.category_desc.text ()).strip ()
273 category_stub = str (dlg.category_stub.text ()).strip ()
274
275 ret = biaweb_db.update_category (self.current_db,
276 catid, category_name, category_desc, category_stub)
277 if ret:
278 PyQt4.QtGui.QMessageBox.information (self, "Success", "Category successfully updated")
279 self.repopulate_categories ()
280 else:
281 PyQt4.QtGui.QMessageBox.critical (self, "Error", "SQLite 3 error in updating category")
282
283
284 # category delete action
285 def onCategoryDelete (self):
286 # if there is no database
287 if self.current_db is None:
288 PyQt4.QtGui.QMessageBox.critical (self, "Error",
289 "Cannot delete category. You need to create or open a website first")
290 else:
291 # get the selected category
292 catid = self.get_selected_item_id (self.categories)
293 if catid is None:
294 PyQt4.QtGui.QMessageBox.critical (self, "Error", "No category selected")
295 # category is selected
296 else:
297 # get confirmation first
298 flag = PyQt4.QtGui.QMessageBox.question (self, "Confirm",
299 "This will delete the category and all associated articles. Are you sure you wish to continue?",
300 PyQt4.QtGui.QMessageBox.Yes, PyQt4.QtGui.QMessageBox.No)
301 # if confirmed
302 if flag == PyQt4.QtGui.QMessageBox.Yes:
303 ret = biaweb_db.remove_category (self.current_db, catid)
304 if not ret:
305 PyQt4.QtGui.QMessageBox.critical (self, "Error", "SQLite 3 error in deleting category")
306 else:
307 self.repopulate_categories ()
308 self.repopulate_articles ()
309
310 # category add action
311 def onCategoryAdd (self):
312 # if there is no database
313 if self.current_db is None:
314 PyQt4.QtGui.QMessageBox.critical (self, "Error",
315 "Cannot add category. You need to create or open a website first")
316 else:
317 # show the category add dialog
318 dlg = catd.CategoryDialog (self)
319 # if OK button is pressed
320 if dlg.exec_ () == PyQt4.QtGui.QDialog.Accepted:
321 cat_name = str (dlg.category_name.text ()).strip ()
322 cat_desc = str (dlg.category_desc.text ()).strip ()
323 cat_stub = str (dlg.category_stub.text ()).strip ()
324 ret = biaweb_db.create_category (self.current_db, cat_name, cat_desc, cat_stub)
325 if ret:
326 PyQt4.QtGui.QMessageBox.information (self, "Success", "Category successfully created")
327 self.repopulate_categories ()
328 self.repopulate_articles ()
329 else:
330 PyQt4.QtGui.QMessageBox.critical (self, "Error", "SQLite 3 error in creating category")
331
332 # file open menu is clicked
333 def onFileOpen (self):
334 filename = PyQt4.QtGui.QFileDialog.getOpenFileName (self, "Open Site Database")
335 if filename:
336 self.current_db = str (filename)
337
338 # added to check whether categories are loaded successfully or not
339 # if not, then reset the current_db to None
340 loaded_cats = self.repopulate_categories ()
341 loaded_arts = self.repopulate_articles ()
342 # if failed in loading either categories or articles (note: checking against
343 # False and not None)
344 if loaded_cats == False or loaded_arts == False:
345 self.current_db = None
346 PyQt4.QtGui.QMessageBox.critical (self, "Error",
347 "SQLite 3 error in loading site database. This appears to be an invalid BiaWeb database")
348 else:
349 # set the window title to the database
350 self.setWindowTitle ("BiaWeb - " + self.current_db)
351
352
353 # file new menu is clicked
354 def onFileNew (self):
355 # show the site configuration dialog to get the new site details
356 dlg = scd.SiteConfigDialog (self)
357 # if OK button is pressed
358 if dlg.exec_ () == PyQt4.QtGui.QDialog.Accepted:
359 site_title = str (dlg.site_title.text ()).strip ()
360 site_url = str (dlg.site_url.text ()).strip ()
361 keywords = str (dlg.keywords.text ()).strip ()
362 destination = str (dlg.destination.text ()).strip ()
363 description = str (dlg.description.toPlainText ()).strip ()
364 num_rss = dlg.num_rss_items.value ()
365 copyright = str (dlg.copyright.text ()).strip ()
366
367 savefilename = PyQt4.QtGui.QFileDialog.getSaveFileName (self, "Save site database to")
368
369 if savefilename:
370 self.current_db = str (savefilename)
371 self.setWindowTitle ("BiaWeb - " + self.current_db)
372 flag = biaweb_db.create_db (self.current_db, site_title, site_url, keywords, description,
373 copyright, num_rss, destination)
374 if flag:
375 PyQt4.QtGui.QMessageBox.information (self, "Success",
376 "New site db successfully created")
377 self.articles.clear ()
378 self.categories.clear ()
379 else:
380 PyQt4.QtGui.QMessageBox.critical (self, "Error", "System or SQLite 3 error in creating database")
381
382 # when generate site menu is triggered
383 def onGenerateSite (self):
384 if self.current_db is None:
385 PyQt4.QtGui.QMessageBox.critical (self, "Error",
386 "Cannot generate site. You need to create or open a website first")
387 else:
388 # run the generate site dialog
389 gendlg = gend.GenerateDialog (self, self.current_db)
390 gendlg.exec_ ()
391
392 # about menu is triggered
393 def onAbout (self):
394 PyQt4.QtGui.QMessageBox.about (self, "BiaWeb Qt",
395 "<b>A static website/weblog content management system</b><br /><br />\
396 Copyright &copy; 2010 <a href=\"http://www.harishankar.org\">Harishankar</a><br />\
397 Licensed under GNU/GPL v3")
398
399 # file quit is clicked
400 def onFileQuit (self):
401 sys.exit (0)