Index: pyatcron/src/lib/gui.py =================================================================== RCS file: /cvsroot/pyatcron/pyatcron/src/lib/gui.py,v retrieving revision 1.4 diff -u -r1.4 gui.py --- pyatcron/src/lib/gui.py 27 Apr 2004 14:56:25 -0000 1.4 +++ pyatcron/src/lib/gui.py 29 Apr 2004 09:04:53 -0000 @@ -1,7 +1,58 @@ from gtk import * import gtk.glade +import gobject + +from parser import * +from syntacticengine import * from config import GLADE_FILE_PATH + +class ScheduleListStore(gtk.ListStore): + def __init__(self,activeColor,inactiveColor): + # Call parent constructor with column defintions + gtk.ListStore.__init__(self, + gobject.TYPE_PYOBJECT, + gobject.TYPE_STRING, + gobject.TYPE_STRING, + gobject.TYPE_STRING) + + # store active and inactive colors as internal fields + self.activeColor = activeColor + self.inactiveColor = inactiveColor + + # Foreach system scheduled job, add them to ourself (ListStore) + for entry in CronEntryParser().getEntryList(): + self.addScheduler(entry) + for entry in AtEntryParser().getEntryList(): + self.addScheduler(entry) + for entry in PyAtCronEntryParser().getEntryList(): + self.addScheduler(entry) + + return + + def addScheduler(self,scheduler): + # Start a syntactic engine + syntactic = SyntacticEngine(scheduler) + # get an GtkIter object on a new row at top of list + iter = self.prepend(None) + # set values to this new row + if(scheduler.isActive()): + color = self.activeColor + else: + color = self.inactiveColor + self.set(iter,0,scheduler, + 1,syntactic.getSchedulerName(), + 2,syntactic.getNextRunString(), + 3,color) + + def delScheduler (self,iter): + self.remove (iter) + + def saveSchedulers(self): + print "ScheduleListStore::saveSchedulers: NOT IMPLEMENTED" + return + + class SchedulerEditor: Index: pyatcron/src/lib/mainwin.py =================================================================== RCS file: /cvsroot/pyatcron/pyatcron/src/lib/mainwin.py,v retrieving revision 1.8 diff -u -r1.8 mainwin.py --- pyatcron/src/lib/mainwin.py 28 Apr 2004 08:09:02 -0000 1.8 +++ pyatcron/src/lib/mainwin.py 29 Apr 2004 09:04:53 -0000 @@ -4,94 +4,71 @@ import datetime import time -from lib.schedulelist import ScheduleList -from syntacticengine import SyntacticEngine -from lib.gui import SchedulerEditor +from gui import * +from newtask import NewTask +from about import About # import glade path from config module from config import GLADE_FILE_PATH -from newtask import NewTask -from about import About - - # The main window's class. class MainWin: - def __init__ (self): - # The index of the task currently highlighted (if any). - self.taskIndex = None - - # Get the list of schedulers - self.scheduleList = ScheduleList () - + def __init__ (self): # The GtkTreePath of the last highlighted inactive task. # It's used to switch between the inactive/highlighted colors # in the task list. self.lastPath = None # We load the widgets and the callbacks from the glade file. - self.widgetTree = gtk.glade.XML (GLADE_FILE_PATH + - "/mainwin.glade") + self.widgetTree = gtk.glade.XML (GLADE_FILE_PATH + "/mainwin.glade") - dict = {} - for key in dir(self.__class__): - dict[key] = getattr(self, key) - self.widgetTree.signal_autoconnect (dict) - - # When the selection changes, we call self.on_selection_changed(). - # This can't be handled directly by glade if not by using - # the on_cursor_changed callback, which doesn't work well. - self.widgetTree.get_widget ("tasklist").get_selection().connect("changed", self.on_selection_changed) - # It's the base widget. self.win = self.widgetTree.get_widget ("mainwin") - - # This is used to get the "highlighted" color from the GTK - # theme. - self.highlightedColor = self.getThemeColor (3) - - # This is used to get the "insensitive" color from the GTK - # theme. - self.insensitiveColor = self.getThemeColor (4) - - # This is used to get the main background color from the GTK - #theme. - self.backgroundColor = self.getThemeColor (8) - # We build the task list. - self.updateTaskList () - - # We get the current highlighted task's index. - self.updateCurrentTask () - - # Gets the colors from the GTK theme - def getThemeColor (self, num): - if (num < 5): - redhex = hex (self.win.rc_get_style ().fg [num].red) - else: - redhex = hex (self.win.rc_get_style ().bg [num - 5].red) - redsplit = redhex.split ('0x') - redstr = redsplit [1] + # Get normal and insensitive state color from Gtk theme + self.normalColor = self.getThemeColor(gtk.STATE_NORMAL) + self.insensitiveColor = self.getThemeColor(gtk.STATE_INSENSITIVE) + self.selectedColor = self.getThemeColor(gtk.STATE_SELECTED) + + # Initialize a ScheduleListStore object + self.listStore=ScheduleListStore(self.normalColor, + self.insensitiveColor) - if (num < 5): - greenhex = hex (self.win.rc_get_style ().fg [num].green) - else: - greenhex = hex (self.win.rc_get_style ().bg [num - 5].green) - greensplit = greenhex.split ('0x') - greenstr = greensplit [1] + # and set it as model of our main Gtk::TreeView + self.taskList = self.widgetTree.get_widget("tasklist") + self.taskList.set_model(self.listStore) - if (num < 5): - bluehex = hex (self.win.rc_get_style ().fg [num].blue) - else: - bluehex = hex (self.win.rc_get_style ().bg [num - 5].blue) - bluesplit = bluehex.split ('0x') - bluestr = bluesplit [1] + # Disable multiselect on TreeView + self.taskList.get_selection().set_mode(gtk.SELECTION_SINGLE) - color = "#" + redstr + greenstr + bluestr - - return color + # initialize a cell renderer + renderer = CellRendererText() + + # and finally set the visible column + column = gtk.TreeViewColumn("Task", renderer, text=1, foreground=3) + self.taskList.append_column(column) + column = gtk.TreeViewColumn("Next run", renderer, text=2, foreground=3) + self.taskList.append_column(column) + + # autoconnect signals to callbacks + dict = {} + for key in dir(self.__class__): + dict[key] = getattr(self, key) + self.widgetTree.signal_autoconnect (dict) + + # connect some specific signals + selection = self.taskList.get_selection() + selection.connect("changed",self.on_tasklist_selection_changed) + + # update the GUI items + self.updateItemsSensitivity() + ############################################### + # # + # SIGNALS CALLBACKS # + # # + ############################################### def on_mainwin_delete_event (self, obj, event): self.quit () @@ -99,28 +76,13 @@ self.quit () def on_tasklist_button_press_event (self, obj, event): - # If the right-mouse button is pressed, get the current selection. + # If the right-mouse button is pressed, show popup menu if (event.button == 3): - taskList = self.widgetTree.get_widget ("tasklist") - iter = taskList.get_selection ().get_selected () [1] - - # If there is a selection, check that the click occured inside the selected row. - if (iter != None ): - model = taskList.get_model () - path = model.get_path (iter) - column = taskList.get_column (0) - cell_area = taskList.get_cell_area (path, column) - # If it's the case, setup and display the popup menu - if (event.y >= cell_area.y and event.y <= cell_area.y + cell_area.height): - activable = model.get_value (iter, 1) - - self.widgetTree.get_widget ("popup_properties").set_sensitive (1) - self.widgetTree.get_widget ("popup_activate").set_sensitive (activable) - self.widgetTree.get_widget ("popup_deactivate").set_sensitive (1 - activable) - self.widgetTree.get_widget ("popup_delete").set_sensitive (1) - - - self.widgetTree.get_widget ("popup").popup (None, None, None, event.button, event.time) + self.showPopupMenu(event) + + def on_tasklist_selection_changed(self,obj): + self.updateItemsSensitivity() + self.updateCurrentTask () def on_mainmenu_save_activate (self, obj): self.save () @@ -135,13 +97,13 @@ self.editTask () def on_mainmenu_activate_activate (self, obj): - self.activateTask () + self.setSchedulerActiveStatus(True) def on_mainmenu_deactivate_activate (self, obj): - self.deactivateTask () + self.setSchedulerActiveStatus(False) def on_mainmenu_delete_activate (self, obj): - self.confirmDeleteTask () + self.deleteScheduler () def on_mainmenu_about_activate (self, obj): self.about () @@ -150,13 +112,13 @@ self.editTask () def on_popup_activate_activate (self, obj): - self.activateTask () + self.setSchedulerActiveStatus(True) def on_popup_deactivate_activate (self, obj): - self.deactivateTask () + self.setSchedulerActiveStatus(False) def on_popup_delete_activate (self, obj): - self.confirmDeleteTask () + self.deleteScheduler () def on_toolbar_new_clicked (self, obj): self.createTask () @@ -165,188 +127,226 @@ self.editTask () def on_toolbar_activate_clicked (self, obj): - self.activateTask () + self.setSchedulerActiveStatus(True) def on_toolbar_deactivate_clicked (self, obj): - self.deactivateTask () + self.setSchedulerActiveStatus(False) def on_toolbar_delete_clicked (self, obj): - self.confirmDeleteTask () + self.deleteScheduler() def on_tasklist_row_activated (self, obj, path, column): self.editTask () - - def on_selection_changed (self, obj): - self.updateCurrentTask () - + def on_confirm_delete_response (self, obj, response): # If deletion is confirmed, delete the task. if (response == -8): - self.deleteTask () - + self.deleteScheduler(True) # Free the dialog. obj.destroy () - + + ############################################### + # # + # CLASS METHODS # + # # + ############################################### + + # Gets the colors from the GTK theme + def getThemeColor (self, num): + if (num < 5): + redhex = hex (self.win.rc_get_style ().fg [num].red) + greenhex = hex (self.win.rc_get_style ().fg [num].green) + bluehex = hex (self.win.rc_get_style ().fg [num].blue) + else: + redhex = hex (self.win.rc_get_style ().bg [num - 5].red) + greenhex = hex (self.win.rc_get_style ().bg [num - 5].green) + bluehex = hex (self.win.rc_get_style ().bg [num - 5].blue) + redstr = redhex.split ('0x')[1] + greenstr = greenhex.split ('0x')[1] + bluestr = bluehex.split ('0x') [1] + + return "#" + redstr + greenstr + bluestr + + # Show a confirmation dialog before deleting the task. + def deleteScheduler (self,confirm = False): + if (confirm): + # deletion is confirmed, delete Scheduler + model,iter = self.taskList.get_selection().get_selected() + self.listStore.delScheduler (iter) + else: + # Load a delete confirmation dialog window + xml = gtk.glade.XML (GLADE_FILE_PATH + "/confirm_delete.glade") + # autoconnect signals + dict = {} + for key in dir(self.__class__): + dict[key] = getattr(self, key) + xml.signal_autoconnect (dict) + + # get the dialog window widget + confirm = xml.get_widget ("confirm_delete") + + # Center the dialog on the main window. + confirm.set_transient_for (self.win) + confirm.set_position (gtk.WIN_POS_CENTER_ON_PARENT) + + # Display the dialog. + confirm.show () + return + + def showPopupMenu(self,event): + self.widgetTree.get_widget ("popup").popup (None, None, None, + event.button, event.time) + + def updateItemsSensitivity(self): + itemDict = { + "mainmenu_properties": 1, + "mainmenu_activate" : 1, + "mainmenu_deactivate": 1, + "mainmenu_delete" : 1, + "toolbar_new" : 1, + "toolbar_properties" : 1, + "toolbar_activate" : 1, + "toolbar_deactivate" : 1, + "toolbar_delete" : 1, + "popup_properties" : 1, + "popup_activate" : 1, + "popup_deactivate" : 1, + "popup_delete" : 1 + } + # get iter of selected row + model,iter = self.taskList.get_selection().get_selected() + # check if there is a selected row + if(not iter): + itemDict["mainmenu_properties"] = 0 + itemDict["mainmenu_activate"] = 0 + itemDict["mainmenu_deactivate"] = 0 + itemDict["mainmenu_delete"] = 0 + itemDict["toolbar_properties"] = 0 + itemDict["toolbar_activate"] = 0 + itemDict["toolbar_deactivate"] = 0 + itemDict["toolbar_delete"] = 0 + + else: + # check if the selected Scheduler is active + # NOTE: Not implemented at the moment, active is alwas True + active = model.get_value(iter,0).isActive() + itemDict["mainmenu_activate"] = not active + itemDict["mainmenu_deactivate"] = active + itemDict["toolbar_activate"] = not active + itemDict["toolbar_deactivate"] = active + itemDict["popup_activate"] = not active + itemDict["popup_deactivate"] = active + + # set sensitivity on items + for key in itemDict: + self.widgetTree.get_widget(key).set_sensitive(itemDict[key]) + + + # Set the active status of the selected Scheduler + def setSchedulerActiveStatus(self,status): + # get selected row + model,iter = self.taskList.get_selection().get_selected() + # do something only if there is a selected row + if(iter): + # set status to scheduler + model.get_value(iter,0).setActive(status) + # change color of text + if(status): + model.set_value(iter,3,self.normalColor) + else: + model.set_value(iter,3,self.insensitiveColor) + # update sensitivity of menu items + self.updateItemsSensitivity() + self.updateCurrentTask() + # Writes the current configuration. def save (self): - print "TODO: save" + self.listStore.saveSchedulers() # Unreferences the main window's widgets, and exits. def quit (self): self.save () gtk.main_quit () + # Launches the "about" dialog. + def about (self): + aboutObject = About (self.win) + + + +####################################### +# TO BE REWRITTEN OR DELETED # +####################################### + # Gets the current highlighted task's index. def updateCurrentTask (self): - taskList = self.widgetTree.get_widget ("tasklist") - iter = taskList.get_selection ().get_selected () [1] - model = taskList.get_model () + # get iter of selected row + model,iter = self.taskList.get_selection().get_selected() # If we were on an inactive task, restore its color to "insensitive". - if (self.lastPath != None): - model.set_value (model.get_iter (self.lastPath), 4, self.insensitiveColor) + if (self.lastPath): + lastIter = model.get_iter (self.lastPath) + + if (model.get_value (lastIter, 0).isActive ()): + model.set_value (model.get_iter (self.lastPath), 3, self.normalColor) + else: + model.set_value (model.get_iter (self.lastPath), 3, self.insensitiveColor) + self.lastPath = None - # If no row is selected, the "properties", "activate", "deactivate" and "delete" toolbar icons/mainmenu entries are insensitive, else they are sensitive. - if (iter == None): - self.widgetTree.get_widget ("toolbar_properties").set_sensitive (0) - self.widgetTree.get_widget ("toolbar_activate").set_sensitive (0) - self.widgetTree.get_widget ("toolbar_deactivate").set_sensitive (0) - self.widgetTree.get_widget ("toolbar_delete").set_sensitive (0) - self.widgetTree.get_widget ("mainmenu_properties").set_sensitive (0) - self.widgetTree.get_widget ("mainmenu_activate").set_sensitive (0) - self.widgetTree.get_widget ("mainmenu_deactivate").set_sensitive (0) - self.widgetTree.get_widget ("mainmenu_delete").set_sensitive (0) - else: - # If the task is inactive, the "deactivate" icon toolbar is insensitive, the "activate" icon is sensitive and vice-versa. - activable = model.get_value (iter, 1) - - self.widgetTree.get_widget ("toolbar_properties").set_sensitive (1) - self.widgetTree.get_widget ("toolbar_activate").set_sensitive (activable) - self.widgetTree.get_widget ("toolbar_deactivate").set_sensitive (1 - activable) - self.widgetTree.get_widget ("toolbar_delete").set_sensitive (1) - self.widgetTree.get_widget ("mainmenu_properties").set_sensitive (1) - self.widgetTree.get_widget ("mainmenu_activate").set_sensitive (activable) - self.widgetTree.get_widget ("mainmenu_deactivate").set_sensitive (1 - activable) - self.widgetTree.get_widget ("mainmenu_delete").set_sensitive (1) - - # Here, we get the task's index. - self.taskIndex = model.get_value (iter, 0) - - if (activable == 1): - # We save the task's path for next time. - path = taskList.get_cursor () [0] - self.lastPath = taskList.get_cursor () [0] - # We set the inactive task's color to "highlighted". - model.set_value (model.get_iter (path), 4, self.highlightedColor) + if (iter): + # We save the task's path for next time. + path = self.taskList.get_cursor () [0] + self.lastPath = self.taskList.get_cursor () [0] + + # We set the task's color to "selected". + model.set_value (model.get_iter (path), 3, self.selectedColor) - # Launches the new task assistant and refreshes the task list if a new task was created. + # Launches the new task assistant and refreshes the task list + # if a new task was created. def createTask (self): assistantObject = NewTask (self) def on_editor_changed(self, *args): print "Updating list (only the task, not the scheduler)" self.updateTaskList (True, True, False) - # Launches the properties dialog and refreshes the task list if changes were made. + # Launches the properties dialog def editTask (self): - print "edit task #" + str (self.taskIndex) - self.editor = SchedulerEditor(self.scheduleList[self.taskIndex]) + print "edit task" + model,iter = self.taskList.get_selection().get_selected() + currentTask = model.get_value (iter, 0) + self.editor = SchedulerEditor(currentTask) self.editor.show(self.win) - self.scheduleList[self.taskIndex].task.connect('changed', self.on_editor_changed) - #self.updateTaskList () + currentTask.task.connect('changed', self.on_editor_changed) - # Makes the current task active and refreshes the task list. - def activateTask (self): - self.scheduleList [self.taskIndex].setActive (1) - self.lastPath = None - self.updateTaskList () - # Makes the current task inactive and refreshes the task list. - def deactivateTask (self): - self.scheduleList [self.taskIndex].setActive (0) - self.updateTaskList () - # Show a confirmation dialog before deleting the task. - def confirmDeleteTask (self): - # Load the dialog. - xml = gtk.glade.XML (GLADE_FILE_PATH + - "/confirm_delete.glade") - - dict = {} - for key in dir(self.__class__): - dict[key] = getattr(self, key) - xml.signal_autoconnect (dict) - - confirm = xml.get_widget ("confirm_delete") - - # Center the dialog on the main window. - confirm.set_transient_for (self.win) - confirm.set_position (gtk.WIN_POS_CENTER_ON_PARENT) - - # Display the dialog. - confirm.show () - - # Deletes the current task and refreshes the task list. - def deleteTask (self): - del(self.scheduleList[self.taskIndex]) - self.updateTaskList () - - # Launches the "about" dialog. - def about (self): - aboutObject = About (self.win) - - # Builds or refreshes the task list. + # Refreshes the task list. def updateTaskList (self, onlyCurrentTask = False, updateTask = True, updateScheduler = True): + model = self.taskList.get_model () - taskList = self.widgetTree.get_widget ("tasklist") + iter = model.get_iter_first () + while (iter): + selectedModel,selectedIter = self.taskList.get_selection().get_selected() + selectedTask = selectedModel.get_value (selectedIter, 0) + currentTask = model.get_value (iter, 0) - # If the task list has not already been built, ceate it. Else, get its current model, get the position of the cursor from it and clear the current model. - if (taskList.get_model () == None): - model = gtk.ListStore (gobject.TYPE_INT, gobject.TYPE_BOOLEAN, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING) - else: - model = taskList.get_model () - cursor = taskList.get_cursor () - if (not onlyCurrentTask): - model.clear () - - # Add each task, or update the current one - curIndex = 0 - if (onlyCurrentTask): - self.updateCurrentTask () - iter = model.get_iter_first () - - for entry in self.scheduleList: - if (curIndex == self.taskIndex or not onlyCurrentTask): - if (not onlyCurrentTask): - iter = model.append () + if (selectedTask == currentTask or not onlyCurrentTask): + model.set (iter, 0, currentTask) - model.set (iter, 0, curIndex) - model.set (iter, 1, entry.isActive () == False) if (updateTask): - model.set (iter, 2, entry) + model.set (iter, 1, str (currentTask)) if (updateScheduler): # Determine when the task will occur next - syntactic = SyntacticEngine(entry) - model.set (iter, 3, syntactic.getNextRunString()) + syntactic = SyntacticEngine(currentTask) + model.set (iter, 2, syntactic.getNextRunString()) - model.set (iter, 4, self.insensitiveColor) + if (currentTask.isActive ()): + model.set (iter, 3, self.normalColor) + else: + model.set (iter, 3, self.insensitiveColor) - if (onlyCurrentTask): - iter = model.iter_next (iter) - curIndex = curIndex + 1 - - # If we are building the task list, associate the model to the task list and create the headers. Else, restore the cursor's position. - if (taskList.get_model () == None): - taskList.set_model (model) - - textRenderer = gtk.CellRendererText () - textColumn = gtk.TreeViewColumn ("Description", textRenderer, text=2, foreground_set=1, foreground=4) - taskList.append_column (textColumn) - - textRenderer = gtk.CellRendererText () - textColumn = gtk.TreeViewColumn ("Next run time", textRenderer, text=3, foreground_set=1, foreground=4) - taskList.append_column (textColumn) - else: - if (cursor [0] != None): - taskList.set_cursor (cursor [0]) + iter = model.iter_next (iter) + + self.updateCurrentTask () Index: pyatcron/src/lib/newtask.py =================================================================== RCS file: /cvsroot/pyatcron/pyatcron/src/lib/newtask.py,v retrieving revision 1.4 diff -u -r1.4 newtask.py --- pyatcron/src/lib/newtask.py 28 Apr 2004 08:09:02 -0000 1.4 +++ pyatcron/src/lib/newtask.py 29 Apr 2004 09:04:53 -0000 @@ -51,8 +51,8 @@ self.win.set_position (gtk.WIN_POS_CENTER_ON_PARENT) # Sets the color of the bars. - frameBackground = gtk.gdk.color_parse (self.parent.backgroundColor) - mainBackground = gtk.gdk.color_parse (self.parent.highlightedColor) + frameBackground = gtk.gdk.color_parse (self.parent.normalColor) + mainBackground = gtk.gdk.color_parse (self.parent.selectedColor) self.widgetTree.get_widget ("titlebar").modify_bg (gtk.STATE_NORMAL, frameBackground) self.widgetTree.get_widget ("topbar").modify_bg (gtk.STATE_NORMAL, frameBackground) @@ -165,8 +165,7 @@ self.updatePage () else: scheduler = Scheduler ([[1],[1],[1],[1],[1],[1]], self.task) - self.parent.scheduleList.addSchedule (scheduler) - self.parent.updateTaskList () + self.parent.listStore.addScheduler (scheduler) self.quit () def updatePage (self): @@ -186,7 +185,7 @@ self.widgetTree.get_widget ("widgetbar").remove (self.oldPage) # Set the assistant's title. - title = '' + self.pages [self.currentPage]["title"] + '' + title = '' + self.pages [self.currentPage]["title"] + '' self.widgetTree.get_widget ("title").set_markup (title) # Add the current page to the dialog (with a 4 pixels padding), and display it. Index: pyatcron/src/lib/scheduler.py =================================================================== RCS file: /cvsroot/pyatcron/pyatcron/src/lib/scheduler.py,v retrieving revision 1.8 diff -u -r1.8 scheduler.py --- pyatcron/src/lib/scheduler.py 27 Apr 2004 14:56:25 -0000 1.8 +++ pyatcron/src/lib/scheduler.py 29 Apr 2004 09:04:53 -0000 @@ -34,10 +34,12 @@ return str(self.task) def setActive(self,value): - if value == 1: - self.active = 1 + if (value): + self.active = True + print "Scheduler::setActive: active status set to True" else: - self.active = 0 + self.active = False + print "Scheduler::setActive: active status set to False" return def isActive(self): Index: pyatcron/src/lib/syntacticengine.py =================================================================== RCS file: /cvsroot/pyatcron/pyatcron/src/lib/syntacticengine.py,v retrieving revision 1.2 diff -u -r1.2 syntacticengine.py --- pyatcron/src/lib/syntacticengine.py 15 Apr 2004 14:34:46 -0000 1.2 +++ pyatcron/src/lib/syntacticengine.py 29 Apr 2004 09:04:53 -0000 @@ -7,6 +7,9 @@ self.scheduler = scheduler return + def getSchedulerName(self): + return str(self.scheduler) + def getNextRunString(self): # Determine when the task will occur next values = self.scheduler.getAttributes ()