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))
class Page(WizardPage): ## Constructor # # \param parent # Parent <b><i>wx.Window</i></b> instance def __init__(self, parent): WizardPage.__init__(self, parent, pgid.COPYRIGHT) self.custom_licenses = [] ## A list of available license templates self.sel_templates = Choice(self, selid.LICENSE, name=u'list»') # Initialize the template list self.OnRefreshList() btn_template = CreateButton(self, label=GT(u'Full Template'), image=u'full', name=u'full»') self.btn_template_simple = CreateButton(self, label=GT(u'Short Template'), image=u'short', name=u'short»') btn_refresh = CreateButton(self, btnid.REFRESH, GT(u'Refresh Template List'), u'refresh', name=u'btn refresh') btn_open = CreateButton(self, btnid.BROWSE, GT(u'Open Template Directory'), u'browse', name=u'btn opendir', commands=u'xdg-open') if not self.sel_templates.GetCount(): self.sel_templates.Enable(False) btn_template.Enable(False) self.btn_template_simple.Enable(False) ## Area where license text is displayed self.dsp_copyright = TextAreaPanelESS(self, monospace=True, name=u'license') self.dsp_copyright.EnableDropTarget() SetPageToolTips(self) # Initiate tooltip for drop-down selector if self.sel_templates.IsEnabled(): self.OnSelectLicense(self.sel_templates) # *** Event Handling *** # self.sel_templates.Bind(wx.EVT_CHOICE, self.OnSelectLicense) btn_open.Bind(wx.EVT_BUTTON, self.OnOpenPath) btn_refresh.Bind(wx.EVT_BUTTON, self.OnRefreshList) btn_template.Bind(wx.EVT_BUTTON, self.OnTemplateFull) self.btn_template_simple.Bind(wx.EVT_BUTTON, self.OnTemplateShort) # *** Layout *** # lyt_top = BoxSizer(wx.HORIZONTAL) lyt_top.Add(wx.StaticText(self, label=GT(u'Available Templates')), 0, lyt.ALGN_CV) lyt_top.Add(self.sel_templates, 0, lyt.ALGN_CV|wx.LEFT, 5) lyt_top.Add(btn_template, 0, wx.LEFT, 5) lyt_top.Add(self.btn_template_simple) lyt_top.Add(btn_refresh) lyt_top.Add(btn_open) lyt_main = BoxSizer(wx.VERTICAL) lyt_main.AddSpacer(10) lyt_main.Add(lyt_top, 0, lyt.PAD_LR|wx.BOTTOM, 5) lyt_main.Add(self.dsp_copyright, 1, wx.EXPAND|lyt.PAD_LRB, 5) self.SetAutoLayout(True) self.SetSizer(lyt_main) self.Layout() ## Displays a confirmation dialog to clear the text area if it is not empty # # \return # <b><i>True</i></b>, if user confirmed def DestroyLicenseText(self): if not TextIsEmpty(self.dsp_copyright.GetValue()): warn_msg = GT(u'This will destroy all license text.') warn_msg = u'{}\n\n{}'.format(warn_msg, GT(u'Continue?')) if ConfirmationDialog(GetMainWindow(), text=warn_msg).ShowModal() not in (wx.ID_OK, wx.OK): return False return True ## \see wiz.wizard.WizardPage.ExportBuild def ExportBuild(self, stage): stage = u'{}/usr/share/doc/{}'.format(stage, GetPage(pgid.CONTROL).GetPackageName()).replace(u'//', u'/') # FIXME: Should be error check self.Export(stage, u'copyright') return (0, None) ## Retrieves copyright/license text # # \return # <b><i>tuple(str, str)</i></b>: Filename & copyright/license text def Get(self, getModule=False): page = self.dsp_copyright.GetValue() if TextIsEmpty(page): page = None if getModule: page = (__name__, page,) return page ## Retrieves license path # # \param licName # License file basename to search for # If 'None', uses currently selected license # \return # Full path to license file if found def GetLicensePath(self, licName=None): # Default to currently selected template if not licName: licName = self.GetSelectedName() return GetLicenseTemplateFile(licName) ## Retrieves the name of the template currently selected def GetSelectedName(self): return GetField(self, selid.LICENSE).GetStringSelection() ## Sets page's fields from opened file def ImportFromFile(self, filename): if not os.path.isfile(filename): return dbrerrno.ENOENT copyright_data = ReadFile(filename, split=True) # Remove preceding empty lines remove_index = 0 for I in copyright_data: if not TextIsEmpty(I): break remove_index += 1 for I in reversed(range(remove_index)): copyright_data.remove(copyright_data[I]) copyright_data = u'\n'.join(copyright_data) self.dsp_copyright.SetValue(copyright_data) return 0 ## Checks if page can be exported or or added to build def IsOkay(self): return not TextIsEmpty(self.dsp_copyright.GetValue()) ## Opens directory containing currently selected license def OnOpenPath(self, event=None): CMD_open = GetExecutable(u'xdg-open') if CMD_open: path = self.GetLicensePath() if not path: ShowErrorDialog(GT(u'Error retrieving template path: {}').format(self.GetSelectedName())) return False path = os.path.dirname(path) if os.path.isdir(path): ExecuteCommand(CMD_open, (path,)) return True return False ## Repopulates template list def OnRefreshList(self, event=None): # FIXME: Ignore symbolic links??? self.custom_licenses = GetLocalLicenses() licenses = list(self.custom_licenses) # System licenses are not added to "custom" list for LIC in GetSysLicenses(): if LIC not in licenses: licenses.append(LIC) for LIC in GetCustomLicenses(): if LIC not in licenses: licenses.append(LIC) self.custom_licenses.append(LIC) self.custom_licenses.sort(key=GS.lower) sel_templates = GetField(self, selid.LICENSE) selected = None if sel_templates.GetCount(): selected = sel_templates.GetStringSelection() sel_templates.Set(sorted(licenses, key=GS.lower)) if selected: if not sel_templates.SetStringSelection(selected): # Selected template file was not found sel_templates.SetSelection(sel_templates.GetDefaultValue()) # Update short template button enabled state self.OnSelectLicense() else: sel_templates.SetSelection(sel_templates.GetDefaultValue()) ## Enables/Disables simple template button # # Simple template generation is only available # for system licenses. def OnSelectLicense(self, event=None): choice = GetField(self, selid.LICENSE) if choice: template = choice.GetString(choice.GetSelection()) if template in self.custom_licenses: self.btn_template_simple.Disable() else: self.btn_template_simple.Enable() self.SetLicenseTooltip() ## Generates a full license template def OnTemplateFull(self, event=None): selected_template = self.sel_templates.GetStringSelection() template_file = self.GetLicensePath(selected_template) if self.DestroyLicenseText(): if not template_file or not os.path.isfile(template_file): ShowErrorDialog(GT(u'Could not locate license file: {}').format(self.GetSelectedName())) return Logger.Debug(__name__, u'Copying license {}'.format(template_file)) license_text = ReadFile(template_file, noStrip=u' ') # Number defines how many empty lines to add after the copyright header # Boolean/Integer defines whether copyright header should be centered/offset add_header = { u'Artistic': (1, True), u'BSD': (0, False), } template_name = os.path.basename(template_file) if template_name in add_header: license_text = license_text.split(u'\n') empty_lines = add_header[template_name][0] for L in range(empty_lines): license_text.insert(0, wx.EmptyString) header = copyright_header.format(GetYear()) center_header = add_header[template_name][1] if center_header: Logger.Debug(__name__, u'Centering header...') offset = 0 # Don't use isinstance() here because boolean is an instance of integer if type(center_header) == int: offset = center_header else: # Use the longest line found in the text to center the header longest_line = GetLongestLine(license_text) Logger.Debug(__name__, u'Longest line: {}'.format(longest_line)) header_length = len(header) if header_length < longest_line: offset = (longest_line - header_length) / 2 if offset: Logger.Debug(__name__, u'Offset: {}'.format(offset)) header = u'{}{}'.format(u' ' * offset, header) # Special changes for BSD license if template_name == u'BSD': line_index = 0 for LI in license_text: if u'copyright (c)' in LI.lower(): license_text[line_index] = header break line_index += 1 else: license_text.insert(0, header) license_text = u'\n'.join(license_text) if not license_text: ShowErrorDialog(GT(u'License template is empty')) return self.dsp_copyright.SetValue(license_text) self.dsp_copyright.SetInsertionPoint(0) self.dsp_copyright.SetFocus() ## Generates a short reference template for a system license def OnTemplateShort(self, event=None): if self.DestroyLicenseText(): self.dsp_copyright.Clear() license_path = u'{}/{}'.format(sys_licenses_path, self.sel_templates.GetString(self.sel_templates.GetSelection())) self.dsp_copyright.WriteText(u'{}\n\n{}'.format(copyright_header.format(GetYear()), license_path)) self.dsp_copyright.SetInsertionPoint(0) self.dsp_copyright.SetFocus() ## Resets all page fields to default values def Reset(self): self.dsp_copyright.Clear() if self.sel_templates.IsEnabled(): self.sel_templates.Reset() self.OnSelectLicense(self.sel_templates) ## Sets the text of the displayed copyright # # \param data # Text to parse for field values def Set(self, data): self.dsp_copyright.SetValue(data) ## Changes the Choice instance's tooltip for the current license def SetLicenseTooltip(self): license_name = self.sel_templates.GetString(self.sel_templates.GetSelection()) license_path = self.GetLicensePath(license_name) if license_path: self.sel_templates.SetToolTip(wx.ToolTip(license_path)) return self.sel_templates.SetToolTip(None)
def __init__(self, parent, 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()