Example #1
0
class GUI(wx.Frame):
    '''mfc1.GUI(tna, clock, menu, tbicon)

    GUI of the MindfulClock.
    tna = True, False, start in the taskbar notification area.
    clock = True, False, start clock automatically.
    menu = True, False, show the time not beside te indicator.
    tbicon = True, False, use instead of appindicator wx.TaskBarIcon.

    '''

    def __init__(self, tna, clock, menu, tbicon):
        '''Initalize the wx.Frame.
        timer = wx.Timer

        '''
        # Init public attributes.
        self.init_public_system()
        # Internationalisation
        self.set_in18()
        # Load saved datas.
        self.config_load()
        self.init_public_user()
        # Get frame title, frame size and icon.
        title = self.data.system['frame_title']
        size = self.data.user['frame_size']
        icon = os.path.join(self.mfcdir, self.data.system['icon_name'])
        # Subclass
        super(GUI, self).__init__(None, wx.ID_ANY, title, size=size)
        # Icon
        if icon.endswith('.png'):
            self.SetIcon(wx.Icon(icon, wx.BITMAP_TYPE_PNG))
        # Initalize time interval.
        intervalbox = self.init_interval()
        # Initialize text notification.
        textbox = self.init_text()
        # Initialize Sound notification.
        soundbox = self.init_sound()
        # Ininitialize clock control.
        controlbox = self.init_buttons()
        # wx.Timer
        self.timer = wx.Timer(self, 1)
        self.Bind(wx.EVT_TIMER, self.on_timer, self.timer)
        # Lock file
        self.lock_file()
        # Exit bindings.
        self.Bind(wx.EVT_CLOSE, self.on_system_close)
        # Exit when tbicon is False and __lockstate is 'exit'
        if not tbicon and self.lockstate == 'exit':
            self.Close()
        # Layout
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(intervalbox, 0, wx.EXPAND | wx.ALL, self.bdist)
        vbox.Add(textbox, 1, wx.EXPAND | wx.ALL, self.bdist)
        vbox.Add(soundbox, 0, wx.EXPAND | wx.ALL, self.bdist)
        vbox.Add(controlbox, 0, wx.EXPAND | wx.ALL, self.bdist)
        self.SetSizer(vbox)
        # Disable stop & pause button
        self.btnstop.Enable(False)
        self.btnpause.Enable(False)
        # Taskbar, command line option, checkbox in GUI.
        if tna:
            # Start in the taskbar.
            self.tna = True
        else:
            if self.miniopt.GetValue():
                # Checkbox is set, start in the taskbar.
                self.tna = True
            else:
                # Start normal.
                self.tna = False
        if tbicon:
            # Use wx.TaskBarIcon
            self.init_tbicon()
        else:
            # Use Appindicator
            if menu:
                # Show the time not beside the indicator.
                self.menutime = True
            else:
                # Show the time beside.
                self.menutime = False
            wx.FutureCall(100, self.init_appind)
        # Centre window, show window.
        self.Center()
        # Exit when tbicon is True and __lockstate is 'exit'
        if tbicon and self.lockstate == 'exit':
            self.Close()
        # Check autostart, command line option, check box in GUI.
        if clock:
            # Start clock automatically.
            wx.FutureCall(200, self.clock_start)
        else:
            if self.autostart.GetValue():
                # Checkbox is set, start clock automatically.
                wx.FutureCall(200, self.clock_start)
        if self.tna:
            # Start in the system tray.
            self.Hide()
        else:
            self.Show()

    def clock_pause(self):
        '''Pause the clock.'''
        # stop timer
        self.timer.Stop()
        # Show start icon, hide stop & pause icon
        self.btnstart.Enable(True)
        self.btnstop.Enable(True)
        self.btnpause.Enable(False)
        self.clockstatus = True
        # Read current time, set elapsed seconds
        timenow = int(time.time())
        self.pausetime = timenow - self.start
        # Remaining minutes as text.
        remain = self.get_text_minutes(self.end - timenow)
        remain = '%s (pause)' % remain
        # Taskbar
        if self.tbtype == 'appind':
            # Application indicator
            self.indic.set_menu_stop()
            self.indic.set_menu_continue()
            self.indic.set_remain_time(remain)
        elif self.tbtype == 'tbicon':
            # TaskBarIcon
            self.tbicon.set_menu_stop()
            self.tbicon.set_menu_continue()
            self.tbicon.set_remain_time(remain)

    def clock_start(self):
        '''Start the clock.'''
        # Clock paused ?
        if self.pausetime == -99:
            # No pause, start clock, read interval
            interval = self.get_integer_interval()
            if interval != 'dev':
                # Time interval in seconds
                self.seconds = interval * 60.0
                # Start and end time, UTC in seconds
                self.start = int(time.time())
                self.end = self.start + self.seconds
            else:
                self.seconds = 5.0
                self.start = int(time.time())
                self.end = self.start + self.seconds
            # Status text notification & sound.
            self.textnotif = 'clear'
            self.soundplay = 'clear'
        else:
            # Clock paused, continue.
            timenow = int(time.time())
            self.start = timenow - self.pausetime
            self.end = self.start + self.seconds
            self.pausetime = -99
        # Start timer
        self.timer.Start(self.data.system['wxtimer'])
        # Hide start icon, show stop & pause icon
        self.btnstart.Enable(False)
        self.btnstop.Enable(True)
        self.btnpause.Enable(True)
        self.clockstatus = True
        # Taskbar
        if self.tbtype == 'appind':
            # Application indicator
            self.indic.set_menu_stop()
            self.indic.set_menu_pause()
        elif self.tbtype == 'tbicon':
            # TaskBarIcon
            self.tbicon.set_menu_stop()
            self.tbicon.set_menu_pause()

    def clock_stop(self):
        '''Stop the clock.'''
        # stop timer
        self.timer.Stop()
        # Show start icon, hide stop & pause icon
        self.btnstart.Enable(True)
        self.btnstop.Enable(False)
        self.btnpause.Enable(False)
        self.clockstatus = False
        # No pause
        self.pausetime = -99
        # Gauge
        self.gauge.SetValue(0)
        # Taskbar
        if self.tbtype == 'appind':
            # Application indicator
            self.indic.set_menu_start()
            self.indic.set_menu_pause_clear()
            self.indic.set_remain_time('--:--')
        elif self.tbtype == 'tbicon':
            # TaskBarIcon
            self.tbicon.set_menu_start()
            self.tbicon.set_menu_pause_clear()
            self.tbicon.set_remain_time('--:--')

    def config_load(self):
        '''Load the settings with wx.config.'''
        # Config file
        config = wx.Config(self.data.system['config_file'])
        # Get the default dictionairy as text
        deftextdic = str(self.data.user)
        # Read new text, textdic as default.
        newtextdic = config.Read(key='dic', defaultVal=deftextdic)
        # Set new text as new dictionairy.
        self.data.set_user_textdic(newtextdic)

    def config_save(self):
        '''Save the settings with wx.config.'''
        # Config file
        config = wx.Config(self.data.system['config_file'])
        # Set text notification.
        self.data.user['text'] = self.msgtext.GetValue()
        # Set sound notification.
        self.data.user['sound'] = self.sound
        # Set time interval.
        if self.interval != 'dev':
            self.data.user['interval'] = self.interval
        # Set frame size.
        size = self.GetSize()
        self.data.user['frame_size'] = (size[0], size[1])
        # Set checkbox values.
        self.data.user['mini_opt'] = self.miniopt.GetValue()
        self.data.user['autostart'] = self.autostart.GetValue()
        # Get data dictionariy as text.
        textdic = str(self.data.user)
        # Write text.
        config.Write(key='dic', value=textdic)

    def determine_path(self):
        '''Borrowed from wxglade.py, get the package directory.'''
        try:
            root = __file__
            if os.path.islink(root):
                root = os.path.realpath(root)
            return os.path.dirname(os.path.abspath(root))
        except:
            print('There is no __file__ variable.')

    def get_integer_interval(self):
        '''Convert time interval as text to a integer value.'''
        # Get text from entry.
        text = self.txtinterval.GetValue()
        # Error handling.
        try:
            if text != 'dev':
                interval = int(text)
            else:
                interval = text
        except ValueError:
            interval = self.interval
        # Return integer.
        return(interval)

    def get_pause(self):
        '''Is the clock paused, True of False.'''
        if self.pausetime == -99:
            # Clock not paused.
            status = False
        else:
            # Clock paused.
            status = True
        return(status)

    def get_text_minutes(self, seconds):
        '''Get the seconds in minutes as text, 'mm:ss'.'''
        try:
            mins = int(seconds // 60)
            secs = int(seconds % 60)
        except ValueError:
            mins, secs = 0, 0
        return('%#02d:%#02d' % (mins, secs))

    def init_appind(self):
        '''Create the application indicator. Public objects:
        indic = mfc1.AppIndicator

        '''
        # status of the indicator.
        self.tbtype = 'appind'
        # Application indicator.
        icon = self.data.system['indicator_icon']
        path = os.path.join(self.mfcdir,
                        self.data.system['indicator_path'])
        self.indic = AppIndicator(frame=self,
                                  icon=icon,
                                  path=path,
                                  textdic={'start': _(u'Start'),
                                           'stop': _(u'Stop'),
                                           'show': _(u'Show'),
                                           'hide': _(u'Hide'),
                                           'exit': _(u'Exit'),
                                           'pause': _(u'Pause'),
                                           'cont': _(u'Continue')},
                                  menutime=self.menutime)
        if self.tna:
            # Start in the system tray.
            self.indic.set_menu_show()
        self.indic.main()

    def init_buttons(self):
        '''Create the control buttons. Public widgets:
        btnstart = wx.BitmapButton
        btnstop = wx.BitmapButton
        btnpause = wx.BitmapButton
        gauge = wx.Gauge
        miniopt = wx.CheckBox
        autostart = wx.CheckBox

        '''
        # Title
        t = _(u'Clock control')
        label = wx.StaticText(self, label=t)
        # Start bitmap button.
        icon = os.path.join(self.mfcdir, self.data.system['icon_start'])
        self.btnstart = wx.BitmapButton(self, bitmap=wx.Bitmap(icon))
        self.btnstart.SetToolTip(wx.ToolTip(_(u'Start Clock')))
        # Stop bitmap button.
        icon = os.path.join(self.mfcdir, self.data.system['icon_stop'])
        self.btnstop = wx.BitmapButton(self, bitmap=wx.Bitmap(icon))
        self.btnstop.SetToolTip(wx.ToolTip(_(u'Clock stop')))
        # Pause bitmap button.
        icon = os.path.join(self.mfcdir, self.data.system['icon_pause'])
        self.btnpause = wx.BitmapButton(self, bitmap=wx.Bitmap(icon))
        self.btnpause.SetToolTip(wx.ToolTip(_(u'Clock pause')))
        # Minimize bitmap button.
        icon = os.path.join(self.mfcdir,
                            self.data.system['icon_minimize'])
        minimize = wx.BitmapButton(self, bitmap=wx.Bitmap(icon))
        t = _(u'Minimize to Taskbar Notification Area')
        minimize.SetToolTip(wx.ToolTip(t))
        # Exit bitmap button.
        icon = os.path.join(self.mfcdir, self.data.system['icon_exit'])
        exit_ = wx.BitmapButton(self, bitmap=wx.Bitmap(icon))
        exit_.SetToolTip(wx.ToolTip(_(u'Exit Clock')))
        # Gauge to show the process.
        self.gauge = wx.Gauge(self, range=self.gaugerange)
        # Checkbox options
        t = _(u'Start in the Taskbar Notification Area')
        self.miniopt = wx.CheckBox(self, label=t)
        t = _(u'Automatically start the clock on program startup')
        self.autostart = wx.CheckBox(self, label=t)
        # Set value from user datas.
        if self.data.user['mini_opt']:
            self.miniopt.SetValue(True)
        else:
            self.miniopt.SetValue(False)
        if self.data.user['autostart']:
            self.autostart.SetValue(True)
        else:
            self.autostart.SetValue(False)
        # Bindings.
        self.btnstart.Bind(wx.EVT_BUTTON, self.on_start)
        self.btnstop.Bind(wx.EVT_BUTTON, self.on_stop)
        self.btnpause.Bind(wx.EVT_BUTTON, self.on_pause)
        minimize.Bind(wx.EVT_BUTTON, self.on_minimize)
        exit_.Bind(wx.EVT_BUTTON, self.on_exit)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        vsiz.Add(label, 0, wx.EXPAND | wx.LEFT, self.bdist)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        hsiz.Add(self.btnstart, 0, wx.EXPAND | wx.ALL, self.bdist)
        hsiz.Add(self.btnpause, 0, wx.EXPAND | wx.ALL, self.bdist)
        hsiz.Add(self.btnstop, 0, wx.EXPAND | wx.ALL, self.bdist)
        hsiz.AddStretchSpacer()
        hsiz.Add(minimize, 0, wx.EXPAND | wx.ALL, self.bdist)
        hsiz.Add(exit_, 0, wx.EXPAND | wx.ALL, self.bdist)
        vsiz.Add(hsiz, 1, wx.EXPAND)
        vsiz.Add(self.gauge, 0, wx.EXPAND | wx.ALL, self.bdist)
        vsiz.Add(self.miniopt,
                 0,
                 wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP,
                 self.bdist)
        vsiz.Add(self.autostart,
                 0,
                 wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM,
                 self.bdist)
        return(vsiz)

    def init_interval(self):
        '''Create the time interval widgets. Public widgets:
        txtinterval = wx.TextCtrl

        '''
        # Title
        t = _(u'Time interval in minutes')
        label = wx.StaticText(self, label=t)
        # Text entry: Read default, create entry.
        self.txtinterval = wx.TextCtrl(self, value=str(self.interval))
        # Increase bitmap button.
        icon = os.path.join(self.mfcdir,
                            self.data.system['icon_increase'])
        increase = wx.BitmapButton(self, bitmap=wx.Bitmap(icon))
        increase.SetToolTip(wx.ToolTip(_(u'Increase time')))
        # Decrease bitmap button.
        icon = os.path.join(self.mfcdir,
                            self.data.system['icon_decrease'])
        decrease = wx.BitmapButton(self, bitmap=wx.Bitmap(icon))
        decrease.SetToolTip(wx.ToolTip(_(u'Decrease time')))
        # Bindings.
        increase.Bind(wx.EVT_BUTTON, self.on_increase)
        decrease.Bind(wx.EVT_BUTTON, self.on_decrease)
        self.txtinterval.Bind(wx.EVT_KILL_FOCUS, self.on_interval)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        vsiz.Add(label, 0, wx.EXPAND | wx.LEFT, self.bdist)
        hsiz.Add(self.txtinterval, 1, wx.EXPAND | wx.ALL, self.bdist)
        hsiz.Add(increase, 0, wx.EXPAND | wx.ALL, self.bdist)
        hsiz.Add(decrease, 0, wx.EXPAND | wx.ALL, self.bdist)
        vsiz.Add(hsiz, 1, wx.EXPAND)
        return(vsiz)

    def init_public_system(self):
        '''Initialize public system attributes.
        data = Data object, mfc1.Data()
        mfcdir = Path of the package mfc1, string.
        bstyl = GUI border style, wx.BORDER.
        bdist = GUI distance between widgets, integer.
        clockstatus = Clock is running, True or False.
        tbtype = Type of Taskbar Notification, string.
            'appind' = application indicator
            'tbicon' = taskbaricon
            '' = no taskbar started.
        textnotif = Status of the text notification, string.
            'show' message on the screen
            'close' message closed,
            'clear' since the clock is running no message showed.
        playsound = Status of the sound message, string.
            'clear' = since the clock is running no sound played,
            'close' = sound finished.,
            'play-sound' = play wav or ogg
            'play-music' = play mp3
        pausetime >= 0:   clock is paused, elapsed time.
                  == -99: clock is not paused.

        '''
        self.data = Data()
        self.mfcdir = self.determine_path()
        # bstyl
        bstyl = self.data.system['gui_borderstyle']
        guiborders = {'simple': wx.SIMPLE_BORDER,
                      'raised': wx.RAISED_BORDER,
                      'sunken': wx.SUNKEN_BORDER,
                      'no': wx.NO_BORDER}
        if bstyl in guiborders:
            self.bstyl = guiborders[bstyl]
        else:
            self.bstyl = wx.SIMPLE_BORDER
        # bdist
        self.bdist = self.data.system['gui_borderdist']
        # gaugerange, clockstatus, tbtype.
        self.gaugerange = self.data.system['gauge']
        self.clockstatus = False
        self.tbtype = ''
        # textnotif, soundplay, pausetime.
        self.textnotif = 'clear'
        self.soundplay = 'clear'
        self.pausetime = -99

    def init_public_user(self):
        '''Initialize public user datas.
        interval = Interval in seconds, integer.
        sound = Path to sound, music, file, string.

        '''
        self.interval = self.data.user['interval']
        s = self.data.user['sound']
        if s:
            self.sound = os.path.join(self.mfcdir, s)
        else:
            self.sound = ''

    def init_sound(self):
        '''Create the sound notification widgets. Public objects:
        msgsound = wx.TextCtrl

        '''
        # Title
        t = _(u'Sound notification')
        label = wx.StaticText(self, label=t)
        # Sound change button
        icon = os.path.join(self.mfcdir,
                            self.data.system['icon_change'])
        change = wx.BitmapButton(self, bitmap=wx.Bitmap(icon))
        change.SetToolTip(wx.ToolTip(_(u'Change sound file')))
        # Sound preview button
        icon = os.path.join(self.mfcdir,
                            self.data.system['icon_preview'])
        preview = wx.BitmapButton(self, bitmap=wx.Bitmap(icon))
        preview.SetToolTip(wx.ToolTip(_(u'Preview sound')))
        # Text entry, read defaults
        self.msgsound = wx.TextCtrl(self, value=self.sound)
        # Bindings
        change.Bind(wx.EVT_BUTTON, self.on_change)
        preview.Bind(wx.EVT_BUTTON, self.on_preview)
        self.msgsound.Bind(wx.EVT_KILL_FOCUS, self.on_msgsound)
        # Layout
        vsiz = wx.BoxSizer(wx.VERTICAL)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        vsiz.Add(label, 0, wx.EXPAND | wx.LEFT, self.bdist)
        hsiz.Add(self.msgsound, 1, wx.EXPAND | wx.ALL, self.bdist)
        hsiz.Add(change, 0, wx.EXPAND | wx.ALL, self.bdist)
        hsiz.Add(preview, 0, wx.EXPAND | wx.ALL, self.bdist)
        vsiz.Add(hsiz, 1, wx.EXPAND)
        return(vsiz)

    def init_tbicon(self):
        '''Create the wx.TaskBarIcon. Public objects:
        tbicon = mfc1.TBIcon

        '''
        self.tbtype = 'tbicon'
        # TaskbarIcon
        icon = os.path.join(self.mfcdir,
                            self.data.system['tna_icon'])
        title = self.data.system['frame_title']
        self.tbicon = TBIcon(frame=self,
                             icon=icon,
                             title=title,
                             textdic={'start': _(u'Start'),
                                      'stop': _(u'Stop'),
                                      'show': _(u'Show'),
                                      'hide': _(u'Hide'),
                                      'exit': _(u'Exit'),
                                      'pause': _(u'Pause'),
                                      'cont': _(u'Continue')})
        if self.tna:
            # Start in the system tray.
            self.tbicon.set_menu_show()

    def init_text(self):
        '''Create the text notification widgets. Public widgets:
        msgtext = wx.TextCtrl

        '''
        # Title
        t = _(u'Text notification')
        label = wx.StaticText(self, label=t)
        # Text entry, read default, create entry.
        t = self.data.user['text']
        self.msgtext = wx.TextCtrl(self,
                                     value=t,
                                     style=wx.TE_MULTILINE)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        vsiz.Add(label, 0, wx.EXPAND | wx.LEFT, self.bdist)
        vsiz.Add(self.msgtext, 1, wx.EXPAND | wx.ALL, self.bdist)
        return(vsiz)

    def lock_file(self):
        '''Handle the mc1.Lock object. Public objects:
        lock = mfc1.Lock
        lockstate = Status of the lock file.
                    '' = No status.
                    'written' = Lock file is written
                    'deleted' = Lock file is deleted
                    'exit' = Program exit

        '''
        userid = wx.GetUserId()
        wxpath = wx.StandardPaths.Get()
        userdir = wxpath.GetDocumentsDir()
        self.lock = Lock(path=userdir, userid=userid)
        self.lockstate = ''
        if self.lock.one_instance('mindfulclock1'):
            # One instance.
            self.lock.write_lock()
            self.lockstate = 'written'
        else:
            # More than one instance.
            if self.start_question():
                # Start the clock.
                self.lock.write_lock()
                self.lockstate = 'written'
            else:
                # Exit the program.
                self.lockstate = 'exit'

    def on_change(self, event):
        '''Event for button, change sound file.'''
        # Set filename, directory path, wildcards and title.
        t = _(u'file')
        w1 = 'OGG- %s (*.ogg)|*.ogg' % (t)
        w2 = 'MP3- %s (*.mp3)|*.mp3' % (t)
        w3 = 'WAV- %s (*.wav)|*.wav' % (t)
        #~ wcard =
        # Show open dialog, get user datas.
        dlg = wx.FileDialog(self,
                            _(u'Select the sound file'),
                            os.path.dirname(self.sound),
                            os.path.basename(self.sound),
                            '%s|%s|%s' % (w1, w2, w3),
                            wx.FD_OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            # Clicked ok, set path, destroy dialog.
            path = dlg.GetPath()
            dlg.Destroy()
            # Set path to text entry and sound attribute.
            self.sound = path
            self.msgsound.SetValue(path)
            self.msgsound.SetInsertionPointEnd()
        else:
            # Not clicked ok, destroy dialog.
            dlg.Destroy()

    def on_decrease(self, event):
        '''Event for bitmap button, decrease time interval.'''
        # Get interval as integer.
        interval = self.get_integer_interval()
        # decrease interval and set it to the text entry.
        self.set_integer_interval(interval - 1)

    def on_exit(self, event):
        '''Event for button, exit program.'''
        self.Close()

    def on_increase(self, event):
        '''Event for bitmap button, increase time interval.'''
        # Get interval as integer.
        interval = self.get_integer_interval()
        # decrease interval and set it to the text entry.
        self.set_integer_interval(interval + 1)

    def on_interval(self, event):
        '''Event for text control, check time interval.'''
        # Get interval as integer.
        interval = self.get_integer_interval()
        # Set interval to the text entry.
        self.set_integer_interval(interval)

    def on_minimize(self, event):
        '''Event for button, minimize frame.'''
        if self.IsShown():
            self.Hide()
            if self.tbtype == 'appind':
                # Application indicator
                self.indic.set_menu_show()
            elif self.tbtype == 'tbicon':
                # wx.TaskBarIcon
                self.tbicon.set_menu_show()

    def on_msgsound(self, event):
        '''Event for text control, check path to sound file.'''
        # Get text from entry.
        text = self.msgsound.GetValue()
        if text:
            # Text is set, check path
            if not os.path.exists(text):
                self.msgsound.SetValue(self.sound)
            else:
                self.sound = text
        else:
            # Text is not set.
            self.sound = ''

    def on_pause(self, event):
        '''Event for button, pause the clock.'''
        self.clock_pause()

    def on_preview(self, event):
        '''Event for button, preview sound file.'''
        self.pygame_sound(True)

    def on_start(self, event):
        '''Event for button, start the clock.'''
        self.config_save()
        self.clock_start()

    def on_stop(self, event):
        '''Event for button, stop the clock.'''
        self.clock_stop()

    def on_system_close(self, event):
        '''Event before close the frame.'''
        if self.lockstate == 'written':
            # Normal program start, normal program end,
            # delete lock file.
            self.lock.delete_lock()
            self.lockstate = 'deleted'
        # Close the taksbar or the indicator.
        if self.tbtype == 'appind':
            # Application indicator
            self.indic.quit_()
        elif self.tbtype == 'tbicon':
            # TaskBarIcon
            self.tbicon.Destroy()
        # Save the settings
        self.config_save()
        self.Destroy()

    def on_timer(self, event):
        '''Event for timer, the MindfulClock.'''
        timenow = int(time.time())
        if self.textnotif == 'close' and self.soundplay == 'close':
            # Text message & sound closed, start new interval.
            self.start = timenow
            self.end = self.start + self.seconds
            self.gauge.SetValue(0)
            # Remaining minutes as text.
            remain = self.get_text_minutes(self.seconds)
            # Set text notification & sound clear.
            self.textnotif = 'clear'
            self.soundplay = 'clear'
        elif self.textnotif == 'clear' and \
             self.soundplay == 'clear' and timenow < self.end:
            # End is not reached.
            progress = timenow - self.start + 1
            value = (self.gaugerange / self.seconds) * progress
            self.gauge.SetValue(value)
            # Remaining minutes as text.
            remain = self.get_text_minutes(self.end - timenow)
        elif self.textnotif == 'clear' and \
             self.soundplay == 'clear' and timenow >= self.end:
            # Play sound.
            self.pygame_sound(False)
            # Show text.
            self.show_popup()
        if self.textnotif == 'clear' and self.soundplay == 'clear':
            # Taskbar
            if self.tbtype == 'appind':
                # Application indicator
                self.indic.set_remain_time(remain)
            elif self.tbtype == 'tbicon':
                # wx.TaskBarIcon
                self.tbicon.set_remain_time(remain)
        elif self.textnotif == 'show' or \
             self.soundplay.startswith('play'):
            # Taskbar
            if self.tbtype == 'appind':
                # Application indicator
                self.indic.set_remain_time('..')
            elif self.tbtype == 'tbicon':
                # wx.TaskBarIcon
                self.tbicon.set_remain_time('..')
        # Check sound.
        if self.soundplay == 'play-sound':
            # wav or ogg
            if not pygame.mixer.get_busy():
                self.soundplay = 'close'
        elif self.soundplay == 'play-music':
            # mp3
            if not pygame.mixer.music.get_busy():
                self.soundplay = 'close'

    def pygame_sound(self, preview):
        '''Play the 'soundfile' with Pygame, preview= True or False.'''
        # preview = False: Clock stop while playing sound or music.
        # preview = True: No interrupt of the clock.
        if self.sound:
            # Soundfile is set, play sound.
            if self.sound.endswith('.wav') or \
               self.sound.endswith('.ogg'):
                mixer = pygame.mixer.Sound(self.sound)
                mixer.play()
                if not preview:
                    self.soundplay = 'play-sound'
            elif self.sound.endswith('.mp3'):
                pygame.mixer.music.load(self.sound)
                pygame.mixer.music.play()
                if not preview:
                    self.soundplay = 'play-music'
        else:
            # No sound, set __soundplay 'close'.
            self.soundplay = 'close'


    def set_integer_interval(self, interval):
        '''Control value of time interval and set it to the entry.'''
        # Check interval
        if interval != 'dev':
            minimum = self.data.system['min_interval']
            maximum = self.data.system['max_interval']
            if interval < minimum:
                interval = minimum
            elif interval > maximum:
                interval = maximum
            self.txtinterval.SetValue(str(interval))
            # Set current value as new default value.
            self.interval = interval

    def start_question(self):
        '''Show Question, run mfc again?, return True or False.'''
        t1 = _(u'It seems the MindfulClock is running.')
        t2 = _(u'Do you want to start the clock anyway?')
        style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION
        dlg = wx.MessageDialog(None,
                               '%s %s' %(t1, t2),
                               _(u'Start control'),
                               style)
        answer = dlg.ShowModal()
        if answer == wx.ID_NO:
            # Do not overwrite, return None
            status = False
        else:
            # Overwrite, return 'path'
            status = True
        return(status)

    def set_in18(self):
        '''Set the internationalization.'''
        # Get directory
        dir_ = os.path.join(self.mfcdir, 'locale')
        # Locale, set default language.
        self.wxloc = wx.Locale(wx.LANGUAGE_DEFAULT)
        self.wxloc.AddCatalogLookupPathPrefix(dir_)
        self.wxloc.AddCatalog('mfc1')

    def show_popup(self):
        '''Show the text notification popup.'''
        text = self.msgtext.GetValue()
        if text:
            # Text is set, show dialog.  Status of text notification.
            self.textnotif = 'show'
            font = self.data.system['msg_font']
            colors = self.data.system['popup_colors']
            icon = os.path.join(self.mfcdir,
                               self.data.system['icon_close'])
            popup = Popup(parent=self,
                      style=self.bdist,
                      text=text,
                      font=font,
                      colors=colors,
                      icon=icon)
            popw, poph = popup.size
            dispw, disph = wx.GetDisplaySize()
            offx = (dispw - popw) / 2
            offy = (disph - poph) / 2
            popup.Position(ptOrigin=(0, 0), size=(offx, offy))
            popup.Popup()
        else:
            # No text, no Popup, set __textnotif 'close'.
            self.textnotif = 'close'
Example #2
0
class GUI(wx.Frame):
    """mfc1.GUI(tna, clock, menu, tbicon)

    GUI of the MindfulClock.
    tna = True, False, start in the taskbar notification area.
    clock = True, False, start clock automatically.
    menu = True, False, show the time not beside te indicator.
    tbicon = True, False, use instead of appindicator wx.TaskBarIcon.

    """

    def __init__(self, tna, clock, menu, tbicon):
        # Data object.
        self.__data = Data()
        # Package directory
        self.__dir = self.determine_path()
        # Internationalisation
        self.set_in18()
        # Load saved datas.
        self.config_load()
        # Get frame title, frame size and icon.
        title = self.__data.get_sys("frame_title")
        size = self.__data.get_user("frame_size")
        icon = os.path.join(self.__dir, self.__data.get_sys("icon_name"))
        # Subclass
        wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title=title, size=size)
        # Lock file
        userid = wx.GetUserId()
        wxpath = wx.StandardPaths.Get()
        userdir = wxpath.GetDocumentsDir()
        self.__lock = Lock(path=userdir, userid=userid)
        self.__lockwrite = False
        if self.__lock.is_lock():
            # Lock file exist.
            if self.start_question():
                # Start the clock.
                self.__lock.write_lock()
                self.__lockwrite = True
            else:
                # Exit the program.
                self.Close()
        else:
            # Lock file don't exist.
            self.__lock.write_lock()
            self.__lockwrite = True
        # Icon
        if icon.endswith(".png"):
            self.SetIcon(wx.Icon(name=icon, type=wx.BITMAP_TYPE_PNG))
        # GUI border style and distance between widgets.
        bstyl = self.__data.get_sys("gui_borderstyle")
        guiborders = {
            "simple": wx.SIMPLE_BORDER,
            "raised": wx.RAISED_BORDER,
            "sunken": wx.SUNKEN_BORDER,
            "no": wx.NO_BORDER,
        }
        if bstyl in guiborders:
            self.__bstyl = guiborders[bstyl]
        else:
            self.__bstyl = wx.SIMPLE_BORDER
        self.__bdist = self.__data.get_sys("gui_borderdist")
        if not self.__bdist:
            self.__bdist = 5
        # Set attributes for time interval and sound file.
        self.__interval = self.__data.get_user("interval")
        self.__sound = os.path.join(self.__dir, self.__data.get_user("sound"))
        # time interval.
        intervalbox = self.init_interval()
        # Text notification.
        textbox = self.init_text()
        # Sound notification.
        soundbox = self.init_sound()
        # Clock control.
        controlbox = self.init_buttons()
        # Timer
        self.__timer = wx.Timer(self, 1)
        self.Bind(event=wx.EVT_TIMER, handler=self.on_timer, source=self.__timer)
        # Clock status
        self.__clockstatus = False
        # Exit bindings.
        self.Bind(event=wx.EVT_CLOSE, handler=self.on_system_close)
        # Layout
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(item=intervalbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        vbox.Add(item=textbox, proportion=1, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        vbox.Add(item=soundbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        vbox.Add(item=controlbox, proportion=0, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        self.SetSizer(vbox)
        # Disable stop & pause button
        self.__btnstop.Enable(False)
        self.__btnpause.Enable(False)
        # Clock not paused.
        self.__pausetime = -99
        # System tray from command line options
        if tna:
            # Start in the taskbar.
            self.__tna = True
        else:
            if self.__miniopt.GetValue():
                # Checkbox is set, start in the taskbar.
                self.__tna = True
            else:
                # Start normal.
                self.__tna = False
        if tbicon:
            # Use wx.TaskBarIcon
            self.init_tbicon()
        else:
            # Use Appindicator
            if menu:
                # Show the time not beside the indicator.
                self.__menutime = True
            else:
                # Show the time beside.
                self.__menutime = False
            wx.FutureCall(100, self.init_appind)
        # Centre window, show window.
        self.Center()
        # Check autostart
        if clock:
            # Start clock automatically.
            wx.FutureCall(200, self.clock_start)
        else:
            if self.__autostart.GetValue():
                # Checkbox is set, start clock automatically.
                wx.FutureCall(200, self.clock_start)
        if self.__tna:
            # Start in the system tray.
            self.Hide()
        else:
            self.Show()

    def clock_pause(self):
        """Pause the clock."""
        # stop timer
        self.__timer.Stop()
        # Show start icon, hide stop & pause icon
        self.__btnstart.Enable(True)
        self.__btnstop.Enable(True)
        self.__btnpause.Enable(False)
        self.__clockstatus = True
        # Read current time, set elapsed seconds
        timenow = int(time.time())
        self.__pausetime = timenow - self.__start
        # Remaining minutes as text.
        remain = self.get_text_minutes(self.__end - timenow)
        remain = "%s (pause)" % remain
        # Taskbar
        if self.__indstatus:
            # Application indicator
            self.__ind.set_menu_stop()
            self.__ind.set_menu_continue()
            self.__ind.set_remain_time(remain)
        else:
            # TaskBarIcon
            self.__tbicon.set_menu_stop()
            self.__tbicon.set_menu_continue()
            self.__tbicon.set_remain_time(remain)

    def clock_start(self):
        """Start the clock."""
        # Clock paused ?
        if self.__pausetime == -99:
            # No pause, start clock, read interval
            interval = self.get_integer_interval()
            if interval != "dev":
                # Time interval in seconds
                self.__seconds = interval * 60.0
                # Start and end time, UTC in seconds
                self.__start = int(time.time())
                self.__end = self.__start + self.__seconds
            else:
                self.__seconds = 5.0
                self.__start = int(time.time())
                self.__end = self.__start + self.__seconds
            # Status is text notification shown.
            self.__textnotif = "clear"
        else:
            # Clock paused, continue.
            timenow = int(time.time())
            self.__start = timenow - self.__pausetime
            self.__end = self.__start + self.__seconds
            self.__pausetime = -99
        # Start timer
        self.__timer.Start(self.__data.get_sys("wxtimer"))
        # Hide start icon, show stop & pause icon
        self.__btnstart.Enable(False)
        self.__btnstop.Enable(True)
        self.__btnpause.Enable(True)
        self.__clockstatus = True
        # Taskbar
        if self.__indstatus:
            # Application indicator
            self.__ind.set_menu_stop()
            self.__ind.set_menu_pause()
        else:
            # TaskBarIcon
            self.__tbicon.set_menu_stop()
            self.__tbicon.set_menu_pause()

    def clock_stop(self):
        """Stop the clock."""
        # stop timer
        self.__timer.Stop()
        # Show start icon, hide stop & pause icon
        self.__btnstart.Enable(True)
        self.__btnstop.Enable(False)
        self.__btnpause.Enable(False)
        self.__clockstatus = False
        # No pause
        self.__pausetime = -99
        # Gauge
        self.__gauge.SetValue(0)
        # Taskbar
        if self.__indstatus:
            # Application indicator
            self.__ind.set_menu_start()
            self.__ind.set_menu_pause_clear()
            self.__ind.set_remain_time("--:--")
        else:
            # TaskBarIcon
            self.__tbicon.set_menu_start()
            self.__tbicon.set_menu_pause_clear()
            self.__tbicon.set_remain_time("--:--")

    def config_load(self):
        """Load the settings with wx.config."""
        # Config file
        config = wx.Config(self.__data.get_sys("config_file"))
        # Get the default dictionairy as text
        textdic = self.__data.get_user_textdic()
        # Read text, textdic as default.
        newdic = config.Read(key="dic", defaultVal=textdic)
        # Set text as new dictionairy.
        self.__data.set_user_textdic(newdic)

    def config_save(self):
        """Save the settings with wx.config."""
        # Config file
        config = wx.Config(self.__data.get_sys("config_file"))
        # Set text notification.
        self.__data.set_user("text", self.__msgtext.GetValue())
        # Set sound notification.
        self.__data.set_user("sound", self.__sound)
        # Set time interval.
        if self.__interval != "dev":
            self.__data.set_user("interval", self.__interval)
        # Set frame size.
        size = self.GetSize()
        self.__data.set_user("frame_size", (size[0], size[1]))
        # Set checkbox values.
        self.__data.set_user("mini_opt", self.__miniopt.GetValue())
        self.__data.set_user("autostart", self.__autostart.GetValue())
        # Get data dictionariy as text.
        textdic = self.__data.get_user_textdic()
        # Write text.
        config.Write(key="dic", value=textdic)

    def determine_path(self):
        """Borrowed from wxglade.py, get the package directory."""
        try:
            root = __file__
            if os.path.islink(root):
                root = os.path.realpath(root)
            return os.path.dirname(os.path.abspath(root))
        except:
            print "I am sorry, but something is wrong.  There is no "
            print "__file__ variable. Please contact the author."

    def get_clock(self):
        """Get the status of the clock, True of False."""
        return self.__clockstatus

    def get_integer_interval(self):
        """Convert time interval as text to a integer value."""
        # Get text from entry.
        text = self.__txtinterval.GetValue()
        # Error handling.
        try:
            if text != "dev":
                interval = int(text)
            else:
                interval = text
        except ValueError:
            interval = self.__interval
        # Return integer.
        return interval

    def get_pause(self):
        """Is the clock paused, True of False."""
        if self.__pausetime == -99:
            # Clock not paused.
            status = False
        else:
            # Clock paused.
            status = True
        return status

    def get_text_minutes(self, seconds):
        """Get the seconds in minutes as text, 'mm:ss'."""
        try:
            mins = int(seconds // 60)
            secs = int(seconds % 60)
        except ValueError:
            mins, secs = 0, 0
        return "%#02d:%#02d" % (mins, secs)

    def init_appind(self):
        """Create the application indicator."""
        # status of the indicator.
        self.__indstatus = True
        # Application indicator.
        icon = self.__data.get_sys("indicator_icon")
        path = os.path.join(self.__dir, self.__data.get_sys("indicator_path"))
        self.__ind = AppIndicator(
            frame=self,
            icon=icon,
            path=path,
            textdic={
                "start": _(u"Start"),
                "stop": _(u"Stop"),
                "show": _(u"Show"),
                "hide": _(u"Hide"),
                "exit": _(u"Exit"),
                "pause": _(u"Pause"),
                "cont": _(u"Continue"),
            },
            menutime=self.__menutime,
        )
        if self.__tna:
            # Start in the system tray.
            self.__ind.set_menu_show()
        self.__ind.main()

    def init_buttons(self):
        """Create the control buttons."""
        # Title
        t = _(u"Clock control")
        label = wx.StaticText(parent=self, label=t)
        # Start bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys("icon_start"))
        self.__btnstart = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        self.__btnstart.SetToolTip(wx.ToolTip(_(u"Start Clock")))
        # Stop bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys("icon_stop"))
        self.__btnstop = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        self.__btnstop.SetToolTip(wx.ToolTip(_(u"Clock stop")))
        # Pause bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys("icon_pause"))
        self.__btnpause = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        self.__btnpause.SetToolTip(wx.ToolTip(_(u"Clock pause")))
        # Minimize bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys("icon_minimize"))
        minimize = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        t = _(u"Minimize to Taskbar Notification Area")
        minimize.SetToolTip(wx.ToolTip(t))
        # Exit bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys("icon_exit"))
        exit_ = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        exit_.SetToolTip(wx.ToolTip(_(u"Exit Clock")))
        # Gauge to show the process.
        self.__gaugerange = self.__data.get_sys("gauge")
        self.__gauge = wx.Gauge(parent=self, range=self.__gaugerange)
        # Checkbox options
        t = _(u"Start in the Taskbar Notification Area")
        self.__miniopt = wx.CheckBox(parent=self, label=t)
        t = _(u"Automatically start the clock on program startup")
        self.__autostart = wx.CheckBox(parent=self, label=t)
        # Set value from user datas.
        if self.__data.get_user("mini_opt"):
            self.__miniopt.SetValue(True)
        else:
            self.__miniopt.SetValue(False)
        if self.__data.get_user("autostart"):
            self.__autostart.SetValue(True)
        else:
            self.__autostart.SetValue(False)
        # Bindings.
        self.__btnstart.Bind(event=wx.EVT_BUTTON, handler=self.on_start)
        self.__btnstop.Bind(event=wx.EVT_BUTTON, handler=self.on_stop)
        self.__btnpause.Bind(event=wx.EVT_BUTTON, handler=self.on_pause)
        minimize.Bind(event=wx.EVT_BUTTON, handler=self.on_minimize)
        exit_.Bind(event=wx.EVT_BUTTON, handler=self.on_exit)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        vsiz.Add(item=label, flag=wx.EXPAND | wx.LEFT, border=self.__bdist)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        hsiz.Add(item=self.__btnstart, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        hsiz.Add(item=self.__btnpause, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        hsiz.Add(item=self.__btnstop, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        hsiz.AddStretchSpacer()
        hsiz.Add(item=minimize, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        hsiz.Add(item=exit_, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        vsiz.Add(item=hsiz, proportion=1, flag=wx.EXPAND)
        vsiz.Add(item=self.__gauge, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        vsiz.Add(item=self.__miniopt, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, border=self.__bdist)
        vsiz.Add(item=self.__autostart, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.BOTTOM, border=self.__bdist)
        return vsiz

    def init_interval(self):
        """Create the time interval widgets."""
        # Title
        t = _(u"Time interval in minutes")
        label = wx.StaticText(parent=self, label=t)
        # Text entry: Read default, create entry.
        self.__txtinterval = wx.TextCtrl(parent=self, value=str(self.__interval))
        # Increase bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys("icon_increase"))
        increase = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        increase.SetToolTip(wx.ToolTip(_(u"Increase time")))
        # Decrease bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys("icon_decrease"))
        decrease = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        decrease.SetToolTip(wx.ToolTip(_(u"Decrease time")))
        # Bindings.
        increase.Bind(event=wx.EVT_BUTTON, handler=self.on_increase)
        decrease.Bind(event=wx.EVT_BUTTON, handler=self.on_decrease)
        self.__txtinterval.Bind(event=wx.EVT_KILL_FOCUS, handler=self.on_interval)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        vsiz.Add(item=label, flag=wx.EXPAND | wx.LEFT, border=self.__bdist)
        hsiz.Add(item=self.__txtinterval, proportion=1, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        hsiz.Add(item=increase, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        hsiz.Add(item=decrease, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        vsiz.Add(item=hsiz, proportion=1, flag=wx.EXPAND)
        return vsiz

    def init_sound(self):
        """Create the sound notification widgets."""
        # Title
        t = _(u"Sound notification")
        label = wx.StaticText(parent=self, label=t)
        # Sound change button
        icon = os.path.join(self.__dir, self.__data.get_sys("icon_change"))
        change = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        change.SetToolTip(wx.ToolTip(_(u"Change sound file")))
        # Sound preview button
        icon = os.path.join(self.__dir, self.__data.get_sys("icon_preview"))
        preview = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        preview.SetToolTip(wx.ToolTip(_(u"Preview sound")))
        # Text entry, read defaults
        self.__msgsound = wx.TextCtrl(parent=self, value=self.__sound)
        # Bindings
        change.Bind(event=wx.EVT_BUTTON, handler=self.on_change)
        preview.Bind(event=wx.EVT_BUTTON, handler=self.on_preview)
        self.__msgsound.Bind(event=wx.EVT_KILL_FOCUS, handler=self.on_msgsound)
        # Layout
        vsiz = wx.BoxSizer(wx.VERTICAL)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        vsiz.Add(item=label, flag=wx.EXPAND | wx.LEFT, border=self.__bdist)
        hsiz.Add(item=self.__msgsound, proportion=1, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        hsiz.Add(item=change, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        hsiz.Add(item=preview, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        vsiz.Add(item=hsiz, proportion=1, flag=wx.EXPAND)
        return vsiz

    def init_tbicon(self):
        """Create the wx.TaskBarIcon."""
        self.__indstatus = False
        # TaskbarIcon
        icon = os.path.join(self.__dir, self.__data.get_sys("tna_icon"))
        title = self.__data.get_sys("frame_title")
        self.__tbicon = TBIcon(
            frame=self,
            icon=icon,
            title=title,
            textdic={
                "start": _(u"Start"),
                "stop": _(u"Stop"),
                "show": _(u"Show"),
                "hide": _(u"Hide"),
                "exit": _(u"Exit"),
                "pause": _(u"Pause"),
                "cont": _(u"Continue"),
            },
        )
        if self.__tna:
            # Start in the system tray.
            self.__tbicon.set_menu_show()

    def init_text(self):
        """Create the text notification widgets."""
        # Title
        t = _(u"Text notification")
        label = wx.StaticText(parent=self, label=t)
        # Text entry, read default, create entry.
        t = self.__data.get_user("text")
        self.__msgtext = wx.TextCtrl(parent=self, value=t, style=wx.TE_MULTILINE)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        vsiz.Add(item=label, flag=wx.EXPAND | wx.LEFT, border=self.__bdist)
        vsiz.Add(item=self.__msgtext, proportion=1, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        return vsiz

    def on_change(self, event):
        """Event for button, change sound file."""
        # Set filename, directory path, wildcards and title.
        sfile = os.path.basename(self.__sound)
        sdir = os.path.dirname(self.__sound)
        t = _(u"file")
        w1 = "OGG- %s (*.ogg)|*.ogg" % (t)
        w2 = "MP3- %s (*.mp3)|*.mp3" % (t)
        w3 = "WAV- %s (*.wav)|*.wav" % (t)
        wcard = "%s|%s|%s" % (w1, w2, w3)
        t = _(u"Select the sound file")
        # Show open dialog, get user datas.
        dlg = wx.FileDialog(
            parent=self, message=t, defaultDir=sdir, defaultFile=sfile, wildcard=wcard, style=wx.FD_OPEN
        )
        if dlg.ShowModal() == wx.ID_OK:
            # Clicked ok, set path, destroy dialog.
            path = dlg.GetPath()
            dlg.Destroy()
            # Set path to text entry and sound attribute.
            self.__sound = path
            self.__msgsound.SetValue(path)
            self.__msgsound.SetInsertionPointEnd()
        else:
            # Not clicked ok, destroy dialog.
            dlg.Destroy()

    def on_decrease(self, event):
        """Event for bitmap button, decrease time interval."""
        # Get interval as integer.
        interval = self.get_integer_interval()
        # decrease interval and set it to the text entry.
        self.set_integer_interval(interval - 1)

    def on_exit(self, event):
        """Event for button, exit program."""
        self.Close()

    def on_increase(self, event):
        """Event for bitmap button, increase time interval."""
        # Get interval as integer.
        interval = self.get_integer_interval()
        # decrease interval and set it to the text entry.
        self.set_integer_interval(interval + 1)

    def on_interval(self, event):
        """Event for text control, check time interval."""
        # Get interval as integer.
        interval = self.get_integer_interval()
        # Set interval to the text entry.
        self.set_integer_interval(interval)

    def on_minimize(self, event):
        """Event for button, minimize frame."""
        if self.IsShown():
            self.Hide()
            if self.__indstatus:
                # Application indicator
                self.__ind.set_menu_show()
            else:
                # wx.TaskBarIcon
                self.__tbicon.set_menu_show()

    def on_msgsound(self, event):
        """Event for text control, check path to sound file."""
        # Get text from entry.
        text = self.__msgsound.GetValue()
        if text:
            # Text is set, check path
            if not os.path.exists(text):
                self.__msgsound.SetValue(self.__sound)
            else:
                self.__sound = text
        else:
            # Text is not set.
            self.__sound = ""

    def on_pause(self, event):
        """Event for button, pause the clock."""
        self.clock_pause()

    def on_preview(self, event):
        """Event for button, preview sound file."""
        self.pygame_sound()

    def on_start(self, event):
        """Event for button, start the clock."""
        self.clock_start()

    def on_stop(self, event):
        """Event for button, stop the clock."""
        self.clock_stop()

    def on_system_close(self, event):
        """Event before close the frame."""
        if self.__lockwrite:
            # Normal program start, normal program end, delte lock file.
            self.__lock.delete_lock()
            # Close the taksbar or the indicator.
            if self.__indstatus:
                # Application indicator
                self.__ind.quit()
            elif not self.__indstatus:
                # TaskBarIcon
                self.__tbicon.Destroy()
            # Save the settings
            self.config_save()
        self.Destroy()

    def on_timer(self, event):
        """Event for timer, the MindfulClock."""
        timenow = int(time.time())
        if self.__textnotif == "close":
            # Text message closed, start new interval.
            self.__start = timenow
            self.__end = self.__start + self.__seconds
            self.__gauge.SetValue(0)
            # Remaining minutes as text.
            remain = self.get_text_minutes(self.__seconds)
            # Set textnotification clear.
            self.__textnotif = "clear"
        elif self.__textnotif == "clear" and timenow < self.__end:
            # End is not reached.
            progress = timenow - self.__start + 1
            value = (self.__gaugerange / self.__seconds) * progress
            self.__gauge.SetValue(value)
            # Remaining minutes as text.
            remain = self.get_text_minutes(self.__end - timenow)
        elif self.__textnotif == "clear" and timenow >= self.__end:
            # Play sound.
            self.pygame_sound()
            # Show text.
            self.show_popup()
        if self.__textnotif == "clear":
            # Taskbar
            if self.__indstatus:
                # Application indicator
                self.__ind.set_remain_time(remain)
            else:
                # wx.TaskBarIcon
                self.__tbicon.set_remain_time(remain)
        elif self.__textnotif == "show":
            # Taskbar
            if self.__indstatus:
                # Application indicator
                self.__ind.set_remain_time("..")
            else:
                # wx.TaskBarIcon
                self.__tbicon.set_remain_time("..")

    def pygame_sound(self):
        """Play the 'soundfile' with Pygame."""
        if self.__sound:
            # Soundfile is set, play sound.
            if self.__sound.endswith(".wav") or self.__sound.endswith(".ogg"):
                pygame.init()
                mixer = pygame.mixer.Sound(self.__sound)
                mixer.play()
            elif self.__sound.endswith(".mp3"):
                pygame.init()
                pygame.mixer.music.load(self.__sound)
                pygame.mixer.music.play()

    def set_integer_interval(self, interval):
        """Control value of time interval and set it to the entry."""
        # Check interval
        if interval != "dev":
            minimum = self.__data.get_sys("min_interval")
            maximum = self.__data.get_sys("max_interval")
            if interval < minimum:
                interval = minimum
            elif interval > maximum:
                interval = maximum
            self.__txtinterval.SetValue(str(interval))
            # Set current value as new default value.
            self.__interval = interval

    def start_question(self):
        """Show Question, run mfc again?, return True or False."""
        t1 = _(u"It seems the MindfulClock is running.")
        t2 = _(u"Do you want to start the clock anyway?")
        style = wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION
        dlg = wx.MessageDialog(parent=None, message="%s %s" % (t1, t2), caption=_(u"Start control"), style=style)
        answer = dlg.ShowModal()
        if answer == wx.ID_NO:
            # Do not overwrite, return None
            status = False
        else:
            # Overwrite, return 'path'
            status = True
        return status

    def set_in18(self):
        """Set the internationalization."""
        # Get directory
        dir_ = os.path.join(self.__dir, "locale")
        # Locale, set default language.
        self.__wxloc = wx.Locale(wx.LANGUAGE_DEFAULT)
        self.__wxloc.AddCatalogLookupPathPrefix(dir_)
        self.__wxloc.AddCatalog("mfc1")

    def set_textnotif(self, value):
        """Set the value of __textnotif."""
        # Values = 'show' message on the screen, 'close' message closed,
        # 'clear' since the clock is running no message showed.
        if value in ("show", "close", "clear"):
            self.__textnotif = value
        else:
            self.__textnotif = None

    def show_popup(self):
        """Show the text notification popup."""
        text = self.__msgtext.GetValue()
        if text:
            # Text is set, show dialog.  Status of text notification.
            self.__textnotif = "show"
            font = self.__data.get_sys("msg_font")
            colors = self.__data.get_sys("popup_colors")
            icon = os.path.join(self.__dir, self.__data.get_sys("icon_close"))
            popup = Popup(parent=self, style=self.__bdist, text=text, font=font, colors=colors, icon=icon)
            popw, poph = popup.get_size()
            dispw, disph = wx.GetDisplaySize()
            offx = (dispw - popw) / 2
            offy = (disph - poph) / 2
            popup.Position(ptOrigin=(0, 0), size=(offx, offy))
            popup.Popup()
Example #3
0
class GUI(wx.Frame):
    '''mfc1.GUI(tna, tbicon)
       GUI of the MindfulClock.
       tna = True, False, start in the taskbar notification area.
       tbicon = True, False, use instead of appindicator wx.TaskBarIcon.

    clock_start()
    Start the clock.

    clock_stop()
    Stop the clock.

    config_load()
    Load the settings with wx.config.

    config_save()
    Save the settings with wx.config.

    determine_path()
    Borrowed from wxglade.py, get the package directory.

    get_clock()
    Get the status of the clock, True of False.

    get_integer_interval
    Convert time interval as text to a integer value.

    get_text_minutes(seconds):
    Get the seconds in minutes as text, 'mm:ss'.

    init_appind():
    Create the application indicator.

    init_buttons():
    Create the control buttons.

    init_interval()
    Create the time interval widgets.

    init_sound()
    Create the sound notification widgets.

    init_tbicon(self):
    Create the wx.TaskBarIcon.

    init_text()
    Create the text notification widgets.

    on_change(event)
    Event for button, change sound file.

    on_decrease(event)
    Event for Bitmap Button, decrease time interval.

    on_exit(event)
    Event for button, exit program.

    on_increase(event)
    Event for Bitmap Button, increase time interval.

    on_interval(event)
    Event for text control, check time interval.

    on_minimize(event)
    Event for button, minimize frame.

    on_msgsound(event)
    Event for text control, check path to sound file.

    on_preview(event)
    Event for button, preview sound file.

    on_start(event)
    Event for button, start the clock.

    on_stop(event)
    Event for button, stop the clock.

    on_system_close(event)
    Event before close the frame.

    on_timer(event)
    Event for timer, the MindfulClock.

    pygame_sound()
    Play the soundfile with Pygame.

    set_in18(self):
    Set the internationalization.

    set_integer_interval(interval)
    Control value of time interval and set it to the entry.

    show_dialog(self):
    Show the text notification dialogue.

    show_popup(self):
    Show the text notification popup.

    '''

    def __init__(self, tna, tbicon):
        # Data object.
        self.__data = Data()
        # Package directory
        self.__dir = self.determine_path()
        # Internationalisation
        self.set_in18()
        # Load saved datas.
        self.config_load()
        # Get frame title, frame size and icon.
        title = self.__data.get_sys('frame_title')
        size = self.__data.get_user('frame_size')
        icon = os.path.join(self.__dir,
                            self.__data.get_sys('icon_name'))
        # Subclass
        wx.Frame.__init__(self,
                          parent=None,
                          id=wx.ID_ANY,
                          title=title,
                          size=size)
        # Icon
        if icon.endswith('.png'):
            self.SetIcon(wx.Icon(name=icon, type=wx.BITMAP_TYPE_PNG))
        # GUI border style and distance between widgets.
        bstyl = self.__data.get_sys('gui_borderstyle')
        guiborders = {'simple': wx.SIMPLE_BORDER,
                      'raised': wx.RAISED_BORDER,
                      'sunken': wx.SUNKEN_BORDER,
                      'no': wx.NO_BORDER}
        if bstyl in guiborders:
            self.__bstyl = guiborders[bstyl]
        else:
            self.__bstyl = wx.SIMPLE_BORDER
        self.__bdist = self.__data.get_sys('gui_borderdist')
        if not self.__bdist:
            self.__bdist = 5
        # Set attributes for time interval and sound file.
        self.__interval = self.__data.get_user('interval')
        self.__sound = os.path.join(self.__dir,
                                    self.__data.get_user('sound'))
        # time interval.
        intervalbox = self.init_interval()
        # Text notification.
        textbox = self.init_text()
        # Sound notification.
        soundbox = self.init_sound()
        # Clock control.
        controlbox = self.init_buttons()
        # Timer
        self.__timer = wx.Timer(self, 1)
        self.Bind(event=wx.EVT_TIMER,
                  handler=self.on_timer,
                  source=self.__timer)
        # Clock status
        self.__clockstatus = False
        # Exit bindings.
        self.Bind(event=wx.EVT_CLOSE, handler=self.on_system_close)
        # Layout
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(item=intervalbox,
                 proportion=0,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        vbox.Add(item=textbox,
                 proportion=1,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        vbox.Add(item=soundbox,
                 proportion=0,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        vbox.Add(item=controlbox,
                 proportion=0,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        self.SetSizer(vbox)
        # Disable stop button
        self.__btnstop.Enable(False)
        # System tray from command line options
        if tna:
            self.__tna = True
        else:
            if self.__miniopt.GetValue():
                # Minimize option is set.
                self.__tna = True
            else:
                self.__tna = False
        if tbicon:
            # TaskBarIcon
            self.init_tbicon()
        else:
            # Appiciation indicator
            wx.FutureCall(100, self.init_appind)
        # Centre window, show window.
        self.Center()
        if self.__tna:
            # Start in the system tray.
            self.Hide()
        else:
            self.Show()

    def clock_start(self):
        '''Start the clock.'''
        # Read interval
        interval = self.get_integer_interval()
        if interval != 'dev':
            # Time interval in seconds
            self.__seconds = interval * 60.0
            # Start and end time, UTC in seconds
            self.__start = int(time.time())
            self.__end = self.__start + self.__seconds
        else:
            self.__seconds = 5.0
            self.__start = int(time.time())
            self.__end = self.__start + self.__seconds
        #  start timer
        self.__timer.Start(self.__data.get_sys('wxtimer'))
        # Hide start icon, show stop icon
        self.__btnstart.Enable(False)
        self.__btnstop.Enable(True)
        self.__clockstatus = True
        if self.__indstatus:
            # Application indicator
            self.__ind.set_menu_stop()
        else:
            # TaskBarIcon
            self.__tbicon.set_menu_stop()

    def clock_stop(self):
        '''Stop the clock.'''
        # stop timer
        self.__timer.Stop()
        # Show start icon, hide stop icon
        self.__btnstart.Enable(True)
        self.__btnstop.Enable(False)
        self.__gauge.SetValue(0)
        self.__clockstatus = False
        if self.__indstatus:
            # Application indicator
            self.__ind.set_menu_start()
            self.__ind.set_remain_time('--:--')
        else:
            # TaskBarIcon
            self.__tbicon.set_menu_start()
            self.__tbicon.set_remain_time('--:--')

    def config_load(self):
        '''Load the settings with wx.config.'''
        # Config file
        config = wx.Config(self.__data.get_sys('config_file'))
        # Get the default dictionairy as text
        textdic = self.__data.get_user_textdic()
        # Read text, textdic as default.
        newdic = config.Read(key='dic', defaultVal=textdic)
        # Set text as new dictionairy.
        self.__data.set_user_textdic(newdic)

    def config_save(self):
        '''Save the settings with wx.config.'''
        # Config file
        config = wx.Config(self.__data.get_sys('config_file'))
        # Set text notification.
        self.__data.set_user('text', self.__msgtext.GetValue())
        # Set sound notification.
        self.__data.set_user('sound', self.__sound)
        # Set time interval.
        if self.__interval != 'dev':
            self.__data.set_user('interval', self.__interval)
        # Set frame size.
        size = self.GetSize()
        self.__data.set_user('frame_size', (size[0], size[1]))
        # Set start minimize option
        self.__data.set_user('mini_opt', self.__miniopt.GetValue())
        # Get data dictionariy as text.
        textdic = self.__data.get_user_textdic()
        # Write text.
        config.Write(key='dic', value=textdic)

    def determine_path(self):
        '''Borrowed from wxglade.py, get the package directory.'''
        try:
            root = __file__
            if os.path.islink(root):
                root = os.path.realpath(root)
            return os.path.dirname(os.path.abspath(root))
        except:
            print 'I am sorry, but something is wrong.  There is no '
            print '__file__ variable. Please contact the author.'

    def get_clock(self):
        '''Get the status of the clock, True of False.'''
        return(self.__clockstatus)

    def get_integer_interval(self):
        '''Convert time interval as text to a integer value.'''
        # Get text from entry.
        text = self.__txtinterval.GetValue()
        # Error handling.
        try:
            if text != 'dev':
                interval = int(text)
            else:
                interval = text
        except ValueError:
            interval = self.__interval
        # Return integer.
        return(interval)

    def get_text_minutes(self, seconds):
        '''Get the seconds in minutes as text, 'mm:ss'.'''
        try:
            mins = int(seconds // 60)
            secs = int(seconds % 60)
        except ValueError:
            mins, secs = 0, 0
        return('%#02d:%#02d' % (mins, secs))

    def init_appind(self):
        '''Create the application indicator.'''
        # status of the indicator.
        self.__indstatus = True
        # Application indicator.
        icon = self.__data.get_sys('indicator_icon')
        path = os.path.join(self.__dir,
                        self.__data.get_sys('indicator_path'))
        self.__ind = AppIndicator(frame=self,
                                  icon=icon,
                                  path=path,
                                  textdic={'start': _(u'Start'),
                                           'stop': _(u'Stop'),
                                           'show': _(u'Show'),
                                           'hide': _(u'Hide'),
                                           'exit': _(u'Exit')})
        if self.__tna:
            # Start in the system tray.
            self.__ind.set_menu_show()
        self.__ind.main()

    def init_buttons(self):
        '''Create the control buttons.'''
        # Title
        t = _(u'Clock control')
        label = wx.StaticText(parent=self, label=t)
        # Start bitmap button.
        icon = os.path.join(self.__dir,
                            self.__data.get_sys('icon_start'))
        self.__btnstart = wx.BitmapButton(parent=self,
                                          bitmap=wx.Bitmap(icon))
        self.__btnstart.SetToolTip(wx.ToolTip(_(u'Start Clock')))
        # Stop bitmap button.
        icon = os.path.join(self.__dir,
                            self.__data.get_sys('icon_stop'))
        self.__btnstop = wx.BitmapButton(parent=self,
                                         bitmap=wx.Bitmap(icon))
        self.__btnstop.SetToolTip(wx.ToolTip(_(u'Stop Clock')))
        # Minimize bitmap button.
        icon = os.path.join(self.__dir,
                            self.__data.get_sys('icon_minimize'))
        minimize = wx.BitmapButton(parent=self,
                                   bitmap=wx.Bitmap(icon))
        t = _(u'Minimize to Taskbar Notification Area')
        minimize.SetToolTip(wx.ToolTip(t))
        # Exit bitmap button.
        icon = os.path.join(self.__dir,
                            self.__data.get_sys('icon_exit'))
        exit_ = wx.BitmapButton(parent=self,
                                   bitmap=wx.Bitmap(icon))
        exit_.SetToolTip(wx.ToolTip(_(u'Exit Clock')))
        # Gauge to show the process.
        self.__gaugerange = self.__data.get_sys('gauge')
        self.__gauge = wx.Gauge(parent=self,
                                range=self.__gaugerange)
        # Checkbox option
        t = _(u'Start in the Taskbar Notification Area')
        self.__miniopt = wx.CheckBox(parent=self,
                                     label=t)
        # Set value from user datas.
        if self.__data.get_user('mini_opt'):
            self.__miniopt.SetValue(True)
        else:
            self.__miniopt.SetValue(False)
        # Bindings.
        self.__btnstart.Bind(event=wx.EVT_BUTTON, handler=self.on_start)
        self.__btnstop.Bind(event=wx.EVT_BUTTON, handler=self.on_stop)
        minimize.Bind(event=wx.EVT_BUTTON, handler=self.on_minimize)
        exit_.Bind(event=wx.EVT_BUTTON, handler=self.on_exit)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        vsiz.Add(item=label,
                 flag=wx.EXPAND | wx.LEFT,
                 border=self.__bdist)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        hsiz.Add(item=self.__btnstart,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        hsiz.Add(item=self.__btnstop,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        hsiz.AddStretchSpacer()
        hsiz.Add(item=minimize,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        hsiz.Add(item=exit_,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        vsiz.Add(item=hsiz, proportion=1, flag=wx.EXPAND)
        vsiz.Add(item=self.__gauge,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        vsiz.Add(item=self.__miniopt,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        return(vsiz)

    def init_interval(self):
        '''Create the time interval widgets.'''
        # Title
        t = _(u'Time interval in minutes')
        label = wx.StaticText(parent=self, label=t)
        # Text entry: Read default, create entry.
        self.__txtinterval = wx.TextCtrl(parent=self,
                                         value=str(self.__interval))
        # Increase bitmap button.
        icon = os.path.join(self.__dir,
                            self.__data.get_sys('icon_increase'))
        increase = wx.BitmapButton(parent=self,
                                   bitmap=wx.Bitmap(icon))
        increase.SetToolTip(wx.ToolTip(_(u'Increase time')))
        # Decrease bitmap button.
        icon = os.path.join(self.__dir,
                            self.__data.get_sys('icon_decrease'))
        decrease = wx.BitmapButton(parent=self,
                                   bitmap=wx.Bitmap(icon))
        decrease.SetToolTip(wx.ToolTip(_(u'Decrease time')))
        # Bindings.
        increase.Bind(event=wx.EVT_BUTTON, handler=self.on_increase)
        decrease.Bind(event=wx.EVT_BUTTON, handler=self.on_decrease)
        self.__txtinterval.Bind(event=wx.EVT_KILL_FOCUS,
                                handler=self.on_interval)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        vsiz.Add(item=label,
                 flag=wx.EXPAND | wx.LEFT,
                 border=self.__bdist)
        hsiz.Add(item=self.__txtinterval,
                 proportion=1,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        hsiz.Add(item=increase,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        hsiz.Add(item=decrease,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        vsiz.Add(item=hsiz, proportion=1, flag=wx.EXPAND)
        return(vsiz)

    def init_sound(self):
        '''Create the sound notification widgets.'''
        # Title
        t = _(u'Sound notification')
        label = wx.StaticText(parent=self, label=t)
        # Sound change button
        icon = os.path.join(self.__dir,
                            self.__data.get_sys('icon_change'))
        change = wx.BitmapButton(parent=self,
                                 bitmap=wx.Bitmap(icon))
        change.SetToolTip(wx.ToolTip(_(u'Change sound file')))
        # Sound preview button
        icon = os.path.join(self.__dir,
                            self.__data.get_sys('icon_preview'))
        preview = wx.BitmapButton(parent=self,
                                  bitmap=wx.Bitmap(icon))
        preview.SetToolTip(wx.ToolTip(_(u'Preview sound')))
        # Text entry, read defaults
        self.__msgsound = wx.TextCtrl(parent=self,
                                      value=self.__sound)
        # Bindings
        change.Bind(event=wx.EVT_BUTTON, handler=self.on_change)
        preview.Bind(event=wx.EVT_BUTTON, handler=self.on_preview)
        self.__msgsound.Bind(event=wx.EVT_KILL_FOCUS,
                             handler=self.on_msgsound)
        # Layout
        vsiz = wx.BoxSizer(wx.VERTICAL)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        vsiz.Add(item=label,
                 flag=wx.EXPAND | wx.LEFT,
                 border=self.__bdist)
        hsiz.Add(item=self.__msgsound,
                 proportion=1,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        hsiz.Add(item=change,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        hsiz.Add(item=preview,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        vsiz.Add(item=hsiz, proportion=1, flag=wx.EXPAND)
        return(vsiz)

    def init_tbicon(self):
        '''Create the wx.TaskBarIcon.'''
        self.__indstatus = False
        # TaskbarIcon
        icon = os.path.join(self.__dir,
                            self.__data.get_sys('tna_icon'))
        title = self.__data.get_sys('frame_title')
        self.__tbicon = TBIcon(frame=self,
                               icon=icon,
                               title=title,
                               textdic={'start': _(u'Start'),
                                        'stop': _(u'Stop'),
                                        'show': _(u'Show'),
                                        'hide': _(u'Hide'),
                                        'exit': _(u'Exit')})
        if self.__tna:
            # Start in the system tray.
            self.__tbicon.set_menu_show()

    def init_text(self):
        '''Create the text notification widgets.'''
        # Title
        t = _(u'Text notification')
        label = wx.StaticText(parent=self, label=t)
        # Text entry, read default, create entry.
        t = self.__data.get_user('text')
        self.__msgtext = wx.TextCtrl(parent=self,
                                     value=t,
                                     style=wx.TE_MULTILINE)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        vsiz.Add(item=label,
                 flag=wx.EXPAND | wx.LEFT,
                 border=self.__bdist)
        vsiz.Add(item=self.__msgtext,
                 proportion=1,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        return(vsiz)

    def on_change(self, event):
        '''Event for button, change sound file.'''
        # Set filename, directory path, wildcards and title.
        sfile = os.path.basename(self.__sound)
        sdir = os.path.dirname(self.__sound)
        t = _(u'file')
        w1 = 'OGG- %s (*.ogg)|*.ogg' % (t)
        w2 = 'MP3- %s (*.mp3)|*.mp3' % (t)
        w3 = 'WAV- %s (*.wav)|*.wav' % (t)
        wcard = '%s|%s|%s' % (w1, w2, w3)
        t = _(u'Select the sound file')
        # Show open dialog, get user datas.
        dlg = wx.FileDialog(parent=self,
                            message=t,
                            defaultDir=sdir,
                            defaultFile=sfile,
                            wildcard=wcard,
                            style=wx.FD_OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            # Clicked ok, set path, destroy dialog.
            path = dlg.GetPath()
            dlg.Destroy()
            # Set path to text entry and sound attribute.
            self.__sound = path
            self.__msgsound.SetValue(path)
            self.__msgsound.SetInsertionPointEnd()
        else:
            # Not clicked ok, destroy dialog.
            dlg.Destroy()

    def on_decrease(self, event):
        '''Event for bitmap button, decrease time interval.'''
        # Get interval as integer.
        interval = self.get_integer_interval()
        # decrease interval and set it to the text entry.
        self.set_integer_interval(interval - 1)

    def on_exit(self, event):
        '''Event for button, exit program.'''
        if self.__indstatus:
            self.__ind.quit()
        self.Close()

    def on_increase(self, event):
        '''Event for bitmap button, increase time interval.'''
        # Get interval as integer.
        interval = self.get_integer_interval()
        # decrease interval and set it to the text entry.
        self.set_integer_interval(interval + 1)

    def on_interval(self, event):
        '''Event for text control, check time interval.'''
        # Get interval as integer.
        interval = self.get_integer_interval()
        # Set interval to the text entry.
        self.set_integer_interval(interval)

    def on_minimize(self, event):
        '''Event for button, minimize frame.'''
        if self.IsShown():
            self.Hide()
            if self.__indstatus:
                # Application indicator
                self.__ind.set_menu_show()
            else:
                # wx.TaskBarIcon
                self.__tbicon.set_menu_show()

    def on_msgsound(self, event):
        '''Event for text control, check path to sound file.'''
        # Get text from entry.
        text = self.__msgsound.GetValue()
        if text:
            # Text is set, check path
            if not os.path.exists(text):
                self.__msgsound.SetValue(self.__sound)
            else:
                self.__sound = text
        else:
            # Text is not set.
            self.__sound = ''

    def on_preview(self, event):
        '''Event for button, preview sound file.'''
        self.pygame_sound()

    def on_start(self, event):
        '''Event for button, start the clock.'''
        self.clock_start()

    def on_stop(self, event):
        '''Event for button, stop the clock.'''
        self.clock_stop()

    def on_system_close(self, event):
        '''Event before close the frame.'''
        # Save the settings
        if not self.__indstatus:
            # TaskBarIcon
            self.__tbicon.Destroy()
        self.config_save()
        self.Destroy()

    def on_timer(self, event):
        '''Event for timer, the MindfulClock.'''
        timenow = int(time.time())
        if timenow < self.__end:
            # End is not reached.
            progress = timenow - self.__start
            value = (self.__gaugerange / self.__seconds) * progress
            self.__gauge.SetValue(value)
            # Remaining minutes as text.
            remain = self.get_text_minutes(self.__end - timenow)
        elif timenow >= self.__end:
            # End is reached, start new interval.
            self.__start = int(time.time())
            self.__end = self.__start + self.__seconds
            self.__gauge.SetValue(0)
            # Play sound.
            self.pygame_sound()
            # Show text, select dialogue or popup.
            if self.__data.get_sys('msg_type') == 'dialog':
                self.show_dialog()
            elif self.__data.get_sys('msg_type') == 'popup':
                self.show_popup()
            # Remaining minutes as text.
            remain = self.get_text_minutes(self.__seconds)
        # Systemtray
        if self.__indstatus:
            # Application indicator
            self.__ind.set_remain_time(remain)
        else:
            # wx.TaskBarIcon
            self.__tbicon.set_remain_time(remain)

    def pygame_sound(self):
        '''Play the 'soundfile' with Pygame.'''
        if self.__sound:
            # Soundfile is set, play sound.
            if self.__sound.endswith('.wav') or \
               self.__sound.endswith('.ogg'):
                pygame.init()
                mixer = pygame.mixer.Sound(self.__sound)
                mixer.play()
            elif self.__sound.endswith('.mp3'):
                pygame.init()
                pygame.mixer.music.load(self.__sound)
                pygame.mixer.music.play()

    def set_integer_interval(self, interval):
        '''Control value of time interval and set it to the entry.'''
        # Check interval
        if interval != 'dev':
            minimum = self.__data.get_sys('min_interval')
            maximum = self.__data.get_sys('max_interval')
            if interval < minimum:
                interval = minimum
            elif interval > maximum:
                interval = maximum
            self.__txtinterval.SetValue(str(interval))
            # Set current value as new default value.
            self.__interval = interval

    def set_in18(self):
        '''Set the internationalization.'''
        # Get directory
        dir_ = os.path.join(self.__dir, 'locale')
        # Locale, set default language.
        self.__wxloc = wx.Locale(wx.LANGUAGE_DEFAULT)
        self.__wxloc.AddCatalogLookupPathPrefix(dir_)
        self.__wxloc.AddCatalog('mfc1')

    def show_dialog(self):
        '''Show the text notification dialogue.'''
        text = self.__msgtext.GetValue()
        if text:
            # Text is set, show dialog.
            title = self.__data.get_sys('msg_title')
            size = self.__data.get_user('msg_size')
            icon = os.path.join(self.__dir,
                               self.__data.get_sys('icon_close'))
            font = self.__data.get_sys('msg_font')
            dlg = Msg(parent=self,
                      title=title,
                      size=size,
                      icon=icon,
                      text=text,
                      font=font)
            dlg.ShowModal()
            # Set dialog size
            size = dlg.GetSize()
            self.__data.set_user('msg_size', (size[0], size[1]))
            # Destroy dialogue.
            dlg.Destroy()

    def show_popup(self):
        '''Show the text notification popup.'''
        text = self.__msgtext.GetValue()
        if text:
            # Text is set, show dialog.
            font = self.__data.get_sys('msg_font')
            colors = self.__data.get_sys('popup_colors')
            icon = os.path.join(self.__dir,
                               self.__data.get_sys('icon_close'))
            popup = Popup(parent=self,
                      style=self.__bdist,
                      text=text,
                      font=font,
                      colors=colors,
                      icon=icon)
            popw, poph = popup.get_size()
            dispw, disph = wx.GetDisplaySize()
            offx = (dispw - popw) / 2
            offy = (disph - poph) / 2
            popup.Position(ptOrigin=(0, 0), size=(offx, offy))
            popup.Popup()
Example #4
0
class GUI(wx.Frame):
    '''mfc1.GUI(tna, tbicon)
       GUI of the MindfulClock.
       tna = True, False, start in the taskbar notification area.
       tbicon = True, False, use instead of appindicator wx.TaskBarIcon.

    clock_start()
    Start the clock.

    clock_stop()
    Stop the clock.

    config_load()
    Load the settings with wx.config.

    config_save()
    Save the settings with wx.config.

    determine_path()
    Borrowed from wxglade.py, get the package directory.

    get_clock()
    Get the status of the clock, True of False.

    get_integer_interval
    Convert time interval as text to a integer value.

    get_text_minutes(seconds):
    Get the seconds in minutes as text, 'mm:ss'.

    init_appind():
    Create the application indicator.

    init_buttons():
    Create the control buttons.

    init_interval()
    Create the time interval widgets.

    init_sound()
    Create the sound notification widgets.

    init_tbicon(self):
    Create the wx.TaskBarIcon.

    init_text()
    Create the text notification widgets.

    on_change(event)
    Event for button, change sound file.

    on_decrease(event)
    Event for Bitmap Button, decrease time interval.

    on_exit(event)
    Event for button, exit program.

    on_increase(event)
    Event for Bitmap Button, increase time interval.

    on_interval(event)
    Event for text control, check time interval.

    on_minimize(event)
    Event for button, minimize frame.

    on_msgsound(event)
    Event for text control, check path to sound file.

    on_preview(event)
    Event for button, preview sound file.

    on_start(event)
    Event for button, start the clock.

    on_stop(event)
    Event for button, stop the clock.

    on_system_close(event)
    Event before close the frame.

    on_timer(event)
    Event for timer, the MindfulClock.

    pygame_sound()
    Play the soundfile with Pygame.

    set_in18(self):
    Set the internationalization.

    set_integer_interval(interval)
    Control value of time interval and set it to the entry.

    show_dialog(self):
    Show the text notification dialogue.

    show_popup(self):
    Show the text notification popup.

    '''
    def __init__(self, tna, tbicon):
        # Data object.
        self.__data = Data()
        # Package directory
        self.__dir = self.determine_path()
        # Internationalisation
        self.set_in18()
        # Load saved datas.
        self.config_load()
        # Get frame title, frame size and icon.
        title = self.__data.get_sys('frame_title')
        size = self.__data.get_user('frame_size')
        icon = os.path.join(self.__dir, self.__data.get_sys('icon_name'))
        # Subclass
        wx.Frame.__init__(self,
                          parent=None,
                          id=wx.ID_ANY,
                          title=title,
                          size=size)
        # Icon
        if icon.endswith('.png'):
            self.SetIcon(wx.Icon(name=icon, type=wx.BITMAP_TYPE_PNG))
        # GUI border style and distance between widgets.
        bstyl = self.__data.get_sys('gui_borderstyle')
        guiborders = {
            'simple': wx.SIMPLE_BORDER,
            'raised': wx.RAISED_BORDER,
            'sunken': wx.SUNKEN_BORDER,
            'no': wx.NO_BORDER
        }
        if bstyl in guiborders:
            self.__bstyl = guiborders[bstyl]
        else:
            self.__bstyl = wx.SIMPLE_BORDER
        self.__bdist = self.__data.get_sys('gui_borderdist')
        if not self.__bdist:
            self.__bdist = 5
        # Set attributes for time interval and sound file.
        self.__interval = self.__data.get_user('interval')
        self.__sound = os.path.join(self.__dir, self.__data.get_user('sound'))
        # time interval.
        intervalbox = self.init_interval()
        # Text notification.
        textbox = self.init_text()
        # Sound notification.
        soundbox = self.init_sound()
        # Clock control.
        controlbox = self.init_buttons()
        # Timer
        self.__timer = wx.Timer(self, 1)
        self.Bind(event=wx.EVT_TIMER,
                  handler=self.on_timer,
                  source=self.__timer)
        # Clock status
        self.__clockstatus = False
        # Exit bindings.
        self.Bind(event=wx.EVT_CLOSE, handler=self.on_system_close)
        # Layout
        vbox = wx.BoxSizer(wx.VERTICAL)
        vbox.Add(item=intervalbox,
                 proportion=0,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        vbox.Add(item=textbox,
                 proportion=1,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        vbox.Add(item=soundbox,
                 proportion=0,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        vbox.Add(item=controlbox,
                 proportion=0,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        self.SetSizer(vbox)
        # Disable stop button
        self.__btnstop.Enable(False)
        # System tray from command line options
        if tna:
            self.__tna = True
        else:
            if self.__miniopt.GetValue():
                # Minimize option is set.
                self.__tna = True
            else:
                self.__tna = False
        if tbicon:
            # TaskBarIcon
            self.init_tbicon()
        else:
            # Appiciation indicator
            wx.FutureCall(100, self.init_appind)
        # Centre window, show window.
        self.Center()
        if self.__tna:
            # Start in the system tray.
            self.Hide()
        else:
            self.Show()

    def clock_start(self):
        '''Start the clock.'''
        # Read interval
        interval = self.get_integer_interval()
        if interval != 'dev':
            # Time interval in seconds
            self.__seconds = interval * 60.0
            # Start and end time, UTC in seconds
            self.__start = int(time.time())
            self.__end = self.__start + self.__seconds
        else:
            self.__seconds = 5.0
            self.__start = int(time.time())
            self.__end = self.__start + self.__seconds
        #  start timer
        self.__timer.Start(self.__data.get_sys('wxtimer'))
        # Hide start icon, show stop icon
        self.__btnstart.Enable(False)
        self.__btnstop.Enable(True)
        self.__clockstatus = True
        if self.__indstatus:
            # Application indicator
            self.__ind.set_menu_stop()
        else:
            # TaskBarIcon
            self.__tbicon.set_menu_stop()

    def clock_stop(self):
        '''Stop the clock.'''
        # stop timer
        self.__timer.Stop()
        # Show start icon, hide stop icon
        self.__btnstart.Enable(True)
        self.__btnstop.Enable(False)
        self.__gauge.SetValue(0)
        self.__clockstatus = False
        if self.__indstatus:
            # Application indicator
            self.__ind.set_menu_start()
            self.__ind.set_remain_time('--:--')
        else:
            # TaskBarIcon
            self.__tbicon.set_menu_start()
            self.__tbicon.set_remain_time('--:--')

    def config_load(self):
        '''Load the settings with wx.config.'''
        # Config file
        config = wx.Config(self.__data.get_sys('config_file'))
        # Get the default dictionairy as text
        textdic = self.__data.get_user_textdic()
        # Read text, textdic as default.
        newdic = config.Read(key='dic', defaultVal=textdic)
        # Set text as new dictionairy.
        self.__data.set_user_textdic(newdic)

    def config_save(self):
        '''Save the settings with wx.config.'''
        # Config file
        config = wx.Config(self.__data.get_sys('config_file'))
        # Set text notification.
        self.__data.set_user('text', self.__msgtext.GetValue())
        # Set sound notification.
        self.__data.set_user('sound', self.__sound)
        # Set time interval.
        if self.__interval != 'dev':
            self.__data.set_user('interval', self.__interval)
        # Set frame size.
        size = self.GetSize()
        self.__data.set_user('frame_size', (size[0], size[1]))
        # Set start minimize option
        self.__data.set_user('mini_opt', self.__miniopt.GetValue())
        # Get data dictionariy as text.
        textdic = self.__data.get_user_textdic()
        # Write text.
        config.Write(key='dic', value=textdic)

    def determine_path(self):
        '''Borrowed from wxglade.py, get the package directory.'''
        try:
            root = __file__
            if os.path.islink(root):
                root = os.path.realpath(root)
            return os.path.dirname(os.path.abspath(root))
        except:
            print 'I am sorry, but something is wrong.  There is no '
            print '__file__ variable. Please contact the author.'

    def get_clock(self):
        '''Get the status of the clock, True of False.'''
        return (self.__clockstatus)

    def get_integer_interval(self):
        '''Convert time interval as text to a integer value.'''
        # Get text from entry.
        text = self.__txtinterval.GetValue()
        # Error handling.
        try:
            if text != 'dev':
                interval = int(text)
            else:
                interval = text
        except ValueError:
            interval = self.__interval
        # Return integer.
        return (interval)

    def get_text_minutes(self, seconds):
        '''Get the seconds in minutes as text, 'mm:ss'.'''
        try:
            mins = int(seconds // 60)
            secs = int(seconds % 60)
        except ValueError:
            mins, secs = 0, 0
        return ('%#02d:%#02d' % (mins, secs))

    def init_appind(self):
        '''Create the application indicator.'''
        # status of the indicator.
        self.__indstatus = True
        # Application indicator.
        icon = self.__data.get_sys('indicator_icon')
        path = os.path.join(self.__dir, self.__data.get_sys('indicator_path'))
        self.__ind = AppIndicator(frame=self,
                                  icon=icon,
                                  path=path,
                                  textdic={
                                      'start': _(u'Start'),
                                      'stop': _(u'Stop'),
                                      'show': _(u'Show'),
                                      'hide': _(u'Hide'),
                                      'exit': _(u'Exit')
                                  })
        if self.__tna:
            # Start in the system tray.
            self.__ind.set_menu_show()
        self.__ind.main()

    def init_buttons(self):
        '''Create the control buttons.'''
        # Title
        t = _(u'Clock control')
        label = wx.StaticText(parent=self, label=t)
        # Start bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys('icon_start'))
        self.__btnstart = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        self.__btnstart.SetToolTip(wx.ToolTip(_(u'Start Clock')))
        # Stop bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys('icon_stop'))
        self.__btnstop = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        self.__btnstop.SetToolTip(wx.ToolTip(_(u'Stop Clock')))
        # Minimize bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys('icon_minimize'))
        minimize = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        t = _(u'Minimize to Taskbar Notification Area')
        minimize.SetToolTip(wx.ToolTip(t))
        # Exit bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys('icon_exit'))
        exit_ = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        exit_.SetToolTip(wx.ToolTip(_(u'Exit Clock')))
        # Gauge to show the process.
        self.__gaugerange = self.__data.get_sys('gauge')
        self.__gauge = wx.Gauge(parent=self, range=self.__gaugerange)
        # Checkbox option
        t = _(u'Start in the Taskbar Notification Area')
        self.__miniopt = wx.CheckBox(parent=self, label=t)
        # Set value from user datas.
        if self.__data.get_user('mini_opt'):
            self.__miniopt.SetValue(True)
        else:
            self.__miniopt.SetValue(False)
        # Bindings.
        self.__btnstart.Bind(event=wx.EVT_BUTTON, handler=self.on_start)
        self.__btnstop.Bind(event=wx.EVT_BUTTON, handler=self.on_stop)
        minimize.Bind(event=wx.EVT_BUTTON, handler=self.on_minimize)
        exit_.Bind(event=wx.EVT_BUTTON, handler=self.on_exit)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        vsiz.Add(item=label, flag=wx.EXPAND | wx.LEFT, border=self.__bdist)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        hsiz.Add(item=self.__btnstart,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        hsiz.Add(item=self.__btnstop,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        hsiz.AddStretchSpacer()
        hsiz.Add(item=minimize, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        hsiz.Add(item=exit_, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        vsiz.Add(item=hsiz, proportion=1, flag=wx.EXPAND)
        vsiz.Add(item=self.__gauge,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        vsiz.Add(item=self.__miniopt,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        return (vsiz)

    def init_interval(self):
        '''Create the time interval widgets.'''
        # Title
        t = _(u'Time interval in minutes')
        label = wx.StaticText(parent=self, label=t)
        # Text entry: Read default, create entry.
        self.__txtinterval = wx.TextCtrl(parent=self,
                                         value=str(self.__interval))
        # Increase bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys('icon_increase'))
        increase = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        increase.SetToolTip(wx.ToolTip(_(u'Increase time')))
        # Decrease bitmap button.
        icon = os.path.join(self.__dir, self.__data.get_sys('icon_decrease'))
        decrease = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        decrease.SetToolTip(wx.ToolTip(_(u'Decrease time')))
        # Bindings.
        increase.Bind(event=wx.EVT_BUTTON, handler=self.on_increase)
        decrease.Bind(event=wx.EVT_BUTTON, handler=self.on_decrease)
        self.__txtinterval.Bind(event=wx.EVT_KILL_FOCUS,
                                handler=self.on_interval)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        vsiz.Add(item=label, flag=wx.EXPAND | wx.LEFT, border=self.__bdist)
        hsiz.Add(item=self.__txtinterval,
                 proportion=1,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        hsiz.Add(item=increase, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        hsiz.Add(item=decrease, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        vsiz.Add(item=hsiz, proportion=1, flag=wx.EXPAND)
        return (vsiz)

    def init_sound(self):
        '''Create the sound notification widgets.'''
        # Title
        t = _(u'Sound notification')
        label = wx.StaticText(parent=self, label=t)
        # Sound change button
        icon = os.path.join(self.__dir, self.__data.get_sys('icon_change'))
        change = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        change.SetToolTip(wx.ToolTip(_(u'Change sound file')))
        # Sound preview button
        icon = os.path.join(self.__dir, self.__data.get_sys('icon_preview'))
        preview = wx.BitmapButton(parent=self, bitmap=wx.Bitmap(icon))
        preview.SetToolTip(wx.ToolTip(_(u'Preview sound')))
        # Text entry, read defaults
        self.__msgsound = wx.TextCtrl(parent=self, value=self.__sound)
        # Bindings
        change.Bind(event=wx.EVT_BUTTON, handler=self.on_change)
        preview.Bind(event=wx.EVT_BUTTON, handler=self.on_preview)
        self.__msgsound.Bind(event=wx.EVT_KILL_FOCUS, handler=self.on_msgsound)
        # Layout
        vsiz = wx.BoxSizer(wx.VERTICAL)
        hsiz = wx.BoxSizer(wx.HORIZONTAL)
        vsiz.Add(item=label, flag=wx.EXPAND | wx.LEFT, border=self.__bdist)
        hsiz.Add(item=self.__msgsound,
                 proportion=1,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        hsiz.Add(item=change, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        hsiz.Add(item=preview, flag=wx.EXPAND | wx.ALL, border=self.__bdist)
        vsiz.Add(item=hsiz, proportion=1, flag=wx.EXPAND)
        return (vsiz)

    def init_tbicon(self):
        '''Create the wx.TaskBarIcon.'''
        self.__indstatus = False
        # TaskbarIcon
        icon = os.path.join(self.__dir, self.__data.get_sys('tna_icon'))
        title = self.__data.get_sys('frame_title')
        self.__tbicon = TBIcon(frame=self,
                               icon=icon,
                               title=title,
                               textdic={
                                   'start': _(u'Start'),
                                   'stop': _(u'Stop'),
                                   'show': _(u'Show'),
                                   'hide': _(u'Hide'),
                                   'exit': _(u'Exit')
                               })
        if self.__tna:
            # Start in the system tray.
            self.__tbicon.set_menu_show()

    def init_text(self):
        '''Create the text notification widgets.'''
        # Title
        t = _(u'Text notification')
        label = wx.StaticText(parent=self, label=t)
        # Text entry, read default, create entry.
        t = self.__data.get_user('text')
        self.__msgtext = wx.TextCtrl(parent=self,
                                     value=t,
                                     style=wx.TE_MULTILINE)
        # Layout.
        vsiz = wx.BoxSizer(wx.VERTICAL)
        vsiz.Add(item=label, flag=wx.EXPAND | wx.LEFT, border=self.__bdist)
        vsiz.Add(item=self.__msgtext,
                 proportion=1,
                 flag=wx.EXPAND | wx.ALL,
                 border=self.__bdist)
        return (vsiz)

    def on_change(self, event):
        '''Event for button, change sound file.'''
        # Set filename, directory path, wildcards and title.
        sfile = os.path.basename(self.__sound)
        sdir = os.path.dirname(self.__sound)
        t = _(u'file')
        w1 = 'OGG- %s (*.ogg)|*.ogg' % (t)
        w2 = 'MP3- %s (*.mp3)|*.mp3' % (t)
        w3 = 'WAV- %s (*.wav)|*.wav' % (t)
        wcard = '%s|%s|%s' % (w1, w2, w3)
        t = _(u'Select the sound file')
        # Show open dialog, get user datas.
        dlg = wx.FileDialog(parent=self,
                            message=t,
                            defaultDir=sdir,
                            defaultFile=sfile,
                            wildcard=wcard,
                            style=wx.FD_OPEN)
        if dlg.ShowModal() == wx.ID_OK:
            # Clicked ok, set path, destroy dialog.
            path = dlg.GetPath()
            dlg.Destroy()
            # Set path to text entry and sound attribute.
            self.__sound = path
            self.__msgsound.SetValue(path)
            self.__msgsound.SetInsertionPointEnd()
        else:
            # Not clicked ok, destroy dialog.
            dlg.Destroy()

    def on_decrease(self, event):
        '''Event for bitmap button, decrease time interval.'''
        # Get interval as integer.
        interval = self.get_integer_interval()
        # decrease interval and set it to the text entry.
        self.set_integer_interval(interval - 1)

    def on_exit(self, event):
        '''Event for button, exit program.'''
        if self.__indstatus:
            self.__ind.quit()
        self.Close()

    def on_increase(self, event):
        '''Event for bitmap button, increase time interval.'''
        # Get interval as integer.
        interval = self.get_integer_interval()
        # decrease interval and set it to the text entry.
        self.set_integer_interval(interval + 1)

    def on_interval(self, event):
        '''Event for text control, check time interval.'''
        # Get interval as integer.
        interval = self.get_integer_interval()
        # Set interval to the text entry.
        self.set_integer_interval(interval)

    def on_minimize(self, event):
        '''Event for button, minimize frame.'''
        if self.IsShown():
            self.Hide()
            if self.__indstatus:
                # Application indicator
                self.__ind.set_menu_show()
            else:
                # wx.TaskBarIcon
                self.__tbicon.set_menu_show()

    def on_msgsound(self, event):
        '''Event for text control, check path to sound file.'''
        # Get text from entry.
        text = self.__msgsound.GetValue()
        if text:
            # Text is set, check path
            if not os.path.exists(text):
                self.__msgsound.SetValue(self.__sound)
            else:
                self.__sound = text
        else:
            # Text is not set.
            self.__sound = ''

    def on_preview(self, event):
        '''Event for button, preview sound file.'''
        self.pygame_sound()

    def on_start(self, event):
        '''Event for button, start the clock.'''
        self.clock_start()

    def on_stop(self, event):
        '''Event for button, stop the clock.'''
        self.clock_stop()

    def on_system_close(self, event):
        '''Event before close the frame.'''
        # Save the settings
        if not self.__indstatus:
            # TaskBarIcon
            self.__tbicon.Destroy()
        self.config_save()
        self.Destroy()

    def on_timer(self, event):
        '''Event for timer, the MindfulClock.'''
        timenow = int(time.time())
        if timenow < self.__end:
            # End is not reached.
            progress = timenow - self.__start
            value = (self.__gaugerange / self.__seconds) * progress
            self.__gauge.SetValue(value)
            # Remaining minutes as text.
            remain = self.get_text_minutes(self.__end - timenow)
        elif timenow >= self.__end:
            # End is reached, start new interval.
            self.__start = int(time.time())
            self.__end = self.__start + self.__seconds
            self.__gauge.SetValue(0)
            # Play sound.
            self.pygame_sound()
            # Show text, select dialogue or popup.
            if self.__data.get_sys('msg_type') == 'dialog':
                self.show_dialog()
            elif self.__data.get_sys('msg_type') == 'popup':
                self.show_popup()
            # Remaining minutes as text.
            remain = self.get_text_minutes(self.__seconds)
        # Systemtray
        if self.__indstatus:
            # Application indicator
            self.__ind.set_remain_time(remain)
        else:
            # wx.TaskBarIcon
            self.__tbicon.set_remain_time(remain)

    def pygame_sound(self):
        '''Play the 'soundfile' with Pygame.'''
        if self.__sound:
            # Soundfile is set, play sound.
            if self.__sound.endswith('.wav') or \
               self.__sound.endswith('.ogg'):
                pygame.init()
                mixer = pygame.mixer.Sound(self.__sound)
                mixer.play()
            elif self.__sound.endswith('.mp3'):
                pygame.init()
                pygame.mixer.music.load(self.__sound)
                pygame.mixer.music.play()

    def set_integer_interval(self, interval):
        '''Control value of time interval and set it to the entry.'''
        # Check interval
        if interval != 'dev':
            minimum = self.__data.get_sys('min_interval')
            maximum = self.__data.get_sys('max_interval')
            if interval < minimum:
                interval = minimum
            elif interval > maximum:
                interval = maximum
            self.__txtinterval.SetValue(str(interval))
            # Set current value as new default value.
            self.__interval = interval

    def set_in18(self):
        '''Set the internationalization.'''
        # Get directory
        dir_ = os.path.join(self.__dir, 'locale')
        # Locale, set default language.
        self.__wxloc = wx.Locale(wx.LANGUAGE_DEFAULT)
        self.__wxloc.AddCatalogLookupPathPrefix(dir_)
        self.__wxloc.AddCatalog('mfc1')

    def show_dialog(self):
        '''Show the text notification dialogue.'''
        text = self.__msgtext.GetValue()
        if text:
            # Text is set, show dialog.
            title = self.__data.get_sys('msg_title')
            size = self.__data.get_user('msg_size')
            icon = os.path.join(self.__dir, self.__data.get_sys('icon_close'))
            font = self.__data.get_sys('msg_font')
            dlg = Msg(parent=self,
                      title=title,
                      size=size,
                      icon=icon,
                      text=text,
                      font=font)
            dlg.ShowModal()
            # Set dialog size
            size = dlg.GetSize()
            self.__data.set_user('msg_size', (size[0], size[1]))
            # Destroy dialogue.
            dlg.Destroy()

    def show_popup(self):
        '''Show the text notification popup.'''
        text = self.__msgtext.GetValue()
        if text:
            # Text is set, show dialog.
            font = self.__data.get_sys('msg_font')
            colors = self.__data.get_sys('popup_colors')
            icon = os.path.join(self.__dir, self.__data.get_sys('icon_close'))
            popup = Popup(parent=self,
                          style=self.__bdist,
                          text=text,
                          font=font,
                          colors=colors,
                          icon=icon)
            popw, poph = popup.get_size()
            dispw, disph = wx.GetDisplaySize()
            offx = (dispw - popw) / 2
            offy = (disph - poph) / 2
            popup.Position(ptOrigin=(0, 0), size=(offx, offy))
            popup.Popup()