def __init__(self, parent): wx.Dialog.__init__(self, parent, title=GT(u'Quick Build'), pos=wx.DefaultPosition, size=wx.Size(400, 260)) self.title = self.GetTitle() label_stage = wx.StaticText(self, label=GT(u'Staged directory tree')) self.input_stage = wx.TextCtrl(self) self.input_stage.SetToolTip( wx.ToolTip(GT(u'Root directory of build tree'))) btn_browse_stage = CreateButton(self, btnid.STAGE, image=u'browse') btn_browse_stage.Bind(wx.EVT_BUTTON, self.OnBrowse) label_target = wx.StaticText(self, label=GT(u'Target file')) self.input_target = wx.TextCtrl(self) self.input_target.SetToolTip(wx.ToolTip(GT(u'Target output file'))) btn_browse_target = CreateButton(self, btnid.TARGET, image=u'browse') btn_browse_target.Bind(wx.EVT_BUTTON, self.OnBrowse) btn_build = CreateButton(self, btnid.BUILD) btn_build.SetToolTip(wx.ToolTip(GT(u'Start building'))) btn_build.Bind(wx.EVT_BUTTON, self.OnBuild) btn_cancel = CreateButton(self, btnid.EXIT) btn_cancel.SetToolTip(wx.ToolTip(GT(u'Close dialog'))) btn_cancel.Bind(wx.EVT_BUTTON, self.OnClose) self.gauge = wx.Gauge(self, GAUGE_MAX) self.timer = DebreateTimer(self) self.Bind(wx.EVT_TIMER, self.OnUpdateProgress) self.Bind(EVT_TIMER_STOP, self.OnTimerStop) # *** Layout *** # Lstage_V1 = BoxSizer(wx.VERTICAL) Lstage_V1.Add(label_stage, 0, wx.ALIGN_LEFT) Lstage_V1.Add(self.input_stage, 1, wx.EXPAND) Lstage_H1 = BoxSizer(wx.HORIZONTAL) Lstage_H1.Add(Lstage_V1, 3, wx.ALIGN_TOP) Lstage_H1.Add(btn_browse_stage, 0, wx.ALIGN_TOP | wx.TOP, 7) Ltarget_V1 = BoxSizer(wx.VERTICAL) Ltarget_V1.Add(label_target, 0, wx.ALIGN_LEFT) Ltarget_V1.Add(self.input_target, 1, wx.EXPAND) Ltarget_H1 = BoxSizer(wx.HORIZONTAL) Ltarget_H1.Add(Ltarget_V1, 3, wx.ALIGN_TOP) Ltarget_H1.Add(btn_browse_target, 0, wx.ALIGN_TOP | wx.TOP, 7) Lbtn_H1 = BoxSizer(wx.HORIZONTAL) Lbtn_H1.Add(btn_build, 1, wx.ALIGN_BOTTOM | wx.RIGHT, 2) Lbtn_H1.Add(btn_cancel, 1, wx.ALIGN_BOTTOM | wx.LEFT, 2) Lguage_H1 = BoxSizer(wx.HORIZONTAL) Lguage_H1.Add(self.gauge, 1, lyt.PAD_LR, 5) Lmain_V = BoxSizer(wx.VERTICAL) Lmain_V.AddSpacer(1, wx.EXPAND) Lmain_V.Add(Lstage_H1, -1, wx.EXPAND | lyt.PAD_LR, 5) Lmain_V.Add(Ltarget_H1, -1, wx.EXPAND | lyt.PAD_LR, 5) Lmain_V.Add(Lbtn_H1, -1, wx.ALIGN_CENTER | wx.ALL, 5) Lmain_V.Add(Lguage_H1, -1, wx.EXPAND | wx.ALL, 5) Lmain_V.AddSpacer(1, wx.EXPAND) self.SetAutoLayout(True) self.SetSizer(Lmain_V) self.Layout() self.Bind(wx.EVT_CLOSE, self.OnClose) self.CenterOnParent() # For showing error dialog after build thread exits self.build_error = None
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))