def __init__(self, parent, scriptId): wx.Panel.__init__(self, parent, scriptId) ## Filename used for exporting script self.FileName = id_definitions[scriptId].lower() ## String name used for display in the application self.ScriptName = None self.SetScriptName() self.ScriptBody = TextAreaPanelESS(self, self.GetId(), monospace=True) self.ScriptBody.EnableDropTarget() self.Check = None # *** Layout *** # lyt_main = BoxSizer(wx.VERTICAL) lyt_main.Add(self.ScriptBody, 1, wx.EXPAND | wx.TOP, 5) self.SetSizer(lyt_main) self.SetAutoLayout(True) self.Layout() # Scripts are hidden by default self.Hide()
def __init__(self, parent, scriptId): wx.Panel.__init__(self, parent, scriptId) ## Filename used for exporting script self.FileName = id_definitions[scriptId].lower() ## String name used for display in the application self.ScriptName = None self.SetScriptName() shell_options = [] shell_options.append(u'/bin/sh') # Place /bin/sh as first item for P in u'/bin/', u'/usr/bin/', u'/usr/bin/env ': for S in sorted(shell_descriptions, key=GS.lower): if S == u'sh': pass else: shell_options.append(P + S) self.Shell = ComboBoxESS(self, self.GetId(), choices=shell_options, monospace=True, defaultValue=u'/bin/bash') self.ScriptBody = TextAreaPanelESS(self, self.GetId(), monospace=True) self.ScriptBody.EnableDropTarget() # *** Layout *** # lyt_shell = BoxSizer(wx.HORIZONTAL) lyt_shell.Add(wx.StaticText(self, label=u'#!'), 0, lyt.ALGN_CV | wx.RIGHT, 5) lyt_shell.Add(self.Shell, 1) lyt_main = BoxSizer(wx.VERTICAL) lyt_main.Add(lyt_shell, 0) lyt_main.Add(self.ScriptBody, 1, wx.EXPAND | wx.TOP, 5) self.SetSizer(lyt_main) self.SetAutoLayout(True) self.Layout() # Scripts are hidden by default self.Hide()
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:]))
class DebianScript(wx.Panel): ## Constructor # # \param parent # The <b><i>wx.Window</i></b> parent instance # \param scriptId # Unique <b><i>integer</i></b> identifier for script def __init__(self, parent, scriptId): wx.Panel.__init__(self, parent, scriptId) ## Filename used for exporting script self.FileName = id_definitions[scriptId].lower() ## String name used for display in the application self.ScriptName = None self.SetScriptName() shell_options = [] shell_options.append(u'/bin/sh') # Place /bin/sh as first item for P in u'/bin/', u'/usr/bin/', u'/usr/bin/env ': for S in sorted(shell_descriptions, key=GS.lower): if S == u'sh': pass else: shell_options.append(P + S) self.Shell = ComboBoxESS(self, self.GetId(), choices=shell_options, monospace=True, defaultValue=u'/bin/bash') self.ScriptBody = TextAreaPanelESS(self, self.GetId(), monospace=True) self.ScriptBody.EnableDropTarget() # *** Layout *** # lyt_shell = BoxSizer(wx.HORIZONTAL) lyt_shell.Add(wx.StaticText(self, label=u'#!'), 0, lyt.ALGN_CV|wx.RIGHT, 5) lyt_shell.Add(self.Shell, 1) lyt_main = BoxSizer(wx.VERTICAL) lyt_main.Add(lyt_shell, 0) lyt_main.Add(self.ScriptBody, 1, wx.EXPAND|wx.TOP, 5) self.SetSizer(lyt_main) self.SetAutoLayout(True) self.Layout() # Scripts are hidden by default self.Hide() ## Exports the script to a text file # # \param out_dir # Target directory of output file # \param executable # If <b><i>True</i></b>, sets the files executable bit # \param build # If <b><i>True</i></b>, format output for final build def Export(self, out_dir, executable=True, build=False): if not os.path.isdir(out_dir): Logger.Error(__name__, GT(u'Directory not available: {}'.format(out_dir))) return (ERR_DIR_NOT_AVAILABLE, __name__) if build: absolute_filename = ConcatPaths((out_dir, self.FileName)) else: filename = u'{}-{}'.format(page_ids[self.Parent.GetId()].upper(), self.FileName) absolute_filename = ConcatPaths((out_dir, filename)) script_text = u'{}\n\n{}'.format(self.GetShebang(), self.ScriptBody.GetValue()) WriteFile(absolute_filename, script_text) if not os.path.isfile(absolute_filename): Logger.Error(__name__, GT(u'Could not write to file: {}'.format(absolute_filename))) return (ERR_FILE_WRITE, __name__) if executable: os.chmod(absolute_filename, 0755) return (0, None) ## Retrieves the filename to use for exporting # # \return # Script filename def GetFilename(self): return self.FileName ## Retrieves the script's name for display # # \return # <b><i>String</i></b> representation of script's name def GetName(self): return self.ScriptName ## Retrieves the description of a shell for display # # \return # Description or <b><i>None</i></b> if using custom shell def GetSelectedShellDescription(self): selected_shell = self.Shell.GetValue() if selected_shell in shell_descriptions: return shell_descriptions[selected_shell] return None ## Retrieves the shebang/shell line def GetShebang(self): shell = self.Shell.GetValue() if shell.startswith(u'/usr/bin/env '): shell = u'#!{}\nset -e'.format(shell) else: shell = u'#!{} -e'.format(shell) return shell ## Retrieves the text body of the script def GetValue(self): return self.ScriptBody.GetValue() ## Checks if the script is used & can be exported # # The text area is checked &, if not empty, signifies that # the user want to export the script. # # \return # <b><i>True</i></b> if text area is not empty, <b><i>False</i></b> otherwise def IsOkay(self): return not TextIsEmpty(self.ScriptBody.GetValue()) ## Resets all members to default values def Reset(self): self.Shell.SetStringSelection(self.Shell.GetDefaultValue()) self.ScriptBody.Clear() ## Sets the name of the script to be displayed # # Sets the displayed script name to a value of either 'Pre Install', # 'Pre Uninstall', 'Post Install', or 'Post Uninstall'. 'self.FileName' # is used to determine the displayed name. # TODO: Add strings to GetText translations def SetScriptName(self): prefix = None suffix = None if u'pre' in self.FileName: prefix = u'Pre' suffix = self.FileName.split(u'pre')[1] elif u'post' in self.FileName: prefix = u'Post' suffix = self.FileName.split(u'post')[1] if suffix.lower() == u'inst': suffix = u'Install' elif suffix.lower() == u'rm': suffix = u'Uninstall' if (prefix != None) and (suffix != None): self.ScriptName = GT(u'{}-{}'.format(prefix, suffix)) ## Sets the shell/shebang line to use for script # # \param shell # Path to desired shell # \param forced # ??? def SetShell(self, shell, forced=False): if forced: self.Shell.SetValue(shell) return self.Shell.SetStringSelection(shell) ## Fills the script # # \param value # Text to be entered into the script body def SetValue(self, value): self.ScriptBody.SetValue(value)
def __init__(self, parent): WizardPage.__init__(self, parent, pgid.COPYRIGHT) self.custom_licenses = [] ## A list of available license templates self.sel_templates = Choice(self, selid.LICENSE, name=u'list»') # Initialize the template list self.OnRefreshList() btn_template = CreateButton(self, label=GT(u'Full Template'), image=u'full', name=u'full»') self.btn_template_simple = CreateButton(self, label=GT(u'Short Template'), image=u'short', name=u'short»') btn_refresh = CreateButton(self, btnid.REFRESH, GT(u'Refresh Template List'), u'refresh', name=u'btn refresh') btn_open = CreateButton(self, btnid.BROWSE, GT(u'Open Template Directory'), u'browse', name=u'btn opendir', commands=u'xdg-open') if not self.sel_templates.GetCount(): self.sel_templates.Enable(False) btn_template.Enable(False) self.btn_template_simple.Enable(False) ## Area where license text is displayed self.dsp_copyright = TextAreaPanelESS(self, monospace=True, name=u'license') self.dsp_copyright.EnableDropTarget() SetPageToolTips(self) # Initiate tooltip for drop-down selector if self.sel_templates.IsEnabled(): self.OnSelectLicense(self.sel_templates) # *** Event Handling *** # self.sel_templates.Bind(wx.EVT_CHOICE, self.OnSelectLicense) btn_open.Bind(wx.EVT_BUTTON, self.OnOpenPath) btn_refresh.Bind(wx.EVT_BUTTON, self.OnRefreshList) btn_template.Bind(wx.EVT_BUTTON, self.OnTemplateFull) self.btn_template_simple.Bind(wx.EVT_BUTTON, self.OnTemplateShort) # *** Layout *** # lyt_top = BoxSizer(wx.HORIZONTAL) lyt_top.Add(wx.StaticText(self, label=GT(u'Available Templates')), 0, lyt.ALGN_CV) lyt_top.Add(self.sel_templates, 0, lyt.ALGN_CV|wx.LEFT, 5) lyt_top.Add(btn_template, 0, wx.LEFT, 5) lyt_top.Add(self.btn_template_simple) lyt_top.Add(btn_refresh) lyt_top.Add(btn_open) lyt_main = BoxSizer(wx.VERTICAL) lyt_main.AddSpacer(10) lyt_main.Add(lyt_top, 0, lyt.PAD_LR|wx.BOTTOM, 5) lyt_main.Add(self.dsp_copyright, 1, wx.EXPAND|lyt.PAD_LRB, 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.COPYRIGHT) self.custom_licenses = [] ## A list of available license templates self.sel_templates = Choice(self, selid.LICENSE, name=u'list»') # Initialize the template list self.OnRefreshList() btn_template = CreateButton(self, label=GT(u'Full Template'), image=u'full', name=u'full»') self.btn_template_simple = CreateButton(self, label=GT(u'Short Template'), image=u'short', name=u'short»') btn_refresh = CreateButton(self, btnid.REFRESH, GT(u'Refresh Template List'), u'refresh', name=u'btn refresh') btn_open = CreateButton(self, btnid.BROWSE, GT(u'Open Template Directory'), u'browse', name=u'btn opendir', commands=u'xdg-open') if not self.sel_templates.GetCount(): self.sel_templates.Enable(False) btn_template.Enable(False) self.btn_template_simple.Enable(False) ## Area where license text is displayed self.dsp_copyright = TextAreaPanelESS(self, monospace=True, name=u'license') self.dsp_copyright.EnableDropTarget() SetPageToolTips(self) # Initiate tooltip for drop-down selector if self.sel_templates.IsEnabled(): self.OnSelectLicense(self.sel_templates) # *** Event Handling *** # self.sel_templates.Bind(wx.EVT_CHOICE, self.OnSelectLicense) btn_open.Bind(wx.EVT_BUTTON, self.OnOpenPath) btn_refresh.Bind(wx.EVT_BUTTON, self.OnRefreshList) btn_template.Bind(wx.EVT_BUTTON, self.OnTemplateFull) self.btn_template_simple.Bind(wx.EVT_BUTTON, self.OnTemplateShort) # *** Layout *** # lyt_top = BoxSizer(wx.HORIZONTAL) lyt_top.Add(wx.StaticText(self, label=GT(u'Available Templates')), 0, lyt.ALGN_CV) lyt_top.Add(self.sel_templates, 0, lyt.ALGN_CV|wx.LEFT, 5) lyt_top.Add(btn_template, 0, wx.LEFT, 5) lyt_top.Add(self.btn_template_simple) lyt_top.Add(btn_refresh) lyt_top.Add(btn_open) lyt_main = BoxSizer(wx.VERTICAL) lyt_main.AddSpacer(10) lyt_main.Add(lyt_top, 0, lyt.PAD_LR|wx.BOTTOM, 5) lyt_main.Add(self.dsp_copyright, 1, wx.EXPAND|lyt.PAD_LRB, 5) self.SetAutoLayout(True) self.SetSizer(lyt_main) self.Layout() ## Displays a confirmation dialog to clear the text area if it is not empty # # \return # <b><i>True</i></b>, if user confirmed def DestroyLicenseText(self): if not TextIsEmpty(self.dsp_copyright.GetValue()): warn_msg = GT(u'This will destroy all license text.') warn_msg = u'{}\n\n{}'.format(warn_msg, GT(u'Continue?')) if ConfirmationDialog(GetMainWindow(), text=warn_msg).ShowModal() not in (wx.ID_OK, wx.OK): return False return True ## \see wiz.wizard.WizardPage.ExportBuild def ExportBuild(self, stage): stage = u'{}/usr/share/doc/{}'.format(stage, GetPage(pgid.CONTROL).GetPackageName()).replace(u'//', u'/') # FIXME: Should be error check self.Export(stage, u'copyright') return (0, None) ## Retrieves copyright/license text # # \return # <b><i>tuple(str, str)</i></b>: Filename & copyright/license text def Get(self, getModule=False): page = self.dsp_copyright.GetValue() if TextIsEmpty(page): page = None if getModule: page = (__name__, page,) return page ## Retrieves license path # # \param licName # License file basename to search for # If 'None', uses currently selected license # \return # Full path to license file if found def GetLicensePath(self, licName=None): # Default to currently selected template if not licName: licName = self.GetSelectedName() return GetLicenseTemplateFile(licName) ## Retrieves the name of the template currently selected def GetSelectedName(self): return GetField(self, selid.LICENSE).GetStringSelection() ## Sets page's fields from opened file def ImportFromFile(self, filename): if not os.path.isfile(filename): return dbrerrno.ENOENT copyright_data = ReadFile(filename, split=True) # Remove preceding empty lines remove_index = 0 for I in copyright_data: if not TextIsEmpty(I): break remove_index += 1 for I in reversed(range(remove_index)): copyright_data.remove(copyright_data[I]) copyright_data = u'\n'.join(copyright_data) self.dsp_copyright.SetValue(copyright_data) return 0 ## Checks if page can be exported or or added to build def IsOkay(self): return not TextIsEmpty(self.dsp_copyright.GetValue()) ## Opens directory containing currently selected license def OnOpenPath(self, event=None): CMD_open = GetExecutable(u'xdg-open') if CMD_open: path = self.GetLicensePath() if not path: ShowErrorDialog(GT(u'Error retrieving template path: {}').format(self.GetSelectedName())) return False path = os.path.dirname(path) if os.path.isdir(path): ExecuteCommand(CMD_open, (path,)) return True return False ## Repopulates template list def OnRefreshList(self, event=None): # FIXME: Ignore symbolic links??? self.custom_licenses = GetLocalLicenses() licenses = list(self.custom_licenses) # System licenses are not added to "custom" list for LIC in GetSysLicenses(): if LIC not in licenses: licenses.append(LIC) for LIC in GetCustomLicenses(): if LIC not in licenses: licenses.append(LIC) self.custom_licenses.append(LIC) self.custom_licenses.sort(key=GS.lower) sel_templates = GetField(self, selid.LICENSE) selected = None if sel_templates.GetCount(): selected = sel_templates.GetStringSelection() sel_templates.Set(sorted(licenses, key=GS.lower)) if selected: if not sel_templates.SetStringSelection(selected): # Selected template file was not found sel_templates.SetSelection(sel_templates.GetDefaultValue()) # Update short template button enabled state self.OnSelectLicense() else: sel_templates.SetSelection(sel_templates.GetDefaultValue()) ## Enables/Disables simple template button # # Simple template generation is only available # for system licenses. def OnSelectLicense(self, event=None): choice = GetField(self, selid.LICENSE) if choice: template = choice.GetString(choice.GetSelection()) if template in self.custom_licenses: self.btn_template_simple.Disable() else: self.btn_template_simple.Enable() self.SetLicenseTooltip() ## Generates a full license template def OnTemplateFull(self, event=None): selected_template = self.sel_templates.GetStringSelection() template_file = self.GetLicensePath(selected_template) if self.DestroyLicenseText(): if not template_file or not os.path.isfile(template_file): ShowErrorDialog(GT(u'Could not locate license file: {}').format(self.GetSelectedName())) return Logger.Debug(__name__, u'Copying license {}'.format(template_file)) license_text = ReadFile(template_file, noStrip=u' ') # Number defines how many empty lines to add after the copyright header # Boolean/Integer defines whether copyright header should be centered/offset add_header = { u'Artistic': (1, True), u'BSD': (0, False), } template_name = os.path.basename(template_file) if template_name in add_header: license_text = license_text.split(u'\n') empty_lines = add_header[template_name][0] for L in range(empty_lines): license_text.insert(0, wx.EmptyString) header = copyright_header.format(GetYear()) center_header = add_header[template_name][1] if center_header: Logger.Debug(__name__, u'Centering header...') offset = 0 # Don't use isinstance() here because boolean is an instance of integer if type(center_header) == int: offset = center_header else: # Use the longest line found in the text to center the header longest_line = GetLongestLine(license_text) Logger.Debug(__name__, u'Longest line: {}'.format(longest_line)) header_length = len(header) if header_length < longest_line: offset = (longest_line - header_length) / 2 if offset: Logger.Debug(__name__, u'Offset: {}'.format(offset)) header = u'{}{}'.format(u' ' * offset, header) # Special changes for BSD license if template_name == u'BSD': line_index = 0 for LI in license_text: if u'copyright (c)' in LI.lower(): license_text[line_index] = header break line_index += 1 else: license_text.insert(0, header) license_text = u'\n'.join(license_text) if not license_text: ShowErrorDialog(GT(u'License template is empty')) return self.dsp_copyright.SetValue(license_text) self.dsp_copyright.SetInsertionPoint(0) self.dsp_copyright.SetFocus() ## Generates a short reference template for a system license def OnTemplateShort(self, event=None): if self.DestroyLicenseText(): self.dsp_copyright.Clear() license_path = u'{}/{}'.format(sys_licenses_path, self.sel_templates.GetString(self.sel_templates.GetSelection())) self.dsp_copyright.WriteText(u'{}\n\n{}'.format(copyright_header.format(GetYear()), license_path)) self.dsp_copyright.SetInsertionPoint(0) self.dsp_copyright.SetFocus() ## Resets all page fields to default values def Reset(self): self.dsp_copyright.Clear() if self.sel_templates.IsEnabled(): self.sel_templates.Reset() self.OnSelectLicense(self.sel_templates) ## Sets the text of the displayed copyright # # \param data # Text to parse for field values def Set(self, data): self.dsp_copyright.SetValue(data) ## Changes the Choice instance's tooltip for the current license def SetLicenseTooltip(self): license_name = self.sel_templates.GetString(self.sel_templates.GetSelection()) license_path = self.GetLicensePath(license_name) if license_path: self.sel_templates.SetToolTip(wx.ToolTip(license_path)) return self.sel_templates.SetToolTip(None)
def __init__(self, parent): WizardPage.__init__(self, parent, pgid.CONTROL) # Bypass checking this page for build # This is mandatory & done manually self.prebuild_check = False self.SetScrollbars(0, 20, 0, 0) pnl_bg = wx.Panel(self) # Buttons to open, save, & preview control file btn_open = CreateButton(pnl_bg, btnid.BROWSE, GT(u'Browse'), u'browse', name=u'btn browse') btn_save = CreateButton(pnl_bg, btnid.SAVE, GT(u'Save'), u'save', name=u'btn save') btn_preview = CreateButton(pnl_bg, btnid.PREVIEW, GT(u'Preview'), u'preview', name=u'btn preview') # *** Required fields *** # pnl_require = BorderedPanel(pnl_bg) txt_package = wx.StaticText(pnl_require, label=GT(u'Package'), name=u'package') txt_package.req = True ti_package = TextAreaESS(pnl_require, inputid.PACKAGE, name=txt_package.Name) ti_package.req = True txt_version = wx.StaticText(pnl_require, label=GT(u'Version'), name=u'version') txt_version.req = True ti_version = TextAreaESS(pnl_require, inputid.VERSION, name=txt_version.Name) ti_version.req = True txt_maintainer = wx.StaticText(pnl_require, label=GT(u'Maintainer'), name=u'maintainer') txt_maintainer.req = True ti_maintainer = TextAreaESS(pnl_require, inputid.MAINTAINER, name=txt_maintainer.Name) ti_maintainer.req = True txt_email = wx.StaticText(pnl_require, label=GT(u'Email'), name=u'email') txt_email.req = True ti_email = TextAreaESS(pnl_require, inputid.EMAIL, name=txt_email.Name) ti_email.req = True opts_arch = ( u'all', u'alpha', u'amd64', u'arm', u'arm64', u'armeb', u'armel', u'armhf', u'avr32', u'hppa', u'i386', u'ia64', u'lpia', u'm32r', u'm68k', u'mips', u'mipsel', u'powerpc', u'powerpcspe', u'ppc64', u's390', u's390x', u'sh3', u'sh3eb', u'sh4', u'sh4eb', u'sparc', u'sparc64', ) txt_arch = wx.StaticText(pnl_require, label=GT(u'Architecture'), name=u'architecture') sel_arch = ChoiceESS(pnl_require, inputid.ARCH, choices=opts_arch, name=txt_arch.Name) sel_arch.Default = 0 sel_arch.SetSelection(sel_arch.Default) # *** Recommended fields *** # pnl_recommend = BorderedPanel(pnl_bg) opts_section = ( u'admin', u'cli-mono', u'comm', u'database', u'devel', u'debug', u'doc', u'editors', u'electronics', u'embedded', u'fonts', u'games', u'gnome', u'graphics', u'gnu-r', u'gnustep', u'hamradio', u'haskell', u'httpd', u'interpreters', u'java', u'kde', u'kernel', u'libs', u'libdevel', u'lisp', u'localization', u'mail', u'math', u'metapackages', u'misc', u'net', u'news', u'ocaml', u'oldlibs', u'otherosfs', u'perl', u'php', u'python', u'ruby', u'science', u'shells', u'sound', u'tex', u'text', u'utils', u'vcs', u'video', u'web', u'x11', u'xfce', u'zope', ) txt_section = wx.StaticText(pnl_recommend, label=GT(u'Section'), name=u'section') ti_section = ComboBoxESS(pnl_recommend, choices=opts_section, name=txt_section.Name) opts_priority = ( u'optional', u'standard', u'important', u'required', u'extra', ) txt_priority = wx.StaticText(pnl_recommend, label=GT(u'Priority'), name=u'priority') sel_priority = ChoiceESS(pnl_recommend, choices=opts_priority, name=txt_priority.Name) sel_priority.Default = 0 sel_priority.SetSelection(sel_priority.Default) txt_synopsis = wx.StaticText(pnl_recommend, label=GT(u'Short Description'), name=u'synopsis') ti_synopsis = TextAreaESS(pnl_recommend, name=txt_synopsis.Name) txt_description = wx.StaticText(pnl_recommend, label=GT(u'Long Description'), name=u'description') self.ti_description = TextAreaPanelESS(pnl_recommend, name=txt_description.Name) # *** Optional fields *** # pnl_option = BorderedPanel(pnl_bg) txt_source = wx.StaticText(pnl_option, label=GT(u'Source'), name=u'source') ti_source = TextAreaESS(pnl_option, name=txt_source.Name) txt_homepage = wx.StaticText(pnl_option, label=GT(u'Homepage'), name=u'homepage') ti_homepage = TextAreaESS(pnl_option, name=txt_homepage.Name) txt_essential = wx.StaticText(pnl_option, label=GT(u'Essential'), name=u'essential') self.chk_essential = CheckBoxESS(pnl_option, name=u'essential') self.chk_essential.Default = False self.grp_input = ( ti_package, ti_version, ti_maintainer, # Maintainer must be listed before email ti_email, ti_section, ti_source, ti_homepage, ti_synopsis, self.ti_description, ) self.grp_select = ( sel_arch, sel_priority, ) SetPageToolTips(self) # *** Event Handling *** # btn_open.Bind(wx.EVT_BUTTON, self.OnBrowse) btn_save.Bind(wx.EVT_BUTTON, self.OnSave) btn_preview.Bind(wx.EVT_BUTTON, self.OnPreviewControl) # *** Layout *** # LEFT_BOTTOM = lyt.ALGN_LB RIGHT_CENTER = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.RIGHT # Buttons lyt_buttons = BoxSizer(wx.HORIZONTAL) lyt_buttons.Add(btn_open, 0) lyt_buttons.Add(btn_save, 0) lyt_buttons.Add(btn_preview, 0) # Required fields lyt_require = wx.FlexGridSizer(0, 4, 5, 5) lyt_require.AddGrowableCol(1) lyt_require.AddGrowableCol(3) lyt_require.AddMany(( (txt_package, 0, RIGHT_CENTER | lyt.PAD_LT, 5), (ti_package, 0, wx.EXPAND | wx.TOP, 5), (txt_version, 0, RIGHT_CENTER | wx.TOP, 5), (ti_version, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 5), (txt_maintainer, 0, RIGHT_CENTER | wx.LEFT, 5), (ti_maintainer, 0, wx.EXPAND), (txt_email, 0, RIGHT_CENTER, 5), (ti_email, 0, wx.EXPAND | wx.RIGHT, 5), (txt_arch, 0, RIGHT_CENTER | lyt.PAD_LB, 5), (sel_arch, 0, wx.BOTTOM, 5), )) pnl_require.SetSizer(lyt_require) pnl_require.SetAutoLayout(True) pnl_require.Layout() # Recommended fields lyt_recommend = wx.GridBagSizer() lyt_recommend.SetCols(4) lyt_recommend.AddGrowableCol(1) lyt_recommend.AddGrowableRow(3) lyt_recommend.Add(txt_section, (0, 2), flag=RIGHT_CENTER | lyt.PAD_TB, border=5) lyt_recommend.Add(ti_section, (0, 3), flag=wx.EXPAND | lyt.PAD_RTB, border=5) lyt_recommend.Add(txt_synopsis, (0, 0), (1, 2), LEFT_BOTTOM | wx.LEFT, 5) lyt_recommend.Add(ti_synopsis, (1, 0), (1, 2), wx.EXPAND | lyt.PAD_LR, 5) lyt_recommend.Add(txt_priority, (1, 2), flag=RIGHT_CENTER, border=5) lyt_recommend.Add(sel_priority, (1, 3), flag=wx.EXPAND | wx.RIGHT, border=5) lyt_recommend.Add(txt_description, (2, 0), (1, 2), LEFT_BOTTOM | lyt.PAD_LT, 5) lyt_recommend.Add(self.ti_description, (3, 0), (1, 4), wx.EXPAND | lyt.PAD_LR | wx.BOTTOM, 5) pnl_recommend.SetSizer(lyt_recommend) pnl_recommend.SetAutoLayout(True) pnl_recommend.Layout() # Optional fields lyt_option = wx.FlexGridSizer(0, 4, 5, 5) lyt_option.AddGrowableCol(1) lyt_option.AddGrowableCol(3) lyt_option.AddSpacer(5) lyt_option.AddSpacer(5) lyt_option.AddSpacer(5) lyt_option.AddSpacer(5) lyt_option.AddMany(( (txt_source, 0, RIGHT_CENTER | wx.LEFT, 5), (ti_source, 0, wx.EXPAND), (txt_homepage, 0, RIGHT_CENTER, 5), (ti_homepage, 0, wx.EXPAND | wx.RIGHT, 5), (txt_essential, 0, RIGHT_CENTER | lyt.PAD_LB, 5), (self.chk_essential, 0, wx.BOTTOM, 5), )) pnl_option.SetSizer(lyt_option) pnl_option.SetAutoLayout(True) pnl_option.Layout() # Main background panel sizer # FIXME: Is background panel (pnl_bg) necessary lyt_bg = BoxSizer(wx.VERTICAL) lyt_bg.Add(lyt_buttons, 0, wx.ALIGN_RIGHT | wx.BOTTOM, 5) lyt_bg.Add(wx.StaticText(pnl_bg, label=GT(u'Required')), 0) lyt_bg.Add(pnl_require, 0, wx.EXPAND) lyt_bg.Add(wx.StaticText(pnl_bg, label=GT(u'Recommended')), 0, wx.TOP, 5) lyt_bg.Add(pnl_recommend, 1, wx.EXPAND) lyt_bg.Add(wx.StaticText(pnl_bg, label=GT(u'Optional')), 0, wx.TOP, 5) lyt_bg.Add(pnl_option, 0, wx.EXPAND) pnl_bg.SetAutoLayout(True) pnl_bg.SetSizer(lyt_bg) pnl_bg.Layout() # Page's main sizer lyt_main = BoxSizer(wx.VERTICAL) lyt_main.AddSpacer(5) lyt_main.Add(pnl_bg, 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.CONTROL) # Bypass checking this page for build # This is mandatory & done manually self.prebuild_check = False self.SetScrollbars(0, 20, 0, 0) pnl_bg = wx.Panel(self) # Buttons to open, save, & preview control file btn_open = CreateButton(pnl_bg, btnid.BROWSE, GT(u'Browse'), u'browse', name=u'btn browse') btn_save = CreateButton(pnl_bg, btnid.SAVE, GT(u'Save'), u'save', name=u'btn save') btn_preview = CreateButton(pnl_bg, btnid.PREVIEW, GT(u'Preview'), u'preview', name=u'btn preview') # *** Required fields *** # pnl_require = BorderedPanel(pnl_bg) txt_package = wx.StaticText(pnl_require, label=GT(u'Package'), name=u'package') txt_package.req = True ti_package = TextAreaESS(pnl_require, inputid.PACKAGE, name=txt_package.Name) ti_package.req = True txt_version = wx.StaticText(pnl_require, label=GT(u'Version'), name=u'version') txt_version.req = True ti_version = TextAreaESS(pnl_require, inputid.VERSION, name=txt_version.Name) ti_version.req = True txt_maintainer = wx.StaticText(pnl_require, label=GT(u'Maintainer'), name=u'maintainer') txt_maintainer.req = True ti_maintainer = TextAreaESS(pnl_require, inputid.MAINTAINER, name=txt_maintainer.Name) ti_maintainer.req = True txt_email = wx.StaticText(pnl_require, label=GT(u'Email'), name=u'email') txt_email.req = True ti_email = TextAreaESS(pnl_require, inputid.EMAIL, name=txt_email.Name) ti_email.req = True opts_arch = ( u'all', u'alpha', u'amd64', u'arm', u'arm64', u'armeb', u'armel', u'armhf', u'avr32', u'hppa', u'i386', u'ia64', u'lpia', u'm32r', u'm68k', u'mips', u'mipsel', u'powerpc', u'powerpcspe', u'ppc64', u's390', u's390x', u'sh3', u'sh3eb', u'sh4', u'sh4eb', u'sparc', u'sparc64', ) txt_arch = wx.StaticText(pnl_require, label=GT(u'Architecture'), name=u'architecture') sel_arch = ChoiceESS(pnl_require, inputid.ARCH, choices=opts_arch, name=txt_arch.Name) sel_arch.Default = 0 sel_arch.SetSelection(sel_arch.Default) # *** Recommended fields *** # pnl_recommend = BorderedPanel(pnl_bg) opts_section = ( u'admin', u'cli-mono', u'comm', u'database', u'devel', u'debug', u'doc', u'editors', u'electronics', u'embedded', u'fonts', u'games', u'gnome', u'graphics', u'gnu-r', u'gnustep', u'hamradio', u'haskell', u'httpd', u'interpreters', u'java', u'kde', u'kernel', u'libs', u'libdevel', u'lisp', u'localization', u'mail', u'math', u'metapackages', u'misc', u'net', u'news', u'ocaml', u'oldlibs', u'otherosfs', u'perl', u'php', u'python', u'ruby', u'science', u'shells', u'sound', u'tex', u'text', u'utils', u'vcs', u'video', u'web', u'x11', u'xfce', u'zope', ) txt_section = wx.StaticText(pnl_recommend, label=GT(u'Section'), name=u'section') ti_section = ComboBoxESS(pnl_recommend, choices=opts_section, name=txt_section.Name) opts_priority = ( u'optional', u'standard', u'important', u'required', u'extra', ) txt_priority = wx.StaticText(pnl_recommend, label=GT(u'Priority'), name=u'priority') sel_priority = ChoiceESS(pnl_recommend, choices=opts_priority, name=txt_priority.Name) sel_priority.Default = 0 sel_priority.SetSelection(sel_priority.Default) txt_synopsis = wx.StaticText(pnl_recommend, label=GT(u'Short Description'), name=u'synopsis') ti_synopsis = TextAreaESS(pnl_recommend, name=txt_synopsis.Name) txt_description = wx.StaticText(pnl_recommend, label=GT(u'Long Description'), name=u'description') self.ti_description = TextAreaPanelESS(pnl_recommend, name=txt_description.Name) # *** Optional fields *** # pnl_option = BorderedPanel(pnl_bg) txt_source = wx.StaticText(pnl_option, label=GT(u'Source'), name=u'source') ti_source = TextAreaESS(pnl_option, name=txt_source.Name) txt_homepage = wx.StaticText(pnl_option, label=GT(u'Homepage'), name=u'homepage') ti_homepage = TextAreaESS(pnl_option, name=txt_homepage.Name) txt_essential = wx.StaticText(pnl_option, label=GT(u'Essential'), name=u'essential') self.chk_essential = CheckBoxESS(pnl_option, name=u'essential') self.chk_essential.Default = False self.grp_input = ( ti_package, ti_version, ti_maintainer, # Maintainer must be listed before email ti_email, ti_section, ti_source, ti_homepage, ti_synopsis, self.ti_description, ) self.grp_select = ( sel_arch, sel_priority, ) SetPageToolTips(self) # *** Event Handling *** # btn_open.Bind(wx.EVT_BUTTON, self.OnBrowse) btn_save.Bind(wx.EVT_BUTTON, self.OnSave) btn_preview.Bind(wx.EVT_BUTTON, self.OnPreviewControl) # *** Layout *** # LEFT_BOTTOM = lyt.ALGN_LB RIGHT_CENTER = wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL | wx.RIGHT # Buttons lyt_buttons = BoxSizer(wx.HORIZONTAL) lyt_buttons.Add(btn_open, 0) lyt_buttons.Add(btn_save, 0) lyt_buttons.Add(btn_preview, 0) # Required fields lyt_require = wx.FlexGridSizer(0, 4, 5, 5) lyt_require.AddGrowableCol(1) lyt_require.AddGrowableCol(3) lyt_require.AddMany(( (txt_package, 0, RIGHT_CENTER | lyt.PAD_LT, 5), (ti_package, 0, wx.EXPAND | wx.TOP, 5), (txt_version, 0, RIGHT_CENTER | wx.TOP, 5), (ti_version, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 5), (txt_maintainer, 0, RIGHT_CENTER | wx.LEFT, 5), (ti_maintainer, 0, wx.EXPAND), (txt_email, 0, RIGHT_CENTER, 5), (ti_email, 0, wx.EXPAND | wx.RIGHT, 5), (txt_arch, 0, RIGHT_CENTER | lyt.PAD_LB, 5), (sel_arch, 0, wx.BOTTOM, 5), )) pnl_require.SetSizer(lyt_require) pnl_require.SetAutoLayout(True) pnl_require.Layout() # Recommended fields lyt_recommend = wx.GridBagSizer() lyt_recommend.SetCols(4) lyt_recommend.AddGrowableCol(1) lyt_recommend.AddGrowableRow(3) lyt_recommend.Add(txt_section, (0, 2), flag=RIGHT_CENTER | lyt.PAD_TB, border=5) lyt_recommend.Add(ti_section, (0, 3), flag=wx.EXPAND | lyt.PAD_RTB, border=5) lyt_recommend.Add(txt_synopsis, (0, 0), (1, 2), LEFT_BOTTOM | wx.LEFT, 5) lyt_recommend.Add(ti_synopsis, (1, 0), (1, 2), wx.EXPAND | lyt.PAD_LR, 5) lyt_recommend.Add(txt_priority, (1, 2), flag=RIGHT_CENTER, border=5) lyt_recommend.Add(sel_priority, (1, 3), flag=wx.EXPAND | wx.RIGHT, border=5) lyt_recommend.Add(txt_description, (2, 0), (1, 2), LEFT_BOTTOM | lyt.PAD_LT, 5) lyt_recommend.Add(self.ti_description, (3, 0), (1, 4), wx.EXPAND | lyt.PAD_LR | wx.BOTTOM, 5) pnl_recommend.SetSizer(lyt_recommend) pnl_recommend.SetAutoLayout(True) pnl_recommend.Layout() # Optional fields lyt_option = wx.FlexGridSizer(0, 4, 5, 5) lyt_option.AddGrowableCol(1) lyt_option.AddGrowableCol(3) lyt_option.AddSpacer(5) lyt_option.AddSpacer(5) lyt_option.AddSpacer(5) lyt_option.AddSpacer(5) lyt_option.AddMany(( (txt_source, 0, RIGHT_CENTER | wx.LEFT, 5), (ti_source, 0, wx.EXPAND), (txt_homepage, 0, RIGHT_CENTER, 5), (ti_homepage, 0, wx.EXPAND | wx.RIGHT, 5), (txt_essential, 0, RIGHT_CENTER | lyt.PAD_LB, 5), (self.chk_essential, 0, wx.BOTTOM, 5), )) pnl_option.SetSizer(lyt_option) pnl_option.SetAutoLayout(True) pnl_option.Layout() # Main background panel sizer # FIXME: Is background panel (pnl_bg) necessary lyt_bg = BoxSizer(wx.VERTICAL) lyt_bg.Add(lyt_buttons, 0, wx.ALIGN_RIGHT | wx.BOTTOM, 5) lyt_bg.Add(wx.StaticText(pnl_bg, label=GT(u'Required')), 0) lyt_bg.Add(pnl_require, 0, wx.EXPAND) lyt_bg.Add(wx.StaticText(pnl_bg, label=GT(u'Recommended')), 0, wx.TOP, 5) lyt_bg.Add(pnl_recommend, 1, wx.EXPAND) lyt_bg.Add(wx.StaticText(pnl_bg, label=GT(u'Optional')), 0, wx.TOP, 5) lyt_bg.Add(pnl_option, 0, wx.EXPAND) pnl_bg.SetAutoLayout(True) pnl_bg.SetSizer(lyt_bg) pnl_bg.Layout() # Page's main sizer lyt_main = BoxSizer(wx.VERTICAL) lyt_main.AddSpacer(5) lyt_main.Add(pnl_bg, 1, wx.EXPAND | lyt.PAD_LR | wx.BOTTOM, 5) self.SetAutoLayout(True) self.SetSizer(lyt_main) self.Layout() ## Export instructions specifically for build phase # # \param target # Path of filename to write # \param installedSize # Manually set installed size for package? # \return # <b><i>Tuple</i></b> containing a return code & string value of page data def ExportBuild(self, target, installedSize=0): self.Export(target, u'control') absolute_filename = ConcatPaths((target, u'control')) if not os.path.isfile(absolute_filename): return GT(u'Control file was not created') if installedSize: control_data = ReadFile(absolute_filename, split=True, convert=list) size_line = u'Installed-Size: {}'.format(installedSize) if len(control_data) > 3: control_data.insert(3, size_line) else: control_data.append(size_line) # Be sure not to strip trailing newline (dpkg is picky) WriteFile(absolute_filename, control_data, noStrip=u'\n') return GT(u'Control file created: {}').format(absolute_filename) ## Retrieves information for control file export # # \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 # A <b><i>tuple</i></b> containing the filename & a string representation # of control file formatted for text output def Get(self, getModule=False): page = self.GetCtrlInfo() if getModule: page = ( __name__, page, ) return page ## Retrieves field values & formats into plain text for output to file # # \return # Control file text def GetCtrlInfo(self): pg_depends = GetPage(pgid.DEPENDS) ctrl_list = [] synopsis = None description = None # Email will be set if maintainer changed to True maintainer = False # Text input fields for field in self.grp_input: field_name = field.GetName().title() field_value = field.GetValue() if FieldEnabled(field) and not TextIsEmpty(field_value): Logger.Debug(__name__, GT(u'Exporting {} field').format(field_name)) # Strip leading & trailing spaces, tabs, & newlines field_value = field_value.strip(u' \t\n') if field_name == u'Synopsis': synopsis = u'{}: {}'.format(u'Description', field_value) continue if field_name == u'Description': description = field_value.split(u'\n') for line_index in range(len(description)): # Remove trailing whitespace description[line_index] = description[ line_index].rstrip() if TextIsEmpty(description[line_index]): # Empty lines are formatted with one space indentation & a period description[line_index] = u' .' else: # All other lines are formatted with one space indentation description[line_index] = u' {}'.format( description[line_index]) description = u'\n'.join(description) continue if field_name in (u'Package', u'Version'): # Don't allow whitespace in package name & version ctrl_list.append(u'{}: {}'.format( field_name, u'-'.join(field_value.split(u' ')))) continue if field_name == u'Email': if maintainer and ctrl_list: # Append email to end of maintainer string for ctrl_index in range(len(ctrl_list)): if ctrl_list[ctrl_index].startswith( u'Maintainer: '): Logger.Debug(__name__, u'Found maintainer') ctrl_list[ctrl_index] = u'{} <{}>'.format( ctrl_list[ctrl_index], field_value) break continue # Don't use 'continue' on this statement if field_name == u'Maintainer': maintainer = True # The rest of the fields ctrl_list.append(u'{}: {}'.format(field_name, field_value)) # Selection box fields for field in self.grp_select: field_name = field.GetName().title() field_value = field.GetStringSelection() if FieldEnabled(field) and not TextIsEmpty(field_value): Logger.Debug(__name__, GT(u'Exporting {} field').format(field_name)) # Strip leading & trailing spaces, tabs, & newlines field_value = field_value.strip(u' \t\n') ctrl_list.append(u'{}: {}'.format(field_name, field_value)) if self.chk_essential.GetValue(): ctrl_list.append(u'Essential: yes') # Dependencies & conflicts dep_list = [] # Depends pre_list = [] # Pre-Depends rec_list = [] # Recommends sug_list = [] # Suggests enh_list = [] # Enhances con_list = [] # Conflicts rep_list = [] # Replaces brk_list = [] # Breaks all_deps = { u'Depends': dep_list, u'Pre-Depends': pre_list, u'Recommends': rec_list, u'Suggests': sug_list, u'Enhances': enh_list, u'Conflicts': con_list, u'Replaces': rep_list, u'Breaks': brk_list, } # Get amount of items to add dep_area = GetField(pg_depends, inputid.LIST) dep_count = dep_area.GetItemCount() count = 0 while count < dep_count: # Get each item from dependencies page dep_type = dep_area.GetItem(count, 0).GetText() dep_val = dep_area.GetItem(count, 1).GetText() for item in all_deps: if dep_type == item: all_deps[item].append(dep_val) count += 1 for item in all_deps: if len(all_deps[item]) != 0: ctrl_list.append(u'{}: {}'.format(item, u', '.join(all_deps[item]))) if synopsis: ctrl_list.append(synopsis) # Long description is only added if synopsis is not empty if description: ctrl_list.append(description) # dpkg requires empty newline at end of file return u'\n'.join(ctrl_list).strip(u'\n') + u'\n' ## Retrieves the name from the 'package' field # # \return # <b><i>String</i></b> package name def GetPackageName(self): return GetField(self, inputid.PACKAGE).GetValue() ## Reads & parses page data from a formatted text file # # TODO: Use 'Set'/'SetPage' method # # \param filename # File path to open def ImportFromFile(self, filename): Logger.Debug(__name__, GT(u'Importing file: {}'.format(filename))) if not os.path.isfile(filename): ShowErrorDialog(GT(u'File does not exist: {}'.format(filename)), linewrap=600) return dbrerrno.ENOENT file_text = ReadFile(filename) page_depends = GetPage(pgid.DEPENDS) # Reset fields to default before opening self.Reset() page_depends.Reset() depends_data = self.Set(file_text) page_depends.Set(depends_data) ## Tells the build script whether page should be built def IsOkay(self): # Build page must always be built return True ## Displays a file open dialog for selecting a text file to read def OnBrowse(self, event=None): browse_dialog = GetFileOpenDialog(GetMainWindow(), GT(u'Open File')) if ShowDialog(browse_dialog): self.ImportFromFile(browse_dialog.GetPath()) ## Creates a formatted preview of the control file text def OnPreviewControl(self, event=None): ctrl_info = self.GetCtrlInfo() preview = TextPreview(title=GT(u'Control File Preview'), text=ctrl_info, size=(600, 400)) ShowDialog(preview) ## Opens a file save dialog to export control file data def OnSave(self, event=None): # Get data to write to control file control = self.GetCtrlInfo() save_dialog = GetFileSaveDialog(GetMainWindow(), GT(u'Save Control Information')) save_dialog.SetFilename(u'control') if ShowDialog(save_dialog): # Be sure not to strip trailing newline (dpkg is picky) WriteFile(save_dialog.GetPath(), control, noStrip=u'\n') ## TODO: Doxygen # # FIXME: Unfinished??? def ReLayout(self): # Organize all widgets correctly lc_width = self.coauth.GetSize()[0] self.coauth.SetColumnWidth(0, lc_width / 2) ## Resets all fields on page to default values def Reset(self): for I in self.grp_input: # Calling 'Clear' on ComboBox removes all options if isinstance(I, ( wx.ComboBox, OwnerDrawnComboBox, )): I.SetValue(wx.EmptyString) else: I.Clear() for S in self.grp_select: S.SetSelection(S.Default) self.chk_essential.SetValue(self.chk_essential.Default) ## Fills page's fields with input data # # \param data # Text to be parsed for values # \return # Leftover text to fill out 'Dependecies' page fields def Set(self, data): # Decode to unicode string if input is byte string if isinstance(data, str): data = data.decode(u'utf-8') # Strip leading & trailing spaces, tabs, & newlines data = data.strip(u' \t\n') control_data = data.split(u'\n') # Store Dependencies depends_containers = ( [u'Depends'], [u'Pre-Depends'], [u'Recommends'], [u'Suggests'], [u'Enhances'], [u'Conflicts'], [u'Replaces'], [u'Breaks'], ) # Anything left over is dumped into this list then into the description field description = [] for line in control_data: if u': ' in line: key = line.split(u': ') value = u': '.join( key[1:] ) # For dependency fields that have ": " in description key = key[0] Logger.Debug(__name__, u'Found key: {}'.format(key)) if key == self.chk_essential.GetName().title() and value.lower( ) in (u'yes', u'true'): self.chk_essential.SetValue(True) # Catch Maintainer if key == u'Maintainer': maintainer = value email = None if u'<' in maintainer and maintainer.endswith(u'>'): maintainer = maintainer.split(u'<') email = maintainer[1].strip(u' <>\t') maintainer = maintainer[0].strip(u' \t') for I in self.grp_input: input_name = I.GetName().title() if input_name == u'Maintainer': I.SetValue(maintainer) continue if input_name == u'Email': I.SetValue(email) # NOTE: Maintainer should be listed before email in input list break continue # Set the rest of the input fields for I in self.grp_input: input_name = I.GetName().title() if input_name == u'Synopsis': input_name = u'Description' if key == input_name: I.SetValue(value) # Set the wx.Choice fields for S in self.grp_select: if key == S.GetName().title(): S.SetStringSelection(value) # Set dependencies for container in depends_containers: if container and key == container[0]: for dep in value.split(u', '): container.append(dep) else: # Description if line.startswith(u' .'): # Add a blank line for lines beginning with a period description.append(wx.EmptyString) continue if not TextIsEmpty(line) and line.startswith(u' '): # Remove the first space generated in the description description.append(line[1:]) continue if not TextIsEmpty(line): description.append(line) # Put leftovers in long description self.ti_description.SetValue(u'\n'.join(description)) # Return depends data to parent to be sent to page_depends return depends_containers
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:]))
class DebianScript(wx.Panel): ## Constructor # # \param parent # The <b><i>wx.Window</i></b> parent instance # \param scriptId # Unique <b><i>integer</i></b> identifier for script def __init__(self, parent, scriptId): wx.Panel.__init__(self, parent, scriptId) ## Filename used for exporting script self.FileName = id_definitions[scriptId].lower() ## String name used for display in the application self.ScriptName = None self.SetScriptName() self.ScriptBody = TextAreaPanelESS(self, self.GetId(), monospace=True) self.ScriptBody.EnableDropTarget() self.Check = None # *** Layout *** # lyt_main = BoxSizer(wx.VERTICAL) lyt_main.Add(self.ScriptBody, 1, wx.EXPAND | wx.TOP, 5) self.SetSizer(lyt_main) self.SetAutoLayout(True) self.Layout() # Scripts are hidden by default self.Hide() ## TODO: Doxygen def Disable(self): return self.Enable(False) ## TODO: Doxygen def Enable(self, enable=True): return self.ScriptBody.Enable(enable) ## Retrieves the filename to use for exporting # # \return # Script filename def GetFilename(self): return self.FileName ## Retrieves the script's name for display # # \return # <b><i>String</i></b> representation of script's name def GetName(self): return self.ScriptName ## Retrieves the text body of the script def GetValue(self): return self.ScriptBody.GetValue() ## TODO: Doxygen def Hide(self): if self.Check: self.Check.Hide() return wx.Panel.Hide(self) ## TODO: Doxygen def IsChecked(self): # FIXME: Should check if field is wx.CheckBox if self.Check: return self.Check.IsChecked() return False ## TODO: Doxygen def IsEnabled(self): return FieldEnabled(self.ScriptBody) ## Checks if the script is used & can be exported # # The text area is checked &, if not empty, signifies that # the user want to export the script. # # \return # <b><i>True</i></b> if text area is not empty, <b><i>False</i></b> otherwise def IsOkay(self): return not TextIsEmpty(self.ScriptBody.GetValue()) ## Resets all members to default values def Reset(self): self.ScriptBody.Clear() if self.Check: self.Check.Reset() ## TODO: Doxygen def SetCheckBox(self, check_box): self.Check = check_box ## TODO: Doxygen def SetChecked(self, value=True): self.Check.SetValue(value) ## Sets the name of the script to be displayed # # Sets the displayed script name to a value of either 'Pre Install', # 'Pre Uninstall', 'Post Install', or 'Post Uninstall'. 'self.FileName' # is used to determine the displayed name. # TODO: Add strings to GetText translations def SetScriptName(self): prefix = None suffix = None if u'pre' in self.FileName: prefix = u'Pre' suffix = self.FileName.split(u'pre')[1] elif u'post' in self.FileName: prefix = u'Post' suffix = self.FileName.split(u'post')[1] if suffix.lower() == u'inst': suffix = u'Install' elif suffix.lower() == u'rm': suffix = u'Uninstall' if (prefix != None) and (suffix != None): self.ScriptName = GT(u'{}-{}'.format(prefix, suffix)) ## Fills the script # # \param value # Text to be entered into the script body def SetValue(self, value): self.ScriptBody.SetValue(value) ## TODO: Doxygen def Show(self): if self.Check: self.Check.Show() return wx.Panel.Show(self)