def CreateDetailedView(self, details): # Controls have not been constructed yet if TextIsEmpty(self.details): self.btn_details = wx.ToggleButton(self, label=GT(u'Details')) #btn_copy = wx.Button(self, label=GT(u'Copy details')) self.dsp_details = TextAreaPanel(self, value=details, style=wx.TE_READONLY) # *** Event handlers *** # self.btn_details.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleDetails) #btn_copy.Bind(wx.EVT_BUTTON, self.OnCopyDetails) layout = self.GetSizer() layout.Add(self.btn_details, (2, 1)) #layout.Add(btn_copy, (2, 2), flag=wx.ALIGN_LEFT|wx.RIGHT, border=5) layout.Add(self.dsp_details, (3, 1), (1, 2), wx.EXPAND | wx.RIGHT, 5) self.ToggleDetails() if not TextIsEmpty(details): for C in self.GetChildren(): if isinstance(C, TextAreaPanel): self.details = details C.SetValue(self.details) return True return False
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 SetModeManual(self): self.ManualText = TextAreaPanel(self) # *** Layout *** # self.lyt_main.Add(self.lyt_buttons, 0, wx.EXPAND | wx.ALL, 5) self.lyt_main.Add(self.ManualText, 1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(self.lyt_main) self.Layout()
def __init__(self, parent=None, ID=wx.ID_ANY, title=GT(u'Preview'), text=wx.EmptyString, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_DIALOG_STYLE, name=wx.DialogNameStr, monospace=True, readonly=True): BaseDialog.__init__(self, parent, ID, title, pos, size, style, name) ti_style = 0 if readonly: ti_style = wx.TE_READONLY # FIXME: Hide caret text_display = TextAreaPanel(self, monospace=monospace, style=ti_style) if text: text_display.SetValue(text) # *** Event Handling *** # self.Bind(wx.EVT_BUTTON, self.OnButton) # *** Layout *** # lyt_main = BoxSizer(wx.VERTICAL) lyt_main.Add(text_display, 1, wx.EXPAND | lyt.PAD_LR | wx.BOTTOM, 5) self.SetAutoLayout(True) self.SetSizer(lyt_main) self.Layout()
def GetObject(self, section_name=None, multiline=False, static=False, expand=False, removable=False): if static: try: self.sect_name = wx.StaticText(self.Parent, label=section_name) except TypeError: err_l1 = GT(u'Could not remove section') err_l2 = GT(u'Please report this problem to the developers') ShowErrorDialog(u'{}\n\n{}'.format(err_l1, err_l2), traceback.format_exc()) return None else: self.sect_name = Choice(self.Parent, choices=self.sections) if multiline: value = TextAreaPanel(self.Parent) FLAG_VALUE = wx.EXPAND | wx.LEFT FLAG_LABEL = wx.ALIGN_TOP else: value = TextArea(self.Parent) FLAG_VALUE = wx.ALIGN_CENTER_VERTICAL | wx.LEFT FLAG_LABEL = wx.ALIGN_CENTER_VERTICAL self.lyt_main.Add(self.sect_name, (0, 0), flag=FLAG_LABEL) self.lyt_main.Add(value, (0, 1), flag=FLAG_VALUE, border=5) if expand: self.lyt_main.AddGrowableCol(1) if removable: self.btn_remove = CreateButton(self.Parent, btnid.REMOVE) self.lyt_main.Add(self.btn_remove, (0, 2), flag=wx.RIGHT, border=5) return ManSectBase.GetObject(self)
def __init__(self, parent, label=None, style=DEFAULT_MANSECT_STYLE): ManSectBase2.__init__(self, parent, label, style) FLAGS = wx.EXPAND | wx.LEFT | wx.ALIGN_CENTER_VERTICAL FLAGS_MAIN = wx.ALIGN_CENTER_VERTICAL if self.HasStyle(manid.MULTILINE): self.Input = TextAreaPanel(self.Panel) #FLAGS = wx.EXPAND|FLAGS FLAGS_MAIN = wx.EXPAND | FLAGS_MAIN else: self.Input = TextArea(self.Panel) lyt_input = BoxSizer(wx.VERTICAL) lyt_input.Add(self.Input, 1, FLAGS, 5) #lyt_input = wx.GridBagSizer() #lyt_input.AddGrowableCol(0) #lyt_input.Add(self.Input, (0, 0), flag=FLAGS, border=5) lyt_main = self.GetSizer() lyt_main.Insert(1, lyt_input, 3, FLAGS_MAIN)
def __init__(self, parent): ManSectBase.__init__(self, parent) self._add_field(GT(u'Synopsis'), TextAreaPanel(parent), expand=True)
def __init__(self, parent): WizardPage.__init__(self, parent, pgid.CHANGELOG) txt_package = wx.StaticText(self, label=GT(u'Package'), name=u'package') self.ti_package = TextArea(self, inputid.PACKAGE, name=txt_package.Name) txt_version = wx.StaticText(self, label=GT(u'Version'), name=u'version') self.ti_version = TextArea(self, inputid.VERSION, name=txt_version.Name) dist_names = GetOSDistNames() txt_dist = wx.StaticText(self, label=GT(u'Distribution'), name=u'dist') if dist_names: self.ti_dist = ComboBox(self, inputid.DIST, choices=dist_names, name=txt_dist.Name) # Use regular text input if could not retrieve distribution names list else: self.ti_dist = TextArea(self, inputid.DIST, name=txt_dist.Name) opts_urgency = ( u'low', u'medium', u'high', u'emergency', ) txt_urgency = wx.StaticText(self, label=GT(u'Urgency'), name=u'urgency') self.sel_urgency = Choice(self, selid.URGENCY, choices=opts_urgency, name=txt_urgency.Name) txt_maintainer = wx.StaticText(self, label=GT(u'Maintainer'), name=u'maintainer') self.ti_maintainer = TextArea(self, inputid.MAINTAINER, name=txt_maintainer.Name) txt_email = wx.StaticText(self, label=GT(u'Email'), name=u'email') self.ti_email = TextArea(self, inputid.EMAIL, name=txt_email.Name) btn_import = CreateButton(self, btnid.IMPORT, GT(u'Import'), u'import', name=u'btn import') txt_import = wx.StaticText( self, label=GT(u'Import information from Control page')) # Changes input self.ti_changes = TextAreaPanel(self, size=(20, 150), name=u'changes') # *** Target installation directory # FIXME: Should this be set by config or project file??? self.pnl_target = FileOTarget(self, u'/usr/share/doc/<package>', name=u'target default', defaultType=CheckBoxESS, customType=PathCtrlESS, pathIds=( chkid.TARGET, inputid.TARGET, )) self.btn_add = CreateButton(self, btnid.ADD, GT(u'Add'), u'add', name=u'btn add') txt_add = wx.StaticText(self, label=GT(u'Insert new changelog entry')) self.chk_indentation = CheckBox(self, label=GT(u'Preserve indentation'), name=u'indent') self.dsp_changes = TextAreaPanelESS(self, inputid.CHANGES, monospace=True, name=u'log') self.dsp_changes.EnableDropTarget() SetPageToolTips(self) # *** Event Handling *** # btn_import.Bind(wx.EVT_BUTTON, self.OnImportFromControl) self.btn_add.Bind(wx.EVT_BUTTON, self.AddInfo) # *** Layout *** # LEFT_BOTTOM = lyt.ALGN_LB LEFT_CENTER = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL RIGHT_CENTER = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL lyt_info = wx.FlexGridSizer(2, 6) lyt_info.AddGrowableCol(1) lyt_info.AddGrowableCol(3) lyt_info.AddGrowableCol(5) lyt_info.AddMany( ((txt_package, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_package, 1, wx.EXPAND | wx.BOTTOM | wx.RIGHT, 5), (txt_version, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_version, 1, wx.EXPAND | wx.BOTTOM | wx.RIGHT, 5), (txt_dist, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_dist, 1, wx.EXPAND | wx.BOTTOM, 5), (txt_urgency, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.sel_urgency, 1, wx.RIGHT, 5), (txt_maintainer, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_maintainer, 1, wx.EXPAND | wx.RIGHT, 5), (txt_email, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_email, 1, wx.EXPAND))) lyt_details = wx.GridBagSizer() lyt_details.SetCols(3) lyt_details.AddGrowableRow(2) lyt_details.AddGrowableCol(1) lyt_details.Add(btn_import, (0, 0)) lyt_details.Add(txt_import, (0, 1), flag=LEFT_CENTER) lyt_details.Add(wx.StaticText(self, label=GT(u'Changes')), (1, 0), flag=LEFT_BOTTOM) lyt_details.Add(wx.StaticText(self, label=GT(u'Target')), (1, 2), flag=LEFT_BOTTOM) lyt_details.Add(self.ti_changes, (2, 0), (1, 2), wx.EXPAND | wx.RIGHT, 5) lyt_details.Add(self.pnl_target, (2, 2)) lyt_details.Add(self.btn_add, (3, 0), (2, 1)) lyt_details.Add(txt_add, (3, 1), flag=LEFT_BOTTOM | wx.TOP, border=5) lyt_details.Add(self.chk_indentation, (4, 1), flag=LEFT_BOTTOM) lyt_main = BoxSizer(wx.VERTICAL) lyt_main.AddSpacer(10) lyt_main.Add(lyt_info, 0, wx.EXPAND | lyt.PAD_LR, 5) lyt_main.AddSpacer(10) lyt_main.Add(lyt_details, 1, wx.EXPAND | lyt.PAD_LR, 5) lyt_main.Add(wx.StaticText(self, label=u'Changelog Output'), 0, LEFT_BOTTOM | lyt.PAD_LT, 5) lyt_main.Add(self.dsp_changes, 1, wx.EXPAND | lyt.PAD_LR | wx.BOTTOM, 5) self.SetAutoLayout(True) self.SetSizer(lyt_main) self.Layout()
class Page(WizardPage): ## Constructor # # \param parent # Parent <b><i>wx.Window</i></b> instance def __init__(self, parent): WizardPage.__init__(self, parent, pgid.CHANGELOG) txt_package = wx.StaticText(self, label=GT(u'Package'), name=u'package') self.ti_package = TextArea(self, inputid.PACKAGE, name=txt_package.Name) txt_version = wx.StaticText(self, label=GT(u'Version'), name=u'version') self.ti_version = TextArea(self, inputid.VERSION, name=txt_version.Name) dist_names = GetOSDistNames() txt_dist = wx.StaticText(self, label=GT(u'Distribution'), name=u'dist') if dist_names: self.ti_dist = ComboBox(self, inputid.DIST, choices=dist_names, name=txt_dist.Name) # Use regular text input if could not retrieve distribution names list else: self.ti_dist = TextArea(self, inputid.DIST, name=txt_dist.Name) opts_urgency = ( u'low', u'medium', u'high', u'emergency', ) txt_urgency = wx.StaticText(self, label=GT(u'Urgency'), name=u'urgency') self.sel_urgency = Choice(self, selid.URGENCY, choices=opts_urgency, name=txt_urgency.Name) txt_maintainer = wx.StaticText(self, label=GT(u'Maintainer'), name=u'maintainer') self.ti_maintainer = TextArea(self, inputid.MAINTAINER, name=txt_maintainer.Name) txt_email = wx.StaticText(self, label=GT(u'Email'), name=u'email') self.ti_email = TextArea(self, inputid.EMAIL, name=txt_email.Name) btn_import = CreateButton(self, btnid.IMPORT, GT(u'Import'), u'import', name=u'btn import') txt_import = wx.StaticText( self, label=GT(u'Import information from Control page')) # Changes input self.ti_changes = TextAreaPanel(self, size=(20, 150), name=u'changes') # *** Target installation directory # FIXME: Should this be set by config or project file??? self.pnl_target = FileOTarget(self, u'/usr/share/doc/<package>', name=u'target default', defaultType=CheckBoxESS, customType=PathCtrlESS, pathIds=( chkid.TARGET, inputid.TARGET, )) self.btn_add = CreateButton(self, btnid.ADD, GT(u'Add'), u'add', name=u'btn add') txt_add = wx.StaticText(self, label=GT(u'Insert new changelog entry')) self.chk_indentation = CheckBox(self, label=GT(u'Preserve indentation'), name=u'indent') self.dsp_changes = TextAreaPanelESS(self, inputid.CHANGES, monospace=True, name=u'log') self.dsp_changes.EnableDropTarget() SetPageToolTips(self) # *** Event Handling *** # btn_import.Bind(wx.EVT_BUTTON, self.OnImportFromControl) self.btn_add.Bind(wx.EVT_BUTTON, self.AddInfo) # *** Layout *** # LEFT_BOTTOM = lyt.ALGN_LB LEFT_CENTER = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL RIGHT_CENTER = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL lyt_info = wx.FlexGridSizer(2, 6) lyt_info.AddGrowableCol(1) lyt_info.AddGrowableCol(3) lyt_info.AddGrowableCol(5) lyt_info.AddMany( ((txt_package, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_package, 1, wx.EXPAND | wx.BOTTOM | wx.RIGHT, 5), (txt_version, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_version, 1, wx.EXPAND | wx.BOTTOM | wx.RIGHT, 5), (txt_dist, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_dist, 1, wx.EXPAND | wx.BOTTOM, 5), (txt_urgency, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.sel_urgency, 1, wx.RIGHT, 5), (txt_maintainer, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_maintainer, 1, wx.EXPAND | wx.RIGHT, 5), (txt_email, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_email, 1, wx.EXPAND))) lyt_details = wx.GridBagSizer() lyt_details.SetCols(3) lyt_details.AddGrowableRow(2) lyt_details.AddGrowableCol(1) lyt_details.Add(btn_import, (0, 0)) lyt_details.Add(txt_import, (0, 1), flag=LEFT_CENTER) lyt_details.Add(wx.StaticText(self, label=GT(u'Changes')), (1, 0), flag=LEFT_BOTTOM) lyt_details.Add(wx.StaticText(self, label=GT(u'Target')), (1, 2), flag=LEFT_BOTTOM) lyt_details.Add(self.ti_changes, (2, 0), (1, 2), wx.EXPAND | wx.RIGHT, 5) lyt_details.Add(self.pnl_target, (2, 2)) lyt_details.Add(self.btn_add, (3, 0), (2, 1)) lyt_details.Add(txt_add, (3, 1), flag=LEFT_BOTTOM | wx.TOP, border=5) lyt_details.Add(self.chk_indentation, (4, 1), flag=LEFT_BOTTOM) lyt_main = BoxSizer(wx.VERTICAL) lyt_main.AddSpacer(10) lyt_main.Add(lyt_info, 0, wx.EXPAND | lyt.PAD_LR, 5) lyt_main.AddSpacer(10) lyt_main.Add(lyt_details, 1, wx.EXPAND | lyt.PAD_LR, 5) lyt_main.Add(wx.StaticText(self, label=u'Changelog Output'), 0, LEFT_BOTTOM | lyt.PAD_LT, 5) lyt_main.Add(self.dsp_changes, 1, wx.EXPAND | lyt.PAD_LR | wx.BOTTOM, 5) self.SetAutoLayout(True) self.SetSizer(lyt_main) self.Layout() ## Formats input text from 'changes' field for new entry in changelog def AddInfo(self, event=None): new_changes = self.ti_changes.GetValue() if TextIsEmpty(new_changes): DetailedMessageDialog( GetMainWindow(), GT(u'Warning'), ICON_WARNING, GT(u'"Changes" section is empty')).ShowModal() self.ti_changes.SetInsertionPointEnd() self.ti_changes.SetFocus() return package = self.ti_package.GetValue() version = self.ti_version.GetValue() dist = self.ti_dist.GetValue() urgency = self.sel_urgency.GetStringSelection() maintainer = self.ti_maintainer.GetValue() email = self.ti_email.GetValue() new_changes = FormatChangelog(new_changes, package, version, dist, urgency, maintainer, email, self.chk_indentation.GetValue()) # Clean up leading & trailing whitespace in old changes old_changes = self.dsp_changes.GetValue().strip(u' \t\n\r') # Only append newlines if log isn't already empty if not TextIsEmpty(old_changes): new_changes = u'{}\n\n\n{}'.format(new_changes, old_changes) # Add empty line to end of log if not new_changes.endswith(u'\n'): new_changes = u'{}\n'.format(new_changes) self.dsp_changes.SetValue(new_changes) # Clear "Changes" text self.ti_changes.Clear() self.ti_changes.SetFocus() ## Exports page's data to file # # \param out_dir # Target directory where file will be written # \out_name # Filename of output file # \compress # If <b><i>True</i></b>, compresses file with gzip def Export(self, out_dir, out_name=wx.EmptyString, compress=False): ret_value = WizardPage.Export(self, out_dir, out_name=out_name) absolute_filename = u'{}/{}'.format(out_dir, out_name).replace(u'//', u'/') CMD_gzip = GetExecutable(u'gzip') if compress and CMD_gzip: commands.getstatusoutput(u'{} -n9 "{}"'.format( CMD_gzip, absolute_filename)) return ret_value ## Export instructions specifically for build phase # # \param stage # Formatted staged directory where file heirarchy is temporarily kept # \return # <b><i>Tuple</i></b> containing a return code & string value of page data def ExportBuild(self, stage): target = self.pnl_target.GetPath() if target == self.pnl_target.GetDefaultPath(): target.replace(u'<package>', GetFieldValue(pgid.CONTROL, inputid.PACKAGE)) stage = ConcatPaths((stage, target)) if not os.path.isdir(stage): os.makedirs(stage) # FIXME: Allow user to set filename self.Export(stage, u'changelog', True) export_summary = GT(u'Changelog export failed') changelog = ConcatPaths((stage, u'changelog.gz')) if os.path.isfile(changelog): export_summary = GT(u'Changelog export to: {}').format(changelog) return (0, export_summary) ## Retrieves changelog text # # The output is a text file that uses sections defined by braces ([, ]) # # \param getModule # If <b><i>True</i></b>, returns a <b><i>tuple</b></i> of the module name # & page data, otherwise return only page data string # \return # <b><i>tuple(str, str)</i></b>: Filename & formatted string of changelog target & body def Get(self, getModule=False): target = self.pnl_target.GetPath() if target == self.pnl_target.GetDefaultPath(): target = u'DEFAULT' body = self.dsp_changes.GetValue() if TextIsEmpty(body): page = None else: page = u'[TARGET={}]\n\n[BODY]\n{}'.format(target, body) if getModule: page = ( __name__, page, ) return page ## Retrieves plain text of the changelog field # # \return # Formatted changelog text def GetChangelog(self): return self.dsp_changes.GetValue() ## Reads & parses page data from a formatted text file # # \param filename # File path to open def ImportFromFile(self, filename): if not os.path.isfile(filename): return dbrerrno.ENOENT clog_data = ReadFile(filename, split=True) sections = {} def parse_section(key, lines): value = u'\n'.join(lines).split(u'\n[')[0] if u'=' in key: key = key.split(u'=') value = (key[-1], value) key = key[0] sections[key] = value # NOTE: This would need to be changed were more sections added to project file for L in clog_data: line_index = clog_data.index(L) if not TextIsEmpty(L) and u'[' in L and u']' in L: L = L.split(u'[')[-1].split(u']')[0] parse_section(L, clog_data[line_index + 1:]) for S in sections: Logger.Debug( __name__, GT(u'Changelog section: "{}", Value:\n{}').format( S, sections[S])) if isinstance(sections[S], (tuple, list)): value_index = 0 for I in sections[S]: Logger.Debug(__name__, GT(u'Value {}: {}').format(value_index, I)) value_index += 1 if S == u'TARGET': Logger.Debug(__name__, u'SECTION TARGET FOUND') if sections[S][0] == u'DEFAULT': Logger.Debug(__name__, u'Using default target') if not self.pnl_target.UsingDefault(): self.pnl_target.Reset() else: Logger.Debug( __name__, GT(u'Using custom target: {}').format(sections[S][0])) self.pnl_target.SetPath(sections[S][0]) continue if S == u'BODY': Logger.Debug(__name__, u'SECTION BODY FOUND') self.dsp_changes.SetValue(sections[S]) continue return 0 ## Checks the page's fields for exporting # # \return # <b><i>False</i></b> if page cannot be exported def IsOkay(self): return not TextIsEmpty(self.dsp_changes.GetValue()) ## Imports select field values from the 'Control' page def OnImportFromControl(self, event=None): fields = ( (self.ti_package, inputid.PACKAGE), (self.ti_version, inputid.VERSION), (self.ti_maintainer, inputid.MAINTAINER), (self.ti_email, inputid.EMAIL), ) for F, FID in fields: field_value = GetFieldValue(pgid.CONTROL, FID) if isinstance(field_value, ErrorTuple): err_msg1 = GT( u'Got error when attempting to retrieve field value') err_msg2 = u'\tError code: {}\n\tError message: {}'.format( field_value.GetCode(), field_value.GetString()) Logger.Error(__name__, u'{}:\n{}'.format(err_msg1, err_msg2)) continue if not TextIsEmpty(field_value): F.SetValue(field_value) ## Sets values of page's fields with given input # # \param data # Text to parse for values def Set(self, data): changelog = data.split(u'\n') target = changelog[0].split(u'<<DEST>>')[1].split(u'<</DEST>>')[0] if target == u'DEFAULT': if not self.pnl_target.UsingDefault(): self.pnl_target.Reset() else: self.pnl_target.SetPath(target) self.dsp_changes.SetValue(u'\n'.join(changelog[1:]))
def __init__(self, parent, size=(600, 558)): wx.Dialog.__init__(self, parent, wx.ID_ABOUT, GT(u'About'), size=size, style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) self.SetMinSize(wx.Size(400, 375)) self.CenterOnParent() # Create a tabbed interface tabs = wx.Notebook(self, -1) # Pages self.t_about = wx.Panel(tabs, -1) t_credits = wx.Panel(tabs, -1) t_changelog = wx.Panel(tabs, -1) t_license = wx.Panel(tabs, -1) # Add pages to tabbed interface tabs.AddPage(self.t_about, GT(u'About')) tabs.AddPage(t_credits, GT(u'Credits')) tabs.AddPage(t_changelog, GT(u'Changelog')) tabs.AddPage(t_license, GT(u'License')) # FIXME: Center verticall on about tab self.about_layout_V1 = BoxSizer(wx.VERTICAL) self.about_layout_V1.AddStretchSpacer() self.about_layout_V1.AddStretchSpacer() self.t_about.SetAutoLayout(True) self.t_about.SetSizer(self.about_layout_V1) self.t_about.Layout() ## List of credits self.credits = ListCtrl(t_credits) self.credits.SetSingleStyle(wx.LC_REPORT) self.credits.InsertColumn(0, GT(u'Name'), width=150) self.credits.InsertColumn(1, GT(u'Job'), width=200) self.credits.InsertColumn(2, GT(u'Email'), width=240) credits_sizer = BoxSizer(wx.VERTICAL) credits_sizer.Add(self.credits, 1, wx.EXPAND) t_credits.SetAutoLayout(True) t_credits.SetSizer(credits_sizer) t_credits.Layout() ## Changelog text area self.changelog = TextAreaPanel(t_changelog, style=wx.TE_READONLY) self.changelog.SetFont(MONOSPACED_MD) log_sizer = BoxSizer(wx.VERTICAL) log_sizer.Add(self.changelog, 1, wx.EXPAND) t_changelog.SetSizer(log_sizer) t_changelog.Layout() ## Licensing information text area self.license = TextAreaPanel(t_license, style=wx.TE_READONLY) self.license.SetFont(MONOSPACED_MD) license_sizer = BoxSizer(wx.VERTICAL) license_sizer.Add(self.license, 1, wx.EXPAND) t_license.SetSizer(license_sizer) t_license.Layout() # System info sys_info = wx.Panel(tabs, -1) tabs.AddPage(sys_info, GT(u'System Information')) ## System's <a href="https://www.python.org/">Python</a> version self.py_info = wx.StaticText( sys_info, -1, GT(u'Python version: {}').format(PY_VER_STRING)) ## System's <a href="https://wxpython.org/">wxPython</a> version self.wx_info = wx.StaticText( sys_info, -1, GT(u'wxPython version: {}').format(WX_VER_STRING)) ## Debreate's installation prefix install_prefix = wx.StaticText( sys_info, label=GT(u'App location: {}').format(PATH_app)) if INSTALLED: install_prefix.SetLabel( GT(u'Installation prefix: {}').format(PREFIX)) self.py_info.SetFont(sys_info_font) self.wx_info.SetFont(sys_info_font) sysinfo_layout_V1 = BoxSizer(wx.VERTICAL) sysinfo_layout_V1.AddStretchSpacer() sysinfo_layout_V1.Add(self.py_info, 0, wx.ALIGN_CENTER | wx.BOTTOM, 5) sysinfo_layout_V1.Add(self.wx_info, 0, wx.ALIGN_CENTER | wx.TOP, 5) sysinfo_layout_V1.AddSpacer(20) sysinfo_layout_V1.Add(install_prefix, 0, wx.ALIGN_CENTER | wx.TOP, 5) sysinfo_layout_V1.AddStretchSpacer() if OS_name: os_info = wx.StaticText(sys_info, label=OS_name) os_info.SetFont(sys_info_font) if OS_version: os_info.SetLabel(u'{} {}'.format(os_info.LabelText, OS_version)) if OS_codename: os_info.SetLabel(u'{} {}'.format(os_info.LabelText, OS_codename)) sysinfo_layout_V1.Insert(1, os_info, 0, wx.ALIGN_CENTER | wx.BOTTOM, 5) sysinfo_layout_V1.InsertSpacer(2, 20) if OS_upstream_name: os_upstream_info = wx.StaticText(sys_info, label=OS_upstream_name) if OS_upstream_version: os_upstream_info.SetLabel(u'{} {}'.format( os_upstream_info.LabelText, OS_upstream_version)) if OS_upstream_codename: os_upstream_info.SetLabel(u'{} {}'.format( os_upstream_info.LabelText, OS_upstream_codename)) sysinfo_layout_V1.Insert(2, os_upstream_info, 0, wx.ALIGN_CENTER | wx.BOTTOM, 5) sys_info.SetSizer(sysinfo_layout_V1) sys_info.Layout() # Button to close the dialog btn_confirm = CreateButton(self, btnid.CONFIRM) sizer = BoxSizer(wx.VERTICAL) sizer.Add(tabs, 1, wx.EXPAND) sizer.Add(btn_confirm, 0, wx.ALIGN_RIGHT | lyt.PAD_RTB, 5) self.SetSizer(sizer) self.Layout()
def __init__(self, parent): WizardPage.__init__(self, parent, pgid.MENU) #, name=GT(u'Menu Launcher')) ## Override default label self.Label = GT(u'Menu Launcher') # --- Buttons to open/preview/save .desktop file btn_open = CreateButton(self, btnid.BROWSE, GT(u'Browse'), u'browse', name=u'btn browse') btn_save = CreateButton(self, btnid.SAVE, GT(u'Save'), u'save', name=u'btn save') btn_preview = CreateButton(self, btnid.PREVIEW, GT(u'Preview'), u'preview', name=u'btn preview') # --- CHECKBOX chk_enable = CheckBox(self, chkid.ENABLE, GT(u'Create system menu launcher')) # --- TYPE opts_type = ( u'Application', u'Link', u'Directory', ) txt_type = wx.StaticText(self, label=GT(u'Type'), name=u'type') ti_type = ComboBoxESS(self, inputid.TYPE, choices=opts_type, name=u'Type', defaultValue=opts_type[0]) # --- ENCODING opts_enc = ( u'UTF-1', u'UTF-7', u'UTF-8', u'CESU-8', u'UTF-EBCDIC', u'UTF-16', u'UTF-32', u'SCSU', u'BOCU-1', u'Punycode', u'GB 18030', ) txt_enc = wx.StaticText(self, label=GT(u'Encoding'), name=u'encoding') ti_enc = ComboBoxESS(self, inputid.ENC, choices=opts_enc, name=u'Encoding', defaultValue=opts_enc[2]) # --- TERMINAL chk_term = CheckBoxESS(self, chkid.TERM, GT(u'Terminal'), name=u'Terminal') # --- STARTUP NOTIFY chk_notify = CheckBoxESS(self, chkid.NOTIFY, GT(u'Startup Notify'), name=u'StartupNotify', defaultValue=True) # --- Custom output filename txt_filename = wx.StaticText(self, txtid.FNAME, GT(u'Filename'), name=u'filename') ti_filename = TextArea(self, inputid.FNAME, name=txt_filename.Name) chk_filename = CheckBox( self, chkid.FNAME, GT(u'Use "Name" as output filename (<Name>.desktop)'), name=u'filename chk', defaultValue=True) # --- NAME (menu) txt_name = wx.StaticText(self, label=GT(u'Name'), name=u'name*') ti_name = TextAreaESS(self, inputid.NAME, name=u'Name') ti_name.req = True # --- EXECUTABLE txt_exec = wx.StaticText(self, label=GT(u'Executable'), name=u'exec') ti_exec = TextAreaESS(self, inputid.EXEC, name=u'Exec') # --- COMMENT txt_comm = wx.StaticText(self, label=GT(u'Comment'), name=u'comment') ti_comm = TextAreaESS(self, inputid.DESCR, name=u'Comment') # --- ICON txt_icon = wx.StaticText(self, label=GT(u'Icon'), name=u'icon') ti_icon = TextAreaESS(self, inputid.ICON, name=u'Icon') txt_mime = wx.StaticText(self, label=GT(u'MIME Type'), name=u'mime') ti_mime = TextAreaESS(self, inputid.MIME, defaultValue=wx.EmptyString, name=u'MimeType') # ----- OTHER/CUSTOM txt_other = wx.StaticText(self, label=GT(u'Custom Fields'), name=u'other') ti_other = TextAreaPanel(self, inputid.OTHER, name=txt_other.Name) ti_other.EnableDropTarget() # --- CATEGORIES opts_category = ( u'2DGraphics', u'Accessibility', u'Application', u'ArcadeGame', u'Archiving', u'Audio', u'AudioVideo', u'BlocksGame', u'BoardGame', u'Calculator', u'Calendar', u'CardGame', u'Compression', u'ContactManagement', u'Core', u'DesktopSettings', u'Development', u'Dictionary', u'DiscBurning', u'Documentation', u'Email', u'FileManager', u'FileTransfer', u'Game', u'GNOME', u'Graphics', u'GTK', u'HardwareSettings', u'InstantMessaging', u'KDE', u'LogicGame', u'Math', u'Monitor', u'Network', u'OCR', u'Office', u'P2P', u'PackageManager', u'Photography', u'Player', u'Presentation', u'Printing', u'Qt', u'RasterGraphics', u'Recorder', u'RemoteAccess', u'Scanning', u'Screensaver', u'Security', u'Settings', u'Spreadsheet', u'System', u'Telephony', u'TerminalEmulator', u'TextEditor', u'Utility', u'VectorGraphics', u'Video', u'Viewer', u'WordProcessor', u'Wine', u'Wine-Programs-Accessories', u'X-GNOME-NetworkSettings', u'X-GNOME-PersonalSettings', u'X-GNOME-SystemSettings', u'X-KDE-More', u'X-Red-Hat-Base', u'X-SuSE-ControlCenter-System', ) txt_category = wx.StaticText(self, label=GT(u'Categories'), name=u'category') # This option does not get set by importing a new project ti_category = ComboBox(self, inputid.CAT, choices=opts_category, name=txt_category.Name, defaultValue=opts_category[0]) btn_catadd = CreateButton(self, btnid.ADD, GT(u'Add'), u'add', name=u'add category') btn_catdel = CreateButton(self, btnid.REMOVE, GT(u'Remove'), u'remove', name=u'rm category') btn_catclr = CreateButton(self, btnid.CLEAR, GT(u'Clear'), u'clear', name=u'clear category') # FIXME: Allow using multi-select + remove lst_categories = ListCtrl(self, listid.CAT, name=u'Categories') # Can't set LC_SINGLE_SEL in constructor for wx 3.0 (ListCtrl bug???) lst_categories.SetSingleStyle(wx.LC_SINGLE_SEL) self.OnToggle() SetPageToolTips(self) # *** Event Handling *** # btn_open.Bind(wx.EVT_BUTTON, self.OnLoadLauncher) btn_save.Bind(wx.EVT_BUTTON, self.OnExportLauncher) btn_preview.Bind(wx.EVT_BUTTON, self.OnPreviewLauncher) chk_enable.Bind(wx.EVT_CHECKBOX, self.OnToggle) chk_filename.Bind(wx.EVT_CHECKBOX, self.OnSetCustomFilename) wx.EVT_KEY_DOWN(ti_category, self.SetCategory) wx.EVT_KEY_DOWN(lst_categories, self.SetCategory) btn_catadd.Bind(wx.EVT_BUTTON, self.SetCategory) btn_catdel.Bind(wx.EVT_BUTTON, self.SetCategory) btn_catclr.Bind(wx.EVT_BUTTON, self.OnClearCategories) # *** Layout *** # LEFT_CENTER = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL LEFT_BOTTOM = lyt.ALGN_LB RIGHT_BOTTOM = wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM lyt_top = BoxSizer(wx.HORIZONTAL) lyt_top.Add(chk_enable, 0, LEFT_BOTTOM) lyt_top.AddStretchSpacer(1) lyt_top.Add(btn_open, 0, wx.ALIGN_TOP) lyt_top.Add(btn_save, 0, wx.ALIGN_TOP) lyt_top.Add(btn_preview, 0, wx.ALIGN_TOP) lyt_opts1 = wx.FlexGridSizer() lyt_opts1.SetCols(3) lyt_opts1.SetRows(2) lyt_opts1.Add(txt_type, 0, LEFT_CENTER) lyt_opts1.Add(ti_type, 0, wx.EXPAND | wx.LEFT, 5) lyt_opts1.Add(chk_term, 0, LEFT_CENTER | wx.LEFT, 5) lyt_opts1.Add(txt_enc, 0, LEFT_CENTER | wx.TOP, 5) lyt_opts1.Add(ti_enc, 0, lyt.PAD_LT, 5) lyt_opts1.Add(chk_notify, 0, LEFT_CENTER | lyt.PAD_LT, 5) lyt_mid = wx.GridBagSizer() lyt_mid.SetCols(4) lyt_mid.AddGrowableCol(1) lyt_mid.AddGrowableCol(3) # Row 1 row = 0 lyt_mid.Add(txt_filename, (row, 0), flag=LEFT_CENTER) lyt_mid.Add(ti_filename, (row, 1), flag=wx.EXPAND | wx.LEFT, border=5) lyt_mid.Add(chk_filename, (row, 2), span=(1, 2), flag=LEFT_CENTER | wx.LEFT, border=5) # Row 2 row += 1 lyt_mid.Add(txt_name, (row, 0), flag=LEFT_CENTER | wx.TOP, border=5) lyt_mid.Add(ti_name, (row, 1), flag=wx.EXPAND | lyt.PAD_LT, border=5) lyt_mid.Add(txt_exec, (row, 2), flag=LEFT_CENTER | lyt.PAD_LT, border=5) lyt_mid.Add(ti_exec, (row, 3), flag=wx.EXPAND | lyt.PAD_LT, border=5) # Row 3 row += 1 lyt_mid.Add(txt_comm, (row, 0), flag=LEFT_CENTER | wx.TOP, border=5) lyt_mid.Add(ti_comm, (row, 1), flag=wx.EXPAND | lyt.PAD_LT, border=5) lyt_mid.Add(txt_icon, (row, 2), flag=LEFT_CENTER | lyt.PAD_LT, border=5) lyt_mid.Add(ti_icon, (row, 3), flag=wx.EXPAND | lyt.PAD_LT, border=5) # Row 4 row += 1 lyt_mid.Add(txt_mime, (row, 0), flag=LEFT_CENTER | wx.TOP, border=5) lyt_mid.Add(ti_mime, (row, 1), flag=wx.EXPAND | lyt.PAD_LT, border=5) lyt_bottom = wx.GridBagSizer() row = 0 lyt_bottom.Add(txt_other, (row, 0), flag=LEFT_BOTTOM) lyt_bottom.Add(txt_category, (row, 2), flag=LEFT_BOTTOM | wx.LEFT, border=5) lyt_bottom.Add(ti_category, (row, 3), flag=LEFT_BOTTOM | wx.LEFT, border=5) lyt_bottom.Add(btn_catadd, (row, 4), flag=RIGHT_BOTTOM) lyt_bottom.Add(btn_catdel, (row, 5), flag=RIGHT_BOTTOM) lyt_bottom.Add(btn_catclr, (row, 6), flag=RIGHT_BOTTOM) row += 1 lyt_bottom.Add(ti_other, (row, 0), (1, 2), wx.EXPAND) lyt_bottom.Add(lst_categories, (row, 2), (1, 5), wx.EXPAND | wx.LEFT, 5) lyt_bottom.AddGrowableRow(1) lyt_bottom.AddGrowableCol(1) lyt_bottom.AddGrowableCol(4) # --- Page 5 Sizer --- # lyt_main = BoxSizer(wx.VERTICAL) lyt_main.AddSpacer(5) lyt_main.Add(lyt_top, 0, wx.EXPAND | lyt.PAD_LR, 5) lyt_main.Add(lyt_opts1, 0, wx.EXPAND | lyt.PAD_LRT, 5) lyt_main.Add(lyt_mid, 0, wx.EXPAND | lyt.PAD_LRT, 5) lyt_main.Add(lyt_bottom, 1, wx.EXPAND | wx.ALL, 5) self.SetAutoLayout(True) self.SetSizer(lyt_main) self.Layout()
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')
class Page(WizardPage): ## Constructor # # \param parent # Parent <b><i>wx.Window</i></b> instance def __init__(self, parent): WizardPage.__init__(self, parent, pgid.CHANGELOG) txt_package = wx.StaticText(self, label=GT(u'Package'), name=u'package') self.ti_package = TextArea(self, inputid.PACKAGE, name=txt_package.Name) txt_version = wx.StaticText(self, label=GT(u'Version'), name=u'version') self.ti_version = TextArea(self, inputid.VERSION, name=txt_version.Name) dist_names = GetOSDistNames() txt_dist = wx.StaticText(self, label=GT(u'Distribution'), name=u'dist') if dist_names: self.ti_dist = ComboBox(self, inputid.DIST, choices=dist_names, name=txt_dist.Name) # Use regular text input if could not retrieve distribution names list else: self.ti_dist = TextArea(self, inputid.DIST, name=txt_dist.Name) opts_urgency = ( u'low', u'medium', u'high', u'emergency', ) txt_urgency = wx.StaticText(self, label=GT(u'Urgency'), name=u'urgency') self.sel_urgency = Choice(self, selid.URGENCY, choices=opts_urgency, name=txt_urgency.Name) txt_maintainer = wx.StaticText(self, label=GT(u'Maintainer'), name=u'maintainer') self.ti_maintainer = TextArea(self, inputid.MAINTAINER, name=txt_maintainer.Name) txt_email = wx.StaticText(self, label=GT(u'Email'), name=u'email') self.ti_email = TextArea(self, inputid.EMAIL, name=txt_email.Name) btn_import = CreateButton(self, btnid.IMPORT, GT(u'Import'), u'import', name=u'btn import') txt_import = wx.StaticText( self, label=GT(u'Import information from Control page')) # Changes input self.ti_changes = TextAreaPanel(self, size=(20, 150), name=u'changes') # *** Target installation directory # FIXME: Should this be set by config or project file??? self.pnl_target = FileOTarget(self, u'/usr/share/doc/<package>', name=u'target default', defaultType=CheckBoxESS, customType=PathCtrlESS, pathIds=( chkid.TARGET, inputid.TARGET, )) self.btn_add = CreateButton(self, btnid.ADD, GT(u'Add'), u'add', name=u'btn add') txt_add = wx.StaticText(self, label=GT(u'Insert new changelog entry')) self.chk_indentation = CheckBox(self, label=GT(u'Preserve indentation'), name=u'indent') self.dsp_changes = TextAreaPanelESS(self, inputid.CHANGES, monospace=True, name=u'log') self.dsp_changes.EnableDropTarget() SetPageToolTips(self) # *** Event Handling *** # btn_import.Bind(wx.EVT_BUTTON, self.OnImportFromControl) self.btn_add.Bind(wx.EVT_BUTTON, self.AddInfo) # *** Layout *** # LEFT_BOTTOM = lyt.ALGN_LB LEFT_CENTER = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL RIGHT_CENTER = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL lyt_info = wx.FlexGridSizer(2, 6) lyt_info.AddGrowableCol(1) lyt_info.AddGrowableCol(3) lyt_info.AddGrowableCol(5) lyt_info.AddMany( ((txt_package, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_package, 1, wx.EXPAND | wx.BOTTOM | wx.RIGHT, 5), (txt_version, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_version, 1, wx.EXPAND | wx.BOTTOM | wx.RIGHT, 5), (txt_dist, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_dist, 1, wx.EXPAND | wx.BOTTOM, 5), (txt_urgency, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.sel_urgency, 1, wx.RIGHT, 5), (txt_maintainer, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_maintainer, 1, wx.EXPAND | wx.RIGHT, 5), (txt_email, 0, RIGHT_CENTER | wx.RIGHT, 5), (self.ti_email, 1, wx.EXPAND))) lyt_details = wx.GridBagSizer() lyt_details.SetCols(3) lyt_details.AddGrowableRow(2) lyt_details.AddGrowableCol(1) lyt_details.Add(btn_import, (0, 0)) lyt_details.Add(txt_import, (0, 1), flag=LEFT_CENTER) lyt_details.Add(wx.StaticText(self, label=GT(u'Changes')), (1, 0), flag=LEFT_BOTTOM) lyt_details.Add(wx.StaticText(self, label=GT(u'Target')), (1, 2), flag=LEFT_BOTTOM) lyt_details.Add(self.ti_changes, (2, 0), (1, 2), wx.EXPAND | wx.RIGHT, 5) lyt_details.Add(self.pnl_target, (2, 2)) lyt_details.Add(self.btn_add, (3, 0), (2, 1)) lyt_details.Add(txt_add, (3, 1), flag=LEFT_BOTTOM | wx.TOP, border=5) lyt_details.Add(self.chk_indentation, (4, 1), flag=LEFT_BOTTOM) lyt_main = BoxSizer(wx.VERTICAL) lyt_main.AddSpacer(10) lyt_main.Add(lyt_info, 0, wx.EXPAND | lyt.PAD_LR, 5) lyt_main.AddSpacer(10) lyt_main.Add(lyt_details, 1, wx.EXPAND | lyt.PAD_LR, 5) lyt_main.Add(wx.StaticText(self, label=u'Changelog Output'), 0, LEFT_BOTTOM | lyt.PAD_LT, 5) lyt_main.Add(self.dsp_changes, 1, wx.EXPAND | lyt.PAD_LR | wx.BOTTOM, 5) self.SetAutoLayout(True) self.SetSizer(lyt_main) self.Layout() ## Formats input text from 'changes' field for new entry in changelog def AddInfo(self, event=None): new_changes = self.ti_changes.GetValue() if TextIsEmpty(new_changes): DetailedMessageDialog( GetMainWindow(), GT(u'Warning'), ICON_WARNING, GT(u'"Changes" section is empty')).ShowModal() self.ti_changes.SetInsertionPointEnd() self.ti_changes.SetFocus() return package = self.ti_package.GetValue() version = self.ti_version.GetValue() dist = self.ti_dist.GetValue() urgency = self.sel_urgency.GetStringSelection() maintainer = self.ti_maintainer.GetValue() email = self.ti_email.GetValue() new_changes = FormatChangelog(new_changes, package, version, dist, urgency, maintainer, email, self.chk_indentation.GetValue()) # Clean up leading & trailing whitespace in old changes old_changes = self.dsp_changes.GetValue().strip(u' \t\n\r') # Only append newlines if log isn't already empty if not TextIsEmpty(old_changes): new_changes = u'{}\n\n\n{}'.format(new_changes, old_changes) # Add empty line to end of log if not new_changes.endswith(u'\n'): new_changes = u'{}\n'.format(new_changes) self.dsp_changes.SetValue(new_changes) # Clear "Changes" text self.ti_changes.Clear() self.ti_changes.SetFocus() ## Retrieves changelog text # # The output is a text file that uses sections defined by braces ([, ]) # # \return # <b><i>tuple(str, str)</i></b>: Filename & formatted string of changelog target & body def Get(self): target = self.pnl_target.GetPath() if target == self.pnl_target.GetDefaultPath(): target = u'STANDARD' return (target, self.GetChangelog()) ## Retrieves plain text of the changelog field # # \return # Formatted changelog text def GetChangelog(self): return self.dsp_changes.GetValue() ## TODO: Doxygen def GetSaveData(self): target = self.pnl_target.GetPath() if target == self.pnl_target.GetDefaultPath(): target = u'<<DEST>>DEFAULT<</DEST>>' else: target = u'<<DEST>>{}<</DEST>>'.format(target) return u'\n'.join((u'<<CHANGELOG>>', target, self.dsp_changes.GetValue(), u'<</CHANGELOG>>')) ## Checks the page's fields for exporting # # \return # <b><i>False</i></b> if page cannot be exported def IsOkay(self): return not TextIsEmpty(self.dsp_changes.GetValue()) ## Imports select field values from the 'Control' page def OnImportFromControl(self, event=None): fields = ( (self.ti_package, inputid.PACKAGE), (self.ti_version, inputid.VERSION), (self.ti_maintainer, inputid.MAINTAINER), (self.ti_email, inputid.EMAIL), ) for F, FID in fields: field_value = GetFieldValue(pgid.CONTROL, FID) if isinstance(field_value, ErrorTuple): err_msg1 = GT( u'Got error when attempting to retrieve field value') err_msg2 = u'\tError code: {}\n\tError message: {}'.format( field_value.GetCode(), field_value.GetString()) Logger.Error(__name__, u'{}:\n{}'.format(err_msg1, err_msg2)) continue if not TextIsEmpty(field_value): F.SetValue(field_value) ## Sets values of page's fields with given input # # \param data # Text to parse for values def Set(self, data): changelog = data.split(u'\n') target = changelog[0].split(u'<<DEST>>')[1].split(u'<</DEST>>')[0] if target == u'DEFAULT': if not self.pnl_target.UsingDefault(): self.pnl_target.Reset() else: self.pnl_target.SetPath(target) self.dsp_changes.SetValue(u'\n'.join(changelog[1:]))
def __init__(self, parent): TextAreaPanel.__init__(self, parent, style=wx.TE_READONLY) self.stdout = sys.stdout self.stderr = sys.stderr
class DetailedMessageDialog(BaseDialog, ButtonDialog): def __init__(self, parent, title=GT(u'Message'), icon=ICON_INFORMATION, text=wx.EmptyString, details=wx.EmptyString, style=wx.DEFAULT_DIALOG_STYLE, buttons=(wx.ID_OK, ), linewrap=0): BaseDialog.__init__(self, parent, wx.ID_ANY, title, style=style) # Allow using strings for 'icon' argument if isinstance(icon, (unicode, str)): icon = wx.Bitmap(icon) icon = wx.StaticBitmap(self, wx.ID_ANY, icon) txt_message = wx.StaticText(self, label=text) if linewrap: txt_message.Wrap(linewrap) # self.details needs to be empty for constructor self.details = wx.EmptyString details = details # *** Layout *** # self.lyt_urls = BoxSizer(wx.VERTICAL) # Only set if buttons are added to dialog self.lyt_buttons = None lyt_main = wx.GridBagSizer(5, 5) lyt_main.SetCols(3) lyt_main.AddGrowableRow(3) lyt_main.AddGrowableCol(2) lyt_main.Add(icon, (0, 0), (5, 1), wx.ALIGN_TOP | lyt.PAD_LR | wx.BOTTOM, 20) lyt_main.Add(txt_message, (0, 1), (1, 2), lyt.PAD_RT, 20) lyt_main.Add(self.lyt_urls, (1, 1), (1, 2), wx.RIGHT, 5) self.SetAutoLayout(True) self.SetSizer(lyt_main) self.AddButtons(buttons) if not TextIsEmpty(details): # self.details will be set here self.CreateDetailedView(details) else: self.Layout() self.Fit() self.SetMinSize(self.GetSize()) self.CenterOnParent() ## Add custom buttons to dialog # # NOTE: Do not call before self.SetSizer # # FIXME: Rename to SetButtons??? # FIXME: Should delete any previous buttons def AddButtons(self, button_ids): self.lyt_buttons = AddCustomButtons(self, button_ids) self.Sizer.Add(self.lyt_buttons, (4, 2), flag=wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM | lyt.PAD_RTB, border=5) ## Adds a clickable link to the dialog def AddURL(self, url): if not isinstance(url, Hyperlink): url = Hyperlink(self, wx.ID_ANY, label=url, url=url) self.lyt_urls.Add(url, 0, wx.ALIGN_CENTER_VERTICAL) self.Layout() self.Fit() self.SetMinSize(self.GetSize()) self.CenterOnParent() ## Shows dialog modal & returns 'confirmed' value # # \return # \b \e bool : True if ShowModal return value one of wx.ID_OK, wx.OK, wx.ID_YES, wx.YES def Confirmed(self): return self.ShowModal() in (wx.ID_OK, wx.OK, wx.ID_YES, wx.YES) ## Adds buttons & details text to dialog # # \param details # \b \e unicode|str : Detailed text to show in dialog def CreateDetailedView(self, details): # Controls have not been constructed yet if TextIsEmpty(self.details): self.btn_details = wx.ToggleButton(self, label=GT(u'Details')) #btn_copy = wx.Button(self, label=GT(u'Copy details')) self.dsp_details = TextAreaPanel(self, value=details, style=wx.TE_READONLY) # *** Event handlers *** # self.btn_details.Bind(wx.EVT_TOGGLEBUTTON, self.ToggleDetails) #btn_copy.Bind(wx.EVT_BUTTON, self.OnCopyDetails) layout = self.GetSizer() layout.Add(self.btn_details, (2, 1)) #layout.Add(btn_copy, (2, 2), flag=wx.ALIGN_LEFT|wx.RIGHT, border=5) layout.Add(self.dsp_details, (3, 1), (1, 2), wx.EXPAND | wx.RIGHT, 5) self.ToggleDetails() if not TextIsEmpty(details): for C in self.GetChildren(): if isinstance(C, TextAreaPanel): self.details = details C.SetValue(self.details) return True return False ## Attempts to retrieve button instance matching btn_id # # FIXME: This will fail if there are standard buttons in the dialog # FIXME: Retrieving by label doesn't work # \param btn_id # ID of the button instance to retrieve # \return # \b \e wx.Button instance or None def GetButton(self, btn_id): # Allow search by label use_label = not isinstance(btn_id, int) if self.lyt_buttons: for sizer in self.lyt_buttons.GetChildren(): sizer = sizer.GetSizer() btn_layout = sizer.GetChildren() if btn_layout: BTN = btn_layout[0].GetWindow() LBL = None if len(btn_layout) < 2 and isinstance(BTN, wx.Button): LBL = BTN.GetLabel() else: LBL = btn_layout[1] if isinstance(LBL, wx.StaticText): LBL = LBL.GetLabel() if not use_label: if BTN.GetId() == btn_id: return BTN else: if LBL == btn_id: return BTN ## TODO: Doxygen # # FIXME: Layout initially wrong # TODO: Allow copying details to clipboard def OnCopyDetails(self, event=None): print(u'DEBUG: Copying details to clipboard ...') DetailedMessageDialog( self, u'FIXME', ICON_EXCLAMATION, u'Copying details to clipboard not functional').ShowModal() return cb_set = False clipboard = wx.Clipboard() if clipboard.Open(): print(u'DEBUG: Clipboard opened') details = wx.TextDataObject(self.dsp_details.GetValue()) print(u'DEBUG: Details set to:\n{}'.format(details.GetText())) clipboard.Clear() print(u'DEBUG: Clipboard cleared') cb_set = clipboard.SetData(details) print(u'DEBUG: Clipboard data set') clipboard.Flush() print(u'DEBUG: Clipboard flushed') clipboard.Close() print(u'DEBUG: Clipboard cloased') del clipboard print(u'DEBUG: Clipboard object deleted') wx.MessageBox(u'FIXME: Details not copied to clipboard', GT(u'Debug')) ## Override inherited method to center on parent window first def ShowModal(self, *args, **kwargs): if self.Parent: self.CenterOnParent() return wx.Dialog.ShowModal(self, *args, **kwargs) ## TODO: Doxygen def SetDetails(self, details): return self.CreateDetailedView(details) ## TODO: Doxygen def ToggleDetails(self, event=None): try: if self.btn_details.GetValue(): self.dsp_details.Show() else: self.dsp_details.Hide() self.Layout() self.Fit() self.SetMinSize(self.GetSize()) return True except AttributeError: # Disable toggling details self.btn_details.Hide() self.Layout() self.Fit() self.SetMinSize(self.GetSize()) return False
class AboutDialog(wx.Dialog): ## Constructor # # \param parent # The <b><i>wx.Window</i></b> parent instance # \param size # Window size <b><i>tuple</i></b> def __init__(self, parent, size=(600, 558)): wx.Dialog.__init__(self, parent, wx.ID_ABOUT, GT(u'About'), size=size, style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER) self.SetMinSize(wx.Size(400, 375)) self.CenterOnParent() # Create a tabbed interface tabs = wx.Notebook(self, -1) # Pages self.t_about = wx.Panel(tabs, -1) t_credits = wx.Panel(tabs, -1) t_changelog = wx.Panel(tabs, -1) t_license = wx.Panel(tabs, -1) # Add pages to tabbed interface tabs.AddPage(self.t_about, GT(u'About')) tabs.AddPage(t_credits, GT(u'Credits')) tabs.AddPage(t_changelog, GT(u'Changelog')) tabs.AddPage(t_license, GT(u'License')) # FIXME: Center verticall on about tab self.about_layout_V1 = BoxSizer(wx.VERTICAL) self.about_layout_V1.AddStretchSpacer() self.about_layout_V1.AddStretchSpacer() self.t_about.SetAutoLayout(True) self.t_about.SetSizer(self.about_layout_V1) self.t_about.Layout() ## List of credits self.credits = ListCtrl(t_credits) self.credits.SetSingleStyle(wx.LC_REPORT) self.credits.InsertColumn(0, GT(u'Name'), width=150) self.credits.InsertColumn(1, GT(u'Job'), width=200) self.credits.InsertColumn(2, GT(u'Email'), width=240) credits_sizer = BoxSizer(wx.VERTICAL) credits_sizer.Add(self.credits, 1, wx.EXPAND) t_credits.SetAutoLayout(True) t_credits.SetSizer(credits_sizer) t_credits.Layout() ## Changelog text area self.changelog = TextAreaPanel(t_changelog, style=wx.TE_READONLY) self.changelog.SetFont(MONOSPACED_MD) log_sizer = BoxSizer(wx.VERTICAL) log_sizer.Add(self.changelog, 1, wx.EXPAND) t_changelog.SetSizer(log_sizer) t_changelog.Layout() ## Licensing information text area self.license = TextAreaPanel(t_license, style=wx.TE_READONLY) self.license.SetFont(MONOSPACED_MD) license_sizer = BoxSizer(wx.VERTICAL) license_sizer.Add(self.license, 1, wx.EXPAND) t_license.SetSizer(license_sizer) t_license.Layout() # System info sys_info = wx.Panel(tabs, -1) tabs.AddPage(sys_info, GT(u'System Information')) ## System's <a href="https://www.python.org/">Python</a> version self.py_info = wx.StaticText( sys_info, -1, GT(u'Python version: {}').format(PY_VER_STRING)) ## System's <a href="https://wxpython.org/">wxPython</a> version self.wx_info = wx.StaticText( sys_info, -1, GT(u'wxPython version: {}').format(WX_VER_STRING)) ## Debreate's installation prefix install_prefix = wx.StaticText( sys_info, label=GT(u'App location: {}').format(PATH_app)) if INSTALLED: install_prefix.SetLabel( GT(u'Installation prefix: {}').format(PREFIX)) self.py_info.SetFont(sys_info_font) self.wx_info.SetFont(sys_info_font) sysinfo_layout_V1 = BoxSizer(wx.VERTICAL) sysinfo_layout_V1.AddStretchSpacer() sysinfo_layout_V1.Add(self.py_info, 0, wx.ALIGN_CENTER | wx.BOTTOM, 5) sysinfo_layout_V1.Add(self.wx_info, 0, wx.ALIGN_CENTER | wx.TOP, 5) sysinfo_layout_V1.AddSpacer(20) sysinfo_layout_V1.Add(install_prefix, 0, wx.ALIGN_CENTER | wx.TOP, 5) sysinfo_layout_V1.AddStretchSpacer() if OS_name: os_info = wx.StaticText(sys_info, label=OS_name) os_info.SetFont(sys_info_font) if OS_version: os_info.SetLabel(u'{} {}'.format(os_info.LabelText, OS_version)) if OS_codename: os_info.SetLabel(u'{} {}'.format(os_info.LabelText, OS_codename)) sysinfo_layout_V1.Insert(1, os_info, 0, wx.ALIGN_CENTER | wx.BOTTOM, 5) sysinfo_layout_V1.InsertSpacer(2, 20) if OS_upstream_name: os_upstream_info = wx.StaticText(sys_info, label=OS_upstream_name) if OS_upstream_version: os_upstream_info.SetLabel(u'{} {}'.format( os_upstream_info.LabelText, OS_upstream_version)) if OS_upstream_codename: os_upstream_info.SetLabel(u'{} {}'.format( os_upstream_info.LabelText, OS_upstream_codename)) sysinfo_layout_V1.Insert(2, os_upstream_info, 0, wx.ALIGN_CENTER | wx.BOTTOM, 5) sys_info.SetSizer(sysinfo_layout_V1) sys_info.Layout() # Button to close the dialog btn_confirm = CreateButton(self, btnid.CONFIRM) sizer = BoxSizer(wx.VERTICAL) sizer.Add(tabs, 1, wx.EXPAND) sizer.Add(btn_confirm, 0, wx.ALIGN_RIGHT | lyt.PAD_RTB, 5) self.SetSizer(sizer) self.Layout() ## Displays logo in 'about' tab # # \param graphic # Path to image file def SetGraphic(self, graphic): insertion_point = GetContainerItemCount(self.about_layout_V1) - 1 if not isinstance(graphic, wx.Bitmap): graphic = wx.Image(graphic) graphic.Rescale(64, 64, wx.IMAGE_QUALITY_HIGH) graphic = graphic.ConvertToBitmap() self.about_layout_V1.Insert( insertion_point, wx.StaticBitmap(self.t_about, wx.ID_ANY, graphic), 0, wx.ALL | wx.ALIGN_CENTER, 10) self.t_about.Layout() ## Displays version in 'about' tab # # \param version # <b><i>String</i></b> to display def SetVersion(self, version): insertion_point = GetContainerItemCount(self.about_layout_V1) - 1 app_label = wx.StaticText(self.t_about, label=u'{} {}'.format(APP_name, version)) app_label.SetFont(bigfont) self.about_layout_V1.Insert(insertion_point, app_label, 0, wx.ALL | wx.ALIGN_CENTER, 10) self.t_about.Layout() ## Display author's name # # \param author # <b><i>String</i></b> to display def SetAuthor(self, author): insertion_point = GetContainerItemCount(self.about_layout_V1) - 1 self.about_layout_V1.Insert(insertion_point, wx.StaticText(self.t_about, label=author), 0, wx.ALL | wx.ALIGN_CENTER, 10) self.t_about.Layout() ## Sets a hotlink to the app's homepage # # TODO: Remove: Deprecated, unused # # \param URL # URL to open when link is clicked def SetWebsite(self, URL): self.website.SetLabel(URL) self.website.SetURL(URL) ## Adds URL hotlinks to about dialog # # \param url_list # Label/URL <b><i>Tuple</i></b> (<i>string</i>, <i>string</i>) list def SetWebsites(self, url_list): insertion_point = GetContainerItemCount(self.about_layout_V1) - 1 link_layout = BoxSizer(wx.VERTICAL) for label, link in url_list: link_layout.Add( Hyperlink(self.t_about, wx.ID_ANY, label=label, url=link), 0, wx.ALIGN_CENTER, 10) self.about_layout_V1.Insert(insertion_point, link_layout, 0, wx.ALL | wx.ALIGN_CENTER, 10) self.t_about.Layout() ## Displays a description about the app on the 'about' tab def SetDescription(self, desc): # Place between spacers insertion_point = GetContainerItemCount(self.about_layout_V1) - 1 self.about_layout_V1.Insert(insertion_point, wx.StaticText(self.t_about, label=desc), 0, wx.ALL | wx.ALIGN_CENTER, 10) self.t_about.Layout() ## Adds a developer to the list of credits # # \param name # Developer's name # \param email # Developer's email address def AddDeveloper(self, name, email): next_item = self.credits.GetItemCount() self.credits.InsertStringItem(next_item, name) self.credits.SetStringItem(next_item, 2, email) self.credits.SetStringItem(next_item, 1, GT(u'Developer')) ## Adds a packager to the list of credits # # \param name # Packager's name # \param email # Packager's email address def AddPackager(self, name, email): next_item = self.credits.GetItemCount() self.credits.InsertStringItem(next_item, name) self.credits.SetStringItem(next_item, 2, email) self.credits.SetStringItem(next_item, 1, GT(u'Packager')) ## Adds a translator to the list of credits # # \param name # Translator's name # \param email # Translator's email address # \param lang # Locale code of the translation def AddTranslator(self, name, email, lang): job = GT(u'Translation') job = u'{} ({})'.format(job, lang) next_item = self.credits.GetItemCount() self.credits.InsertStringItem(next_item, name) self.credits.SetStringItem(next_item, 2, email) self.credits.SetStringItem(next_item, 1, job) ## Adds a general job to the credits list # # \param name # Contributer's name # \param job # Job description # \param email # str : Job holder's email address def AddJob(self, name, job, email=wx.EmptyString): next_item = self.credits.GetItemCount() self.credits.InsertStringItem(next_item, name) self.credits.SetStringItem(next_item, 1, job) if email != wx.EmptyString: self.credits.SetStringItem(next_item, 2, email) ## Adds list of jobs for single contributer # # \param name # <b><i>string</i></b>: # Contributer's name # \param jobs # <b><i>Tuple</i></b> (<i>string</i>, <i>string</i>): # List of contributer's jobs # \param email # <b><i>string</i></b>: # Optional contributer's email address def AddJobs(self, name, jobs, email=wx.EmptyString): if isinstance(jobs, str) or isinstance(jobs, unicode): Logger.Debug(__name__, GT(u'Converting string argument "jobs" to tuple')) jobs = (jobs, ) for x, value in enumerate(jobs): next_item = self.credits.GetItemCount() if x == 0: self.credits.InsertStringItem(next_item, name) if email != wx.EmptyString: self.credits.SetStringItem(next_item, 2, email) else: self.credits.InsertStringItem(next_item, wx.EmptyString) self.credits.SetStringItem(next_item, 1, value) ## FIXME: Unused? def NoResizeCol(self, event=None): if event: event.Veto() ## Sets text to be shown on the 'Changelog' tab # # FIXME: Change to create in class constructor def SetChangelog(self): ## Defines where the changelog is located # # By default it is located in the folder 'doc' # under the applications root directory. The # install script or Makefile should change this # to reflect installed path. if INSTALLED: # FIXME: Read compressed .gz changelog CHANGELOG = u'{}/share/doc/debreate/changelog.gz'.format(PREFIX) else: CHANGELOG = u'{}/docs/changelog'.format(PREFIX) if os.path.isfile(CHANGELOG): changelog_mimetype = GetFileMimeType(CHANGELOG) Logger.Debug( __name__, GT(u'Changelog mimetype: {}').format(changelog_mimetype)) # Set log text in case of read error log_text = GT(u'Error reading changelog: {}\n\t').format(CHANGELOG) log_text = u'{}{}'.format( log_text, GT(u'Cannot decode, unrecognized mimetype: {}').format( changelog_mimetype)) if changelog_mimetype == u'application/gzip': temp_dir = CreateStage() shutil.copy(CHANGELOG, temp_dir) CMD_gzip = GetExecutable(u'gzip') if CMD_gzip: prev_dir = os.getcwd() os.chdir(temp_dir) gzip_output = commands.getstatusoutput(u'{} -fd {}'.format( CMD_gzip, os.path.basename(CHANGELOG))) Logger.Debug( __name__, GT(u'gzip decompress; Code: {}, Output: {}').format( gzip_output[0], gzip_output[1])) os.chdir(prev_dir) changelog_file = os.path.basename(CHANGELOG).split(u'.')[0] changelog_file = u'{}/{}'.format(temp_dir, changelog_file) if os.path.isfile(changelog_file): log_text = ReadFile(changelog_file) RemoveStage(temp_dir) elif changelog_mimetype == u'text/plain': log_text = ReadFile(CHANGELOG) else: ShowErrorDialog(log_text, parent=self) else: log_text = GT( u'ERROR: Could not locate changelog file:\n\t\'{}\' not found'. format(CHANGELOG)) self.changelog.SetValue(log_text) self.changelog.SetInsertionPoint(0) ## Sets text to be shown on the 'License' tab def SetLicense(self): ## Defines where the LICENSE.txt is located # # By default it is located in the folder 'doc' # under the applications root directory. The # install script or Makefile should change this # to reflect installed path. if INSTALLED: license_path = u'{}/share/doc/debreate/copyright'.format(PREFIX) else: license_path = u'{}/docs/LICENSE.txt'.format(PREFIX) if os.path.isfile(license_path): lic_text = ReadFile(license_path) else: lic_text = GT( u'ERROR: Could not locate license file:\n\t\'{}\' not found'. format(license_path)) lic_text += u'\n\nCopyright © {} {} <{}>'.format( GetYear(), AUTHOR_name, AUTHOR_email) lic_text += u'\n\nhttps://opensource.org/licenses/MIT' self.license.SetValue(lic_text) self.license.SetInsertionPoint(0) ## Defines action to take when 'Ok' button is press # # Closes the dialog. # # \param event # <b><em>(wx.EVT_BUTTON)</em></b> def OnOk(self, event=None): self.Close()