class MainWin(gtk.Window, ud.BaseCalObj): _name = 'mainWin' desc = _('Main Window') timeout = 1 ## second setMinHeight = lambda self: self.resize(ui.winWidth, 2) #def maximize(self): # pass def __init__(self, statusIconMode=2): #from gi.repository import Gio #self.app = gtk.Application(application_id="apps.starcal") #self.app.register(Gio.Cancellable.new()) #gtk.ApplicationWindow.__init__(self, application=self.app) gtk.Window.__init__(self) self.add_events(gdk.EventMask.ALL_EVENTS_MASK) self.initVars() ud.windowList.appendItem(self) ui.mainWin = self ################## ## statusIconMode: ## ('none', 'none') ## ('statusIcon', 'normal') ## ('applet', 'gnome') ## ('applet', 'kde') ## ## 0: none (simple window) ## 1: applet ## 2: standard status icon self.statusIconMode = statusIconMode ### #ui.eventManDialog = None #ui.timeLineWin = None ### #ui.weekCalWin = WeekCalWindow() #ud.windowList.appendItem(ui.weekCalWin) ### self.dayInfoDialog = None #print('windowList.items', [item._name for item in ud.windowList.items]) ########### ##self.connect('window-state-event', selfStateEvent) self.set_title('%s %s'%(core.APP_DESC, core.VERSION)) #self.connect('main-show', lambda arg: self.present()) #self.connect('main-hide', lambda arg: self.hide()) self.set_decorated(False) self.set_property('skip-taskbar-hint', not ui.winTaskbar) ## self.set_skip_taskbar_hint ## FIXME self.set_role('starcal') #self.set_focus_on_map(True)#???????? #self.set_type_hint(gdk.WindowTypeHint.NORMAL) #self.connect('realize', self.onRealize) self.set_default_size(ui.winWidth, 1) try: self.move(ui.winX, ui.winY) except: pass ############################################################# self.connect('focus-in-event', self.focusIn, 'Main') self.connect('focus-out-event', self.focusOut, 'Main') self.connect('button-press-event', self.buttonPress) self.connect('key-press-event', self.keyPress) self.connect('configure-event', self.configureEvent) self.connect('destroy', self.quit) ############################################################# """ #self.add_events(gdk.EventMask.VISIBILITY_NOTIFY_MASK) #self.connect('frame-event', show_event) ## Compiz does not send configure-event(or any event) when MOVING window(sends in last point, ## when moving completed) #self.connect('drag-motion', show_event) ud.rootWindow.set_events(... ud.rootWindow.add_filter(self.onRootWinEvent) #self.realize() #gdk.flush() #self.configureEvent(None, None) #self.connect('drag-motion', show_event) ###################### ## ???????????????????????????????????????????????? ## when button is down(before button-release-event), motion-notify-event does not recived! """ ################################################################## self.focus = False #self.focusOutTime = 0 #self.clockTr = None ############################################################################ self.winCon = None ############ self.vbox = MainWinVbox() ui.checkMainWinItems() itemsPkg = 'scal3.ui_gtk.mainwin_items' for (name, enable) in ui.mainWinItems: #print(name, enable) if enable: try: module = __import__( '.'.join([ itemsPkg, name, ]), fromlist=['CalObj'], ) CalObj = module.CalObj except: myRaise() continue item = CalObj() item.enable = enable item.connect('size-allocate', self.childSizeAllocate) #modify_bg_all(item, gtk.StateType.NORMAL, rgbToGdkColor(*ui.bgColor)) else: desc = mainWinItemsDesc[name] item = DummyCalObj(name, desc, itemsPkg, True) self.vbox.appendItem(item) self.appendItem(self.vbox) self.vbox.show() self.customizeDialog = None ####### self.add(self.vbox) #################### self.isMaximized = False #################### #ui.prefDialog = None self.exportDialog = None self.selectDateDialog = None ############### Building About Dialog self.aboutDialog = None ############### self.menuMain = None ##### check = gtk.CheckMenuItem(label=_('_On Top')) check.set_use_underline(True) check.connect('activate', self.keepAboveClicked) check.set_active(ui.winKeepAbove) self.set_keep_above(ui.winKeepAbove) self.checkAbove = check ##### check = gtk.CheckMenuItem(label=_('_Sticky')) check.set_use_underline(True) check.connect('activate', self.stickyClicked) check.set_active(ui.winSticky) if ui.winSticky: self.stick() self.checkSticky = check ############################################################ self.statusIconInit() listener.dateChange.add(self) #if self.statusIconMode!=1: # gobject.timeout_add_seconds(self.timeout, self.statusIconUpdate) ######### self.connect('delete-event', self.onDeleteEvent) ######################################### for plug in core.allPlugList: if plug.external: try: plug.set_dialog(self) except AttributeError: pass ########################### self.onConfigChange() #ud.rootWindow.set_cursor(gdk.Cursor.new(gdk.CursorType.LEFT_PTR)) #def mainWinStateEvent(self, obj, gevent): #print(dir(event)) #print(gevent.new_window_state) #self.event = event def childSizeAllocate(self, cal, req): self.setMinHeight() def selectDateResponse(self, widget, y, m, d): ui.changeDate(y, m, d) self.onDateChange() def keyPress(self, arg, gevent): kname = gdk.keyval_name(gevent.keyval).lower() #print(now(), 'MainWin.keyPress', kname) if kname=='escape': self.onEscape() elif kname=='f1': self.aboutShow() elif kname in ('insert', 'plus', 'kp_add'): self.eventManShow() elif kname in ('q', 'arabic_dad'):## FIXME self.quit() else: self.vbox.keyPress(arg, gevent) return True ## FIXME def focusIn(self, widegt, event, data=None): self.focus = True if self.winCon and self.winCon.enable: self.winCon.windowFocusIn() def focusOut(self, widegt, event, data=None): ## called 0.0004 sec (max) after focusIn (if switched between two windows) dt = now()-ui.focusTime #print('focusOut', dt) if dt > 0.05: ## FIXME self.focus = False gobject.timeout_add(2, self.focusOutDo) def focusOutDo(self): if not self.focus:# and t-self.focusOutTime>0.002: ab = self.checkAbove.get_active() self.set_keep_above(ab) if self.winCon and self.winCon.enable: self.winCon.windowFocusOut() return False """ def checkResize(self, widget, req): if ui.mcalHeight != req.height:# and ui.winWidth==req.width: if req.height==0: req.height=1 ui.mcalHeight = req.height """ def configureEvent(self, widget, gevent): wx, wy = self.get_position() maxPosDelta = max(abs(ui.winX-wx), abs(ui.winY-wy)) #print(wx, wy) ww, wh = self.get_size() #if ui.bgUseDesk and maxPosDelta > 1:## FIXME # self.queue_draw() if self.get_property('visible'): ui.winX, ui.winY = (wx, wy) ui.winWidth = ww liveConfChanged() return False def buttonPress(self, obj, gevent): print('buttonPress') b = gevent.button #print('buttonPress', b) if b==3: self.menuMainCreate() self.menuMain.popup(None, None, None, None, 3, gevent.time) ui.updateFocusTime() elif b==1: self.begin_move_drag(gevent.button, int(gevent.x_root), int(gevent.y_root), gevent.time) return False def childButtonPress(self, widget, gevent): b = gevent.button #print(dir(gevent)) #foo, x, y, mask = gevent.get_window().get_pointer() #x, y = self.get_pointer() x, y = gevent.x_root, gevent.y_root if b == 1: self.begin_move_drag(gevent.button, x, y, gevent.time) return True elif b == 3: self.menuMainCreate() if rtl: x -= get_menu_width(self.menuMain) self.menuMain.popup( None, None, lambda *args: (x, y, True), None, 3, gevent.time, ) ui.updateFocusTime() return True return False def startResize(self, widget, gevent): if self.menuMain: self.menuMain.hide() self.begin_resize_drag( gdk.WindowEdge.SOUTH_EAST, gevent.button, int(gevent.x_root), int(gevent.y_root), gevent.time, ) return True def changeDate(self, year, month, day): ui.changeDate(year, month, day) self.onDateChange() goToday = lambda self, obj=None: self.changeDate(*core.getSysDate(calTypes.primary)) def onDateChange(self, *a, **kw): #print('MainWin.onDateChange') ud.BaseCalObj.onDateChange(self, *a, **kw) #for j in range(len(core.plugIndex)):##???????????????????? # try: # core.allPlugList[core.plugIndex[j]].date_change(*date) # except AttributeError: # pass self.setMinHeight() for j in range(len(core.plugIndex)): try: core.allPlugList[core.plugIndex[j]].date_change_after(*date) except AttributeError: pass #print('Occurence Time: max=%e, avg=%e'%(ui.Cell.ocTimeMax, ui.Cell.ocTimeSum/ui.Cell.ocTimeCount)) def getEventAddToMenuItem(self): from scal3.ui_gtk.drawing import newColorCheckPixbuf addToItem = labelStockMenuItem('_Add to', gtk.STOCK_ADD) if event_lib.readOnly: addToItem.set_sensitive(False) return addToItem menu2 = gtk.Menu() ## for group in ui.eventGroups: if not group.enable: continue if not group.showInCal():## FIXME continue eventTypes = group.acceptsEventTypes if not eventTypes: continue item2 = ImageMenuItem() item2.set_label(group.title) ## image = gtk.Image() if group.icon: image.set_from_file(group.icon) else: image.set_from_pixbuf(newColorCheckPixbuf(group.color, 20, True)) item2.set_image(image) ## if len(eventTypes)==1: item2.connect('activate', self.addToGroupFromMenu, group, eventTypes[0]) else: menu3 = gtk.Menu() for eventType in eventTypes: eventClass = event_lib.classes.event.byName[eventType] item3 = ImageMenuItem() item3.set_label(eventClass.desc) icon = eventClass.getDefaultIcon() if icon: item3.set_image(imageFromFile(icon)) item3.connect('activate', self.addToGroupFromMenu, group, eventType) menu3.add(item3) menu3.show_all() item2.set_submenu(menu3) menu2.add(item2) ## menu2.show_all() addToItem.set_submenu(menu2) return addToItem def menuCellPopup(self, widget, etime, x, y): menu = gtk.Menu() #### menu.add(labelStockMenuItem('_Copy Date', gtk.STOCK_COPY, self.copyDate)) menu.add(labelStockMenuItem('Day Info', gtk.STOCK_INFO, self.dayInfoShow)) menu.add(self.getEventAddToMenuItem()) menu.add(gtk.SeparatorMenuItem()) menu.add(labelStockMenuItem('Select _Today', gtk.STOCK_HOME, self.goToday)) menu.add(labelStockMenuItem('Select _Date...', gtk.STOCK_INDEX, self.selectDateShow)) if widget._name in ('weekCal', 'monthCal'): menu.add(labelStockMenuItem( 'Switch to ' + ('Month Calendar' if widget._name=='weekCal' else 'Week Calendar'), gtk.STOCK_REDO, self.switchWcalMcal, )) if os.path.isfile('/usr/bin/evolution'):##?????????????????? menu.add(labelImageMenuItem('In E_volution', 'evolution-18.png', ui.dayOpenEvolution)) #if os.path.isfile('/usr/bin/sunbird'):##?????????????????? # menu.add(labelImageMenuItem('In _Sunbird', 'sunbird-18.png', ui.dayOpenSunbird)) #### moreMenu = gtk.Menu() moreMenu.add(labelStockMenuItem('_Customize', gtk.STOCK_EDIT, self.customizeShow)) moreMenu.add(labelStockMenuItem('_Preferences', gtk.STOCK_PREFERENCES, self.prefShow)) moreMenu.add(labelStockMenuItem('_Event Manager', gtk.STOCK_ADD, self.eventManShow)) moreMenu.add(labelImageMenuItem('Time Line', 'timeline-18.png', self.timeLineShow)) #moreMenu.add(labelImageMenuItem('Week Calendar', 'weekcal-18.png', self.weekCalShow)) moreMenu.add(labelStockMenuItem(_('Export to %s')%'HTML', gtk.STOCK_CONVERT, self.exportClicked)) moreMenu.add(labelStockMenuItem('_About', gtk.STOCK_ABOUT, self.aboutShow)) if self.statusIconMode!=1: moreMenu.add(labelStockMenuItem('_Quit', gtk.STOCK_QUIT, self.quit)) ## moreMenu.show_all() moreItem = MenuItem(_('More')) moreItem.set_submenu(moreMenu) #moreItem.show_all() menu.add(moreItem) #### menu.show_all() dx, dy = widget.translate_coordinates(self, x, y) foo, wx, wy = self.get_window().get_origin() x = wx+dx y = wy+dy if rtl: x -= get_menu_width(menu) #### etime = gtk.get_current_event_time() #print('menuCellPopup', x, y, etime) self.menuCell = menu ## without this line, the menu was not showing up, WTF?!! menu.popup( None, None, lambda *args: (x, y, True), None, 3, etime, ) ui.updateFocusTime() def menuMainCreate(self): if self.menuMain: return menu = gtk.Menu() #### item = ImageMenuItem(_('Resize')) item.set_image(imageFromFile('resize.png')) item.connect('button-press-event', self.startResize) menu.add(item) ####### menu.add(self.checkAbove) menu.add(self.checkSticky) ####### menu.add(labelStockMenuItem('Select _Today', gtk.STOCK_HOME, self.goToday)) menu.add(labelStockMenuItem('Select _Date...', gtk.STOCK_INDEX, self.selectDateShow)) menu.add(labelStockMenuItem('Day Info', gtk.STOCK_INFO, self.dayInfoShow)) menu.add(labelStockMenuItem('_Customize', gtk.STOCK_EDIT, self.customizeShow)) menu.add(labelStockMenuItem('_Preferences', gtk.STOCK_PREFERENCES, self.prefShow)) #menu.add(labelStockMenuItem('_Add Event', gtk.STOCK_ADD, ui.addCustomEvent)) menu.add(labelStockMenuItem('_Event Manager', gtk.STOCK_ADD, self.eventManShow)) menu.add(labelImageMenuItem('Time Line', 'timeline-18.png', self.timeLineShow)) #menu.add(labelImageMenuItem('Week Calendar', 'weekcal-18.png', self.weekCalShow)) menu.add(labelStockMenuItem(_('Export to %s')%'HTML', gtk.STOCK_CONVERT, self.exportClicked)) menu.add(labelStockMenuItem('_About', gtk.STOCK_ABOUT, self.aboutShow)) if self.statusIconMode!=1: menu.add(labelStockMenuItem('_Quit', gtk.STOCK_QUIT, self.quit)) menu.show_all() self.menuMain = menu def menuMainPopup(self, widget, etime, x, y): self.menuMainCreate() if etime == 0: etime = gtk.get_current_event_time() menu = self.menuMain dx, dy = widget.translate_coordinates(self, x, y) foo, wx, wy = self.get_window().get_origin() x = wx+dx y = wy+dy if rtl: x -= get_menu_width(menu) #print('menuMainPopup', x, y, etime) menu.popup( None, None, lambda *args: (x, y, True), None, 3, etime, ) ui.updateFocusTime() def addToGroupFromMenu(self, menu, group, eventType): from scal3.ui_gtk.event.editor import addNewEvent #print('addToGroupFromMenu', group.title, eventType) title = _('Add ') + event_lib.classes.event.byName[eventType].desc event = addNewEvent( group, eventType, useSelectedDate=True, title=title, parent=self, ) if event is None: return ui.eventDiff.add('+', event) self.onConfigChange() def prefUpdateBgColor(self, cal): if ui.prefDialog: ui.prefDialog.colorbBg.set_color(ui.bgColor) #else:## FIXME ui.saveLiveConf() def keepAboveClicked(self, check): act = check.get_active() self.set_keep_above(act) ui.winKeepAbove = act ui.saveLiveConf() def stickyClicked(self, check): if check.get_active(): self.stick() ui.winSticky = True else: self.unstick() ui.winSticky = False ui.saveLiveConf() def copyDate(self, obj=None, event=None): setClipboard(ui.cell.format(ud.dateFormatBin)) def copyDateToday(self, obj=None, event=None): setClipboard(ui.todayCell.format(ud.dateFormatBin)) def copyTime(self, obj=None, event=None): setClipboard(ui.todayCell.format(ud.clockFormatBin, tm=localtime()[3:6])) """ def updateToolbarClock(self): if ui.showDigClockTb: if self.clock==None: from scal3.ui_gtk.mywidgets.clock import FClockLabel self.clock = FClockLabel(ud.clockFormat) pack(self.toolbBox, self.clock) self.clock.show() else: self.clock.format = ud.clockFormat else: if self.clock!=None: self.clock.destroy() self.clock = None def updateStatusIconClock(self, checkStatusIconMode=True): if checkStatusIconMode and self.statusIconMode!=2: return if ui.showDigClockTr: if self.clockTr==None: from scal3.ui_gtk.mywidgets.clock import FClockLabel self.clockTr = FClockLabel(ud.clockFormat) try: pack(self.statusIconHbox, self.clockTr) except AttributeError: self.clockTr.destroy() self.clockTr = None else: self.clockTr.show() else: self.clockTr.format = ud.clockFormat else: if self.clockTr!=None: self.clockTr.destroy() self.clockTr = None """ #weekCalShow = lambda self, obj=None, data=None: openWindow(ui.weekCalWin) def statusIconInit(self): if self.statusIconMode==2: useAppIndicator = ui.useAppIndicator if useAppIndicator: try: from gi.repository import AppIndicator3 as appIndicator except ImportError: useAppIndicator = False if useAppIndicator: from scal3.ui_gtk.starcal_appindicator import IndicatorStatusIconWrapper self.sicon = IndicatorStatusIconWrapper(self) else: self.sicon = gtk.StatusIcon() ##self.sicon.set_blinking(True) ## for Alarms ## some problem with gnome-shell #self.sicon.set_name('starcal') ## Warning: g_object_notify: object class `GtkStatusIcon' has no property named `name' self.sicon.set_title(core.APP_DESC) self.sicon.set_visible(True)## is needed ???????? self.sicon.connect('button-press-event', self.statusIconButtonPress) self.sicon.connect('activate', self.statusIconClicked) self.sicon.connect('popup-menu', self.statusIconPopup) #self.sicon.set_from_stock(gtk.STOCK_HOME) else: self.sicon = None getMainWinMenuItem = lambda self: labelMenuItem('Main Window', self.statusIconClicked) getStatusIconPopupItems = lambda self: [ labelStockMenuItem('Copy _Time', gtk.STOCK_COPY, self.copyTime), labelStockMenuItem('Copy _Date', gtk.STOCK_COPY, self.copyDateToday), labelStockMenuItem('Ad_just System Time', gtk.STOCK_PREFERENCES, self.adjustTime), #labelStockMenuItem('_Add Event', gtk.STOCK_ADD, ui.addCustomEvent),## FIXME labelStockMenuItem(_('Export to %s')%'HTML', gtk.STOCK_CONVERT, self.exportClickedStatusIcon), labelStockMenuItem('_Preferences', gtk.STOCK_PREFERENCES, self.prefShow), labelStockMenuItem('_Customize', gtk.STOCK_EDIT, self.customizeShow), labelStockMenuItem('_Event Manager', gtk.STOCK_ADD, self.eventManShow), labelImageMenuItem('Time Line', 'timeline-18.png', self.timeLineShow), labelStockMenuItem('_About', gtk.STOCK_ABOUT, self.aboutShow), gtk.SeparatorMenuItem(), labelStockMenuItem('_Quit', gtk.STOCK_QUIT, self.quit), ] def statusIconPopup(self, sicon, button, etime): menu = gtk.Menu() if os.sep == '\\': from scal3.ui_gtk.windows import setupMenuHideOnLeave setupMenuHideOnLeave(menu) items = self.getStatusIconPopupItems() # items.insert(0, self.getMainWinMenuItem())## FIXME geo = self.sicon.get_geometry() ## Returns None on windows, why??? if geo is None:## windows, taskbar is on buttom(below) items.reverse() get_pos_func = None else: #print(dir(geo)) y1 = geo.index(1) try: y = gtk.StatusIcon.position_menu(menu, self.sicon)[1] except TypeError: ## new gi versions y = gtk.StatusIcon.position_menu(menu, 0, 0, self.sicon)[1] if y<y1:## taskbar is on bottom items.reverse() get_pos_func = gtk.StatusIcon.position_menu for item in items: menu.add(item) menu.show_all() #print('statusIconPopup', button, etime) menu.popup(None, None, get_pos_func, self.sicon, button, etime) #self.sicon.do_popup_menu(self.sicon, button, etime) ui.updateFocusTime() self.sicon.menu = menu ## to prevent gurbage collected def onCurrentDateChange(self, gdate): self.statusIconUpdate(gdate=gdate) def getStatusIconTooltip(self): ##tt = core.weekDayName[core.getWeekDay(*ddate)] tt = core.weekDayName[core.jwday(ui.todayCell.jd)] #if ui.pluginsTextStatusIcon:##????????? # sep = _(',')+' ' #else: sep = '\n' for mode in calTypes.active: y, m, d = ui.todayCell.dates[mode] tt += '%s%s %s %s'%(sep, _(d), locale_man.getMonthName(mode, m, y), _(y)) if ui.pluginsTextStatusIcon: text = ui.todayCell.pluginsText if text!='': tt += '\n\n%s'%text ## .replace('\t', '\n') ## FIXME for item in ui.todayCell.eventsData: if not item['showInStatusIcon']: continue itemS = '' if item['time']: itemS += item['time'] + ' - ' itemS += item['text'][0] tt += '\n\n%s'%itemS return tt def statusIconUpdateIcon(self, ddate):## FIXME from scal3.utils import toBytes imagePath = ui.statusIconImageHoli if ui.todayCell.holiday else ui.statusIconImage ext = os.path.splitext(imagePath)[1][1:].lower() loader = GdkPixbuf.PixbufLoader.new_with_type(ext) if ui.statusIconFixedSizeEnable: try: width, height = ui.statusIconFixedSizeWH loader.set_size(width, height) except: myRaise() data = open(imagePath).read() if ext == 'svg': dayNum = _(ddate[2]) if ui.statusIconFontFamilyEnable: if ui.statusIconFontFamily: family = ui.statusIconFontFamily else: family = ui.getFont()[0] dayNum = '<tspan style="font-family:%s">%s</tspan>'%(family, dayNum) data = data.replace( 'TX', dayNum, ) data = toBytes(data) loader.write(data) loader.close() pixbuf = loader.get_pixbuf() self.sicon.set_from_pixbuf(pixbuf) def statusIconUpdateTooltip(self): set_tooltip(self.sicon, self.getStatusIconTooltip()) def statusIconUpdate(self, gdate=None, checkStatusIconMode=True): if checkStatusIconMode and self.statusIconMode < 1: return if gdate is None: gdate = localtime()[:3] if calTypes.primary==core.DATE_GREG: ddate = gdate else: ddate = core.convert(gdate[0], gdate[1], gdate[2], core.DATE_GREG, calTypes.primary) ####### self.sicon.set_from_file(join(pixDir, 'starcal-24.png')) self.statusIconUpdateIcon(ddate) ####### self.statusIconUpdateTooltip() return True def statusIconButtonPress(self, obj, gevent): if gevent.button == 2: ## middle button press self.copyDate() return True def statusIconClicked(self, obj=None): if self.get_property('visible'): #ui.winX, ui.winY = self.get_position()## FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) self.hide() else: self.move(ui.winX, ui.winY) ## every calling of .hide() and .present(), makes dialog not on top ## (forgets being on top) act = self.checkAbove.get_active() self.set_keep_above(act) if self.checkSticky.get_active(): self.stick() self.deiconify() self.present() def onDeleteEvent(self, widget=None, event=None): #ui.winX, ui.winY = self.get_position()## FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) if self.statusIconMode==0 or not self.sicon: self.quit() elif self.statusIconMode>1: if self.sicon.is_embedded(): self.hide() else: self.quit() return True def onEscape(self): #ui.winX, ui.winY = self.get_position()## FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) if self.statusIconMode==0: self.quit() elif self.statusIconMode>1: if self.sicon.is_embedded(): self.hide() def quit(self, widget=None, event=None): try: ui.saveLiveConf() except: myRaise() if self.statusIconMode>1 and self.sicon: self.sicon.set_visible(False) ## needed for windows ## before or after main_quit ? self.destroy() ###### core.stopRunningThreads() ###### return gtk.main_quit() def adjustTime(self, widget=None, event=None): from subprocess import Popen Popen(ud.adjustTimeCmd) def aboutShow(self, obj=None, data=None): if not self.aboutDialog: from scal3.ui_gtk.about import AboutDialog dialog = AboutDialog( name=core.APP_DESC, version=core.VERSION, title=_('About ')+core.APP_DESC, authors=[_(line) for line in open(join(rootDir, 'authors-dialog')).read().splitlines()], comments=core.aboutText, license=core.licenseText, website=core.homePage, parent=self, ) ## add Donate button ## FIXME dialog.connect('delete-event', self.aboutHide) dialog.connect('response', self.aboutHide) #dialog.set_logo(GdkPixbuf.Pixbuf.new_from_file(ui.logo)) #dialog.set_skip_taskbar_hint(True) self.aboutDialog = dialog openWindow(self.aboutDialog) def aboutHide(self, widget, arg=None):## arg maybe an event, or response id self.aboutDialog.hide() return True def prefShow(self, obj=None, data=None): if not ui.prefDialog: from scal3.ui_gtk.preferences import PrefDialog ui.prefDialog = PrefDialog(self.statusIconMode, parent=self) ui.prefDialog.updatePrefGui() openWindow(ui.prefDialog) def eventManCreate(self): checkEventsReadOnly() ## FIXME if not ui.eventManDialog: from scal3.ui_gtk.event.manager import EventManagerDialog ui.eventManDialog = EventManagerDialog(parent=self) def eventManShow(self, obj=None, data=None): self.eventManCreate() openWindow(ui.eventManDialog) def addCustomEvent(self, obj=None): self.eventManCreate() ui.eventManDialog.addCustomEvent() def timeLineShow(self, obj=None, data=None): if not ui.timeLineWin: from scal3.ui_gtk.timeline import TimeLineWindow ui.timeLineWin = TimeLineWindow() openWindow(ui.timeLineWin) def selectDateShow(self, widget=None): if not self.selectDateDialog: from scal3.ui_gtk.selectdate import SelectDateDialog self.selectDateDialog = SelectDateDialog(parent=self) self.selectDateDialog.connect('response-date', self.selectDateResponse) self.selectDateDialog.show() def dayInfoShow(self, widget=None): if not self.dayInfoDialog: from scal3.ui_gtk.day_info import DayInfoDialog self.dayInfoDialog = DayInfoDialog(parent=self) self.dayInfoDialog.onDateChange() openWindow(self.dayInfoDialog) def customizeDialogCreate(self): if not self.customizeDialog: from scal3.ui_gtk.customize_dialog import CustomizeDialog self.customizeDialog = CustomizeDialog(self.vbox) def switchWcalMcal(self, widget=None): self.customizeDialogCreate() self.vbox.switchWcalMcal(self.customizeDialog) self.customizeDialog.updateTreeEnableChecks() self.customizeDialog.save() def customizeShow(self, obj=None, data=None): self.customizeDialogCreate() openWindow(self.customizeDialog) def exportShow(self, year, month): if not self.exportDialog: from scal3.ui_gtk.export import ExportDialog self.exportDialog = ExportDialog(parent=self) self.exportDialog.showDialog(year, month) def exportClicked(self, widget=None): self.exportShow(ui.cell.year, ui.cell.month) def exportClickedStatusIcon(self, widget=None, event=None): year, month, day = core.getSysDate(calTypes.primary) self.exportShow(year, month) def onConfigChange(self, *a, **kw): ud.BaseCalObj.onConfigChange(self, *a, **kw) #self.set_property('skip-taskbar-hint', not ui.winTaskbar) ## self.set_skip_taskbar_hint ## FIXME ## skip-taskbar-hint need to restart ro be applied #self.updateToolbarClock()## FIXME #self.updateStatusIconClock() self.statusIconUpdate()
class MainWin(gtk.Window, ud.BaseCalObj): _name = "mainWin" desc = _("Main Window") timeout = 1 ## second setMinHeight = lambda self: self.resize(ui.winWidth, 2) #def maximize(self): # pass def __init__(self, statusIconMode=2): #from gi.repository import Gio #self.app = gtk.Application(application_id="apps.starcal") #self.app.register(Gio.Cancellable.new()) #gtk.ApplicationWindow.__init__(self, application=self.app) gtk.Window.__init__(self) self.add_events(gdk.EventMask.ALL_EVENTS_MASK) self.initVars() ud.windowList.appendItem(self) ui.mainWin = self ################## # statusIconMode: # ("none", "none") # ("statusIcon", "normal") # ("applet", "gnome") # ("applet", "kde") ## # 0: none (simple window) # 1: applet # 2: standard status icon self.statusIconMode = statusIconMode ### #ui.eventManDialog = None #ui.timeLineWin = None #ui.yearWheelWin = None ### #ui.weekCalWin = WeekCalWindow() #ud.windowList.appendItem(ui.weekCalWin) ### self.dayInfoDialog = None #print("windowList.items", [item._name for item in ud.windowList.items]) ########### ##self.connect("window-state-event", selfStateEvent) self.set_title("%s %s" % (core.APP_DESC, core.VERSION)) #self.connect("main-show", lambda arg: self.present()) #self.connect("main-hide", lambda arg: self.hide()) self.set_decorated(False) self.set_property("skip-taskbar-hint", not ui.winTaskbar) # self.set_skip_taskbar_hint # FIXME self.set_role("starcal") #self.set_focus_on_map(True)#???????? #self.set_type_hint(gdk.WindowTypeHint.NORMAL) #self.connect("realize", self.onRealize) self.set_default_size(ui.winWidth, 1) try: self.move(ui.winX, ui.winY) except: pass ############################################################# self.connect("focus-in-event", self.focusIn, "Main") self.connect("focus-out-event", self.focusOut, "Main") self.connect("button-press-event", self.buttonPress) self.connect("key-press-event", self.keyPress) self.connect("configure-event", self.configureEvent) self.connect("destroy", self.quit) ############################################################# """ #self.add_events(gdk.EventMask.VISIBILITY_NOTIFY_MASK) #self.connect("frame-event", show_event) # Compiz does not send configure-event(or any event) when MOVING # window(sends in last point, ## when moving completed) #self.connect("drag-motion", show_event) ud.rootWindow.set_events(... ud.rootWindow.add_filter(self.onRootWinEvent) #self.realize() #gdk.flush() #self.configureEvent(None, None) #self.connect("drag-motion", show_event) ###################### ## ???????????????????????????????????????????????? # when button is down(before button-release-event), # motion-notify-event does not recived! """ ################################################################## self.focus = False #self.focusOutTime = 0 #self.clockTr = None ################################################################## self.winCon = None ############ self.vbox = MainWinVbox() ui.checkMainWinItems() itemsPkg = "scal3.ui_gtk.mainwin_items" for (name, enable) in ui.mainWinItems: #print(name, enable) if enable: try: module = __import__( ".".join([ itemsPkg, name, ]), fromlist=["CalObj"], ) CalObj = module.CalObj except: myRaise() continue item = CalObj() item.enable = enable item.connect("size-allocate", self.childSizeAllocate) #modify_bg_all( # item, # gtk.StateType.NORMAL, # rgbToGdkColor(*ui.bgColor), #) else: desc = mainWinItemsDesc[name] item = DummyCalObj(name, desc, itemsPkg, True) self.vbox.appendItem(item) self.appendItem(self.vbox) self.vbox.show() self.customizeDialog = None ####### self.add(self.vbox) #################### self.isMaximized = False #################### #ui.prefDialog = None self.exportDialog = None self.selectDateDialog = None ############### Building About Dialog self.aboutDialog = None ############### self.menuMain = None ##### check = gtk.CheckMenuItem(label=_("_On Top")) check.set_use_underline(True) check.connect("activate", self.keepAboveClicked) check.set_active(ui.winKeepAbove) self.set_keep_above(ui.winKeepAbove) self.checkAbove = check ##### check = gtk.CheckMenuItem(label=_("_Sticky")) check.set_use_underline(True) check.connect("activate", self.stickyClicked) check.set_active(ui.winSticky) if ui.winSticky: self.stick() self.checkSticky = check ############################################################ self.statusIconInit() listener.dateChange.add(self) #if self.statusIconMode!=1: # timeout_add_seconds(self.timeout, self.statusIconUpdate) ######### self.connect("delete-event", self.onDeleteEvent) ######################################### for plug in core.allPlugList: if plug.external: try: plug.set_dialog(self) except AttributeError: pass ########################### self.onConfigChange() #ud.rootWindow.set_cursor(gdk.Cursor.new(gdk.CursorType.LEFT_PTR)) #def mainWinStateEvent(self, obj, gevent): #print(dir(event)) #print(gevent.new_window_state) #self.event = event def childSizeAllocate(self, cal, req): self.setMinHeight() def selectDateResponse(self, widget, y, m, d): ui.changeDate(y, m, d) self.onDateChange() def keyPress(self, arg, gevent): kname = gdk.keyval_name(gevent.keyval).lower() #print(now(), "MainWin.keyPress", kname) if kname == "escape": self.onEscape() elif kname == "f1": self.aboutShow() elif kname in ("insert", "plus", "kp_add"): self.eventManShow() elif kname in ("q", "arabic_dad"):## FIXME self.quit() else: self.vbox.keyPress(arg, gevent) return True ## FIXME def focusIn(self, widegt, event, data=None): self.focus = True if self.winCon and self.winCon.enable: self.winCon.windowFocusIn() def focusOut(self, widegt, event, data=None): # called 0.0004 sec (max) after focusIn # (if switched between two windows) dt = now() - ui.focusTime #print("focusOut", dt) if dt > 0.05: # FIXME self.focus = False timeout_add(2, self.focusOutDo) def focusOutDo(self): if not self.focus:# and t-self.focusOutTime>0.002: ab = self.checkAbove.get_active() self.set_keep_above(ab) if self.winCon and self.winCon.enable: self.winCon.windowFocusOut() return False """ def checkResize(self, widget, req): if ui.mcalHeight != req.height:# and ui.winWidth == req.width: if req.height == 0: req.height = 1 ui.mcalHeight = req.height """ def configureEvent(self, widget, gevent): wx, wy = self.get_position() maxPosDelta = max( abs(ui.winX - wx), abs(ui.winY - wy), ) #print(wx, wy) ww, wh = self.get_size() #if ui.bgUseDesk and maxPosDelta > 1:## FIXME # self.queue_draw() if self.get_property("visible"): ui.winX, ui.winY = (wx, wy) ui.winWidth = ww liveConfChanged() return False def buttonPress(self, obj, gevent): print("MainWin.buttonPress") b = gevent.button #print("buttonPress", b) if b == 3: self.menuMainCreate() self.menuMain.popup(None, None, None, None, 3, gevent.time) ui.updateFocusTime() elif b == 1: # FIXME: used to cause problems with `ConButton` when using 'pressed' and 'released' signals self.begin_move_drag( gevent.button, int(gevent.x_root), int(gevent.y_root), gevent.time, ) return False def childButtonPress(self, widget, gevent): b = gevent.button #print(dir(gevent)) #foo, x, y, mask = gevent.get_window().get_pointer() #x, y = self.get_pointer() x, y = gevent.x_root, gevent.y_root if b == 1: self.begin_move_drag(gevent.button, x, y, gevent.time) return True elif b == 3: self.menuMainCreate() if rtl: x -= get_menu_width(self.menuMain) self.menuMain.popup( None, None, lambda *args: (x, y, True), None, 3, gevent.time, ) ui.updateFocusTime() return True return False def startResize(self, widget, gevent): if self.menuMain: self.menuMain.hide() self.begin_resize_drag( gdk.WindowEdge.SOUTH_EAST, gevent.button, int(gevent.x_root), int(gevent.y_root), gevent.time, ) return True def changeDate(self, year, month, day): ui.changeDate(year, month, day) self.onDateChange() def goToday(self, obj=None): return self.changeDate(*core.getSysDate(calTypes.primary)) def onDateChange(self, *a, **kw): #print("MainWin.onDateChange") ud.BaseCalObj.onDateChange(self, *a, **kw) #for j in range(len(core.plugIndex)):##???????????????????? # try: # core.allPlugList[core.plugIndex[j]].date_change(*date) # except AttributeError: # pass self.setMinHeight() for j in range(len(core.plugIndex)): try: core.allPlugList[core.plugIndex[j]].date_change_after(*date) except AttributeError: pass #print("Occurence Time: max=%e, avg=%e" % ( # ui.Cell.ocTimeMax, # ui.Cell.ocTimeSum/ui.Cell.ocTimeCount #)) def getEventAddToMenuItem(self): from scal3.ui_gtk.drawing import newColorCheckPixbuf addToItem = labelStockMenuItem("_Add to", gtk.STOCK_ADD) if event_lib.allReadOnly: addToItem.set_sensitive(False) return addToItem menu2 = gtk.Menu() ## for group in ui.eventGroups: if not group.enable: continue if not group.showInCal():## FIXME continue eventTypes = group.acceptsEventTypes if not eventTypes: continue item2 = ImageMenuItem() item2.set_label(group.title) ## image = gtk.Image() if group.icon: image.set_from_file(group.icon) else: image.set_from_pixbuf(newColorCheckPixbuf(group.color, 20, True)) item2.set_image(image) ## if len(eventTypes) == 1: item2.connect("activate", self.addToGroupFromMenu, group, eventTypes[0]) else: menu3 = gtk.Menu() for eventType in eventTypes: eventClass = event_lib.classes.event.byName[eventType] item3 = ImageMenuItem() item3.set_label(eventClass.desc) icon = eventClass.getDefaultIcon() if icon: item3.set_image(imageFromFile(icon)) item3.connect("activate", self.addToGroupFromMenu, group, eventType) menu3.add(item3) menu3.show_all() item2.set_submenu(menu3) menu2.add(item2) ## menu2.show_all() addToItem.set_submenu(menu2) return addToItem def editEventFromMenu(self, item, groupId, eventId): from scal3.ui_gtk.event.editor import EventEditorDialog event = ui.getEvent(groupId, eventId) group = ui.eventGroups[groupId] parent = self event = EventEditorDialog( event, title=_("Edit ") + event.desc, parent=parent, ).run() if event is None: return ui.eventDiff.add("e", event) self.onConfigChange() def addEditEventCellMenuItems(self, menu): if event_lib.allReadOnly: return eventsData = ui.cell.eventsData if not eventsData: return if len(eventsData) < 4: # make it customizable TODO for eData in eventsData: groupId, eventId = eData["ids"] menu.add(labelImageMenuItem( _("Edit") + ": " + eData["text"][0], eData["icon"], self.editEventFromMenu, groupId, eventId, )) else: subMenu = gtk.Menu() subMenuItem = labelStockMenuItem("_Edit Event", gtk.STOCK_ADD) for eData in eventsData: groupId, eventId = eData["ids"] subMenu.add(labelImageMenuItem( eData["text"][0], eData["icon"], self.editEventFromMenu, groupId, eventId, )) subMenu.show_all() subMenuItem.set_submenu(subMenu) menu.add(subMenuItem) def menuCellPopup(self, widget, etime, x, y): calObjName = widget._name # why private? FIXME # calObjName is in ("weekCal", "monthCal", ...) menu = gtk.Menu() #### for calType in calTypes.active: menu.add(labelStockMenuItem( _("Copy %s Date") % _(calTypes.getDesc(calType)), gtk.STOCK_COPY, self.copyDateGetCallback(calType), calType, )) menu.add(labelStockMenuItem( "Day Info", gtk.STOCK_INFO, self.dayInfoShow, )) menu.add(self.getEventAddToMenuItem()) self.addEditEventCellMenuItems(menu) menu.add(gtk.SeparatorMenuItem()) menu.add(labelStockMenuItem( "Select _Today", gtk.STOCK_HOME, self.goToday, )) menu.add(labelStockMenuItem( "Select _Date...", gtk.STOCK_INDEX, self.selectDateShow, )) if calObjName in ("weekCal", "monthCal"): menu.add(labelStockMenuItem( "Switch to " + ( "Month Calendar" if calObjName == "weekCal" else "Week Calendar" ), gtk.STOCK_REDO, self.switchWcalMcal, )) if os.path.isfile("/usr/bin/evolution"): # FIXME menu.add(labelImageMenuItem( "In E_volution", "evolution-18.png", ui.dayOpenEvolution, )) #if os.path.isfile("/usr/bin/sunbird"): # FIXME # menu.add(labelImageMenuItem( # "In _Sunbird", # "sunbird-18.png", # ui.dayOpenSunbird, #)) #### moreMenu = gtk.Menu() moreMenu.add(labelStockMenuItem( "_Customize", gtk.STOCK_EDIT, self.customizeShow, )) moreMenu.add(labelStockMenuItem( "_Preferences", gtk.STOCK_PREFERENCES, self.prefShow, )) moreMenu.add(labelStockMenuItem( "_Event Manager", gtk.STOCK_ADD, self.eventManShow, )) moreMenu.add(labelImageMenuItem( "Time Line", "timeline-18.png", self.timeLineShow, )) moreMenu.add(labelImageMenuItem( "Year Wheel", "year-wheel-18.png", self.yearWheelShow, )) # icon? FIXME #moreMenu.add(labelImageMenuItem( # "Week Calendar", # "weekcal-18.png", # self.weekCalShow, #)) moreMenu.add(labelStockMenuItem( _("Export to %s") % "HTML", gtk.STOCK_CONVERT, self.exportClicked, )) moreMenu.add(labelStockMenuItem( "_About", gtk.STOCK_ABOUT, self.aboutShow, )) if self.statusIconMode != 1: moreMenu.add(labelStockMenuItem( "_Quit", gtk.STOCK_QUIT, self.quit, )) ## moreMenu.show_all() moreItem = MenuItem(_("More")) moreItem.set_submenu(moreMenu) #moreItem.show_all() menu.add(moreItem) #### menu.show_all() dx, dy = widget.translate_coordinates(self, x, y) foo, wx, wy = self.get_window().get_origin() x = wx + dx y = wy + dy if rtl: x -= get_menu_width(menu) #### etime = gtk.get_current_event_time() #print("menuCellPopup", x, y, etime) self.menuCell = menu # without the above line, the menu is not showing up # some GC-related pygi bug probably menu.popup( None, None, lambda *args: (x, y, True), None, 3, etime, ) ui.updateFocusTime() def menuMainCreate(self): if self.menuMain: return menu = gtk.Menu() #### item = ImageMenuItem(_("Resize")) item.set_image(imageFromFile("resize.png")) item.connect("button-press-event", self.startResize) menu.add(item) ####### menu.add(self.checkAbove) menu.add(self.checkSticky) ####### menu.add(labelStockMenuItem( "Select _Today", gtk.STOCK_HOME, self.goToday, )) menu.add(labelStockMenuItem( "Select _Date...", gtk.STOCK_INDEX, self.selectDateShow, )) menu.add(labelStockMenuItem( "Day Info", gtk.STOCK_INFO, self.dayInfoShow, )) menu.add(labelStockMenuItem( "_Customize", gtk.STOCK_EDIT, self.customizeShow, )) menu.add(labelStockMenuItem( "_Preferences", gtk.STOCK_PREFERENCES, self.prefShow, )) #menu.add(labelStockMenuItem( # "_Add Event", # gtk.STOCK_ADD, # ui.addCustomEvent, #)) #menu.add(labelStockMenuItem( # "_Event Manager", # gtk.STOCK_ADD, # self.eventManShow, #)) menu.add(labelImageMenuItem( "Time Line", "timeline-18.png", self.timeLineShow, )) menu.add(labelImageMenuItem( "Year Wheel", "year-wheel-18.png", self.yearWheelShow, )) # icon? FIXME #menu.add(labelImageMenuItem( # "Week Calendar", # "weekcal-18.png", # self.weekCalShow, #)) menu.add(labelStockMenuItem( _("Export to %s") % "HTML", gtk.STOCK_CONVERT, self.exportClicked, )) menu.add(labelStockMenuItem( "Ad_just System Time", gtk.STOCK_PREFERENCES, self.adjustTime, )) menu.add(labelStockMenuItem( "_About", gtk.STOCK_ABOUT, self.aboutShow, )) if self.statusIconMode != 1: menu.add(labelStockMenuItem( "_Quit", gtk.STOCK_QUIT, self.quit, )) menu.show_all() self.menuMain = menu def menuMainPopup(self, widget, etime, x, y): self.menuMainCreate() if etime == 0: etime = gtk.get_current_event_time() menu = self.menuMain dx, dy = widget.translate_coordinates(self, x, y) foo, wx, wy = self.get_window().get_origin() x = wx + dx y = wy + dy if rtl: x -= get_menu_width(menu) #print("menuMainPopup", x, y, etime) menu.popup( None, None, lambda *args: (x, y, True), None, 3, etime, ) ui.updateFocusTime() def addToGroupFromMenu(self, menu, group, eventType): from scal3.ui_gtk.event.editor import addNewEvent #print("addToGroupFromMenu", group.title, eventType) title = _("Add ") + event_lib.classes.event.byName[eventType].desc event = addNewEvent( group, eventType, useSelectedDate=True, title=title, parent=self, ) if event is None: return ui.eventDiff.add("+", event) self.onConfigChange() def prefUpdateBgColor(self, cal): if ui.prefDialog: ui.prefDialog.colorbBg.set_color(ui.bgColor) #else:## FIXME ui.saveLiveConf() def keepAboveClicked(self, check): act = check.get_active() self.set_keep_above(act) ui.winKeepAbove = act ui.saveLiveConf() def stickyClicked(self, check): if check.get_active(): self.stick() ui.winSticky = True else: self.unstick() ui.winSticky = False ui.saveLiveConf() def copyDate(self, calType: int): setClipboard(ui.cell.format(ud.dateFormatBin, mode=calType)) def copyDateGetCallback(self, calType: int): return lambda obj=None, event=None: setClipboard(ui.cell.format(ud.dateFormatBin, mode=calType)) def copyDateToday(self, obj=None, event=None): setClipboard(ui.todayCell.format(ud.dateFormatBin)) def copyTime(self, obj=None, event=None): setClipboard(ui.todayCell.format( ud.clockFormatBin, tm=localtime()[3:6], )) """ def updateToolbarClock(self): if ui.showDigClockTb: if self.clock is None: from scal3.ui_gtk.mywidgets.clock import FClockLabel self.clock = FClockLabel(ud.clockFormat) pack(self.toolbBox, self.clock) self.clock.show() else: self.clock.format = ud.clockFormat else: if self.clock is not None: self.clock.destroy() self.clock = None def updateStatusIconClock(self, checkStatusIconMode=True): if checkStatusIconMode and self.statusIconMode!=2: return if ui.showDigClockTr: if self.clockTr is None: from scal3.ui_gtk.mywidgets.clock import FClockLabel self.clockTr = FClockLabel(ud.clockFormat) try: pack(self.statusIconHbox, self.clockTr) except AttributeError: self.clockTr.destroy() self.clockTr = None else: self.clockTr.show() else: self.clockTr.format = ud.clockFormat else: if self.clockTr is not None: self.clockTr.destroy() self.clockTr = None """ #def weekCalShow(self, obj=None, data=None): # openWindow(ui.weekCalWin) def statusIconInit(self): if self.statusIconMode == 2: useAppIndicator = ui.useAppIndicator if useAppIndicator: try: import scal3.ui_gtk.starcal_appindicator except (ImportError, ValueError): useAppIndicator = False if useAppIndicator: from scal3.ui_gtk.starcal_appindicator import ( IndicatorStatusIconWrapper, ) self.sicon = IndicatorStatusIconWrapper(self) else: self.sicon = gtk.StatusIcon() ##self.sicon.set_blinking(True) ## ^ for Alarms ## some problem with gnome-shell #self.sicon.set_name("starcal") # Warning: g_object_notify: object class `GtkStatusIcon" # has no property named `name" self.sicon.set_title(core.APP_DESC) self.sicon.set_visible(True) # is needed? self.sicon.connect( "button-press-event", self.statusIconButtonPress, ) self.sicon.connect("activate", self.statusIconClicked) self.sicon.connect("popup-menu", self.statusIconPopup) #self.sicon.set_from_stock(gtk.STOCK_HOME) else: self.sicon = None def getMainWinMenuItem(self): return labelMenuItem("Main Window", self.statusIconClicked) def getStatusIconPopupItems(self): return [ labelStockMenuItem( "Copy _Time", gtk.STOCK_COPY, self.copyTime, ), labelStockMenuItem( "Copy _Date", gtk.STOCK_COPY, self.copyDateToday, ), labelStockMenuItem( "Ad_just System Time", gtk.STOCK_PREFERENCES, self.adjustTime, ), #labelStockMenuItem( # "_Add Event", # gtk.STOCK_ADD, # ui.addCustomEvent, #), # FIXME labelStockMenuItem( _("Export to %s") % "HTML", gtk.STOCK_CONVERT, self.exportClickedStatusIcon, ), labelStockMenuItem( "_Preferences", gtk.STOCK_PREFERENCES, self.prefShow, ), labelStockMenuItem( "_Customize", gtk.STOCK_EDIT, self.customizeShow, ), labelStockMenuItem( "_Event Manager", gtk.STOCK_ADD, self.eventManShow, ), labelImageMenuItem( "Time Line", "timeline-18.png", self.timeLineShow, ), labelImageMenuItem( "Year Wheel", "year-wheel-18.png", self.yearWheelShow, ), # icon? FIXME labelStockMenuItem( "_About", gtk.STOCK_ABOUT, self.aboutShow, ), gtk.SeparatorMenuItem(), labelStockMenuItem( "_Quit", gtk.STOCK_QUIT, self.quit, ), ] def statusIconPopup(self, sicon, button, etime): menu = gtk.Menu() if os.sep == "\\": from scal3.ui_gtk.windows import setupMenuHideOnLeave setupMenuHideOnLeave(menu) items = self.getStatusIconPopupItems() # items.insert(0, self.getMainWinMenuItem())## FIXME get_pos_func = None y1 = 0 geo = self.sicon.get_geometry() ## Previously geo was None on windows, and on Linux it had `geo.index(1)` (not sure about the type) ## Now it's tuple on both Linux and windows if geo is None: items.reverse() elif isinstance(geo, tuple): # geo == (True, screen, area, orientation) y1 = geo[2].y else: y1 = geo.index(1) try: y = gtk.StatusIcon.position_menu(menu, self.sicon)[1] except TypeError: ## new gi versions y = gtk.StatusIcon.position_menu(menu, 0, 0, self.sicon)[1] if y1 > 0 and y < y1: # taskbar is on bottom items.reverse() get_pos_func = gtk.StatusIcon.position_menu for item in items: menu.add(item) menu.show_all() #print("statusIconPopup", button, etime) menu.popup(None, None, get_pos_func, self.sicon, button, etime) #self.sicon.do_popup_menu(self.sicon, button, etime) ui.updateFocusTime() self.sicon.menu = menu ## to prevent gurbage collected def onCurrentDateChange(self, gdate): self.statusIconUpdate(gdate=gdate) def getStatusIconTooltip(self): ##tt = core.weekDayName[core.getWeekDay(*ddate)] tt = core.weekDayName[core.jwday(ui.todayCell.jd)] #if ui.pluginsTextStatusIcon:##????????? # sep = _(",")+" " #else: sep = "\n" for mode in calTypes.active: y, m, d = ui.todayCell.dates[mode] tt += "%s%s %s %s" % ( sep, _(d), locale_man.getMonthName(mode, m, y), _(y), ) if ui.pluginsTextStatusIcon: text = ui.todayCell.pluginsText if text != "": tt += "\n\n%s" % text # .replace("\t", "\n") ## FIXME for item in ui.todayCell.eventsData: if not item["showInStatusIcon"]: continue itemS = "" if item["time"]: itemS += item["time"] + " - " itemS += item["text"][0] tt += "\n\n%s" % itemS return tt def statusIconUpdateIcon(self, ddate): # FIXME from scal3.utils import toBytes imagePath = ( ui.statusIconImageHoli if ui.todayCell.holiday else ui.statusIconImage ) ext = os.path.splitext(imagePath)[1][1:].lower() loader = GdkPixbuf.PixbufLoader.new_with_type(ext) if ui.statusIconFixedSizeEnable: try: width, height = ui.statusIconFixedSizeWH loader.set_size(width, height) except: myRaise() data = open(imagePath, "rb").read() if ext == "svg": dayNum = locale_man.numEncode( ddate[2], mode=calTypes.primary, # FIXME ) if ui.statusIconFontFamilyEnable: if ui.statusIconFontFamily: family = ui.statusIconFontFamily else: family = ui.getFont()[0] dayNum = "<tspan style=\"font-family:%s\">%s</tspan>" % ( family, dayNum, ) data = data.replace( b"TX", toBytes(dayNum), ) loader.write(data) loader.close() pixbuf = loader.get_pixbuf() self.sicon.set_from_pixbuf(pixbuf) def statusIconUpdateTooltip(self): try: sicon = self.sicon except AttributeError: return set_tooltip(sicon, self.getStatusIconTooltip()) def statusIconUpdate(self, gdate=None, checkStatusIconMode=True): if checkStatusIconMode and self.statusIconMode < 1: return if gdate is None: gdate = localtime()[:3] if calTypes.primary == core.DATE_GREG: ddate = gdate else: ddate = core.convert( gdate[0], gdate[1], gdate[2], core.DATE_GREG, calTypes.primary, ) ####### self.sicon.set_from_file(join(pixDir, "starcal-24.png")) self.statusIconUpdateIcon(ddate) ####### self.statusIconUpdateTooltip() return True def statusIconButtonPress(self, obj, gevent): if gevent.button == 2: ## middle button press self.copyDate(calTypes.primary) return True def statusIconClicked(self, obj=None): if self.get_property("visible"): #ui.winX, ui.winY = self.get_position() # ^ FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) self.hide() else: self.move(ui.winX, ui.winY) # every calling of .hide() and .present(), makes dialog not on top # (forgets being on top) act = self.checkAbove.get_active() self.set_keep_above(act) if self.checkSticky.get_active(): self.stick() self.deiconify() self.present() def onDeleteEvent(self, widget=None, event=None): #ui.winX, ui.winY = self.get_position() # ^ FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) if self.statusIconMode == 0 or not self.sicon: self.quit() elif self.statusIconMode > 1: if self.sicon.is_embedded(): self.hide() else: self.quit() return True def onEscape(self): #ui.winX, ui.winY = self.get_position() # ^ FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) if self.statusIconMode == 0: self.quit() elif self.statusIconMode > 1: if self.sicon.is_embedded(): self.hide() def quit(self, widget=None, event=None): try: ui.saveLiveConf() except: myRaise() if self.statusIconMode > 1 and self.sicon: self.sicon.set_visible(False) # ^ needed for windows. before or after main_quit ? self.destroy() ###### core.stopRunningThreads() ###### return gtk.main_quit() def adjustTime(self, widget=None, event=None): from subprocess import Popen if not ud.adjustTimeCmd: showError("Failed to find gksudo, kdesudo, gksu, gnomesu, kdesu or any askpass program to use with sudo") return Popen(ud.adjustTimeCmd, env=ud.adjustTimeEnv) def aboutShow(self, obj=None, data=None): if not self.aboutDialog: from scal3.ui_gtk.about import AboutDialog with open( join(rootDir, "authors-dialog"), encoding="utf-8", ) as authorsFile: authors = authorsFile.read().splitlines() dialog = AboutDialog( name=core.APP_DESC, version=core.VERSION, title=_("About ") + core.APP_DESC, authors=[ _(author) for author in authors ], comments=core.aboutText, license=core.licenseText, website=core.homePage, parent=self, ) # add Donate button, FIXME dialog.connect("delete-event", self.aboutHide) dialog.connect("response", self.aboutHide) #dialog.set_logo(GdkPixbuf.Pixbuf.new_from_file(ui.logo)) #dialog.set_skip_taskbar_hint(True) self.aboutDialog = dialog openWindow(self.aboutDialog) def aboutHide(self, widget, arg=None): # arg maybe an event, or response id self.aboutDialog.hide() return True def prefShow(self, obj=None, data=None): if not ui.prefDialog: from scal3.ui_gtk.preferences import PrefDialog ui.prefDialog = PrefDialog(self.statusIconMode, parent=self) ui.prefDialog.updatePrefGui() openWindow(ui.prefDialog) def eventManCreate(self): checkEventsReadOnly() ## FIXME if not ui.eventManDialog: from scal3.ui_gtk.event.manager import EventManagerDialog ui.eventManDialog = EventManagerDialog(parent=self) def eventManShow(self, obj=None, data=None): self.eventManCreate() openWindow(ui.eventManDialog) def addCustomEvent(self, obj=None): self.eventManCreate() ui.eventManDialog.addCustomEvent() def timeLineShow(self, obj=None, data=None): if not ui.timeLineWin: from scal3.ui_gtk.timeline import TimeLineWindow ui.timeLineWin = TimeLineWindow() openWindow(ui.timeLineWin) def yearWheelShow(self, obj=None, data=None): if not ui.yearWheelWin: from scal3.ui_gtk.year_wheel import YearWheelWindow ui.yearWheelWin = YearWheelWindow() openWindow(ui.yearWheelWin) def selectDateShow(self, widget=None): if not self.selectDateDialog: from scal3.ui_gtk.selectdate import SelectDateDialog self.selectDateDialog = SelectDateDialog(parent=self) self.selectDateDialog.connect( "response-date", self.selectDateResponse, ) self.selectDateDialog.show() def dayInfoShow(self, widget=None): if not self.dayInfoDialog: from scal3.ui_gtk.day_info import DayInfoDialog self.dayInfoDialog = DayInfoDialog(parent=self) self.dayInfoDialog.onDateChange() openWindow(self.dayInfoDialog) def customizeDialogCreate(self): if not self.customizeDialog: from scal3.ui_gtk.customize_dialog import CustomizeDialog self.customizeDialog = CustomizeDialog(self.vbox, parent=self) def switchWcalMcal(self, widget=None): self.customizeDialogCreate() self.vbox.switchWcalMcal(self.customizeDialog) self.customizeDialog.updateTreeEnableChecks() self.customizeDialog.save() def customizeShow(self, obj=None, data=None): self.customizeDialogCreate() openWindow(self.customizeDialog) def exportShow(self, year, month): if not self.exportDialog: from scal3.ui_gtk.export import ExportDialog self.exportDialog = ExportDialog(parent=self) self.exportDialog.showDialog(year, month) def exportClicked(self, widget=None): self.exportShow(ui.cell.year, ui.cell.month) def exportClickedStatusIcon(self, widget=None, event=None): year, month, day = core.getSysDate(calTypes.primary) self.exportShow(year, month) def onConfigChange(self, *a, **kw): ud.BaseCalObj.onConfigChange(self, *a, **kw) #self.set_property("skip-taskbar-hint", not ui.winTaskbar) # self.set_skip_taskbar_hint ## FIXME # skip-taskbar-hint need to restart ro be applied #self.updateToolbarClock()## FIXME #self.updateStatusIconClock() self.statusIconUpdate()
class MainWin(gtk.Window, ud.BaseCalObj): _name = 'mainWin' desc = _('Main Window') timeout = 1 ## second setMinHeight = lambda self: self.resize(ui.winWidth, 2) #def maximize(self): # pass def __init__(self, statusIconMode=2): #from gi.repository import Gio #self.app = gtk.Application(application_id="apps.starcal") #self.app.register(Gio.Cancellable.new()) #gtk.ApplicationWindow.__init__(self, application=self.app) gtk.Window.__init__(self) self.add_events(gdk.EventMask.ALL_EVENTS_MASK) self.initVars() ud.windowList.appendItem(self) ui.mainWin = self ################## ## statusIconMode: ## ('none', 'none') ## ('statusIcon', 'normal') ## ('applet', 'gnome') ## ('applet', 'kde') ## ## 0: none (simple window) ## 1: applet ## 2: standard status icon self.statusIconMode = statusIconMode ### #ui.eventManDialog = None #ui.timeLineWin = None ### #ui.weekCalWin = WeekCalWindow() #ud.windowList.appendItem(ui.weekCalWin) ### self.dayInfoDialog = None #print('windowList.items', [item._name for item in ud.windowList.items]) ########### ##self.connect('window-state-event', selfStateEvent) self.set_title('%s %s'%(core.APP_DESC, core.VERSION)) #self.connect('main-show', lambda arg: self.present()) #self.connect('main-hide', lambda arg: self.hide()) self.set_decorated(False) self.set_property('skip-taskbar-hint', not ui.winTaskbar) ## self.set_skip_taskbar_hint ## FIXME self.set_role('starcal') #self.set_focus_on_map(True)#???????? #self.set_type_hint(gdk.WindowTypeHint.NORMAL) #self.connect('realize', self.onRealize) self.set_default_size(ui.winWidth, 1) try: self.move(ui.winX, ui.winY) except: pass ############################################################# self.connect('focus-in-event', self.focusIn, 'Main') self.connect('focus-out-event', self.focusOut, 'Main') self.connect('button-press-event', self.buttonPress) self.connect('key-press-event', self.keyPress) self.connect('configure-event', self.configureEvent) self.connect('destroy', self.quit) ############################################################# """ #self.add_events(gdk.EventMask.VISIBILITY_NOTIFY_MASK) #self.connect('frame-event', show_event) ## Compiz does not send configure-event(or any event) when MOVING window(sends in last point, ## when moving completed) #self.connect('drag-motion', show_event) ud.rootWindow.set_events(... ud.rootWindow.add_filter(self.onRootWinEvent) #self.realize() #gdk.flush() #self.configureEvent(None, None) #self.connect('drag-motion', show_event) ###################### ## ???????????????????????????????????????????????? ## when button is down(before button-release-event), motion-notify-event does not recived! """ ################################################################## self.focus = False #self.focusOutTime = 0 #self.clockTr = None ############################################################################ self.winCon = None ############ self.vbox = MainWinVbox() ui.checkMainWinItems() itemsPkg = 'scal3.ui_gtk.mainwin_items' for (name, enable) in ui.mainWinItems: #print(name, enable) if enable: try: module = __import__( '.'.join([ itemsPkg, name, ]), fromlist=['CalObj'], ) CalObj = module.CalObj except: myRaise() continue item = CalObj() item.enable = enable item.connect('size-allocate', self.childSizeAllocate) #modify_bg_all(item, gtk.StateType.NORMAL, rgbToGdkColor(*ui.bgColor)) else: desc = mainWinItemsDesc[name] item = DummyCalObj(name, desc, itemsPkg, True) self.vbox.appendItem(item) self.appendItem(self.vbox) self.vbox.show() self.customizeDialog = None ####### self.add(self.vbox) #################### self.isMaximized = False #################### #ui.prefDialog = None self.exportDialog = None self.selectDateDialog = None ############### Building About Dialog self.aboutDialog = None ############### self.menuMain = None ##### check = gtk.CheckMenuItem(label=_('_On Top')) check.set_use_underline(True) check.connect('activate', self.keepAboveClicked) check.set_active(ui.winKeepAbove) self.set_keep_above(ui.winKeepAbove) self.checkAbove = check ##### check = gtk.CheckMenuItem(label=_('_Sticky')) check.set_use_underline(True) check.connect('activate', self.stickyClicked) check.set_active(ui.winSticky) if ui.winSticky: self.stick() self.checkSticky = check ############################################################ self.statusIconInit() listener.dateChange.add(self) #if self.statusIconMode!=1: # gobject.timeout_add_seconds(self.timeout, self.statusIconUpdate) ######### self.connect('delete-event', self.onDeleteEvent) ######################################### for plug in core.allPlugList: if plug.external: try: plug.set_dialog(self) except AttributeError: pass ########################### self.onConfigChange() #ud.rootWindow.set_cursor(gdk.Cursor.new(gdk.CursorType.LEFT_PTR)) #def mainWinStateEvent(self, obj, gevent): #print(dir(event)) #print(gevent.new_window_state) #self.event = event def childSizeAllocate(self, cal, req): self.setMinHeight() def selectDateResponse(self, widget, y, m, d): ui.changeDate(y, m, d) self.onDateChange() def keyPress(self, arg, gevent): kname = gdk.keyval_name(gevent.keyval).lower() #print(now(), 'MainWin.keyPress', kname) if kname=='escape': self.onEscape() elif kname=='f1': self.aboutShow() elif kname in ('insert', 'plus', 'kp_add'): self.eventManShow() elif kname in ('q', 'arabic_dad'):## FIXME self.quit() else: self.vbox.keyPress(arg, gevent) return True ## FIXME def focusIn(self, widegt, event, data=None): self.focus = True if self.winCon and self.winCon.enable: self.winCon.windowFocusIn() def focusOut(self, widegt, event, data=None): ## called 0.0004 sec (max) after focusIn (if switched between two windows) dt = now()-ui.focusTime #print('focusOut', dt) if dt > 0.05: ## FIXME self.focus = False gobject.timeout_add(2, self.focusOutDo) def focusOutDo(self): if not self.focus:# and t-self.focusOutTime>0.002: ab = self.checkAbove.get_active() self.set_keep_above(ab) if self.winCon and self.winCon.enable: self.winCon.windowFocusOut() return False """ def checkResize(self, widget, req): if ui.mcalHeight != req.height:# and ui.winWidth==req.width: if req.height==0: req.height=1 ui.mcalHeight = req.height """ def configureEvent(self, widget, gevent): wx, wy = self.get_position() maxPosDelta = max(abs(ui.winX-wx), abs(ui.winY-wy)) #print(wx, wy) ww, wh = self.get_size() #if ui.bgUseDesk and maxPosDelta > 1:## FIXME # self.queue_draw() if self.get_property('visible'): ui.winX, ui.winY = (wx, wy) ui.winWidth = ww liveConfChanged() return False def buttonPress(self, obj, gevent): print('MainWin.buttonPress') b = gevent.button #print('buttonPress', b) if b==3: self.menuMainCreate() self.menuMain.popup(None, None, None, None, 3, gevent.time) ui.updateFocusTime() elif b==1: # FIXME: used to cause problems with `ConButton` when using 'pressed' and 'released' signals self.begin_move_drag(gevent.button, int(gevent.x_root), int(gevent.y_root), gevent.time) return False def childButtonPress(self, widget, gevent): b = gevent.button #print(dir(gevent)) #foo, x, y, mask = gevent.get_window().get_pointer() #x, y = self.get_pointer() x, y = gevent.x_root, gevent.y_root if b == 1: self.begin_move_drag(gevent.button, x, y, gevent.time) return True elif b == 3: self.menuMainCreate() if rtl: x -= get_menu_width(self.menuMain) self.menuMain.popup( None, None, lambda *args: (x, y, True), None, 3, gevent.time, ) ui.updateFocusTime() return True return False def startResize(self, widget, gevent): if self.menuMain: self.menuMain.hide() self.begin_resize_drag( gdk.WindowEdge.SOUTH_EAST, gevent.button, int(gevent.x_root), int(gevent.y_root), gevent.time, ) return True def changeDate(self, year, month, day): ui.changeDate(year, month, day) self.onDateChange() goToday = lambda self, obj=None: self.changeDate(*core.getSysDate(calTypes.primary)) def onDateChange(self, *a, **kw): #print('MainWin.onDateChange') ud.BaseCalObj.onDateChange(self, *a, **kw) #for j in range(len(core.plugIndex)):##???????????????????? # try: # core.allPlugList[core.plugIndex[j]].date_change(*date) # except AttributeError: # pass self.setMinHeight() for j in range(len(core.plugIndex)): try: core.allPlugList[core.plugIndex[j]].date_change_after(*date) except AttributeError: pass #print('Occurence Time: max=%e, avg=%e'%(ui.Cell.ocTimeMax, ui.Cell.ocTimeSum/ui.Cell.ocTimeCount)) def getEventAddToMenuItem(self): from scal3.ui_gtk.drawing import newColorCheckPixbuf addToItem = labelStockMenuItem('_Add to', gtk.STOCK_ADD) if event_lib.readOnly: addToItem.set_sensitive(False) return addToItem menu2 = gtk.Menu() ## for group in ui.eventGroups: if not group.enable: continue if not group.showInCal():## FIXME continue eventTypes = group.acceptsEventTypes if not eventTypes: continue item2 = ImageMenuItem() item2.set_label(group.title) ## image = gtk.Image() if group.icon: image.set_from_file(group.icon) else: image.set_from_pixbuf(newColorCheckPixbuf(group.color, 20, True)) item2.set_image(image) ## if len(eventTypes)==1: item2.connect('activate', self.addToGroupFromMenu, group, eventTypes[0]) else: menu3 = gtk.Menu() for eventType in eventTypes: eventClass = event_lib.classes.event.byName[eventType] item3 = ImageMenuItem() item3.set_label(eventClass.desc) icon = eventClass.getDefaultIcon() if icon: item3.set_image(imageFromFile(icon)) item3.connect('activate', self.addToGroupFromMenu, group, eventType) menu3.add(item3) menu3.show_all() item2.set_submenu(menu3) menu2.add(item2) ## menu2.show_all() addToItem.set_submenu(menu2) return addToItem def menuCellPopup(self, widget, etime, x, y): menu = gtk.Menu() #### menu.add(labelStockMenuItem('_Copy Date', gtk.STOCK_COPY, self.copyDate)) menu.add(labelStockMenuItem('Day Info', gtk.STOCK_INFO, self.dayInfoShow)) menu.add(self.getEventAddToMenuItem()) menu.add(gtk.SeparatorMenuItem()) menu.add(labelStockMenuItem('Select _Today', gtk.STOCK_HOME, self.goToday)) menu.add(labelStockMenuItem('Select _Date...', gtk.STOCK_INDEX, self.selectDateShow)) if widget._name in ('weekCal', 'monthCal'): menu.add(labelStockMenuItem( 'Switch to ' + ('Month Calendar' if widget._name=='weekCal' else 'Week Calendar'), gtk.STOCK_REDO, self.switchWcalMcal, )) if os.path.isfile('/usr/bin/evolution'):##?????????????????? menu.add(labelImageMenuItem('In E_volution', 'evolution-18.png', ui.dayOpenEvolution)) #if os.path.isfile('/usr/bin/sunbird'):##?????????????????? # menu.add(labelImageMenuItem('In _Sunbird', 'sunbird-18.png', ui.dayOpenSunbird)) #### moreMenu = gtk.Menu() moreMenu.add(labelStockMenuItem('_Customize', gtk.STOCK_EDIT, self.customizeShow)) moreMenu.add(labelStockMenuItem('_Preferences', gtk.STOCK_PREFERENCES, self.prefShow)) moreMenu.add(labelStockMenuItem('_Event Manager', gtk.STOCK_ADD, self.eventManShow)) moreMenu.add(labelImageMenuItem('Time Line', 'timeline-18.png', self.timeLineShow)) #moreMenu.add(labelImageMenuItem('Week Calendar', 'weekcal-18.png', self.weekCalShow)) moreMenu.add(labelStockMenuItem(_('Export to %s')%'HTML', gtk.STOCK_CONVERT, self.exportClicked)) moreMenu.add(labelStockMenuItem('_About', gtk.STOCK_ABOUT, self.aboutShow)) if self.statusIconMode!=1: moreMenu.add(labelStockMenuItem('_Quit', gtk.STOCK_QUIT, self.quit)) ## moreMenu.show_all() moreItem = MenuItem(_('More')) moreItem.set_submenu(moreMenu) #moreItem.show_all() menu.add(moreItem) #### menu.show_all() dx, dy = widget.translate_coordinates(self, x, y) foo, wx, wy = self.get_window().get_origin() x = wx+dx y = wy+dy if rtl: x -= get_menu_width(menu) #### etime = gtk.get_current_event_time() #print('menuCellPopup', x, y, etime) self.menuCell = menu ## without this line, the menu was not showing up, WTF?!! menu.popup( None, None, lambda *args: (x, y, True), None, 3, etime, ) ui.updateFocusTime() def menuMainCreate(self): if self.menuMain: return menu = gtk.Menu() #### item = ImageMenuItem(_('Resize')) item.set_image(imageFromFile('resize.png')) item.connect('button-press-event', self.startResize) menu.add(item) ####### menu.add(self.checkAbove) menu.add(self.checkSticky) ####### menu.add(labelStockMenuItem('Select _Today', gtk.STOCK_HOME, self.goToday)) menu.add(labelStockMenuItem('Select _Date...', gtk.STOCK_INDEX, self.selectDateShow)) menu.add(labelStockMenuItem('Day Info', gtk.STOCK_INFO, self.dayInfoShow)) menu.add(labelStockMenuItem('_Customize', gtk.STOCK_EDIT, self.customizeShow)) menu.add(labelStockMenuItem('_Preferences', gtk.STOCK_PREFERENCES, self.prefShow)) #menu.add(labelStockMenuItem('_Add Event', gtk.STOCK_ADD, ui.addCustomEvent)) menu.add(labelStockMenuItem('_Event Manager', gtk.STOCK_ADD, self.eventManShow)) menu.add(labelImageMenuItem('Time Line', 'timeline-18.png', self.timeLineShow)) #menu.add(labelImageMenuItem('Week Calendar', 'weekcal-18.png', self.weekCalShow)) menu.add(labelStockMenuItem(_('Export to %s')%'HTML', gtk.STOCK_CONVERT, self.exportClicked)) menu.add(labelStockMenuItem('_About', gtk.STOCK_ABOUT, self.aboutShow)) if self.statusIconMode!=1: menu.add(labelStockMenuItem('_Quit', gtk.STOCK_QUIT, self.quit)) menu.show_all() self.menuMain = menu def menuMainPopup(self, widget, etime, x, y): self.menuMainCreate() if etime == 0: etime = gtk.get_current_event_time() menu = self.menuMain dx, dy = widget.translate_coordinates(self, x, y) foo, wx, wy = self.get_window().get_origin() x = wx+dx y = wy+dy if rtl: x -= get_menu_width(menu) #print('menuMainPopup', x, y, etime) menu.popup( None, None, lambda *args: (x, y, True), None, 3, etime, ) ui.updateFocusTime() def addToGroupFromMenu(self, menu, group, eventType): from scal3.ui_gtk.event.editor import addNewEvent #print('addToGroupFromMenu', group.title, eventType) title = _('Add ') + event_lib.classes.event.byName[eventType].desc event = addNewEvent( group, eventType, useSelectedDate=True, title=title, parent=self, ) if event is None: return ui.eventDiff.add('+', event) self.onConfigChange() def prefUpdateBgColor(self, cal): if ui.prefDialog: ui.prefDialog.colorbBg.set_color(ui.bgColor) #else:## FIXME ui.saveLiveConf() def keepAboveClicked(self, check): act = check.get_active() self.set_keep_above(act) ui.winKeepAbove = act ui.saveLiveConf() def stickyClicked(self, check): if check.get_active(): self.stick() ui.winSticky = True else: self.unstick() ui.winSticky = False ui.saveLiveConf() def copyDate(self, obj=None, event=None): setClipboard(ui.cell.format(ud.dateFormatBin)) def copyDateToday(self, obj=None, event=None): setClipboard(ui.todayCell.format(ud.dateFormatBin)) def copyTime(self, obj=None, event=None): setClipboard(ui.todayCell.format(ud.clockFormatBin, tm=localtime()[3:6])) """ def updateToolbarClock(self): if ui.showDigClockTb: if self.clock==None: from scal3.ui_gtk.mywidgets.clock import FClockLabel self.clock = FClockLabel(ud.clockFormat) pack(self.toolbBox, self.clock) self.clock.show() else: self.clock.format = ud.clockFormat else: if self.clock!=None: self.clock.destroy() self.clock = None def updateStatusIconClock(self, checkStatusIconMode=True): if checkStatusIconMode and self.statusIconMode!=2: return if ui.showDigClockTr: if self.clockTr==None: from scal3.ui_gtk.mywidgets.clock import FClockLabel self.clockTr = FClockLabel(ud.clockFormat) try: pack(self.statusIconHbox, self.clockTr) except AttributeError: self.clockTr.destroy() self.clockTr = None else: self.clockTr.show() else: self.clockTr.format = ud.clockFormat else: if self.clockTr!=None: self.clockTr.destroy() self.clockTr = None """ #weekCalShow = lambda self, obj=None, data=None: openWindow(ui.weekCalWin) def statusIconInit(self): if self.statusIconMode==2: useAppIndicator = ui.useAppIndicator if useAppIndicator: try: import scal3.ui_gtk.starcal_appindicator except (ImportError, ValueError): useAppIndicator = False if useAppIndicator: from scal3.ui_gtk.starcal_appindicator import IndicatorStatusIconWrapper self.sicon = IndicatorStatusIconWrapper(self) else: self.sicon = gtk.StatusIcon() ##self.sicon.set_blinking(True) ## for Alarms ## some problem with gnome-shell #self.sicon.set_name('starcal') ## Warning: g_object_notify: object class `GtkStatusIcon' has no property named `name' self.sicon.set_title(core.APP_DESC) self.sicon.set_visible(True)## is needed ???????? self.sicon.connect('button-press-event', self.statusIconButtonPress) self.sicon.connect('activate', self.statusIconClicked) self.sicon.connect('popup-menu', self.statusIconPopup) #self.sicon.set_from_stock(gtk.STOCK_HOME) else: self.sicon = None getMainWinMenuItem = lambda self: labelMenuItem('Main Window', self.statusIconClicked) getStatusIconPopupItems = lambda self: [ labelStockMenuItem('Copy _Time', gtk.STOCK_COPY, self.copyTime), labelStockMenuItem('Copy _Date', gtk.STOCK_COPY, self.copyDateToday), labelStockMenuItem('Ad_just System Time', gtk.STOCK_PREFERENCES, self.adjustTime), #labelStockMenuItem('_Add Event', gtk.STOCK_ADD, ui.addCustomEvent),## FIXME labelStockMenuItem(_('Export to %s')%'HTML', gtk.STOCK_CONVERT, self.exportClickedStatusIcon), labelStockMenuItem('_Preferences', gtk.STOCK_PREFERENCES, self.prefShow), labelStockMenuItem('_Customize', gtk.STOCK_EDIT, self.customizeShow), labelStockMenuItem('_Event Manager', gtk.STOCK_ADD, self.eventManShow), labelImageMenuItem('Time Line', 'timeline-18.png', self.timeLineShow), labelStockMenuItem('_About', gtk.STOCK_ABOUT, self.aboutShow), gtk.SeparatorMenuItem(), labelStockMenuItem('_Quit', gtk.STOCK_QUIT, self.quit), ] def statusIconPopup(self, sicon, button, etime): menu = gtk.Menu() if os.sep == '\\': from scal3.ui_gtk.windows import setupMenuHideOnLeave setupMenuHideOnLeave(menu) items = self.getStatusIconPopupItems() # items.insert(0, self.getMainWinMenuItem())## FIXME geo = self.sicon.get_geometry() ## Returns None on windows, why??? if geo is None:## windows, taskbar is on buttom(below) items.reverse() get_pos_func = None else: #print(dir(geo)) y1 = geo.index(1) try: y = gtk.StatusIcon.position_menu(menu, self.sicon)[1] except TypeError: ## new gi versions y = gtk.StatusIcon.position_menu(menu, 0, 0, self.sicon)[1] if y<y1:## taskbar is on bottom items.reverse() get_pos_func = gtk.StatusIcon.position_menu for item in items: menu.add(item) menu.show_all() #print('statusIconPopup', button, etime) menu.popup(None, None, get_pos_func, self.sicon, button, etime) #self.sicon.do_popup_menu(self.sicon, button, etime) ui.updateFocusTime() self.sicon.menu = menu ## to prevent gurbage collected def onCurrentDateChange(self, gdate): self.statusIconUpdate(gdate=gdate) def getStatusIconTooltip(self): ##tt = core.weekDayName[core.getWeekDay(*ddate)] tt = core.weekDayName[core.jwday(ui.todayCell.jd)] #if ui.pluginsTextStatusIcon:##????????? # sep = _(',')+' ' #else: sep = '\n' for mode in calTypes.active: y, m, d = ui.todayCell.dates[mode] tt += '%s%s %s %s'%(sep, _(d), locale_man.getMonthName(mode, m, y), _(y)) if ui.pluginsTextStatusIcon: text = ui.todayCell.pluginsText if text!='': tt += '\n\n%s'%text ## .replace('\t', '\n') ## FIXME for item in ui.todayCell.eventsData: if not item['showInStatusIcon']: continue itemS = '' if item['time']: itemS += item['time'] + ' - ' itemS += item['text'][0] tt += '\n\n%s'%itemS return tt def statusIconUpdateIcon(self, ddate):## FIXME from scal3.utils import toBytes imagePath = ui.statusIconImageHoli if ui.todayCell.holiday else ui.statusIconImage ext = os.path.splitext(imagePath)[1][1:].lower() loader = GdkPixbuf.PixbufLoader.new_with_type(ext) if ui.statusIconFixedSizeEnable: try: width, height = ui.statusIconFixedSizeWH loader.set_size(width, height) except: myRaise() data = open(imagePath, 'rb').read() if ext == 'svg': dayNum = locale_man.numEncode( ddate[2], mode=calTypes.primary, # FIXME ) if ui.statusIconFontFamilyEnable: if ui.statusIconFontFamily: family = ui.statusIconFontFamily else: family = ui.getFont()[0] dayNum = '<tspan style="font-family:%s">%s</tspan>'%(family, dayNum) data = data.replace( b'TX', toBytes(dayNum), ) loader.write(data) loader.close() pixbuf = loader.get_pixbuf() self.sicon.set_from_pixbuf(pixbuf) def statusIconUpdateTooltip(self): set_tooltip(self.sicon, self.getStatusIconTooltip()) def statusIconUpdate(self, gdate=None, checkStatusIconMode=True): if checkStatusIconMode and self.statusIconMode < 1: return if gdate is None: gdate = localtime()[:3] if calTypes.primary==core.DATE_GREG: ddate = gdate else: ddate = core.convert(gdate[0], gdate[1], gdate[2], core.DATE_GREG, calTypes.primary) ####### self.sicon.set_from_file(join(pixDir, 'starcal-24.png')) self.statusIconUpdateIcon(ddate) ####### self.statusIconUpdateTooltip() return True def statusIconButtonPress(self, obj, gevent): if gevent.button == 2: ## middle button press self.copyDate() return True def statusIconClicked(self, obj=None): if self.get_property('visible'): #ui.winX, ui.winY = self.get_position()## FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) self.hide() else: self.move(ui.winX, ui.winY) ## every calling of .hide() and .present(), makes dialog not on top ## (forgets being on top) act = self.checkAbove.get_active() self.set_keep_above(act) if self.checkSticky.get_active(): self.stick() self.deiconify() self.present() def onDeleteEvent(self, widget=None, event=None): #ui.winX, ui.winY = self.get_position()## FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) if self.statusIconMode==0 or not self.sicon: self.quit() elif self.statusIconMode>1: if self.sicon.is_embedded(): self.hide() else: self.quit() return True def onEscape(self): #ui.winX, ui.winY = self.get_position()## FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) if self.statusIconMode==0: self.quit() elif self.statusIconMode>1: if self.sicon.is_embedded(): self.hide() def quit(self, widget=None, event=None): try: ui.saveLiveConf() except: myRaise() if self.statusIconMode>1 and self.sicon: self.sicon.set_visible(False) ## needed for windows ## before or after main_quit ? self.destroy() ###### core.stopRunningThreads() ###### return gtk.main_quit() def adjustTime(self, widget=None, event=None): from subprocess import Popen Popen(ud.adjustTimeCmd) def aboutShow(self, obj=None, data=None): if not self.aboutDialog: from scal3.ui_gtk.about import AboutDialog dialog = AboutDialog( name=core.APP_DESC, version=core.VERSION, title=_('About ')+core.APP_DESC, authors=[_(line) for line in open(join(rootDir, 'authors-dialog')).read().splitlines()], comments=core.aboutText, license=core.licenseText, website=core.homePage, parent=self, ) ## add Donate button ## FIXME dialog.connect('delete-event', self.aboutHide) dialog.connect('response', self.aboutHide) #dialog.set_logo(GdkPixbuf.Pixbuf.new_from_file(ui.logo)) #dialog.set_skip_taskbar_hint(True) self.aboutDialog = dialog openWindow(self.aboutDialog) def aboutHide(self, widget, arg=None):## arg maybe an event, or response id self.aboutDialog.hide() return True def prefShow(self, obj=None, data=None): if not ui.prefDialog: from scal3.ui_gtk.preferences import PrefDialog ui.prefDialog = PrefDialog(self.statusIconMode, parent=self) ui.prefDialog.updatePrefGui() openWindow(ui.prefDialog) def eventManCreate(self): checkEventsReadOnly() ## FIXME if not ui.eventManDialog: from scal3.ui_gtk.event.manager import EventManagerDialog ui.eventManDialog = EventManagerDialog(parent=self) def eventManShow(self, obj=None, data=None): self.eventManCreate() openWindow(ui.eventManDialog) def addCustomEvent(self, obj=None): self.eventManCreate() ui.eventManDialog.addCustomEvent() def timeLineShow(self, obj=None, data=None): if not ui.timeLineWin: from scal3.ui_gtk.timeline import TimeLineWindow ui.timeLineWin = TimeLineWindow() openWindow(ui.timeLineWin) def selectDateShow(self, widget=None): if not self.selectDateDialog: from scal3.ui_gtk.selectdate import SelectDateDialog self.selectDateDialog = SelectDateDialog(parent=self) self.selectDateDialog.connect('response-date', self.selectDateResponse) self.selectDateDialog.show() def dayInfoShow(self, widget=None): if not self.dayInfoDialog: from scal3.ui_gtk.day_info import DayInfoDialog self.dayInfoDialog = DayInfoDialog(parent=self) self.dayInfoDialog.onDateChange() openWindow(self.dayInfoDialog) def customizeDialogCreate(self): if not self.customizeDialog: from scal3.ui_gtk.customize_dialog import CustomizeDialog self.customizeDialog = CustomizeDialog(self.vbox) def switchWcalMcal(self, widget=None): self.customizeDialogCreate() self.vbox.switchWcalMcal(self.customizeDialog) self.customizeDialog.updateTreeEnableChecks() self.customizeDialog.save() def customizeShow(self, obj=None, data=None): self.customizeDialogCreate() openWindow(self.customizeDialog) def exportShow(self, year, month): if not self.exportDialog: from scal3.ui_gtk.export import ExportDialog self.exportDialog = ExportDialog(parent=self) self.exportDialog.showDialog(year, month) def exportClicked(self, widget=None): self.exportShow(ui.cell.year, ui.cell.month) def exportClickedStatusIcon(self, widget=None, event=None): year, month, day = core.getSysDate(calTypes.primary) self.exportShow(year, month) def onConfigChange(self, *a, **kw): ud.BaseCalObj.onConfigChange(self, *a, **kw) #self.set_property('skip-taskbar-hint', not ui.winTaskbar) ## self.set_skip_taskbar_hint ## FIXME ## skip-taskbar-hint need to restart ro be applied #self.updateToolbarClock()## FIXME #self.updateStatusIconClock() self.statusIconUpdate()
class MainWin(gtk.Window, ud.BaseCalObj): _name = "mainWin" desc = _("Main Window") timeout = 1 ## second setMinHeight = lambda self: self.resize(ui.winWidth, 2) #def maximize(self): # pass def __init__(self, statusIconMode=2): #from gi.repository import Gio #self.app = gtk.Application(application_id="apps.starcal") #self.app.register(Gio.Cancellable.new()) #gtk.ApplicationWindow.__init__(self, application=self.app) gtk.Window.__init__(self) self.add_events(gdk.EventMask.ALL_EVENTS_MASK) self.initVars() ud.windowList.appendItem(self) ui.mainWin = self ################## # statusIconMode: # ("none", "none") # ("statusIcon", "normal") # ("applet", "gnome") # ("applet", "kde") ## # 0: none (simple window) # 1: applet # 2: standard status icon self.statusIconMode = statusIconMode ### #ui.eventManDialog = None #ui.timeLineWin = None #ui.yearWheelWin = None ### #ui.weekCalWin = WeekCalWindow() #ud.windowList.appendItem(ui.weekCalWin) ### self.dayInfoDialog = None #print("windowList.items", [item._name for item in ud.windowList.items]) ########### ##self.connect("window-state-event", selfStateEvent) self.set_title("%s %s" % (core.APP_DESC, core.VERSION)) #self.connect("main-show", lambda arg: self.present()) #self.connect("main-hide", lambda arg: self.hide()) self.set_decorated(False) self.set_property("skip-taskbar-hint", not ui.winTaskbar) # self.set_skip_taskbar_hint # FIXME self.set_role("starcal") #self.set_focus_on_map(True)#???????? #self.set_type_hint(gdk.WindowTypeHint.NORMAL) #self.connect("realize", self.onRealize) self.set_default_size(ui.winWidth, 1) try: self.move(ui.winX, ui.winY) except: pass ############################################################# self.connect("focus-in-event", self.focusIn, "Main") self.connect("focus-out-event", self.focusOut, "Main") self.connect("button-press-event", self.buttonPress) self.connect("key-press-event", self.keyPress) self.connect("configure-event", self.configureEvent) ############################################################# """ #self.add_events(gdk.EventMask.VISIBILITY_NOTIFY_MASK) #self.connect("frame-event", show_event) # Compiz does not send configure-event(or any event) when MOVING # window(sends in last point, ## when moving completed) #self.connect("drag-motion", show_event) ud.rootWindow.set_events(... ud.rootWindow.add_filter(self.onRootWinEvent) #self.realize() #gdk.flush() #self.configureEvent(None, None) #self.connect("drag-motion", show_event) ###################### ## ???????????????????????????????????????????????? # when button is down(before button-release-event), # motion-notify-event does not recived! """ ################################################################## self.focus = False #self.focusOutTime = 0 #self.clockTr = None ################################################################## self.winCon = None ############ self.vbox = MainWinVbox() ui.checkMainWinItems() itemsPkg = "scal3.ui_gtk.mainwin_items" for (name, enable) in ui.mainWinItems: #print(name, enable) if enable: try: module = __import__( ".".join([ itemsPkg, name, ]), fromlist=["CalObj"], ) CalObj = module.CalObj except: myRaise() continue item = CalObj() item.enable = enable item.connect("size-allocate", self.childSizeAllocate) #modify_bg_all( # item, # gtk.StateType.NORMAL, # rgbToGdkColor(*ui.bgColor), #) else: desc = mainWinItemsDesc[name] item = DummyCalObj(name, desc, itemsPkg, True) self.vbox.appendItem(item) self.appendItem(self.vbox) self.vbox.show() self.customizeDialog = None ####### self.add(self.vbox) #################### self.isMaximized = False #################### #ui.prefDialog = None self.exportDialog = None self.selectDateDialog = None ############### Building About Dialog self.aboutDialog = None ############### self.menuMain = None ##### check = gtk.CheckMenuItem(label=_("_On Top")) check.set_use_underline(True) check.connect("activate", self.keepAboveClicked) check.set_active(ui.winKeepAbove) self.set_keep_above(ui.winKeepAbove) self.checkAbove = check ##### check = gtk.CheckMenuItem(label=_("_Sticky")) check.set_use_underline(True) check.connect("activate", self.stickyClicked) check.set_active(ui.winSticky) if ui.winSticky: self.stick() self.checkSticky = check ############################################################ self.statusIconInit() listener.dateChange.add(self) #if self.statusIconMode!=1: # timeout_add_seconds(self.timeout, self.statusIconUpdate) ######### self.connect("delete-event", self.onDeleteEvent) ######################################### for plug in core.allPlugList: if plug.external: try: plug.set_dialog(self) except AttributeError: pass ########################### self.onConfigChange() #ud.rootWindow.set_cursor(gdk.Cursor.new(gdk.CursorType.LEFT_PTR)) #def mainWinStateEvent(self, obj, gevent): #print(dir(event)) #print(gevent.new_window_state) #self.event = event def childSizeAllocate(self, cal, req): self.setMinHeight() def selectDateResponse(self, widget, y, m, d): ui.changeDate(y, m, d) self.onDateChange() def keyPress(self, arg, gevent): kname = gdk.keyval_name(gevent.keyval).lower() #print(now(), "MainWin.keyPress", kname) if kname == "escape": self.onEscape() elif kname == "f1": self.aboutShow() elif kname in ("insert", "plus", "kp_add"): self.eventManShow() elif kname in ("q", "arabic_dad"):## FIXME self.quit() else: self.vbox.keyPress(arg, gevent) return True ## FIXME def focusIn(self, widegt, event, data=None): self.focus = True if self.winCon and self.winCon.enable: self.winCon.windowFocusIn() def focusOut(self, widegt, event, data=None): # called 0.0004 sec (max) after focusIn # (if switched between two windows) dt = now() - ui.focusTime #print("focusOut", dt) if dt > 0.05: # FIXME self.focus = False timeout_add(2, self.focusOutDo) def focusOutDo(self): if not self.focus:# and t-self.focusOutTime>0.002: ab = self.checkAbove.get_active() self.set_keep_above(ab) if self.winCon and self.winCon.enable: self.winCon.windowFocusOut() return False """ def checkResize(self, widget, req): if ui.mcalHeight != req.height:# and ui.winWidth == req.width: if req.height == 0: req.height = 1 ui.mcalHeight = req.height """ def configureEvent(self, widget, gevent): wx, wy = self.get_position() maxPosDelta = max( abs(ui.winX - wx), abs(ui.winY - wy), ) #print(wx, wy) ww, wh = self.get_size() #if ui.bgUseDesk and maxPosDelta > 1:## FIXME # self.queue_draw() if self.get_property("visible"): ui.winX, ui.winY = (wx, wy) ui.winWidth = ww liveConfChanged() return False def buttonPress(self, obj, gevent): print("MainWin.buttonPress") b = gevent.button #print("buttonPress", b) if b == 3: self.menuMainCreate() self.menuMain.popup(None, None, None, None, 3, gevent.time) ui.updateFocusTime() elif b == 1: # FIXME: used to cause problems with `ConButton` when using 'pressed' and 'released' signals self.begin_move_drag( gevent.button, int(gevent.x_root), int(gevent.y_root), gevent.time, ) return False def childButtonPress(self, widget, gevent): b = gevent.button #print(dir(gevent)) #foo, x, y, mask = gevent.get_window().get_pointer() #x, y = self.get_pointer() x, y = gevent.x_root, gevent.y_root if b == 1: self.begin_move_drag(gevent.button, x, y, gevent.time) return True elif b == 3: self.menuMainCreate() if rtl: x -= get_menu_width(self.menuMain) self.menuMain.popup( None, None, lambda *args: (x, y, True), None, 3, gevent.time, ) ui.updateFocusTime() return True return False def begin_resize_drag(self, *args): if self.isMaximized: self.isMaximized = False ui.updateFocusTime() return gtk.Window.begin_resize_drag(self, *args) def startResize(self, widget, gevent): if self.menuMain: self.menuMain.hide() self.begin_resize_drag( gdk.WindowEdge.SOUTH_EAST, gevent.button, int(gevent.x_root), int(gevent.y_root), gevent.time, ) return True def changeDate(self, year, month, day): ui.changeDate(year, month, day) self.onDateChange() def goToday(self, obj=None): return self.changeDate(*core.getSysDate(calTypes.primary)) def onDateChange(self, *a, **kw): #print("MainWin.onDateChange") ud.BaseCalObj.onDateChange(self, *a, **kw) #for j in range(len(core.plugIndex)):##???????????????????? # try: # core.allPlugList[core.plugIndex[j]].date_change(*date) # except AttributeError: # pass self.setMinHeight() for j in range(len(core.plugIndex)): try: core.allPlugList[core.plugIndex[j]].date_change_after(*date) except AttributeError: pass #print("Occurence Time: max=%e, avg=%e" % ( # ui.Cell.ocTimeMax, # ui.Cell.ocTimeSum/ui.Cell.ocTimeCount #)) def getEventAddToMenuItem(self): from scal3.ui_gtk.drawing import newColorCheckPixbuf addToItem = labelStockMenuItem("_Add to", gtk.STOCK_ADD) if event_lib.allReadOnly: addToItem.set_sensitive(False) return addToItem menu2 = gtk.Menu() ## for group in ui.eventGroups: if not group.enable: continue if not group.showInCal():## FIXME continue eventTypes = group.acceptsEventTypes if not eventTypes: continue item2 = ImageMenuItem() item2.set_label(group.title) ## image = gtk.Image() if group.icon: image.set_from_file(group.icon) else: image.set_from_pixbuf(newColorCheckPixbuf(group.color, 20, True)) item2.set_image(image) ## if len(eventTypes) == 1: item2.connect("activate", self.addToGroupFromMenu, group, eventTypes[0]) else: menu3 = gtk.Menu() for eventType in eventTypes: eventClass = event_lib.classes.event.byName[eventType] item3 = ImageMenuItem() item3.set_label(eventClass.desc) icon = eventClass.getDefaultIcon() if icon: item3.set_image(imageFromFile(icon)) item3.connect("activate", self.addToGroupFromMenu, group, eventType) menu3.add(item3) menu3.show_all() item2.set_submenu(menu3) menu2.add(item2) ## menu2.show_all() addToItem.set_submenu(menu2) return addToItem def editEventFromMenu(self, item, groupId, eventId): from scal3.ui_gtk.event.editor import EventEditorDialog event = ui.getEvent(groupId, eventId) group = ui.eventGroups[groupId] parent = self event = EventEditorDialog( event, title=_("Edit ") + event.desc, transient_for=parent, ).run() if event is None: return ui.eventDiff.add("e", event) self.onConfigChange() def trimMenuItemLabel(self, s: str, maxLen: int): if len(s) > maxLen-3: s = s[:maxLen-3].rstrip(" ") + "..." return s def addEditEventCellMenuItems(self, menu): if event_lib.allReadOnly: return eventsData = ui.cell.eventsData if not eventsData: return if len(eventsData) < 4: # make it customizable TODO for eData in eventsData: groupId, eventId = eData["ids"] menu.add(labelImageMenuItem( _("Edit") + ": " + self.trimMenuItemLabel(eData["text"][0], 25), eData["icon"], self.editEventFromMenu, groupId, eventId, )) else: subMenu = gtk.Menu() subMenuItem = labelStockMenuItem("_Edit Event", gtk.STOCK_ADD) for eData in eventsData: groupId, eventId = eData["ids"] subMenu.add(labelImageMenuItem( eData["text"][0], eData["icon"], self.editEventFromMenu, groupId, eventId, )) subMenu.show_all() subMenuItem.set_submenu(subMenu) menu.add(subMenuItem) def menuCellPopup(self, widget, etime, x, y): calObjName = widget._name # why private? FIXME # calObjName is in ("weekCal", "monthCal", ...) menu = gtk.Menu() #### for calType in calTypes.active: menu.add(labelStockMenuItem( _("Copy %s Date") % _(calTypes.getDesc(calType)), gtk.STOCK_COPY, self.copyDateGetCallback(calType), calType, )) menu.add(labelStockMenuItem( "Day Info", gtk.STOCK_INFO, self.dayInfoShow, )) menu.add(self.getEventAddToMenuItem()) self.addEditEventCellMenuItems(menu) menu.add(gtk.SeparatorMenuItem()) menu.add(labelStockMenuItem( "Select _Today", gtk.STOCK_HOME, self.goToday, )) menu.add(labelStockMenuItem( "Select _Date...", gtk.STOCK_INDEX, self.selectDateShow, )) if calObjName in ("weekCal", "monthCal"): menu.add(labelStockMenuItem( "Switch to " + ( "Month Calendar" if calObjName == "weekCal" else "Week Calendar" ), gtk.STOCK_REDO, self.switchWcalMcal, )) if os.path.isfile("/usr/bin/evolution"): # FIXME menu.add(labelImageMenuItem( "In E_volution", "evolution-18.png", ui.dayOpenEvolution, )) #if os.path.isfile("/usr/bin/sunbird"): # FIXME # menu.add(labelImageMenuItem( # "In _Sunbird", # "sunbird-18.png", # ui.dayOpenSunbird, #)) #### moreMenu = gtk.Menu() moreMenu.add(labelStockMenuItem( "_Customize", gtk.STOCK_EDIT, self.customizeShow, )) moreMenu.add(labelStockMenuItem( "_Preferences", gtk.STOCK_PREFERENCES, self.prefShow, )) moreMenu.add(labelStockMenuItem( "_Event Manager", gtk.STOCK_ADD, self.eventManShow, )) moreMenu.add(labelImageMenuItem( "Time Line", "timeline-18.png", self.timeLineShow, )) moreMenu.add(labelImageMenuItem( "Year Wheel", "year-wheel-18.png", self.yearWheelShow, )) # icon? FIXME #moreMenu.add(labelImageMenuItem( # "Week Calendar", # "weekcal-18.png", # self.weekCalShow, #)) moreMenu.add(labelStockMenuItem( _("Export to %s") % "HTML", gtk.STOCK_CONVERT, self.exportClicked, )) moreMenu.add(labelStockMenuItem( "_About", gtk.STOCK_ABOUT, self.aboutShow, )) if self.statusIconMode != 1: moreMenu.add(labelStockMenuItem( "_Quit", gtk.STOCK_QUIT, self.quit, )) ## moreMenu.show_all() moreItem = MenuItem(_("More")) moreItem.set_submenu(moreMenu) #moreItem.show_all() menu.add(moreItem) #### menu.show_all() dx, dy = widget.translate_coordinates(self, x, y) foo, wx, wy = self.get_window().get_origin() x = wx + dx y = wy + dy if rtl: x -= get_menu_width(menu) #### etime = gtk.get_current_event_time() #print("menuCellPopup", x, y, etime) self.menuCell = menu # without the above line, the menu is not showing up # some GC-related pygi bug probably menu.popup( None, None, lambda *args: (x, y, True), None, 3, etime, ) ui.updateFocusTime() def menuMainCreate(self): if self.menuMain: return menu = gtk.Menu() #### item = ImageMenuItem(_("Resize")) item.set_image(imageFromFile("resize.png")) item.connect("button-press-event", self.startResize) menu.add(item) ####### menu.add(self.checkAbove) menu.add(self.checkSticky) ####### menu.add(labelStockMenuItem( "Select _Today", gtk.STOCK_HOME, self.goToday, )) menu.add(labelStockMenuItem( "Select _Date...", gtk.STOCK_INDEX, self.selectDateShow, )) menu.add(labelStockMenuItem( "Day Info", gtk.STOCK_INFO, self.dayInfoShow, )) menu.add(labelStockMenuItem( "_Customize", gtk.STOCK_EDIT, self.customizeShow, )) menu.add(labelStockMenuItem( "_Preferences", gtk.STOCK_PREFERENCES, self.prefShow, )) #menu.add(labelStockMenuItem( # "_Add Event", # gtk.STOCK_ADD, # ui.addCustomEvent, #)) #menu.add(labelStockMenuItem( # "_Event Manager", # gtk.STOCK_ADD, # self.eventManShow, #)) menu.add(labelImageMenuItem( "Time Line", "timeline-18.png", self.timeLineShow, )) menu.add(labelImageMenuItem( "Year Wheel", "year-wheel-18.png", self.yearWheelShow, )) # icon? FIXME #menu.add(labelImageMenuItem( # "Week Calendar", # "weekcal-18.png", # self.weekCalShow, #)) menu.add(labelStockMenuItem( _("Export to %s") % "HTML", gtk.STOCK_CONVERT, self.exportClicked, )) menu.add(labelStockMenuItem( "Ad_just System Time", gtk.STOCK_PREFERENCES, self.adjustTime, )) menu.add(labelStockMenuItem( "_About", gtk.STOCK_ABOUT, self.aboutShow, )) if self.statusIconMode != 1: menu.add(labelStockMenuItem( "_Quit", gtk.STOCK_QUIT, self.quit, )) menu.show_all() self.menuMain = menu def menuMainPopup(self, widget, etime, x, y): self.menuMainCreate() if etime == 0: etime = gtk.get_current_event_time() menu = self.menuMain dx, dy = widget.translate_coordinates(self, x, y) foo, wx, wy = self.get_window().get_origin() x = wx + dx y = wy + dy if rtl: x -= get_menu_width(menu) #print("menuMainPopup", x, y, etime) menu.popup( None, None, lambda *args: (x, y, True), None, 3, etime, ) ui.updateFocusTime() def addToGroupFromMenu(self, menu, group, eventType): from scal3.ui_gtk.event.editor import addNewEvent #print("addToGroupFromMenu", group.title, eventType) title = _("Add ") + event_lib.classes.event.byName[eventType].desc event = addNewEvent( group, eventType, useSelectedDate=True, title=title, transient_for=self, ) if event is None: return ui.eventDiff.add("+", event) self.onConfigChange() def prefUpdateBgColor(self, cal): if ui.prefDialog: ui.prefDialog.colorbBg.set_color(ui.bgColor) #else:## FIXME ui.saveLiveConf() def keepAboveClicked(self, check): act = check.get_active() self.set_keep_above(act) ui.winKeepAbove = act ui.saveLiveConf() def stickyClicked(self, check): if check.get_active(): self.stick() ui.winSticky = True else: self.unstick() ui.winSticky = False ui.saveLiveConf() def copyDate(self, calType: int): setClipboard(ui.cell.format(ud.dateFormatBin, mode=calType)) def copyDateGetCallback(self, calType: int): return lambda obj=None, event=None: setClipboard(ui.cell.format(ud.dateFormatBin, mode=calType)) def copyDateToday(self, obj=None, event=None): setClipboard(ui.todayCell.format(ud.dateFormatBin)) def copyTime(self, obj=None, event=None): setClipboard(ui.todayCell.format( ud.clockFormatBin, tm=localtime()[3:6], )) """ def updateToolbarClock(self): if ui.showDigClockTb: if self.clock is None: from scal3.ui_gtk.mywidgets.clock import FClockLabel self.clock = FClockLabel(ud.clockFormat) pack(self.toolbBox, self.clock) self.clock.show() else: self.clock.format = ud.clockFormat else: if self.clock is not None: self.clock.destroy() self.clock = None def updateStatusIconClock(self, checkStatusIconMode=True): if checkStatusIconMode and self.statusIconMode!=2: return if ui.showDigClockTr: if self.clockTr is None: from scal3.ui_gtk.mywidgets.clock import FClockLabel self.clockTr = FClockLabel(ud.clockFormat) try: pack(self.statusIconHbox, self.clockTr) except AttributeError: self.clockTr.destroy() self.clockTr = None else: self.clockTr.show() else: self.clockTr.format = ud.clockFormat else: if self.clockTr is not None: self.clockTr.destroy() self.clockTr = None """ #def weekCalShow(self, obj=None, data=None): # openWindow(ui.weekCalWin) def statusIconInit(self): if self.statusIconMode == 2: useAppIndicator = ui.useAppIndicator if useAppIndicator: try: import scal3.ui_gtk.starcal_appindicator except (ImportError, ValueError): useAppIndicator = False if useAppIndicator: from scal3.ui_gtk.starcal_appindicator import ( IndicatorStatusIconWrapper, ) self.sicon = IndicatorStatusIconWrapper(self) else: self.sicon = gtk.StatusIcon() ##self.sicon.set_blinking(True) ## ^ for Alarms ## some problem with gnome-shell #self.sicon.set_name("starcal") # Warning: g_object_notify: object class `GtkStatusIcon" # has no property named `name" self.sicon.set_title(core.APP_DESC) self.sicon.set_visible(True) # is needed? self.sicon.connect( "button-press-event", self.statusIconButtonPress, ) self.sicon.connect("activate", self.statusIconClicked) self.sicon.connect("popup-menu", self.statusIconPopup) #self.sicon.set_from_stock(gtk.STOCK_HOME) else: self.sicon = None def getMainWinMenuItem(self): return labelMenuItem("Main Window", self.statusIconClicked) def getStatusIconPopupItems(self): return [ labelStockMenuItem( "Copy _Time", gtk.STOCK_COPY, self.copyTime, ), labelStockMenuItem( "Copy _Date", gtk.STOCK_COPY, self.copyDateToday, ), labelStockMenuItem( "Ad_just System Time", gtk.STOCK_PREFERENCES, self.adjustTime, ), #labelStockMenuItem( # "_Add Event", # gtk.STOCK_ADD, # ui.addCustomEvent, #), # FIXME labelStockMenuItem( _("Export to %s") % "HTML", gtk.STOCK_CONVERT, self.exportClickedStatusIcon, ), labelStockMenuItem( "_Preferences", gtk.STOCK_PREFERENCES, self.prefShow, ), labelStockMenuItem( "_Customize", gtk.STOCK_EDIT, self.customizeShow, ), labelStockMenuItem( "_Event Manager", gtk.STOCK_ADD, self.eventManShow, ), labelImageMenuItem( "Time Line", "timeline-18.png", self.timeLineShow, ), labelImageMenuItem( "Year Wheel", "year-wheel-18.png", self.yearWheelShow, ), # icon? FIXME labelStockMenuItem( "_About", gtk.STOCK_ABOUT, self.aboutShow, ), gtk.SeparatorMenuItem(), labelStockMenuItem( "_Quit", gtk.STOCK_QUIT, self.quit, ), ] def statusIconPopup(self, sicon, button, etime): menu = gtk.Menu() if os.sep == "\\": from scal3.ui_gtk.windows import setupMenuHideOnLeave setupMenuHideOnLeave(menu) items = self.getStatusIconPopupItems() # items.insert(0, self.getMainWinMenuItem())## FIXME get_pos_func = None y1 = 0 geo = self.sicon.get_geometry() ## Previously geo was None on windows, and on Linux it had `geo.index(1)` (not sure about the type) ## Now it's tuple on both Linux and windows if geo is None: items.reverse() elif isinstance(geo, tuple): # geo == (True, screen, area, orientation) y1 = geo[2].y else: y1 = geo.index(1) try: y = gtk.StatusIcon.position_menu(menu, self.sicon)[1] except TypeError: ## new gi versions y = gtk.StatusIcon.position_menu(menu, 0, 0, self.sicon)[1] if y1 > 0 and y < y1: # taskbar is on bottom items.reverse() get_pos_func = gtk.StatusIcon.position_menu for item in items: menu.add(item) menu.show_all() #print("statusIconPopup", button, etime) menu.popup(None, None, get_pos_func, self.sicon, button, etime) #self.sicon.do_popup_menu(self.sicon, button, etime) ui.updateFocusTime() self.sicon.menu = menu ## to prevent gurbage collected def onCurrentDateChange(self, gdate): self.statusIconUpdate(gdate=gdate) def getStatusIconTooltip(self): ##tt = core.weekDayName[core.getWeekDay(*ddate)] tt = core.weekDayName[core.jwday(ui.todayCell.jd)] #if ui.pluginsTextStatusIcon:##????????? # sep = _(",")+" " #else: sep = "\n" for mode in calTypes.active: y, m, d = ui.todayCell.dates[mode] tt += "%s%s %s %s" % ( sep, _(d), locale_man.getMonthName(mode, m, y), _(y), ) if ui.pluginsTextStatusIcon: text = ui.todayCell.pluginsText if text != "": tt += "\n\n%s" % text # .replace("\t", "\n") ## FIXME for item in ui.todayCell.eventsData: if not item["showInStatusIcon"]: continue itemS = "" if item["time"]: itemS += item["time"] + " - " itemS += item["text"][0] tt += "\n\n%s" % itemS return tt def statusIconUpdateIcon(self, ddate): # FIXME from scal3.utils import toBytes imagePath = ( ui.statusIconImageHoli if ui.todayCell.holiday else ui.statusIconImage ) ext = os.path.splitext(imagePath)[1][1:].lower() loader = GdkPixbuf.PixbufLoader.new_with_type(ext) if ui.statusIconFixedSizeEnable: try: width, height = ui.statusIconFixedSizeWH loader.set_size(width, height) except: myRaise() data = open(imagePath, "rb").read() if ext == "svg": dayNum = locale_man.numEncode( ddate[2], mode=calTypes.primary, # FIXME ) if ui.statusIconFontFamilyEnable: if ui.statusIconFontFamily: family = ui.statusIconFontFamily else: family = ui.getFont()[0] dayNum = "<tspan style=\"font-family:%s\">%s</tspan>" % ( family, dayNum, ) data = data.replace( b"TX", toBytes(dayNum), ) loader.write(data) loader.close() pixbuf = loader.get_pixbuf() self.sicon.set_from_pixbuf(pixbuf) def statusIconUpdateTooltip(self): try: sicon = self.sicon except AttributeError: return set_tooltip(sicon, self.getStatusIconTooltip()) def statusIconUpdate(self, gdate=None, checkStatusIconMode=True): if checkStatusIconMode and self.statusIconMode < 1: return if gdate is None: gdate = localtime()[:3] if calTypes.primary == core.DATE_GREG: ddate = gdate else: ddate = core.convert( gdate[0], gdate[1], gdate[2], core.DATE_GREG, calTypes.primary, ) ####### self.sicon.set_from_file(join(pixDir, "starcal-24.png")) self.statusIconUpdateIcon(ddate) ####### self.statusIconUpdateTooltip() return True def statusIconButtonPress(self, obj, gevent): if gevent.button == 2: ## middle button press self.copyDate(calTypes.primary) return True def statusIconClicked(self, obj=None): if self.get_property("visible"): #ui.winX, ui.winY = self.get_position() # ^ FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) self.hide() else: self.move(ui.winX, ui.winY) # every calling of .hide() and .present(), makes dialog not on top # (forgets being on top) act = self.checkAbove.get_active() self.set_keep_above(act) if self.checkSticky.get_active(): self.stick() self.deiconify() self.present() def onDeleteEvent(self, widget=None, event=None): #ui.winX, ui.winY = self.get_position() # ^ FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) if self.statusIconMode == 0 or not self.sicon: self.quit() elif self.statusIconMode > 1: if self.sicon.is_embedded(): self.hide() else: self.quit() return True def onEscape(self): #ui.winX, ui.winY = self.get_position() # ^ FIXME gives bad position sometimes #liveConfChanged() #print(ui.winX, ui.winY) if self.statusIconMode == 0: self.quit() elif self.statusIconMode > 1: if self.sicon.is_embedded(): self.hide() def quit(self, widget=None, event=None): try: ui.saveLiveConf() except: myRaise() if self.statusIconMode > 1 and self.sicon: self.sicon.set_visible(False) # ^ needed for windows. before or after main_quit ? self.destroy() ###### core.stopRunningThreads() ###### return gtk.main_quit() def adjustTime(self, widget=None, event=None): from subprocess import Popen if not ud.adjustTimeCmd: showError("Failed to find gksudo, kdesudo, gksu, gnomesu, kdesu or any askpass program to use with sudo") return Popen(ud.adjustTimeCmd, env=ud.adjustTimeEnv) def aboutShow(self, obj=None, data=None): if not self.aboutDialog: from scal3.ui_gtk.about import AboutDialog with open( join(rootDir, "authors-dialog"), encoding="utf-8", ) as authorsFile: authors = authorsFile.read().splitlines() dialog = AboutDialog( name=core.APP_DESC, version=core.VERSION, title=_("About ") + core.APP_DESC, authors=[ _(author) for author in authors ], comments=core.aboutText, license=core.licenseText, website=core.homePage, transient_for=self, ) # add Donate button, FIXME dialog.connect("delete-event", self.aboutHide) dialog.connect("response", self.aboutHide) #dialog.set_logo(GdkPixbuf.Pixbuf.new_from_file(ui.logo)) #dialog.set_skip_taskbar_hint(True) self.aboutDialog = dialog openWindow(self.aboutDialog) def aboutHide(self, widget, arg=None): # arg maybe an event, or response id self.aboutDialog.hide() return True def prefShow(self, obj=None, data=None): if not ui.prefDialog: from scal3.ui_gtk.preferences import PrefDialog ui.prefDialog = PrefDialog(self.statusIconMode, transient_for=self) ui.prefDialog.updatePrefGui() openWindow(ui.prefDialog) def eventManCreate(self): checkEventsReadOnly() ## FIXME if not ui.eventManDialog: from scal3.ui_gtk.event.manager import EventManagerDialog ui.eventManDialog = EventManagerDialog(transient_for=self) def eventManShow(self, obj=None, data=None): self.eventManCreate() openWindow(ui.eventManDialog) def eventSearchCreate(self): if ui.eventSearchWin is None: from scal3.ui_gtk.event.search_events import EventSearchWindow ui.eventSearchWin = EventSearchWindow() def eventSearchShow(self, obj=None, data=None): self.eventSearchCreate() openWindow(ui.eventSearchWin) def addCustomEvent(self, obj=None): self.eventManCreate() ui.eventManDialog.addCustomEvent() def timeLineShow(self, obj=None, data=None): if not ui.timeLineWin: from scal3.ui_gtk.timeline import TimeLineWindow ui.timeLineWin = TimeLineWindow() openWindow(ui.timeLineWin) def yearWheelShow(self, obj=None, data=None): if not ui.yearWheelWin: from scal3.ui_gtk.year_wheel import YearWheelWindow ui.yearWheelWin = YearWheelWindow() openWindow(ui.yearWheelWin) def selectDateShow(self, widget=None): if not self.selectDateDialog: from scal3.ui_gtk.selectdate import SelectDateDialog self.selectDateDialog = SelectDateDialog(transient_for=self) self.selectDateDialog.connect( "response-date", self.selectDateResponse, ) self.selectDateDialog.show() def dayInfoShow(self, widget=None): if not self.dayInfoDialog: from scal3.ui_gtk.day_info import DayInfoDialog self.dayInfoDialog = DayInfoDialog(transient_for=self) self.dayInfoDialog.onDateChange() openWindow(self.dayInfoDialog) def customizeDialogCreate(self): if not self.customizeDialog: from scal3.ui_gtk.customize_dialog import CustomizeDialog self.customizeDialog = CustomizeDialog(self.vbox, transient_for=self) def switchWcalMcal(self, widget=None): self.customizeDialogCreate() self.vbox.switchWcalMcal(self.customizeDialog) self.customizeDialog.updateTreeEnableChecks() self.customizeDialog.save() def customizeShow(self, obj=None, data=None): self.customizeDialogCreate() openWindow(self.customizeDialog) def exportShow(self, year, month): if not self.exportDialog: from scal3.ui_gtk.export import ExportDialog self.exportDialog = ExportDialog(transient_for=self) self.exportDialog.showDialog(year, month) def exportClicked(self, widget=None): self.exportShow(ui.cell.year, ui.cell.month) def exportClickedStatusIcon(self, widget=None, event=None): year, month, day = core.getSysDate(calTypes.primary) self.exportShow(year, month) def onConfigChange(self, *a, **kw): ud.BaseCalObj.onConfigChange(self, *a, **kw) #self.set_property("skip-taskbar-hint", not ui.winTaskbar) # self.set_skip_taskbar_hint ## FIXME # skip-taskbar-hint need to restart ro be applied #self.updateToolbarClock()## FIXME #self.updateStatusIconClock() self.statusIconUpdate()