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)
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)])
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()
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')
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