コード例 #1
0
class Wizard(wx.Panel):
    ## Constructor
    #
    #  \param parent
    #    Parent <b><i>wx.Window</i></b> instance
    #  \param pageList
    #    <b><i>List</i></b> of wiz.wizard.WizardPage instances to initialize
    #    wizard with
    def __init__(self, parent, pageList=None):
        wx.Panel.__init__(self, parent, wx.ID_ANY, pageList)
        
        testing = u'alpha' in GetTestList()
        
        # List of pages available in the wizard
        self.Pages = []
        
        self.PagesIds = {}
        
        # IDs for first & last pages
        self.ID_FIRST = None
        self.ID_LAST = None
        
        if testing:
            # Help button
            btn_help = CreateButton(self, btnid.HELP)
            btn_help.SetToolTipString(GT(u'Page help'))
        
        # A Header for the wizard
        pnl_title = wx.Panel(self, style=wx.RAISED_BORDER)
        pnl_title.SetBackgroundColour((10, 47, 162))
        
        # Text displayed from objects "name" - object.GetName()
        self.txt_title = wx.StaticText(pnl_title, label=GT(u'Title'))
        self.txt_title.SetForegroundColour((255, 255, 255))
        
        # font to use in the header
        headerfont = wx.Font(18, wx.DEFAULT, wx.NORMAL, wx.BOLD)
        
        self.txt_title.SetFont(headerfont)
        
        # Previous and Next buttons
        self.btn_prev = CreateButton(self, btnid.PREV)
        self.btn_prev.SetToolTip(TT_wiz_prev)
        self.btn_next = CreateButton(self, btnid.NEXT)
        self.btn_next.SetToolTip(TT_wiz_next)
        
        # These widgets are put into a list so that they are not automatically hidden
        self.permanent_children = [
            pnl_title,
            self.btn_prev,
            self.btn_next,
            ]
        
        if testing:
            self.permanent_children.insert(0, btn_help)
        
        # *** Event Handling *** #
        
        if testing:
            btn_help.Bind(wx.EVT_BUTTON, self.OnHelpButton)
        
        self.btn_prev.Bind(wx.EVT_BUTTON, self.ChangePage)
        self.btn_next.Bind(wx.EVT_BUTTON, self.ChangePage)
        
        # *** Layout *** #
        
        # Position the text in the header
        lyt_title = wx.GridSizer(1, 1)
        lyt_title.Add(self.txt_title, 0, wx.ALIGN_CENTER|wx.ALIGN_CENTER_VERTICAL)
        
        pnl_title.SetSizer(lyt_title)
        
        # Button sizer includes header
        lyt_buttons = BoxSizer(wx.HORIZONTAL)
        
        if testing:
            lyt_buttons.Add(btn_help, 0, wx.LEFT, 5)
        
        lyt_buttons.AddSpacer(5)
        lyt_buttons.Add(pnl_title, 1, wx.EXPAND|wx.RIGHT, 5)
        lyt_buttons.Add(self.btn_prev)
        lyt_buttons.AddSpacer(5)
        lyt_buttons.Add(self.btn_next)
        lyt_buttons.AddSpacer(5)
        
        lyt_main = BoxSizer(wx.VERTICAL)
        lyt_main.Add(lyt_buttons, 0, wx.EXPAND)
        
        self.SetSizer(lyt_main)
        self.SetAutoLayout(True)
        self.Layout()
    
    
    ## Add a new page to the wizard
    #
    #  \param page
    #    Must either be a wiz.wizard.WizardPage instance or the string suffix of the page's module
    def AddPage(self, page):
        err_msg = None
        err_det = None
        
        if not isinstance(page, WizardPage):
            try:
                pagemod = u'wizbin.{}'.format(page)
                page = mimport(pagemod).Page(self)
            
            except ImportError:
                err_msg = u'module does not exist'
                err_det = traceback.format_exc()
        
        lyt_main = self.GetSizer()
        
        if not err_msg:
            # Must already be child
            if not isinstance(page, WizardPage):
                err_msg = u'not WizardPage instance'
            
            elif page not in self.GetChildren():
                err_msg = u'not child of wizard'
            
            elif page in lyt_main.GetChildWindows():
                err_msg = u'page is already added to wizard'
        
        if err_msg:
            err_msg = u'Cannot add page, {}'.format(err_msg)
            
            if err_det:
                ShowErrorDialog(err_msg, err_det)
            
            else:
                ShowErrorDialog(err_msg)
            
            return
        
        main_window = GetMainWindow()
        
        lyt_main.Add(page, 1, wx.EXPAND)
        self.Pages.append(page)
        
        # Add to page menu
        page_menu = GetMenu(menuid.PAGE)
        
        page_menu.AppendItem(
            wx.MenuItem(page_menu, page.Id, page.GetTitle(),
            kind=wx.ITEM_RADIO))
        
        # Bind menu event to ID
        wx.EVT_MENU(main_window, page.Id, main_window.OnMenuChangePage)
    
    
    ## Handles displaying a new page when commanded
    def ChangePage(self, event=None):
        event_id = event.GetEventObject().GetId()
        
        # Get index of currently shown page
        for page in self.Pages:
            if page.IsShown():
                index = self.Pages.index(page)
                
                break
        
        if event_id == btnid.PREV:
            if index != 0:
                index -= 1
        
        elif event_id == btnid.NEXT:
            if index != len(self.Pages) - 1:
                index += 1
        
        page_id = self.Pages[index].GetId()
        
        # Show the indexed page
        self.ShowPage(page_id)
        
        GetMenu(menuid.PAGE).Check(page_id, True)
    
    
    ## Deletes all pages from the wizard
    def ClearPages(self):
        for page in self.Pages:
            self.GetSizer().Remove(page)
        
        self.Pages = []
        
        # Re-enable the buttons if they have been disabled
        self.EnableNext()
        self.EnablePrev()
    
    
    ## Disables the 'next' page button when displaying the last page
    def DisableNext(self):
        self.EnableNext(False)
    
    
    ## Disables 'previous' page button when displaying the first page
    def DisablePrev(self):
        self.EnablePrev(False)
    
    
    ## Enables/Disables 'next' page button dependent on if the last
    #  page is displayed
    #
    #  \param value
    #    Button is enabled <b><i>True</i></b>, disabled otherwise
    def EnableNext(self, value=True):
        if isinstance(value, (bool, int)):
            if value:
                self.btn_next.Enable()
            
            else:
                self.btn_next.Disable()
        
        else:
            # FIXME: Should not raise error here???
            raise TypeError(u'Must be bool or int value')
    
    
    ## Enables/Disables 'previous' page button dependent on if the last
    #  page is displayed
    #
    #  \param value
    #    Button is enabled <b><i>True</i></b>, disabled otherwise
    def EnablePrev(self, value=True):
        if isinstance(value, (bool, int)):
            if value:
                self.btn_prev.Enable()
            
            else:
                self.btn_prev.Disable()
        
        else:
            # FIXME: Should not raise error here???
            raise TypeError(u'Must be bool or int value')
    
    
    ## Exports pages individually by calling wiz.wizard.WizardPage.Export
    #
    #  Filename output is handled by classes inheriting WizardPage
    #
    #  \param pageList
    #    List of WizardPage instances, or page IDs, to be exported
    #  \param outDir
    #    Path to target directory
    def ExportPages(self, pageList, outDir):
        for P in pageList:
            # Support using list of IDs instead of WizardPage instances
            if not isinstance(P, WizardPage):
                P = self.GetPage(P)
            
            P.Export(outDir)
    
    
    ## Retrieves all current wiz.wizard.WizardPage instances
    #
    #  \return
    #    <b><i>Tuple</i></b> list of currently available wizard pages
    def GetAllPages(self):
        return tuple(self.Pages)
    
    
    ## Retrieves currently displayed page
    #
    #  \return
    #    wiz.wizard.WizardPage instance
    def GetCurrentPage(self):
        for page in self.Pages:
            if page.IsShown():
                return page
    
    
    ## Retrieve currently displayed page's ID
    #
    #  \return
    #    <b><i>Integer</i></b> ID of page
    def GetCurrentPageId(self):
        current_page = self.GetCurrentPage()
        if current_page:
            return current_page.GetId()
    
    
    ## Retrieves a page by ID
    #
    #  \param pageId
    #    <b><i>Integer</i></b> ID of desired page
    #  \return
    #    wiz.wizard.WizardPage instance or <b><i>None</i></b> if ID not found
    def GetPage(self, pageId):
        for P in self.Pages:
            if P.GetId() == pageId:
                return P
        
        Logger.Warn(__name__, u'Page with ID {} has not been constructed'.format(pageId))
    
    
    ## Retrieves the full list of page IDs
    #
    #  \return
    #    <b><i>Tuple</i></b> list of all current pages IDs
    def GetPagesIdList(self):
        page_ids = []
        
        for P in self.Pages:
            page_ids.append(P.GetId())
        
        return tuple(page_ids)
    
    
    ## Fills information for each page when project file is opened
    #
    #  Each page imports a file by parsing the filename
    #
    #  \param filesDir
    #    Path to directory where project files have been extracted
    def ImportPagesInfo(self, filesDir):
        for PATH, DIRS, FILES in os.walk(filesDir):
            for F in FILES:
                for page in self.Pages:
                    page_name = page_ids[page.GetId()].upper()
                    n_index = len(page_name)
                    
                    if F[:n_index] == page_name:
                        Logger.Debug(__name__,
                                GT(u'Imported project file {} matches page {}'.format(F, page_name)))
                        
                        page.ImportFromFile(u'{}/{}'.format(PATH, F))
    
    
    ## Initializes wizard by displaying an initial page
    #
    #  \param showPage
    #    <b><i>Integer</i></b> index of page to be shown
    def Initialize(self, showPage=0):
        if self.Pages:
            self.ID_FIRST = self.Pages[0].Id
            self.ID_LAST = self.Pages[-1].Id
        
        if not showPage:
            self.ShowPage(self.ID_FIRST)
        
        else:
            self.ShowPage(self.Pages[showPage].Id)
        
        for PAGE in self.Pages:
            PAGE.InitPage()
        
        self.Layout()
    
    
    ## Uses children wiz.wizard.WizardPage instances to set pages
    #
    #  \return
    #    Value of wiz.wizard.Wizard.SetPages
    def InitPages(self):
        pages = []
        
        for C in self.GetChildren():
            if isinstance(C, WizardPage):
                pages.append(C)
        
        return self.SetPages(pages)
    
    
    ## Handles event emitted by 'help' button
    #
    #  Shows a help dialog for currently displayed page
    def OnHelpButton(self, event=None):
        label = self.GetCurrentPage().GetTitle()
        page_help = MarkdownDialog(self, title=GT(u'Help'), readonly=True)
        
        page_help.SetText(GT(u'Help information for page "{}"'.format(label)))
        
        ShowDialog(page_help)
    
    
    ## Removes a page from the wizard & memory
    #
    #  \param pageId
    #    <b><i>Integer</i></b> ID of the page to be removed
    def RemovePage(self, pageId):
        page = self.GetPage(pageId)
        
        if page in self.Pages:
            self.Pages.pop(self.Pages.index(page))
        
        lyt_main = self.GetSizer()
        if page in lyt_main.GetChildWindows():
            lyt_main.Remove(page)
        
        self.Layout()
        
        # Remove from page menu
        GetMenu(menuid.PAGE).Remove(pageId).Destroy()
    
    
    ## Resets all but greeting page
    #
    #  \return
    #    Value of wiz.wizard.Wizard.Initialize
    def Reset(self):
        for PAGE in reversed(self.Pages):
            if PAGE.Id != pgid.GREETING:
                self.RemovePage(PAGE.Id)
        
        return self.Initialize()
    
    
    ## Resets each page's fields to default settings
    #
    #  Calls wiz.wizard.WizardPage.Reset
    def ResetPagesInfo(self):
        for page in self.Pages:
            page.Reset()
    
    
    ## Sets up the wizard for 'binary' mode
    #
    #  \param startPage
    #    <b><i>Integer</i></b> index of page to be initially displayed
    def SetModeBin(self, startPage=1):
        self.Reset()
        
        mods = [
            u'control',
            u'depends',
            u'files',
            u'scripts',
            u'changelog',
            u'copyright',
            u'launchers',
            u'build',
            ]
        
        if u'alpha' in GetTestList() or DebugEnabled():
            mods.insert(3, u'manuals')
        
        for M in mods:
            self.AddPage(M)
        
        self.Initialize(startPage)
    
    
    ## Sets up the wizard for 'source' mode
    #
    #  FIXME: WIP
    def SetModeSrc(self):
        self.Reset()
    
    
    ## Organizes wiz.wizard.WizardPage instances for displaying as pages in wizard
    #
    #  FIXME: Deprecated???
    #
    #  \param pages
    #    List of pages owned by wizard to be used
    #  \deprecated
    def SetPages(self, pages):
        self.ID_FIRST = pages[0].GetId()
        self.ID_LAST = pages[-1].GetId()
        
        main_window = GetMainWindow()
        
        # Make sure all pages are hidden
        children = self.GetChildren()
        for child in children:
            if child not in self.permanent_children:
                child.Hide()
        
        # Remove any current pages from the wizard
        self.ClearPages()
        
        if not isinstance(pages, (list, tuple)):
            # FIXME: Should not raise error here???
            raise TypeError(u'Argument 2 of Wizard.SetPages() must be List or Tuple')
        
        for PAGE in pages:
            if PAGE.GetId() != pgid.GREETING:
                self.Pages.append(PAGE)
                self.PagesIds[PAGE.GetId()] = PAGE.GetName().upper()
                self.GetSizer().Insert(1, PAGE, 1, wx.EXPAND)
                
                page_id = PAGE.GetId()
                
                # Add pages to main menu
                page_menu = main_window.GetMenu(menuid.PAGE)
                
                page_menu.AppendItem(
                    wx.MenuItem(page_menu, page_id, PAGE.GetTitle(),
                    kind=wx.ITEM_RADIO))
                
                # Bind menu event to ID
                wx.EVT_MENU(main_window, page_id, main_window.OnMenuChangePage)
        
        # Initailize functions that can only be called after all pages are constructed
        for PAGE in pages:
            PAGE.InitPage()
        
        self.ShowPage(self.ID_FIRST)
        
        self.Layout()
    
    
    ## Sets the text displayed in the wizard title bar
    #
    #  \param title
    #    Text to be displayed
    def SetTitle(self, title):
        self.txt_title.SetLabel(title)
        self.Layout()
    
    
    ## Sets or changes the displayed page
    #
    #  Posts a 'change page' event to notify the main window
    #
    #  \param pageId
    #    globals.ident.pgid of the page to be displayed
    def ShowPage(self, pageId):
        for p in self.Pages:
            if p.GetId() != pageId:
                p.Hide()
            
            else:
                p.Show()
                self.txt_title.SetLabel(p.GetTitle())
        
        if pageId == self.ID_FIRST:
            self.btn_prev.Enable(False)
        
        elif not FieldEnabled(self.btn_prev):
            self.btn_prev.Enable(True)
        
        if pageId == self.ID_LAST:
            self.btn_next.Enable(False)
        
        elif not FieldEnabled(self.btn_next):
            self.btn_next.Enable(True)
        
        self.Layout()
        
        wx.PostEvent(GetMainWindow(), ChangePageEvent(0))
コード例 #2
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)
コード例 #3
0
    def __init__(self, parent, win_id=wx.ID_ANY, name=u'launcher'):
        ScrolledPanel.__init__(self, parent, win_id, name=name)

        # --- Buttons to open/preview/save .desktop file
        btn_open = CreateButton(self,
                                btnid.BROWSE,
                                GT(u'Browse'),
                                u'browse',
                                name=u'btn browse')
        btn_save = CreateButton(self,
                                btnid.SAVE,
                                GT(u'Save'),
                                u'save',
                                name=u'btn save')
        btn_preview = CreateButton(self,
                                   btnid.PREVIEW,
                                   GT(u'Preview'),
                                   u'preview',
                                   name=u'btn preview')

        # --- TYPE
        opts_type = (
            u'Application',
            u'Link',
            u'Directory',
        )

        txt_type = wx.StaticText(self, label=GT(u'Type'), name=u'type')
        ti_type = ComboBoxESS(self,
                              inputid.TYPE,
                              choices=opts_type,
                              name=u'Type',
                              defaultValue=opts_type[0])

        # --- ENCODING
        opts_enc = (
            u'UTF-1',
            u'UTF-7',
            u'UTF-8',
            u'CESU-8',
            u'UTF-EBCDIC',
            u'UTF-16',
            u'UTF-32',
            u'SCSU',
            u'BOCU-1',
            u'Punycode',
            u'GB 18030',
        )

        txt_enc = wx.StaticText(self, label=GT(u'Encoding'), name=u'encoding')
        ti_enc = ComboBoxESS(self,
                             inputid.ENC,
                             choices=opts_enc,
                             name=u'Encoding',
                             defaultValue=opts_enc[2])

        # --- TERMINAL
        chk_term = CheckBoxESS(self,
                               chkid.TERM,
                               GT(u'Terminal'),
                               name=u'Terminal')

        # --- STARTUP NOTIFY
        chk_notify = CheckBoxESS(self,
                                 chkid.NOTIFY,
                                 GT(u'Startup Notify'),
                                 name=u'StartupNotify',
                                 defaultValue=True)

        # --- NAME (menu)
        txt_name = wx.StaticText(self, label=GT(u'Name'), name=u'name*')
        ti_name = TextAreaESS(self, inputid.NAME, name=u'Name')
        ti_name.req = True

        # --- EXECUTABLE
        txt_exec = wx.StaticText(self, label=GT(u'Executable'), name=u'exec')
        ti_exec = TextAreaESS(self, inputid.EXEC, name=u'Exec')

        # --- COMMENT
        txt_comm = wx.StaticText(self, label=GT(u'Comment'), name=u'comment')
        ti_comm = TextAreaESS(self, inputid.DESCR, name=u'Comment')

        # --- ICON
        txt_icon = wx.StaticText(self, label=GT(u'Icon'), name=u'icon')
        ti_icon = TextAreaESS(self, inputid.ICON, name=u'Icon')

        txt_mime = wx.StaticText(self, label=GT(u'MIME Type'), name=u'mime')
        ti_mime = TextAreaESS(self,
                              inputid.MIME,
                              defaultValue=wx.EmptyString,
                              name=u'MimeType',
                              outLabel=u'MimeType')

        # ----- OTHER/CUSTOM
        txt_other = wx.StaticText(self,
                                  label=GT(u'Custom Fields'),
                                  name=u'other')
        btn_other = CreateButton(self,
                                 label=GT(u'Other'),
                                 image=u'add',
                                 name=u'btn other')
        btn_rm_other = CreateButton(self,
                                    btnid.REMOVE,
                                    GT(u'Remove Other'),
                                    u'remove',
                                    name=u'btn rm other')
        pnl_other = SectionedPanel(self, inputid.OTHER)

        btn_rm_other.Enable(pnl_other.HasSelected())

        # --- CATEGORIES
        opts_category = (
            u'2DGraphics',
            u'Accessibility',
            u'Application',
            u'ArcadeGame',
            u'Archiving',
            u'Audio',
            u'AudioVideo',
            u'BlocksGame',
            u'BoardGame',
            u'Calculator',
            u'Calendar',
            u'CardGame',
            u'Compression',
            u'ContactManagement',
            u'Core',
            u'DesktopSettings',
            u'Development',
            u'Dictionary',
            u'DiscBurning',
            u'Documentation',
            u'Email',
            u'FileManager',
            u'FileTransfer',
            u'Game',
            u'GNOME',
            u'Graphics',
            u'GTK',
            u'HardwareSettings',
            u'InstantMessaging',
            u'KDE',
            u'LogicGame',
            u'Math',
            u'Monitor',
            u'Network',
            u'OCR',
            u'Office',
            u'P2P',
            u'PackageManager',
            u'Photography',
            u'Player',
            u'Presentation',
            u'Printing',
            u'Qt',
            u'RasterGraphics',
            u'Recorder',
            u'RemoteAccess',
            u'Scanning',
            u'Screensaver',
            u'Security',
            u'Settings',
            u'Spreadsheet',
            u'System',
            u'Telephony',
            u'TerminalEmulator',
            u'TextEditor',
            u'Utility',
            u'VectorGraphics',
            u'Video',
            u'Viewer',
            u'WordProcessor',
            u'Wine',
            u'Wine-Programs-Accessories',
            u'X-GNOME-NetworkSettings',
            u'X-GNOME-PersonalSettings',
            u'X-GNOME-SystemSettings',
            u'X-KDE-More',
            u'X-Red-Hat-Base',
            u'X-SuSE-ControlCenter-System',
        )

        txt_category = wx.StaticText(self,
                                     label=GT(u'Categories'),
                                     name=u'category')
        btn_catclr = CreateButton(self,
                                  btnid.CLEAR,
                                  GT(u'Clear'),
                                  u'clear',
                                  name=u'clear category')
        lst_categories = CheckList(self,
                                   listid.CAT,
                                   opts_category,
                                   name=u'Categories')

        if not lst_categories.HasSelected():
            btn_catclr.Disable()

        txt_catcustom = wx.StaticText(
            self, label=GT(u'Custom Categories (Separate by "," or ";")'))
        # Set to 'True' to list custom categories first
        # FIXME: Should this be saved to project instead of config???
        chk_catcustom = CheckBoxCFG(self,
                                    chkid.CAT,
                                    GT(u'List first'),
                                    name=u'chk catcustom',
                                    cfgKey=u'prioritize custom categories')
        ti_catcustom = TextAreaESS(self, inputid.CAT2, name=u'category custom')

        # *** Event Handling *** #

        btn_open.Bind(wx.EVT_BUTTON, self.OnLoadLauncher)
        btn_save.Bind(wx.EVT_BUTTON, self.OnExportLauncher)
        btn_preview.Bind(wx.EVT_BUTTON, self.OnPreviewLauncher)

        btn_other.Bind(wx.EVT_BUTTON, self.OnOtherAdd)
        btn_rm_other.Bind(wx.EVT_BUTTON, self.OnOtherRemove)

        btn_catclr.Bind(wx.EVT_BUTTON, self.OnClearCategories)

        wx.EVT_CHECKBOX(self, inputid.OTHER, self.OnOtherSelect)
        wx.EVT_CHECKBOX(self, listid.CAT, self.OnCatSelect)

        # *** Layout *** #

        LEFT_CENTER = wx.ALIGN_LEFT | wx.ALIGN_CENTER_VERTICAL
        LEFT_BOTTOM = wx.ALIGN_LEFT | wx.ALIGN_BOTTOM
        RIGHT_BOTTOM = wx.ALIGN_RIGHT | wx.ALIGN_BOTTOM

        lyt_opts1 = wx.FlexGridSizer()
        lyt_opts1.SetCols(3)
        lyt_opts1.SetRows(2)

        lyt_opts1.Add(txt_type, 0, LEFT_CENTER)
        lyt_opts1.Add(ti_type, 0, wx.EXPAND | wx.LEFT, 5)
        lyt_opts1.Add(chk_term, 0, LEFT_CENTER | wx.LEFT, 5)
        lyt_opts1.Add(txt_enc, 0, LEFT_CENTER | wx.TOP, 5)
        lyt_opts1.Add(ti_enc, 0, wx.LEFT | wx.TOP, 5)
        lyt_opts1.Add(chk_notify, 0, LEFT_CENTER | wx.LEFT | wx.TOP, 5)

        lyt_top = BoxSizer(wx.HORIZONTAL)
        lyt_top.Add(lyt_opts1, 0, wx.EXPAND | wx.ALIGN_BOTTOM)
        lyt_top.AddStretchSpacer(1)
        lyt_top.Add(btn_open, 0, wx.ALIGN_TOP)
        lyt_top.Add(btn_save, 0, wx.ALIGN_TOP)
        lyt_top.Add(btn_preview, 0, wx.ALIGN_TOP)

        lyt_mid = wx.GridBagSizer()
        lyt_mid.SetCols(4)
        lyt_mid.AddGrowableCol(1)
        lyt_mid.AddGrowableCol(3)

        # Row 1
        row = 0
        lyt_mid.Add(txt_name, (row, 0), flag=LEFT_CENTER)
        lyt_mid.Add(ti_name, (row, 1), flag=wx.EXPAND | wx.LEFT, border=5)
        lyt_mid.Add(txt_exec, (row, 2), flag=LEFT_CENTER | wx.LEFT, border=5)
        lyt_mid.Add(ti_exec, (row, 3), flag=wx.EXPAND | wx.LEFT, border=5)

        # Row 2
        row += 1
        lyt_mid.Add(txt_comm, (row, 0), flag=LEFT_CENTER | wx.TOP, border=5)
        lyt_mid.Add(ti_comm, (row, 1),
                    flag=wx.EXPAND | wx.LEFT | wx.TOP,
                    border=5)
        lyt_mid.Add(txt_icon, (row, 2),
                    flag=LEFT_CENTER | wx.LEFT | wx.TOP,
                    border=5)
        lyt_mid.Add(ti_icon, (row, 3),
                    flag=wx.EXPAND | wx.LEFT | wx.TOP,
                    border=5)

        # Row 3
        row += 1
        lyt_mid.Add(txt_mime, (row, 0), flag=LEFT_CENTER | wx.TOP, border=5)
        lyt_mid.Add(ti_mime, (row, 1),
                    flag=wx.EXPAND | wx.LEFT | wx.TOP,
                    border=5)

        lyt_bottom = wx.GridBagSizer()

        row = 0
        lyt_bottom.Add(txt_other, (row, 0), flag=LEFT_BOTTOM)
        lyt_bottom.Add(btn_other, (row, 1), flag=RIGHT_BOTTOM)
        lyt_bottom.Add(btn_rm_other, (row, 2), flag=RIGHT_BOTTOM)
        lyt_bottom.Add(txt_category, (row, 3),
                       flag=LEFT_BOTTOM | wx.LEFT,
                       border=5)
        lyt_bottom.Add(btn_catclr, (row, 4), flag=RIGHT_BOTTOM)

        row += 1
        lyt_bottom.Add(pnl_other, (row, 0), (3, 3), wx.EXPAND)
        lyt_bottom.Add(lst_categories, (row, 3), (1, 2), wx.EXPAND | wx.LEFT,
                       5)

        row += 1
        lyt_bottom.Add(txt_catcustom, (row, 3),
                       flag=LEFT_BOTTOM | wx.LEFT | wx.TOP,
                       border=5)
        lyt_bottom.Add(chk_catcustom, (row, 4), flag=RIGHT_BOTTOM)

        row += 1
        lyt_bottom.Add(ti_catcustom, (row, 3), (1, 2),
                       flag=wx.EXPAND | wx.LEFT,
                       border=5)

        lyt_bottom.AddGrowableRow(1)
        lyt_bottom.AddGrowableCol(1)
        lyt_bottom.AddGrowableCol(3)

        # --- Page 5 Sizer --- #
        lyt_main = BoxSizer(wx.VERTICAL)
        lyt_main.AddSpacer(5)
        lyt_main.Add(lyt_top, 0, wx.EXPAND | wx.LEFT | wx.RIGHT, 5)
        lyt_main.Add(lyt_mid, 0, wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, 5)
        lyt_main.Add(lyt_bottom, 1, wx.EXPAND | wx.ALL, 5)

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