Beispiel #1
0
 def __init__(self, parent, logFile):
     wx.Dialog.__init__(self, parent, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER)
     
     self.SetIcon(APP_logo)
     
     self.LogFile = FileItem(logFile)
     self.SetTitle()
     
     self.LogPollThread = Thread(self.PollLogFile)
     
     self.DspLog = TextAreaPanel(self, style=wx.TE_READONLY)
     self.DspLog.font_size = 8
     self.DspLog.SetFont(GetMonospacedFont(self.DspLog.font_size))
     
     btn_open = CreateButton(self, btnid.BROWSE, GT(u'Open and Display Log File'), u'browse')
     btn_font = CreateButton(self, btnid.ZOOM, GT(u'Zoom Text'), u'zoom')
     btn_refresh = CreateButton(self, btnid.REFRESH, GT(u'Refresh'), u'refresh')
     btn_hide = CreateButton(self, btnid.CLOSE, GT(u'Hide'), u'hide')
     
     # *** Event Handling *** #
     
     EVT_REFRESH_LOG(self, wx.ID_ANY, self.OnLogTimestampChanged)
     
     wx.EVT_BUTTON(self, btnid.BROWSE, self.OnOpenLogFile)
     wx.EVT_BUTTON(self, btnid.ZOOM, self.OnChangeFont)
     wx.EVT_BUTTON(self, btnid.REFRESH, self.RefreshLog)
     wx.EVT_BUTTON(self, btnid.CLOSE, self.OnClose)
     
     wx.EVT_CLOSE(self, self.OnClose)
     wx.EVT_SHOW(self, self.OnShow)
     wx.EVT_SHOW(GetMainWindow(), self.OnShowMainWindow)
     
     # *** Layout *** #
     
     layout_btnF1 = wx.FlexGridSizer(cols=5)
     layout_btnF1.AddGrowableCol(1, 1)
     layout_btnF1.Add(btn_open, 0, wx.LEFT, 5)
     layout_btnF1.AddStretchSpacer(1)
     layout_btnF1.Add(btn_font, 0, wx.RIGHT, 5)
     layout_btnF1.Add(btn_refresh, 0, wx.RIGHT, 5)
     layout_btnF1.Add(btn_hide, 0, wx.RIGHT, 5)
     
     layout_mainV1 = BoxSizer(wx.VERTICAL)
     layout_mainV1.Add(self.DspLog, 1, wx.ALL|wx.EXPAND, 5)
     layout_mainV1.Add(layout_btnF1, 0, wx.EXPAND|wx.BOTTOM, 5)
     
     self.SetAutoLayout(True)
     self.SetSizer(layout_mainV1)
     self.Layout()
     
     self.SetMinSize(self.GetSize())
     
     self.SetSize(wx.Size(600, 600))
     
     self.AlignWithMainWindow()
     
     # Make sure log window is not shown at initialization
     self.Show(False)
Beispiel #2
0
 def OnHelp(self, event=None):  #@UnusedVariable
     if u'alpha' in GetTestList():
         HelpDialog(self).ShowModal()
     else:
         # FIXME: files should be re-cached when Debreate upgraded to new version
         # TODO: trim unneeded text
         cached = False
         manual_cache = ConcatPaths(PATH_cache, u'manual')
         manual_index = ConcatPaths(manual_cache, u'index.html')
         if not os.path.isdir(manual_cache):
             os.makedirs(manual_cache)
         elif os.path.isfile(manual_index):
             cached = True
         url_manual = u'https://debreate.wordpress.com/manual/'
         # NOTE: use urllib.request.urlopen for Python 3
         manual_data = urllib.urlopen(url_manual)
         url_state = manual_data.getcode()
         if url_state == 200:
             # cache files
             if not cached:
                 self.progress = ProgressDialog(
                     self,
                     message=GT(u'Caching manual files'),
                     style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)
                 self.Disable()
                 self.timer.Start(100)
                 Thread(self.__cacheManualFiles, (
                     url_manual,
                     manual_cache,
                     manual_index,
                 )).Start()
                 self.progress.ShowModal()
             manual_dialog = wx.Dialog(self,
                                       title=u'Debreate Manual',
                                       size=(800, 500),
                                       style=wx.DEFAULT_DIALOG_STYLE
                                       | wx.RESIZE_BORDER)
             manual = wx.html.HtmlWindow(manual_dialog)
             wx.Yield()
             if manual.LoadFile(manual_index):
                 manual_dialog.CenterOnParent()
                 manual_dialog.ShowModal()
             else:
                 wx.Yield()
                 webbrowser.open(url_manual)
             manual_dialog.Destroy()
         else:
             # open local document
             wx.Yield()
             subprocess.call(
                 [u'xdg-open', u'{}/docs/usage.pdf'.format(PATH_app)])
Beispiel #3
0
    def OnBuild(self, event=None):
        stage = self.input_stage.GetValue()
        target = self.input_target.GetValue().rstrip(u'/')

        # Attempt to use DEBIAN/control file to set output filename. This is normally
        # done automatically by the dpkg command, but we need to set it manually to
        # check for overwriting a file.
        if os.path.isdir(target):
            control_file = ConcatPaths((stage, u'DEBIAN/control'))
            if os.path.isfile(control_file):
                control_lines = ReadFile(control_file, split=True)

                name = None
                version = None
                arch = None

                for LINE in control_lines:
                    if LINE.startswith(u'Package:'):
                        name = LINE.replace(u'Package: ', u'').strip()

                    elif LINE.startswith(u'Version:'):
                        version = LINE.replace(u'Version: ', u'').strip()

                    elif LINE.startswith(u'Architecture:'):
                        arch = LINE.replace(u'Architecture: ', u'').strip()

                if name and version and arch:
                    target = ConcatPaths((target, u'{}.deb'.format(u'_'.join((
                        name,
                        version,
                        arch,
                    )))))

        # Automatically add .deb filename extension if not present
        elif not target.lower().endswith(u'.deb'):
            target = u'{}.deb'.format(target)

        if not os.path.isdir(stage):
            ShowErrorDialog(GT(u'Stage directory does not exist'), stage, self,
                            True)
            return

        target_path = os.path.dirname(target)
        if not os.path.isdir(target_path):
            ShowErrorDialog(GT(u'Target directory does not exist'),
                            target_path, self, True)
            return

        elif not os.access(target_path, os.W_OK):
            ShowErrorDialog(GT(u'No write access to target directory'),
                            target_path, self, True)
            return

        # Update the text input if target altered
        if target != self.input_target.GetValue():
            self.input_target.SetValue(target)

        # Check for pre-existing file
        if os.path.isfile(target):
            if not OverwriteDialog(self, target).Confirmed():
                return

        self.SetTitle(u'{} ({})'.format(self.title, GT(u'in progress')))

        # Don't allow dialog to be closed while build in progress
        self.Disable()
        self.timer.Start(100)

        # Start new thread for background process
        Thread(self.Build, stage, target).Start()
Beispiel #4
0
class LogWindow(wx.Dialog):
    def __init__(self, parent, logFile):
        wx.Dialog.__init__(self,
                           parent,
                           style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)

        self.SetIcon(APP_logo)

        self.LogFile = FileItem(logFile)
        self.SetTitle()

        self.LogPollThread = Thread(self.PollLogFile)

        self.DspLog = TextAreaPanel(self, style=wx.TE_READONLY)
        self.DspLog.font_size = 8
        self.DspLog.SetFont(GetMonospacedFont(self.DspLog.font_size))

        btn_open = CreateButton(self, btnid.BROWSE,
                                GT(u'Open and Display Log File'), u'browse')
        btn_font = CreateButton(self, btnid.ZOOM, GT(u'Zoom Text'), u'zoom')
        btn_refresh = CreateButton(self, btnid.REFRESH, GT(u'Refresh'),
                                   u'refresh')
        btn_hide = CreateButton(self, btnid.CLOSE, GT(u'Hide'), u'hide')

        # *** Event Handling *** #

        EVT_REFRESH_LOG(self, wx.ID_ANY, self.OnLogTimestampChanged)

        wx.EVT_BUTTON(self, btnid.BROWSE, self.OnOpenLogFile)
        wx.EVT_BUTTON(self, btnid.ZOOM, self.OnChangeFont)
        wx.EVT_BUTTON(self, btnid.REFRESH, self.RefreshLog)
        wx.EVT_BUTTON(self, btnid.CLOSE, self.OnClose)

        wx.EVT_CLOSE(self, self.OnClose)
        wx.EVT_SHOW(self, self.OnShow)
        wx.EVT_SHOW(GetMainWindow(), self.OnShowMainWindow)

        # *** Layout *** #

        layout_btnF1 = wx.FlexGridSizer(cols=5)
        layout_btnF1.AddGrowableCol(1, 1)
        layout_btnF1.Add(btn_open, 0, wx.LEFT, 5)
        layout_btnF1.AddStretchSpacer(1)
        layout_btnF1.Add(btn_font, 0, wx.RIGHT, 5)
        layout_btnF1.Add(btn_refresh, 0, wx.RIGHT, 5)
        layout_btnF1.Add(btn_hide, 0, wx.RIGHT, 5)

        layout_mainV1 = BoxSizer(wx.VERTICAL)
        layout_mainV1.Add(self.DspLog, 1, wx.ALL | wx.EXPAND, 5)
        layout_mainV1.Add(layout_btnF1, 0, wx.EXPAND | wx.BOTTOM, 5)

        self.SetAutoLayout(True)
        self.SetSizer(layout_mainV1)
        self.Layout()

        self.SetMinSize(self.GetSize())

        self.SetSize(wx.Size(600, 600))

        self.AlignWithMainWindow()

        # Make sure log window is not shown at initialization
        self.Show(False)

    ## Positions the log window relative to the main window
    def AlignWithMainWindow(self):
        debreate_pos = GetMainWindow().GetPosition()
        width = self.GetSize()[0]
        posX = debreate_pos[0] - width
        posY = debreate_pos[1]

        self.SetPosition(wx.Point(posX, posY))

    ## Hides the log window & clears contents
    def HideLog(self):
        self.Show(False)
        self.DspLog.Clear()

    ## Changes the font size
    def OnChangeFont(self, event=None):
        font_sizes = {
            7: 8,
            8: 10,
            10: 7,
        }

        current_font_size = self.DspLog.font_size

        for S in font_sizes:
            if S == current_font_size:
                self.DspLog.SetFont(GetMonospacedFont(font_sizes[S]))
                self.DspLog.font_size = font_sizes[S]

                return

        Logger.Error(__name__, GT(u'Can\'t change log window font'))

    ## Hides the log window when close event occurs
    def OnClose(self, event=None):
        self.HideLog()

    ## Called by refresh event to update the log display
    def OnLogTimestampChanged(self, event=None):
        self.RefreshLog()

    ## Opens a new log file
    def OnOpenLogFile(self, event=None):
        log_select = GetFileOpenDialog(self,
                                       GT(u'Open Log'),
                                       directory=PATH_logs)

        if ShowDialog(log_select):
            logFile = log_select.GetPath()

            if os.path.isfile(logFile):
                self.SetLogFile(logFile)

                return

            ShowErrorDialog(u'{}: {}'.format(GT(u'File does not exist'),
                                             logFile),
                            parent=self)

    ## Guarantees that menu item is synced with window's shown status
    def OnShow(self, event=None):
        menu_debug = GetMenu(menuid.DEBUG)

        # In case main window has been destroyed, but sub thread still active
        if GetMainWindow():
            window_shown = self.IsShown()
            m_checked = menu_debug.IsChecked(menuid.LOG)

            if m_checked != window_shown:
                menu_debug.Check(menuid.LOG, window_shown)

        else:
            Logger.Warn(__name__, u'Log thread still active!')

    ## Use an event to show the log window
    #
    #  By waiting until the main window emits a show event
    #	a separate item is not added in the system window
    #	list for the log.
    def OnShowMainWindow(self, event=None):
        main_window = GetMainWindow()

        # Make sure the main window has not been destroyed before showing log
        if main_window and main_window.IsShown():
            if GetMenu(menuid.DEBUG).IsChecked(menuid.LOG):
                self.ShowLog()

    ## Toggles the log window shown or hidden
    def OnToggleWindow(self, event=None):
        show = GetMenu(menuid.DEBUG).IsChecked(menuid.LOG)

        if show:
            self.ShowLog()
            return

        self.HideLog()

        if event:
            event.Skip(True)

    ## Creates a thread that polls for changes in log file
    def PollLogFile(self, args=None):
        while self and self.IsShown():
            if self.LogFile.TimestampChanged():
                print(u'Log timestamp changed, loading new log ...')

                wx.PostEvent(self, RefreshLogEvent(0))

            time.sleep(LOG_WINDOW_REFRESH_INTERVAL)

    ## Fills log with text file contents
    def RefreshLog(self, event=None):
        if self.LogFile.IsFile():
            log_data = self.LogFile.Read()

            if not self.DspLog.IsEmpty():
                self.DspLog.Clear()

            self.DspLog.SetValue(log_data)

            try:
                # Yield here to make sure last line is displayed
                # FIXME: Causes delay when debug enabled
                wx.SafeYield()
                self.DspLog.ShowPosition(self.DspLog.GetLastPosition())

            except wx.PyDeadObjectError:
                tb_error = GS(traceback.format_exc())

                Logger.Warn(
                    __name__,
                    u'Error refreshing log window. Details below:\n\n{}'.
                    format(tb_error))

    ## Changes the file to be loaded & displayed
    #
    #  \param logFile
    #	Absolute path of file to load
    def SetLogFile(self, logFile):
        self.LogFile = FileItem(logFile)
        self.RefreshLog()
        self.SetTitle()

    ## Updates the window's title using path of log file
    def SetTitle(self):
        new_title = self.LogFile.GetPath()
        if new_title:
            return wx.Dialog.SetTitle(self, new_title)

    ## Shows the log window
    def ShowLog(self):
        self.RefreshLog()
        self.Show(True)

        if not self.LogPollThread.IsActive():
            Logger.Debug(__name__, u'Starting log polling thread ...')

            self.LogPollThread.Start()

        else:
            Logger.Debug(__name__, u'Log polling thread is already started')
Beispiel #5
0
    def OnUpdateCache(self, event=None):
        try:
            # Timer must be started before executing new thread
            self.timer.Start(100)

            if not self.timer.IsRunning():
                self.error_message = GT(
                    u'Could not start progress dialog timer')
                self.CheckErrors()
                return False

            self.Disable()

            # Start new thread for updating cache in background
            Thread(self.UpdateCache, None).Start()

            # Create the progress dialog & start timer
            # NOTE: Progress dialog is reset by timer stop event
            self.progress = ProgressDialog(
                self,
                message=GT(u'Contacting remote sites'),
                style=wx.PD_APP_MODAL | wx.PD_AUTO_HIDE)

            # Use ShowModal to wait for timer to stop before continuing
            self.progress.ShowModal()

            self.Enable()

            if self.CheckErrors():
                return False

            # FIXME: Should check timestamps to make sure file was updated
            cache_updated = os.path.isfile(FILE_distnames)

            if cache_updated:
                distname_input = GetField(pgid.CHANGELOG, inputid.DIST)

                if isinstance(distname_input, OwnerDrawnComboBox):
                    distname_input.Set(GetOSDistNames())

                else:
                    ShowMessageDialog(GT(
                        u'The distribution names cache has been updated but Debreate needs to restart to reflect the changes on the changelog page'
                    ),
                                      parent=self,
                                      linewrap=410)

            self.btn_preview.Enable(cache_updated)

            return cache_updated

        except:
            # Make sure dialog is re-enabled
            self.Enable()

            # Make sure progress dialog & background thread instances are reset to None
            if self.progress:
                self.progress.EndModal(0)
                self.progress = None

            cache_exists = os.path.isfile(FILE_distnames)

            err_msg = GT(
                u'An error occurred when trying to update the distribution names cache'
            )
            err_msg2 = GT(
                u'The cache file exists but may not have been updated')
            if cache_exists:
                err_msg = u'{}\n\n{}'.format(err_msg, err_msg2)

            ShowErrorDialog(err_msg, traceback.format_exc(), self)

            self.btn_preview.Enable(cache_exists)

        return False