Example #1
0
    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()
Example #2
0
    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()
Example #3
0
    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()
Example #4
0
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:]))
Example #5
0
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)
Example #6
0
 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()
Example #7
0
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)
Example #8
0
    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()
Example #9
0
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
Example #10
0
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:]))
Example #11
0
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)