Initial work for bts#46: set alarm for due items
[qtodo.git] / QtNote.py
blob8b333c9bcbb3b6927b68dddfba5eca7397f3dffb
1 #!/usr/bin/env python
5 from PyQt4 import Qt, QtCore, QtGui
6 import sys, time, os, ConfigParser
8 homeEnv = os.getenv('HOME')
9 config = ConfigParser.ConfigParser()
10 try:
11 config.readfp(open('QtNote.cfg'))
12 except:
13 config.readfp(open(homeEnv+'/.QtNote.cfg'))
15 homedir = config.get("main", "homedir")
17 sys.path.append(homedir+'/src')
19 from QtNoteIO import *
20 from gui_MainWin import *
21 from gui_AddCatDlg import Ui_D_Add
22 from ToDoCategoryList import *
23 from ToDoItemList import *
26 class Trash(QtGui.QLabel):
27 def __init__(self, QtNoteWin, DbEngine, parent=None):
28 QtGui.QLabel.__init__(self, parent)
29 self.setAcceptDrops(True)
30 self.setPixmap(QtGui.QPixmap(homedir+"/pixmaps/eraser.png"))
31 self.setSizePolicy(QtGui.QSizePolicy.Minimum,QtGui.QSizePolicy.Minimum)
32 self.setMargin(2)
33 self.adjustSize()
34 self.DbEngine = DbEngine
35 self.QtNoteWin = QtNoteWin
37 def dropEvent(self, event):
38 if event.mimeData().hasFormat("application/x-QtNote"):
39 pieceData = event.mimeData().data("application/x-QtNote")
40 dataStream = QtCore.QDataStream(pieceData, QtCore.QIODevice.ReadOnly)
41 oid = QtCore.QString()
42 item_type = QtCore.QString()
43 dataStream >> oid >> item_type
44 event.setDropAction(QtCore.Qt.MoveAction)
45 if item_type == TYPE_LIST:
46 # Delete the category from database
47 res = self.DbEngine.DeleteList(oid)
48 if res == -1:
49 res = QtGui.QMessageBox.critical(None, "Error",
50 "There are some items still assigned to this category",
51 QtGui.QMessageBox.Ok )
52 self.setFrameShape(QtGui.QFrame.NoFrame)
53 self.setFrameShadow(QtGui.QFrame.Plain)
54 event.ignore()
55 else:
56 event.accept()
57 if item_type == TYPE_TODO:
58 # Delete the category from database
59 res = self.DbEngine.DeleteItem(oid)
60 event.accept()
61 else:
62 event.ignore()
63 self.setFrameShape(QtGui.QFrame.NoFrame)
64 self.setFrameShadow(QtGui.QFrame.Plain)
65 self.QtNoteWin.RefreshSummaryList()
67 def dragEnterEvent(self, event):
68 self.setFrameShape(QtGui.QFrame.Panel)
69 self.setFrameShadow(QtGui.QFrame.Raised)
70 event.accept()
72 def dragLeaveEvent(self, event):
73 self.setFrameShape(QtGui.QFrame.NoFrame)
74 self.setFrameShadow(QtGui.QFrame.Plain)
76 class AddList(QtGui.QLabel):
77 def __init__(self, DbEngine, parent=None):
78 QtGui.QLabel.__init__(self, parent)
79 self.setAcceptDrops(True)
80 self.setPixmap(QtGui.QPixmap(homedir+"/pixmaps/eraser.png"))
81 self.DbEngine = DbEngine
83 def dropEvent(self, event):
84 if event.mimeData().hasFormat("application/x-QtNote"):
85 pieceData = event.mimeData().data("application/x-QtNote")
86 dataStream = QtCore.QDataStream(pieceData, QtCore.QIODevice.ReadOnly)
88 oid_cat = QtCore.QString()
89 id_cat = QtCore.QString()
91 dataStream >> oid_cat >> id_cat
92 event.setDropAction(QtCore.Qt.MoveAction)
93 event.accept()
94 # Delete the category from database
95 self.DbEngine.DeleteList(oid_cat)
97 def dragEnterEvent(self, event):
98 event.accept()
100 class QtNote(Ui_MainWindow):
101 def __init__(self, parent=None):
102 self.config = config
103 self.IOEngine = QtNoteIO(self.config)
104 self.Filters = {
105 "Oid" : None,
106 "OidCategory" : None,
107 "OidPriority" : None,
108 "OidStatus" : None
112 def Finalize(self):
113 # set the trash zone
114 ui.trash = Trash(ui, self.IOEngine)
115 ui.actions_box.layout().addWidget(ui.trash)
117 # insert a stretch to keep aligned the controls
118 ui.actions_box.layout().insertStretch(-1, 20)
120 # set the todo category area
121 ui.todo_lists = TodoLists(ui)
122 ui.lists_box.layout().addWidget(ui.todo_lists, 0, 0)
123 ui.todo_lists.setSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
124 ui.todo_items = ToDoItemList(ui, self.IOEngine)
125 ui.items_box.layout().addWidget(ui.todo_items, 1, 0)
128 # check for new overdue items
129 self.IOEngine.CheckForDeadlines()
130 self.RefreshSummaryList()
132 cats = self.IOEngine.GetCategories()
133 ui.CB_CategoryFilter.addItem('All')
134 for c in cats:
135 ui.CB_CategoryFilter.addItem(c["id_cat"])
137 stats = self.IOEngine.LoadStatus()
138 ui.CB_StatusFilter.addItem('All')
139 for s in stats:
140 ui.CB_StatusFilter.addItem(s["desc"])
142 prior = self.IOEngine.LoadPriorities()
143 ui.CB_PriorityFilter.addItem('All')
144 for p in prior:
145 ui.CB_PriorityFilter.addItem(p["id_pr"])
147 QtCore.QObject.connect(ui.action_Quit, QtCore.SIGNAL("triggered()"), self.QuitApp)
148 QtCore.QObject.connect(ui.action_About, QtCore.SIGNAL("triggered()"), self.About)
149 QtCore.QObject.connect(ui.action_Documentation, QtCore.SIGNAL("triggered()"), self.Documentation)
150 QtCore.QObject.connect(ui.action_Category, QtCore.SIGNAL("triggered()"), self.CategoryConf)
152 QtCore.QObject.connect(ui.CB_CategoryFilter, QtCore.SIGNAL("currentIndexChanged(QString)"), self.UpdateCategoryFilter)
153 QtCore.QObject.connect(ui.CB_PriorityFilter, QtCore.SIGNAL("currentIndexChanged(QString)"), self.UpdatePriorityFilter)
154 QtCore.QObject.connect(ui.CB_StatusFilter, QtCore.SIGNAL("currentIndexChanged(QString)"), self.UpdateStatusFilter)
157 def LoadData(self):
158 categories = self.IOEngine.GetCategories()
159 for rec in categories:
160 ui.todo_lists.addList(rec["oid"], rec["id_cat"])
161 self.RefreshItemList()
164 def RefreshItemList(self):
165 items = self.IOEngine.GetItems(self.Filters)
166 for rec in items:
167 ui.todo_items.addItem(rec)
169 def RefreshSummaryList(self):
170 cA = self.IOEngine.CountItems(ST_ACTIVE)
171 cC = self.IOEngine.CountItems(ST_CLOSED)
172 cO = self.IOEngine.CountItems(ST_OVERDUE)
173 ui.L_ActiveItem.setText(str(cA))
174 ui.L_CloseItem.setText(str(cC))
175 if cO > 0:
176 f = ui.L_OverdueItem.palette()
177 f.setColor(QtGui.QPalette.Foreground,QtGui.QColor(255, 0, 0))
178 ui.L_OverdueItem.setPalette(f)
179 ui.L_OverdueItem.setText(str(cO))
181 def QuitApp(self):
182 global PidFilePath
183 try:
184 os.remove(PidFilePath)
185 except:
186 pass
187 systray.hide()
188 app.quit()
190 def UpdateCategoryFilter(self, text):
191 if str(text) == ALL_RECORD:
192 self.Filters["OidCategory"] = None
193 else:
194 oidcat = self.IOEngine.GetCategory(str(text))
195 self.Filters["OidCategory"] = oidcat
196 self.UpdateItemList()
198 def UpdatePriorityFilter(self, text):
199 if str(text) == ALL_RECORD:
200 self.Filters["OidPriority"] = None
201 else:
202 oidpr = self.IOEngine.GetPriority(str(text))
203 self.Filters["OidPriority"] = oidpr
204 self.UpdateItemList()
206 def UpdateStatusFilter(self, text):
207 if str(text) == ALL_RECORD:
208 self.Filters["OidStatus"] = None
209 else:
210 oidsta = self.IOEngine.GetStatus(str(text))
211 self.Filters["OidStatus"] = oidsta
212 self.UpdateItemList()
214 def UpdateItemList(self):
215 ui.todo_items.clear()
216 self.RefreshItemList()
219 def CategoryConf(self):
220 AddCatDlg = QtGui.QDialog()
221 AddCat = Ui_D_Add()
222 AddCat.setupUi(AddCatDlg)
223 if AddCatDlg.exec_():
224 cat = AddCat.LE_cat_name.text()
225 if str(cat) == '':
226 return
227 desc = AddCat.LE_cat_desc.text()
228 Data = {"id_category" : str(cat),
229 "ds_category" : str(desc) }
230 oid_cat = self.IOEngine.InsertCategory(Data)
231 if oid_cat == DUPLICATED_CATEGORY:
232 res = QtGui.QMessageBox.critical(None, "Error",
233 "The category is already present",
234 QtGui.QMessageBox.Ok )
235 return
236 it = QtGui.QListWidgetItem(QtGui.QIcon(homedir+"/pixmaps/todo_list.png"),cat)
237 it.setTextAlignment(QtCore.Qt.AlignVCenter)
238 ui.todo_lists.insertItem(0,it)
239 it.setData(QtCore.Qt.UserRole, QtCore.QVariant(oid_cat))
240 it.setData(QtCore.Qt.UserRole+1, QtCore.QVariant(TYPE_LIST))
243 def DeleteCategory(self):
244 pass
246 def EditCategory(self):
247 pass
249 def About(self):
250 QtGui.QMessageBox.about(None, "About QNotes", "QNotes Ver %s.\nA simple todo manager"%VERSION)
253 def Documentation(self):
254 pass
256 class MainWindow(QtGui.QMainWindow):
257 def __init__(self):
258 QtGui.QMainWindow.__init__(self)
260 def closeEvent(self, ev):
261 self.hide()
262 systray.showMessage('QtNotes', 'Application minimized')
263 ev.ignore()
265 def ShowWindow(self):
266 self.show()
268 # implement also on minimize window
270 def CheckForPid():
271 try:
272 res = os.stat(PidFilePath)
273 return -1
274 except:
275 PF = open(PidFilePath, 'w')
276 PF.close()
277 return 0
279 def ShowAlarm():
280 print "Alarm work"
283 if __name__ == "__main__":
284 app = QtGui.QApplication(sys.argv)
286 PidFilePath = os.environ["HOME"]+"/.QtNotes"
287 if os.sys.platform == "win32":
288 PidFilePath = os.environ["TEMP"]+"/.QtNotes"
289 res = CheckForPid()
290 res = 0
291 if res == -1:
292 QtGui.QMessageBox.critical(None,
293 "QtNotes - Error",
294 "The program is alred running",
295 QtGui.QMessageBox.StandardButtons(\
296 QtGui.QMessageBox.Ok),
297 QtGui.QMessageBox.Ok)
298 sys.exit()
300 #window = QtGui.QMainWindow()
301 window = MainWindow()
302 ui = QtNote()
303 ui.setupUi(window)
304 window.setWindowTitle(str(window.windowTitle()) + " " +VERSION)
306 #connect the menu items
307 ui.Finalize()
308 #Load the data present
309 ui.LoadData()
310 window.show()
312 app.connect(app, QtCore.SIGNAL("lastWindowClosed()"),ui.QuitApp)
314 icon=QtGui.QIcon(homedir+"/pixmaps/todo_list.png")
315 systray=QtGui.QSystemTrayIcon(icon)
316 menu = QtGui.QMenu()
317 showAction = menu.addAction('Show')
318 sep1 = menu.addSeparator()
319 quitAction = menu.addAction('Quit')
320 QtCore.QObject.connect(quitAction, QtCore.SIGNAL("triggered()"), ui.QuitApp)
321 QtCore.QObject.connect(showAction, QtCore.SIGNAL("triggered()"), window.ShowWindow)
322 systray.setContextMenu(menu)
323 systray.show()
325 # Imposto il timer per il primo evento che scade.
326 value = ui.IOEngine.GetNextAlarm()
327 print value
328 timer = QtCore.QTimer()
329 QtCore.QObject.connect(timer, QtCore.SIGNAL("timeout()"), ShowAlarm)
330 timer.setSingleShot(True)
331 timer.start(1000)
333 sys.exit(app.exec_())