Пример #1
0
    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
Пример #2
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))