Example #1
0
    def onClick(self, event):
        """Swap through the three states when the check box is clicked."""

        if self.widgetId:
            w = self.getWxWidget()
            state = w.Get3StateValue()

            if (state == wx.CHK_UNDETERMINED and 
                pr.getActive() is pr.getDefaults()):
                state = wx.CHK_UNCHECKED
                w.Set3StateValue(state)

            if state == wx.CHK_CHECKED:
                pr.getActive().setValue(self.widgetId, 'yes')
                newValue = 'yes'
                
            elif state == wx.CHK_UNCHECKED:
                pr.getActive().setValue(self.widgetId, 'no')
                newValue = 'no'

            else:
                pr.getActive().removeValue(self.widgetId)
                newValue = 'default'

            self.updateState()
            events.send(events.EditNotify(self.widgetId, newValue))
        
        # Let wxWidgets process the event, too.
        event.Skip()
Example #2
0
def create(name, gameComponent):
    """Create a new profile with the specified name.  The identifier
    of the profile is generated automatically.  The identifier is not
    visible to the user.

    @param name The visible name of the new profile.

    @param gameComponent The game that the profile will be using.

    @return The Profile object that was created.
    """

    # Generate an unused identifier.
    identifier = _getNewProfileId()

    p = sb.profile.Profile(identifier)

    # Set the basic information of the profile.
    p.setName(name)
    p.setValue('game', gameComponent)

    # Add it to the list of profiles and send a notification.
    profiles.append(p)
    events.send(events.ProfileNotify(p))
    setActive(p)
    return p
Example #3
0
def refresh():
    """Empties the data of all loaded addons from the database and reloads
    everything. Sends out a 'addon-database-reloaded' notification."""

    init()
    loadAll()
    events.send(events.Notify("addon-database-reloaded"))
Example #4
0
    def onWindowClose(self, ev):
        """Handle the window close event that is sent when the user
        tries to close the main window.  Broadcasts a 'quit'
        events.Notify object so that all the listeners will know that
        the application is closing down.

        @param ev A wxCloseEvent object.
        """
        # Send a 'quit' command so that everyone has a chance to save
        # their current status.
        events.send(events.Notify('quit'))

        # Save window size to UserHome/conf/window.conf.
        winSize = self.GetSizeTuple()
        fileName = os.path.join(paths.getUserPath(paths.CONF), 'window.conf')
        try:
            f = file(fileName, 'w')
            f.write('# This file is generated automatically.\n')
            f.write('appearance main (\n')
            f.write('  width = %i\n  height = %i\n' % winSize)
            f.write('  x = %i\n  y = %i\n' % self.GetPositionTuple())
            if self.splitPos != None:
                f.write('  split-position = %i\n' % self.splitPos)
            f.write('  profile-split-position = %i\n' % self.profSplitPos)
            f.write(')\n')
        except:
            # Window size not saved.
            pass

        # Destroy the main frame.
        self.Destroy()
        return True
Example #5
0
    def setValue(self, settingId, newValue, doNotify=True):
        """Set the value of the setting in this profile.

        @param settingId Identifier of the setting to set.

        @param newValue New value for the setting (as a string).

        @param doNotify If True, a notification event will be sent.
        """
        value = None

        if st.isDefined(settingId):
            # System settings are not saved into profiles.
            return

        # Change the value of an existing Value.
        for v in self.values:
            if v.getId() == settingId:
                value = v

        if value:
            value.setValue(newValue)
        else:
            value = Value(settingId, newValue)
            self.values.append(value)

        # A kludge for detecting a change of the language.
        if self is profdb.defaults and settingId == 'language':
            language.change(newValue)
                
        # Send a notification of this.
        if doNotify:
            events.send(events.ValueNotify(settingId, newValue, self))
Example #6
0
    def onToggle(self, ev):
        """Handle a wxWidgets toggle button click event."""
        # Since this is supposed to be a normal button and not a
        # toggle button, return to the Off-state automatically.
        self.getWxWidget().SetValue(False)
        events.send(events.Command(self.widgetId))

        # This causes a reaction.
        self.react()
Example #7
0
    def onItemSelected(self, ev):
        """Handle the wxWidgets event that is sent when the current
        selection changes in the list box.

        @param ev A wxWidgets event.
        """
        ev.Skip()
        events.send(events.SelectNotify(self.widgetId,
                                        self.items[ev.GetSelection()][0]))
Example #8
0
def prepareWindows():
    """Layout windows and make everything ready for action."""

    events.send(events.Notify('preparing-windows'))

    app.mainFrame.updateMenus()
    app.mainFrame.updateLayout()
    app.mainFrame.Show()
    app.mainFrame.Freeze()
Example #9
0
    def onFocus(self, event):
        """Handle the wxWidgets event that's sent when the widget
        received input focus.

        @param event A wxWidgets event.
        """
        # Send a focus event if a focus identifier has been specified.
        if self.focusId:
            events.send(events.FocusNotify(self.focusId))
        event.Skip()
Example #10
0
    def onItemDeselected(self, event):
        """Handle the wxWidgets item deselection event.

        @param event  A wxWidgets event.
        """
        if self.widgetId:
            item = self.items[self.getWxWidget().GetItemData(event.GetIndex())]
            events.send(events.DeselectNotify(self.widgetId, item))

        event.Skip()
Example #11
0
    def onTabChange(self, ev):
        """Handle the wxWidgets event that occurs when the currently
        selected tab changes."""

        # Figure out which panel is now visible.
        tabPanel = self.getWxWidget().GetPage(ev.GetSelection())

        # Send a notification event.
        notification = events.SelectNotify(self.widgetId, self.__lookupPanel(tabPanel))
        events.send(notification)
Example #12
0
    def onThumbTrack(self, ev):
        if self.widgetId:
            newValue = self.getValue()

            if newValue != self.oldValue:
                pr.getActive().setValue(self.widgetId, str(newValue))

                # Send a notification.
                events.send(events.EditNotify(self.widgetId, newValue))
                self.oldValue = newValue
Example #13
0
def hide(identifier):
    """Mark a profile hidden."""

    prof = get(identifier)

    if prof is defaults:
        # Hiding the defaults is not possible.
        return

    prof.setHidden(True)
    events.send(events.ProfileNotify(prof))
Example #14
0
    def onClick(self, ev):
        """Clicking a label causes a focus request to be sent."""
        
        focusId = self.focusId
        if not focusId:
            focusId = self.widgetId
        
        if focusId:
            event = events.FocusRequestNotify(focusId)
            events.send(event)

        ev.Skip()
Example #15
0
def refresh(hasChanged=False):
    """Send a notification that will cause everybody to refresh their
    state with regards to the active profile.
    
    @todo  Move this out of the module so the import is unnecessary?
    """
    ui.freeze()
    
    event = events.ActiveProfileNotify(active, hasChanged)
    events.send(event)

    ui.unfreeze() 
Example #16
0
    def removeValue(self, settingId):
        """Remove this value from the profile entirely.

        @param settingId Identifier of the setting.
        """
        # Kludge for detecting the change of the language.
        if self is profdb.defaults and settingId == 'language':
            language.change(None)

        for v in self.values:
            if v.getId() == settingId:
                self.values.remove(v)
                events.send(events.ValueNotify(settingId, None, self))
Example #17
0
 def __new__(meta, class_name, bases, new_attrs):
     post_funcs = []
     early_funcs = []
     events.send(events.ClassCreateSignal, bases[0], class_name, bases, new_attrs, post_funcs, early_funcs)
     cls = type.__new__(meta, class_name, bases, new_attrs)
     for func in early_funcs:
         func(cls)
     if new_attrs.has_key("__classinit__"):
         cls.__classinit__ = staticmethod(cls.__classinit__.im_func)
     cls.__classinit__(cls, new_attrs)
     for func in post_funcs:
         func(cls)
     return cls
Example #18
0
def duplicate(identifier, name):
    if identifier == 'defaults':
        return

    # Generate an unused identifier.
    p = get(identifier).duplicate(_getNewProfileId())

    p.setName(name)

    # Add it to the list of profiles and send a notification.
    profiles.append(p)
    events.send(events.ProfileNotify(p))
    setActive(p)
    return p
Example #19
0
def startMainLoop():
    """Start the wxWidgets main loop."""

    # Before we give wxPython all control, update the layout of UI
    # areas.
    app.showMainWindow()

    # Display any issues that came up during init.
    logger.show()

    # Notify everyone that the main loop is about to kick in.
    events.send(events.Notify('init-done'))

    app.MainLoop()
Example #20
0
def startMainLoop():
    """Start the wxWidgets main loop."""

    # Before we give wxPython all control, update the layout of UI
    # areas.
    app.showMainWindow()

    # Display any issues that came up during init.
    logger.show()

    # Notify everyone that the main loop is about to kick in.
    events.send(events.Notify('init-done'))

    app.MainLoop()
Example #21
0
 def __new__(meta, class_name, bases, new_attrs):
     post_funcs = []
     early_funcs = []
     events.send(events.ClassCreateSignal,
                 bases[0], class_name, bases, new_attrs,
                 post_funcs, early_funcs)
     cls = type.__new__(meta, class_name, bases, new_attrs)
     for func in early_funcs:
         func(cls)
     if '__classinit__' in new_attrs:
         cls.__classinit__ = staticmethod(cls.__classinit__.im_func)
     cls.__classinit__(cls, new_attrs)
     for func in post_funcs:
         func(cls)
     return cls
Example #22
0
    def onItemSelected(self, event):
        """Handle the wxWidgets item selection event.

        @param event A wxWidgets event.
        """
        if self.widgetId and self.style == List.STYLE_COLUMNS:
            # Identifier of the selected item is sent with the
            # notification.
            item = self.items[self.getWxWidget().GetItemData(event.GetIndex())]

            # Send a notification about the selected item.
            events.send(events.SelectNotify(self.widgetId, item))

        event.Skip()
        self.react()
Example #23
0
    def onRightDown(self, event):
        """Right button down."""

        w = self.getWxWidget()

        #print "right down in list " + str(event.GetPosition())
        item = w.HitTest(event.GetPosition())
        #print item
        if item >= 0:
            w.SetSelection(item)
            if self.widgetId:
                events.send(events.SelectNotify(
                    self.widgetId, self.items[item][0]))

        event.Skip()
Example #24
0
    def onRightDown(self, event):
        """Right button down."""

        w = self.getWxWidget()

        #print "right down in list " + str(event.GetPosition())
        item = w.HitTest(event.GetPosition())
        #print item
        if item >= 0:
            w.SetSelection(item)
            if self.widgetId:
                events.send(
                    events.SelectNotify(self.widgetId, self.items[item][0]))

        event.Skip()
Example #25
0
    def onItemSelected(self, event):
        """Handle the wxWidgets item selection event.

        @param event A wxWidgets event.
        """
        if self.widgetId and self.style == List.STYLE_COLUMNS:
            # Identifier of the selected item is sent with the
            # notification.
            item = self.items[self.getWxWidget().GetItemData(event.GetIndex())]
            
            # Send a notification about the selected item.
            events.send(events.SelectNotify(self.widgetId, item))

        event.Skip()
        self.react()
Example #26
0
    def onRightClick(self, ev):
        # Let wxWidgets handle the event, too.
        widget = self.getWxWidget()
        if not widget.IsEnabled():
            return

        # Going up or down?
        if ev.ButtonDown():
            # Mouse right down doesn't do anything.
            return

        # Request an update to the popup menu.
        if self.menuId:
            events.send(events.Notify(self.menuId + '-update-request'))

        # Display the popup menu.
        if self.menuItems:
            menu = wx.Menu()
            self.commandMap = {}

            idCounter = 10000

            # Create the menu items.
            for item in self.menuItems:
                if type(item) == tuple:
                    itemId = item[0]
                    itemCommand = item[1]
                else:
                    itemId = item
                    itemCommand = item

                if itemId == '-':
                    # This is just a separator.
                    menu.AppendSeparator()
                    continue

                # Generate a new ID for the item.
                wxId = idCounter
                idCounter += 1
                self.commandMap[wxId] = itemCommand
                menu.Append(
                    wxId,
                    widgets.uniConv(language.translate('menu-' + itemId)))
                wx.EVT_MENU(widget, wxId, self.onPopupCommand)

            # Display the menu.  The callback gets called during this.
            widget.PopupMenu(menu, ev.GetPosition())
            menu.Destroy()
Example #27
0
    def onRightClick(self, ev):
        # Let wxWidgets handle the event, too.
        widget = self.getWxWidget()
        if not widget.IsEnabled():
            return
            
        # Going up or down?
        if ev.ButtonDown():
            # Mouse right down doesn't do anything.
            return

        # Request an update to the popup menu.
        if self.menuId:
            events.send(events.Notify(self.menuId + '-update-request'))

        # Display the popup menu.
        if self.menuItems:
            menu = wx.Menu()
            self.commandMap = {}

            idCounter = 10000

            # Create the menu items.
            for item in self.menuItems:
                if type(item) == tuple:
                    itemId = item[0]
                    itemCommand = item[1]
                else:
                    itemId = item
                    itemCommand = item

                if itemId == '-':
                    # This is just a separator.
                    menu.AppendSeparator()
                    continue
                
                # Generate a new ID for the item.
                wxId = idCounter
                idCounter += 1
                self.commandMap[wxId] = itemCommand
                menu.Append(wxId,
                            widgets.uniConv(language.translate('menu-' + itemId)))
                wx.EVT_MENU(widget, wxId, self.onPopupCommand)

            # Display the menu.  The callback gets called during this.
            widget.PopupMenu(menu, ev.GetPosition())
            menu.Destroy()            
Example #28
0
def install(sourceName):
    """Installs the specified addon into the user's addon database.

    @param fileName Full path of the addon to install.

    @throw AddonFormatError If the addon is not one of the recognized
    formats, this exception is raised.

    @return Identifier of the installed addon.

    @throws Exception The installation failed.
    """
    isManifest = paths.hasExtension("manifest", sourceName)

    if isManifest:
        # Manifests are copied to the manifest directory.
        destPath = paths.getUserPath(paths.MANIFESTS)
    else:
        destPath = paths.getUserPath(paths.ADDONS)

    destName = os.path.join(destPath, os.path.basename(sourceName))

    try:
        # Directories must be copied as a tree.
        if os.path.isdir(sourceName):
            shutil.copytree(sourceName, destName)
        else:
            shutil.copy2(sourceName, destName)

        # Load the new addon.
        if not isManifest:
            identifier = load(destName)
        else:
            identifier = loadManifest(destName)

        # Now that the addon has been installed, save the updated cache.
        writeMetaCache()

        # Send a notification of the new addon.
        notify = events.Notify("addon-installed")
        notify.addon = identifier
        events.send(notify)

    except Exception, x:
        # Unsuccessful.
        raise x
Example #29
0
def install(sourceName):
    """Installs the specified addon into the user's addon database.

    @param fileName Full path of the addon to install.

    @throw AddonFormatError If the addon is not one of the recognized
    formats, this exception is raised.

    @return Identifier of the installed addon.

    @throws Exception The installation failed.
    """
    isManifest = paths.hasExtension('manifest', sourceName)

    if isManifest:
        # Manifests are copied to the manifest directory.
        destPath = paths.getUserPath(paths.MANIFESTS)
    else:
        destPath = paths.getUserPath(paths.ADDONS)

    destName = os.path.join(destPath, os.path.basename(sourceName))

    try:
        # Directories must be copied as a tree.
        if os.path.isdir(sourceName):
            shutil.copytree(sourceName, destName)
        else:
            shutil.copy2(sourceName, destName)

        # Load the new addon.
        if not isManifest:
            identifier = load(destName)
        else:
            identifier = loadManifest(destName)

        # Now that the addon has been installed, save the updated cache.
        writeMetaCache()

        # Send a notification of the new addon.
        notify = events.Notify('addon-installed')
        notify.addon = identifier
        events.send(notify)

    except Exception, x:
        # Unsuccessful.
        raise x
Example #30
0
def uninstall(identifier, doNotify=False):
    """Uninstall an addon.  Uninstalling an addon causes a full reload
    of the entire addon database.
    
    @param identifier  Identifier of the addon to uninstall.
    @param doNotify  True, if a notification should be sent.
    """
    addon = get(identifier)
    path = addon.getSource()
    destPath = os.path.join(paths.getUserPath(paths.UNINSTALLED),
                            os.path.basename(path))

    if os.path.exists(destPath):
        # Simply remove any existing addons with the same name.
        # TODO: Is this wise? Rename old.
        if os.path.isdir(destPath):
            shutil.rmtree(destPath)
        else:
            os.remove(destPath)

    shutil.move(path, destPath)

    # Is there a manifest to uninstall?
    manifest = addon.getId() + '.manifest'
    manifestFile = os.path.join(paths.getUserPath(paths.MANIFESTS), manifest)
    if os.path.exists(manifestFile):
        # Move it to the uninstalled folder.
        destPath = os.path.join(paths.getUserPath(paths.UNINSTALLED), manifest)
        if os.path.exists(destPath):
            os.remove(destPath)
        shutil.move(manifestFile, destPath)

    # Mark as uninstalled.
    addon.uninstall()

    # Detach from all profiles.

    for p in sb.profdb.getProfiles():
        p.dontUseAddon(identifier)

    # Send a notification.
    if doNotify:
        notify = events.Notify('addon-uninstalled')
        notify.addon = identifier
        events.send(notify)
Example #31
0
    def onLeftUp(self, ev):
        """Handle the wxWidgets event when the user clicks on the list widget.

        @param ev A wxWidgets event object.
        """
        w = self.getWxWidget()

        item, flags = w.HitTest(ev.GetPosition())
        if item < 0:
            ev.Skip()
            return

        if flags & wx.LIST_HITTEST_ONITEMICON:
            e = events.Notify(self.widgetId + '-icon-click')
            e.item = self.items[w.GetItemData(item)]
            events.send(e)
           
        ev.Skip()
Example #32
0
    def onLeftUp(self, ev):
        """Handle the wxWidgets event when the user clicks on the list widget.

        @param ev A wxWidgets event object.
        """
        w = self.getWxWidget()

        item, flags = w.HitTest(ev.GetPosition())
        if item < 0:
            ev.Skip()
            return

        if flags & wx.LIST_HITTEST_ONITEMICON:
            e = events.Notify(self.widgetId + '-icon-click')
            e.item = self.items[w.GetItemData(item)]
            events.send(e)

        ev.Skip()
Example #33
0
 def __new__(meta, class_name, bases, new_attrs):
     post_funcs = []
     early_funcs = []
     events.send(events.ClassCreateSignal,
                 bases[0], class_name, bases, new_attrs,
                 post_funcs, early_funcs)
     cls = type.__new__(meta, class_name, bases, new_attrs)
     for func in early_funcs:
         func(cls)
     if new_attrs.has_key('__classinit__'):
         cls.__classinit__ = staticmethod(cls.__classinit__.im_func)
     cls.__classinit__(cls, new_attrs)
     if new_attrs.has_key('__init__'):
         lock = threading.RLock()
         cls.__init__ = threadSafeMethod(lock)(cls.__init__)
     for func in post_funcs:
         func(cls)
     return cls
Example #34
0
def uninstall(identifier, doNotify=False):
    """Uninstall an addon.  Uninstalling an addon causes a full reload
    of the entire addon database.
    
    @param identifier  Identifier of the addon to uninstall.
    @param doNotify  True, if a notification should be sent.
    """
    addon = get(identifier)
    path = addon.getSource()
    destPath = os.path.join(paths.getUserPath(paths.UNINSTALLED), os.path.basename(path))

    if os.path.exists(destPath):
        # Simply remove any existing addons with the same name.
        # TODO: Is this wise? Rename old.
        if os.path.isdir(destPath):
            shutil.rmtree(destPath)
        else:
            os.remove(destPath)

    shutil.move(path, destPath)

    # Is there a manifest to uninstall?
    manifest = addon.getId() + ".manifest"
    manifestFile = os.path.join(paths.getUserPath(paths.MANIFESTS), manifest)
    if os.path.exists(manifestFile):
        # Move it to the uninstalled folder.
        destPath = os.path.join(paths.getUserPath(paths.UNINSTALLED), manifest)
        if os.path.exists(destPath):
            os.remove(destPath)
        shutil.move(manifestFile, destPath)

    # Mark as uninstalled.
    addon.uninstall()

    # Detach from all profiles.

    for p in sb.profdb.getProfiles():
        p.dontUseAddon(identifier)

    # Send a notification.
    if doNotify:
        notify = events.Notify("addon-uninstalled")
        notify.addon = identifier
        events.send(notify)
    def addAddon(self, identifier):
        """Attaches an addon to the profile.  If this is the Defaults
        profile, the addon is detached from all the other profiles.
        This is necessary because of the exclusion rule (see
        getUsedAddons()).

        @param identifier Addon identifier.
        """
        if identifier not in self.addons:
            self.addons.append(identifier)
            # Also send a notification.
            events.send(events.AttachNotify(identifier, self, True))

            if self is profdb.defaults:
                # Detach from others.  The appropriate detach events
                # will be transmitted.
                for p in profdb.getProfiles():
                    if p is not self:
                        p.removeAddon(identifier)
Example #36
0
def change(language):
    """Change the language at runtime.

    @param language Identifier of the new language.
    """
    try:
        if language:
            actual = language
        else:
            actual = 'language-english'

        # Select the new language.
        select(actual[9:])

        # Send a notification so others may update their content.
        events.send(events.LanguageNotify(actual))
        
    except KeyError:
        # Language doesn't exist?
        pass
Example #37
0
    def onItemSelected(self, ev):
        """Handle the wxWidgets event that is sent when the current
        selection changes in the list box.

        @param ev A wxWidgets event.
        """
        if self.widgetId:
            newSelection = self.items[ev.GetSelection()]

            if sb.confdb.isSettingDefined(self.widgetId):
                # This is a setting.
                if newSelection == 'default':
                    pr.getActive().removeValue(self.widgetId)
                else:
                    pr.getActive().setValue(self.widgetId, newSelection)

                # Notify everyone of the change.
                events.send(events.EditNotify(self.widgetId, newSelection))
            else:
                # Normal list.
                events.send(events.SelectNotify(self.widgetId, newSelection))
Example #38
0
    def onItemSelected(self, ev):
        """Handle the wxWidgets event that is sent when the current
        selection changes in the list box.

        @param ev A wxWidgets event.
        """
        if self.widgetId:
            newSelection = self.items[ev.GetSelection()]

            if sb.confdb.isSettingDefined(self.widgetId):
                # This is a setting.
                if newSelection == 'default':
                    pr.getActive().removeValue(self.widgetId)
                else:
                    pr.getActive().setValue(self.widgetId, newSelection)

                # Notify everyone of the change.
                events.send(events.EditNotify(self.widgetId, newSelection))
            else:
                # Normal list.
                events.send(events.SelectNotify(self.widgetId, newSelection))
Example #39
0
    def onEnterWidget(self, event):
        """Handle the wxWidget event of entering the window."""

        if self.focusId:
            events.send(events.FocusNotify(self.focusId))
        event.Skip()
Example #40
0
 def onPopupCommand(self, ev):
     events.send(events.Command(self.commandMap[ev.GetId()]))
Example #41
0
    def onClick(self, ev):
        """Handle a wxWidgets button click event."""
        events.send(events.Command(self.widgetId))

        # This causes a reaction.
        self.react()
Example #42
0
 def onColumnClick(self, ev):
     events.send(
         events.Notify(self.columns[ev.GetColumn()] + '-column-click'))
     ev.Skip()
Example #43
0
 def onItemDoubleClick(self, ev):
     ev.Skip()
     events.send(
         events.SelectNotify(self.widgetId,
                             self.items[ev.GetSelection()][0], True))
Example #44
0
 def onSelectionChanged(self, treeEvent):
     """Send a notification that the selection has changed in the tree."""
     
     item = treeEvent.GetItem()
     events.send(events.SelectNotify(self.widgetId, self.lookupItem(item)))
Example #45
0
 def onLeftClick(self, event):
     if self.widgetId:
         events.send(events.FocusNotify(self.widgetId))
         self.getWxWidget().SetFocus()
     event.Skip()
def commandHandler(event):
    """This is called when a Command event is broadcasted."""

    global profileListDisabled

    if event.hasId('freeze'):
        profileListDisabled = True

    elif event.hasId('unfreeze'):
        profileListDisabled = False
        #notifyHandler(events.Notify('active-profile-changed'))
        pr.refresh()

    elif event.hasId('new-profile'):
        dialog, area = sb.util.dialog.createButtonDialog('new-profile-dialog',
                                                         ['cancel', 'ok'],
                                                         'ok',
                                                         resizable=False)
        dialog.disableWidget('ok')

        entry = area.createArea(alignment=ALIGN_HORIZONTAL)
        entry.setExpanding(False)

        # The name of the profile.
        entry.setWeight(1)
        entry.setBorder(4, ui.BORDER_RIGHT)
        entry.createText('new-profile-name', ':', align=wt.Text.RIGHT)
        entry.setBorder(0)
        entry.setWeight(2)
        nameField = entry.createTextField('')
        nameField.focus()

        # Only enable the OK button if there is something in the name field.
        def buttonEnabler():
            dialog.enableWidget('ok', len(nameField.getText()) > 0)

        nameField.addReaction(buttonEnabler)

        # The game component.
        entry = area.createArea(alignment=ALIGN_HORIZONTAL)
        entry.setExpanding(False)

        entry.setWeight(1)
        entry.setBorder(4, ui.BORDER_RIGHT)
        entry.createText('new-profile-game', ':', align=wt.Text.RIGHT)
        entry.setBorder(0)
        entry.setWeight(2)
        gameDrop = entry.createDropList('')

        for game in st.getGameComponents():
            gameDrop.addItem(game.getId())

        gameDrop.sortItems()

        # Select the first one.
        gameDrop.selectItem(gameDrop.getItems()[0])

        if dialog.run() == 'ok':
            # Get the values from the controls.
            pr.create(nameField.getText(), gameDrop.getSelectedItem())

    elif event.hasId('rename-profile'):
        dialog, area = sb.util.dialog.createButtonDialog(
            'rename-profile-dialog', ['cancel', 'ok'], 'ok', resizable=False)

        prof = pr.getActive()

        # A text field of the new name.
        entry = area.createArea(alignment=ALIGN_HORIZONTAL)
        entry.setExpanding(False)

        # The name of the profile.
        entry.setWeight(1)
        entry.setBorder(4, ui.BORDER_RIGHT)
        entry.createText('rename-profile-name', ':', align=wt.Text.RIGHT)
        entry.setBorder(0)
        entry.setWeight(2)
        nameField = entry.createTextField('')
        nameField.setText(prof.getName())
        nameField.focus()

        # Only enable the OK button if there is something in the name
        # field.
        def buttonEnabler():
            dialog.enableWidget('ok', len(nameField.getText()) > 0)

        nameField.addReaction(buttonEnabler)

        if dialog.run() == 'ok':
            prof.setName(nameField.getText())
            # The profile list needs to be updated, too.
            events.send(events.ProfileNotify(prof))
            pr.refresh()

    elif event.hasId('reset-profile'):
        dialog, area = sb.util.dialog.createButtonDialog(
            'reset-profile-dialog', [
                'cancel', 'reset-profile-values', 'reset-profile-addons',
                'reset-profile-everything'
            ],
            'cancel',
            resizable=False)

        text = language.translate('reset-profile-query')
        message = area.createRichText(
            language.expand(text,
                            pr.getActive().getName()))

        # Accept these as dialog-closing commands.
        dialog.addEndCommand('reset-profile-values')
        dialog.addEndCommand('reset-profile-addons')
        dialog.addEndCommand('reset-profile-everything')

        result = dialog.run()
        if result == 'cancel':
            return

        resetValues = True
        resetAddons = True
        if result == 'reset-profile-values':
            resetAddons = False
        elif result == 'reset-profile-addons':
            resetValues = False
        pr.reset(pr.getActive().getId(), resetValues, resetAddons)
        pr.refresh()

    elif event.hasId('delete-profile'):
        # If this is a system profile, just hide it.
        if pr.getActive().isSystemProfile():
            pr.hide(pr.getActive().getId())
            return

        dialog, area = sb.util.dialog.createButtonDialog(
            'delete-profile-dialog', ['no', 'yes'], 'no', resizable=False)

        text = language.translate('delete-profile-query')
        area.createRichText(language.expand(text, pr.getActive().getName()))

        if dialog.run() == 'yes':
            # Get the values from the controls.
            pr.remove(pr.getActive().getId())

    elif event.hasId('duplicate-profile'):
        dialog, area = sb.util.dialog.createButtonDialog(
            'duplicate-profile-dialog', ['cancel', 'ok'],
            'ok',
            resizable=False)

        text = language.translate('duplicating-profile')
        area.setWeight(1)
        area.createRichText(language.expand(text, pr.getActive().getName()))

        area.setWeight(1)
        entry = area.createArea(alignment=ALIGN_HORIZONTAL)
        entry.setExpanding(False)

        # The name of the profile.
        entry.setWeight(1)
        entry.setBorder(4, ui.BORDER_RIGHT)
        entry.createText('new-profile-name', ':', align=wt.Text.RIGHT)
        entry.setBorder(0)
        entry.setWeight(3)
        nameField = entry.createTextField('')
        nameField.setText(pr.getActive().getName())
        nameField.focus()

        # Only enable the OK button if there is something in the name field.
        def buttonEnabler():
            dialog.enableWidget('ok', len(nameField.getText()) > 0)

        nameField.addReaction(buttonEnabler)

        if dialog.run() == 'ok':
            pr.duplicate(pr.getActive().getId(), nameField.getText())

    elif event.hasId('hide-profile'):
        pr.hide(pr.getActive().getId())

    elif event.hasId('unhide-profiles'):
        # Display a dialog bog for unhiding hidden profiles.
        hiddenProfiles = pr.getProfiles(lambda p: p.isHidden())

        dialog, area = sb.util.dialog.createButtonDialog(
            'unhide-profile-dialog', ['cancel', 'ok'], 'ok', resizable=False)

        area.setWeight(0)
        area.createText('unhiding-profiles')

        area.setWeight(3)
        area.setBorder(0)
        profList = area.createList('', sb.widget.list.List.STYLE_CHECKBOX)
        profList.setMinSize(50, 150)

        def selectAll():
            # Check the entire list.
            for item in profList.getItems():
                profList.checkItem(item, True)

        def clearAll():
            # Uncheck the entire list.
            for item in profList.getItems():
                profList.checkItem(item, False)

        area.setWeight(0)
        controls = area.createArea(alignment=ALIGN_HORIZONTAL, border=2)
        controls.setWeight(0)
        button = controls.createButton(
            'unhide-select-all', style=sb.widget.button.Button.STYLE_MINI)
        button.addReaction(selectAll)
        button.resizeToBestSize()
        button = controls.createButton(
            'unhide-clear-all', style=sb.widget.button.Button.STYLE_MINI)
        button.addReaction(clearAll)
        button.resizeToBestSize()

        for prof in hiddenProfiles:
            profList.addItem(prof.getId())

        if dialog.run() == 'ok':
            # Unhide all the selected items.
            selected = profList.getSelectedItems()
            for sel in selected:
                pr.show(sel)

            if len(selected):
                # Select the first one that was shown.
                pr.setActive(pr.get(selected[0]))
Example #47
0
def handleCommand(event):
    """This is called when someone sends a command event.

    @param event An events.Command object."""

    # Figure out which addon has been currently selected in the addons
    # tree.  The action will target this addon.
    selected = ''

    if event.hasId('refresh-addon-database'):
        ao.refresh()

    elif event.hasId('install-addon'):
        tab30.installer.run()

    elif event.hasId('uninstall-addon'):
        selectedItems = addonList.getSelectedItems()

        # Only take the uninstallable addons.
        addons = filter(lambda i: ao.isUninstallable(i), selectedItems)
        if len(addons) == 0:
            return

        # Make sure the user wants to uninstall.
        dialog, area = sb.util.dialog.createButtonDialog(
            'uninstall-addon-dialog', ['no', 'yes'], 'no', resizable=False)

        if len(addons) == 1:
            text = language.translate('uninstall-addon-query')
            area.setExpanding(True)
            area.createRichText(
                language.expand(text, language.translate(addons[0])))
        else:
            area.setWeight(0)
            area.createText('uninstall-addon-query-several')
            msg = '<html><ul>'
            for addon in addons:
                msg += '<li>' + language.translate(addon) + '</li>'
            msg += '</ul></html>'
            ft = area.createFormattedText()
            ft.setText(msg)
            ft.setMinSize(400, 150)

        if dialog.run() == 'yes':
            for addon in addons:
                ao.uninstall(addon)
            ao.refresh()

    elif event.hasId('addon-info'):
        sel = addonList.getSelectedItems()
        if len(sel) > 0:
            # Show the Addon Inspector.
            tab30.inspector.run(ao.get(sel[0]))

    elif event.hasId('addon-settings'):
        sel = addonList.getSelectedItems()
        if len(sel) > 0:
            command = events.Command('show-addon-settings')
            command.addon = sel[0]
            events.send(command)

    elif event.hasId('load-order'):
        # Open the Load Order dialog.
        tab30.loadorder.run(pr.getActive())

    elif event.hasId('addon-list-check-selected'):
        for addon in addonList.getSelectedItems():
            pr.getActive().useAddon(addon)

    elif event.hasId('addon-list-uncheck-selected'):
        for addon in addonList.getSelectedItems():
            pr.getActive().dontUseAddon(addon)

    elif event.hasId('addon-list-check-all'):
        for addon in addonList.getItems():
            pr.getActive().useAddon(addon)

    elif event.hasId('addon-list-uncheck-all'):
        for addon in addonList.getItems():
            pr.getActive().dontUseAddon(addon)

    elif event.hasId('addon-show-parent-box'):
        for addon in addonList.getSelectedItems():
            a = ao.get(addon)
            if a.getBox():
                showInAddonList(a.getBox().getId())
            break

    elif event.hasId('addon-show-box-category'):
        for addon in addonList.getSelectedItems():
            a = ao.get(addon)
            if a.getType() == 'addon-type-box':
                addonList.deselectAllItems()
                tree.selectItem(a.getContentCategoryLongId())
                refreshListIfVisible()
            break
Example #48
0
 def onPageChange(self, event):
     pageId = event.GetPage().getId()
     events.send(events.SelectNotify('wizard', pageId))
     if self.pageReaction:
         self.pageReaction(event.GetPage())
def restore():
    """Reads all the profiles from disk.  Restores the currently active
    profile as well.  This function has to be called after starting
    the program before any profiles are accessed.

    System profiles that aren't present in the user's profile
    directory are copied to the user's profile directory.
    """
    global defaults
    global profiles
    global restoredActiveId

    # By default, restore selection to the Defaults profile.
    restoredActiveId = 'defaults'

    # Clear the current profile list.
    profiles = []

    systemProfilePaths = [paths.getSystemPath(paths.PROFILES)] + \
                          paths.getBundlePaths(paths.PROFILES)
    userProfilePath = paths.getUserPath(paths.PROFILES)

    # List all the system and user profiles.
    availSystem = _listProfilesIn(systemProfilePaths)
    availUser = _listProfilesIn([userProfilePath])

    # We are going to load only the profiles in the user's direcory,
    # but before that make sure that the user has an instance of each
    # system profile.
    for sysFile in availSystem:
        identifier = paths.getBase(sysFile)

        # Does this exist in the user's directory?
        gotIt = False
        for userFile in availUser:
            if paths.getBase(userFile) == identifier:
                gotIt = True
                break

        if not gotIt:
            # Since the system profile does not exist on the user,
            # copy it to the user profile directory.
            shutil.copyfile(
                sysFile,
                os.path.join(userProfilePath, os.path.basename(sysFile)))

    # Find every profile in system's and user's profile directories.
    # Files in the user's directory augment the files in the system
    # directory.
    for name in _listProfilesIn([userProfilePath]):
        load(os.path.join(userProfilePath, name), False)
    logger.show()

    defaults = get('defaults')

    if defaults is None:
        # Recreate the Defaults profile.
        load(os.path.join(systemProfilePath, "defaults.prof"), False)
        defaults = get('defaults')
        logger.show()

    # Set the default language.
    lang = defaults.getValue('language')
    if lang:
        language.change(lang.getValue())

    # Send profile-loaded notifications.
    for p in profiles:
        if not p.isHidden():
            events.send(events.ProfileNotify(p))

    # Restore the previously active profile.
    prof = get(restoredActiveId)
    if prof:
        setActive(prof)
    else:
        setActive(defaults)
Example #50
0
def generateOptions(profile):
    """Generate a text string of all the command line options used
    when launching a game.

    @param profile A profiles.Profile object.  The values of settings
    are retrieved from here.

    @return All the options in a single string.  Returns None if there
    is an unresolved addon conflict.
    """
    clearLog()
    
    # Determine which addons are in use.  The final list of addons
    # includes all the addons that must be loaded at launch (defaults;
    # required parts of boxes).
    usedAddonIds = profile.getFinalAddons()
    usedAddons = map(lambda id: ao.get(id), usedAddonIds)

    # Form the command line.
    cmdLine = []
    
    # Determine the settings that apply to the components and
    # addons.
    effectiveSettings = st.getCompatibleSettings(profile)

    # Are there any system-specific options defined?
    if st.isDefined('common-options'):
        cmdLine.append(ex.evaluate(st.getSystemString('common-options'), None))

    # All profiles use the same runtime directory.
    if st.isDefined('doomsday-base'):
        basePath = os.path.abspath(st.getSystemString('doomsday-base'))
        cmdLine.append('-basedir ' + paths.quote(basePath))

    # Determine the components used by the profile.
    for compId in profile.getComponents():
        # Append the component's options to the command line as-is.
        cmdLine.append( st.getComponent(compId).getOption() )

    # Resolve conflicting addons by letting the user choose between
    # them.
    if not resolveAddonConflicts(usedAddons, profile):
        # Launch aborted!
        return None

    # Get the command line options for loading all the addons.
    for addon in usedAddons:
        params = addon.getCommandLine(profile).strip()
        if params:
            cmdLine.append(params)

    # Update IDs of used addons.
    usedAddonsId = map(lambda a: a.getId(), usedAddons)

    # Get the command line options from each setting.
    for setting in effectiveSettings:
        # If the setting's required addons are not being loaded, skip
        # this setting.
        skipThis = False
        for req in setting.getRequiredAddons():
            if req not in usedAddonIds:
                skipThis = True
                break

        if skipThis:
            continue
        
        # All settings can't be used at all times.  In
        # case of a conflict, some of the settings are ignored.
        if setting.isEnabled(profile):
            params = setting.getCommandLine(profile).strip()
            if params:
                cmdLine.append(params)

    # Send a launch options notification.  This is done so that
    # plugins are able to observe/modify the list of launch options.
    events.send(events.LaunchNotify(cmdLine))

    return string.join(cmdLine, ' ')
Example #51
0
def handleCommand(event):
    if event.hasId('show-addon-paths'):
        events.send(events.Command('show-snowberry-settings'))
        prefTabs.selectTab('addon-paths')
        pathList.focus()
def show(identifier):
    """Clear the hide flag and show a profile."""

    prof = get(identifier)
    prof.setHidden(False)
    events.send(events.ProfileNotify(prof))
Example #53
0
def runWizard():
    """Run the wizard dialog."""

    # Make sure the help panel isn't updated during the wizard.
    #events.send(events.Command('freeze'))

    suggested = {
        'doom1': 'DOOM.WAD',
        'doom1-share': 'DOOM1.WAD',
        'doom1-ultimate': 'DOOM.WAD',
        'doom2': 'DOOM2.WAD',
        'doom2-tnt': 'TNT.WAD',
        'doom2-plut': 'PLUTONIA.WAD',
        'heretic-ext': 'HERETIC.WAD',
        'heretic-share': 'HERETIC.WAD',
        'heretic': 'HERETIC.WAD',
        'hexen': 'HEXEN.WAD',
        'hexen-demo': 'HEXEN.WAD',
        'hexen-dk': 'HEXEN.WAD',
        'hacx': 'HACX.WAD',
        'chex': 'CHEX.WAD'
    }
    
    events.mute()
    
    # Make the Defaults profile active.
    pr.setActive(pr.getDefaults())
    
    wiz = WizardDialog(language.translate('setup-wizard'),
                       paths.findBitmap('wizard'))

    # Language selection page.
    langPage = WizardPage(wiz, 'wizard-language')
    area = langPage.getArea()
    area.createText('wizard-language-explanation', maxLineLength=65).resizeToBestSize()
    sar, languageCheckBox = area.createSetting(st.getSetting('language'))
    languageCheckBox.getFromProfile(pr.getActive())

    # Game selection.
    gamePage = ProfileWizardPage(wiz, 'wizard-games', None)
    gamePage.follows(langPage)
    area = gamePage.getArea()
    area.createText('wizard-select-games', maxLineLength=65).resizeToBestSize()
    area.setBorderDirs(ui.BORDER_NOT_BOTTOM)
    games = area.createList('', style=sb.widget.list.List.STYLE_CHECKBOX)
    area.setBorderDirs(ui.BORDER_NOT_TOP)
    games.setMinSize(50, 180)
    gamePage.setGameList(games)

    def allGames():
        # Check the entire list.
        for item in games.getItems():
            games.checkItem(item, True)

    def clearGames():
        # Uncheck the entire list.
        for item in games.getItems():
            games.checkItem(item, False)

    
    controls = area.createArea(alignment=ui.ALIGN_HORIZONTAL, border=2)
    controls.setWeight(0)
    button = controls.createButton('wizard-games-all', wb.Button.STYLE_MINI)
    button.addReaction(allGames)
    button.resizeToBestSize()
    button = controls.createButton('wizard-games-clear', wb.Button.STYLE_MINI)
    button.addReaction(clearGames)
    button.resizeToBestSize()

    # The pages will be linked together.
    previousPage = gamePage

    deathKingsWad = None

    # We'll do this dynamically.
    checkedProfiles = ['doom1', 'doom2', 'heretic', 'hexen']
    # Only display the system profiles in the wizard (not any user
    # profiles).
    profiles = pr.getProfiles(lambda p: p.isSystemProfile())
    for p in profiles:
        if p is not pr.getDefaults():
            games.addItem(p.getId(), p.getId() in checkedProfiles)

            # Create a page for the profile.
            page = ProfileWizardPage(wiz, p.getId(), games)

            # Link the pages together.
            page.follows(previousPage)
            previousPage = page
            
            area = page.getArea()

            area.createText('wizard-locate-iwad', maxLineLength=65).resizeToBestSize()

            # The suggestion.
            if suggested.has_key(p.getId()):
                sugArea = area.createArea(alignment=ui.ALIGN_HORIZONTAL, border=2)
                sugArea.setExpanding(False)
                sugArea.setWeight(1)
                sugArea.createText('wizard-suggested-iwad', ':', align=wt.Text.RIGHT)
                sugArea.setWeight(2)
                sug = sugArea.createText('')
                sug.setText(suggested[p.getId()])

            sar, page.iwadText = area.createSetting(st.getSetting('iwad'))

            if p.getId() == 'hexen-dk':
                area.setBorder(12, ui.BORDER_ALL)
                area.createLine()
                area.setBorder(6, ui.BORDER_ALL)
                area.createText('deathkings-selection-title').setHeadingStyle()
                
                # Death Kings is an extension to Hexen.  It uses the
                # same Hexen IWAD, but also an addon IWAD.
                area.createText('wizard-locate-iwad-deathkings', maxLineLength=65).resizeToBestSize()

                entry = area.createArea(alignment=ui.ALIGN_HORIZONTAL, border=4)
                entry.setExpanding(False)
                entry.setWeight(1)
                entry.setBorderDirs(ui.BORDER_NOT_LEFT)
                deathKingsWad = entry.createTextField('')
                entry.setWeight(0)
                entry.setBorderDirs(ui.BORDER_TOP_BOTTOM)
                browseButton = entry.createButton('browse-button', wb.Button.STYLE_MINI)

                def browseDeathKings():
                    # Open a file browser.
                    selection = sb.util.dialog.chooseFile('deathkings-selection-title',
                                                          '', True,
                                                          [('file-type-wad', 'wad')])
                
                    if len(selection) > 0:
                        deathKingsWad.setText(selection)

                browseButton.addReaction(browseDeathKings)

	# Addon paths.
	pathsPage = ProfileWizardPage(wiz, 'wizard-addon-paths', games)
	pathsPage.follows(previousPage)
	area = pathsPage.getArea()
	area.createText('wizard-addon-paths-explanation',
                    maxLineLength=65).resizeToBestSize()

    area.setBorderDirs(ui.BORDER_NOT_BOTTOM)
    pathList = area.createList('addon-paths-list')
    pathList.setMinSize(100, 120)

    # Insert the current custom paths into the list.
    for p in paths.getAddonPaths():
        pathList.addItem(p)

    def addAddonPath():
        selection = sb.util.dialog.chooseFolder('addon-paths-add-prompt', '')
        if selection:
            pathList.addItem(selection)
            pathList.selectItem(selection)

    def removeAddonPath():
        selection = pathList.getSelectedItem()
        if selection:
            pathList.removeItem(selection)

    area.setWeight(0)
    area.setBorderDirs(ui.BORDER_NOT_TOP)
    commands = area.createArea(alignment=ui.ALIGN_HORIZONTAL, border=2)
    commands.setWeight(0)

    # Button for adding new paths.
    button = commands.createButton('new-addon-path', wb.Button.STYLE_MINI)
    button.addReaction(addAddonPath)

    # Button for removing a path.
    button = commands.createButton('delete-addon-path', wb.Button.STYLE_MINI)
    button.addReaction(removeAddonPath)

    # Launch options.
    quitPage = WizardPage(wiz, 'wizard-launching') 
    quitPage.follows(pathsPage)
    area = quitPage.getArea()
    area.createText('wizard-launching-explanation').resizeToBestSize()
    sar, quitCheckBox = area.createSetting(st.getSetting('quit-on-launch'))
    quitCheckBox.getFromProfile(pr.getActive())

    # List of unusable profiles, due to a missing IWAD.
    unusableProfiles = []
    
    # When the page changes in the wizard, change the active profile.
    def changeActiveProfile(page):
        prof = pr.get(page.getId())
        if prof:
            pr.setActive(prof)
        else:
            pr.setActive(pr.getDefaults())
        # Update page with values from the current profile.
        page.update()
                       
    wiz.setPageReaction(changeActiveProfile)
    
    if wiz.run(langPage) == 'ok':
        events.unmute()
        
        # Show the profiles that now have an IWAD.
        for prof in profiles:
            if prof.getValue('iwad', False) != None:
                pr.show(prof.getId())
                if prof.getId() in unusableProfiles:
                    unusableProfiles.remove(prof.getId())
            else:
                pr.hide(prof.getId())
                if prof.getId() not in unusableProfiles and \
                   prof.getId() in games.getSelectedItems():
                    unusableProfiles.append(prof.getId())

        # Install the Death Kings WAD?
        if deathKingsWad:
            try:
                ident = ao.install(deathKingsWad.getText())

                # Attach the WAD as an addon.
                kingsProfile = pr.get('hexen-dk')
                kingsProfile.useAddon(ident)
            except:
                # TODO: Handle error.
                pass

        # Update custom addon paths.
        currentAddonPaths = paths.getAddonPaths()
        wasModified = False
        for path in pathList.getItems():
            if path not in currentAddonPaths:
                paths.addAddonPath(path)
                wasModified = True
        for path in currentAddonPaths:
            if path not in pathList.getItems():
                paths.removeAddonPath(path)
                wasModified = True

        if wasModified:
            # Load addons from new paths.
            ao.refresh()

        events.send(events.Notify('addon-paths-changed'))

        # The wizard will only be shown once automatically.
        pr.getDefaults().setValue(HAS_BEEN_RUN, 'yes', False)

    else:
        # Wizard was canceled.
        events.unmute()

    pr.refresh()

    # This'll destroy all the pages of the wizard as well.
    wiz.destroy()

    # Enable help panel updates again.
    #events.send(events.Command('unfreeze'))
    
    # Tell the user about unusable profiles.
    if len(unusableProfiles) > 0:
        dialog, area = sb.util.dialog.createButtonDialog(
            'wizard-unlaunchable-profiles',
            ['ok'], 'ok', resizable=False)
        # Compose a list of the unlaunchable profiles.
        profList = ''
        unusableProfiles.sort(lambda a, b: cmp(language.translate(a),
                                               language.translate(b)))
        for p in unusableProfiles:
            profList += "\n" + language.translate(p)
        msg = area.createText()
        msg.setText(language.translate('wizard-unlaunchable-profiles-listed') + "\n" + 
                    profList)
        msg.resizeToBestSize()
        dialog.run()
        elif e.isList() and e.getName() == 'addons':
            # The addons attached to the profile.
            profile.setAddons(e.getContents())

        elif e.isKey():
            # A value for a setting?
            try:
                # No notifications will be sent.
                profile.setValue(e.getName(), e.getValue(), False)
            except KeyError:
                # Setting does not exist, ignore it.
                pass

    if notify:
        # The profile has been loaded.
        events.send(events.ProfileNotify(profile))


def _getNewProfileId():
    # Choose the new identifier by comparing against the profiles
    # already loaded in memory.
    for i in range(10000):
        identifier = 'userprofile%i' % i
        if not get(identifier):
            # This is unused.
            break
    return identifier


def create(name, gameComponent):
    """Create a new profile with the specified name.  The identifier
Example #55
0
def requestPopulation():
    # Request others to create widgets in the setting tabs, if
    # necessary.
    for areaId, area in categoryTabs:
        events.send(events.PopulateNotify(areaId, area))
        area.updateLayout()
Example #56
0
 def send(self, event_name, **keys):
     result1 = send(self._getMessage(event_name), **keys)
     result2 = send('%s.%d' % (event_name, id(self)), **keys)
     return [result1, result2]
Example #57
0
    def onEnterWidget(self, event):
        """Handle the wxWidget event of entering the window."""

        if self.focusId:
            events.send(events.FocusNotify(self.focusId))
        event.Skip()
def chooseAddons(dialogId, title, actionButton):
    """Opens an addon selection dialog.

    @param title Title of the dialog.

    @param actionButton The button that will perform the affirmative
    action of the dialog.
    """
    dialog, area = sb.util.dialog.createButtonDialog(dialogId,
                                                     ['cancel', actionButton],
                                                     actionButton)

    dialog.addEndCommand('addon-dialog-add-to-custom-folders')

    # The action button is disabled until a valid selection has been
    # made.
    dialog.disableWidget(actionButton)

    area.setWeight(0)
    folderArea = area.createArea(alignment=ui.ALIGN_HORIZONTAL)
    folderArea.setExpanding(False)
    folderArea.setBorder(2, ui.BORDER_NOT_LEFT)
    folderArea.setWeight(0)
    folderArea.createText('addon-dialog-folder').resizeToBestSize()
    folderArea.setBorderDirs(ui.BORDER_ALL)
    folderArea.setWeight(1)
    pathField = folderArea.createTextField('')
    pathField.setText(os.getcwd())
    pathField.select()
    pathField.focus()
    folderArea.setWeight(0)
    folderArea.setBorderDirs(ui.BORDER_NOT_RIGHT)
    browseButton = folderArea.createButton('addon-dialog-folder-browse',
                                           style=wg.Button.STYLE_MINI)
    #folderArea.addSpacer()
    #folderArea.setBorderDirs(ui.BORDER_NOT_RIGHT)

    folderCmdArea = area.createArea(alignment=ui.ALIGN_HORIZONTAL)
    folderCmdArea.setExpanding(False)
    folderCmdArea.setBorder(6, ui.BORDER_NOT_TOP)
    folderCmdArea.setWeight(1)
    folderCmdArea.addSpacer()
    folderCmdArea.setWeight(0)

    uninstButton = folderCmdArea.createButton(
        'addon-dialog-folder-uninstalled')

    # Add to Custom Folders button.
    folderCmdArea.setBorder(6, ui.BORDER_LEFT | ui.BORDER_BOTTOM)
    addToMyButton = folderCmdArea.createButton(
        'addon-dialog-add-to-custom-folders')

    def goToUninstalled():
        pathField.setText(paths.getUserPath(paths.UNINSTALLED))
        pathField.select()
        addToMyButton.disable()

    uninstButton.addReaction(goToUninstalled)

    area.createText('addon-dialog-found')
    area.setWeight(1)
    foundList = area.createList('', style=sb.widget.list.List.STYLE_COLUMNS)
    foundList.setMinSize(500, 300)

    area.setWeight(0)
    area.createText('addon-dialog-addons-copied',
                    maxLineLength=70).resizeToBestSize()

    def selectAction():
        dialog.enableWidget(actionButton)

    foundList.addReaction(selectAction)

    for col, width in [('name', None), ('type', 180)]:
        foundList.addColumn('addon-dialog-' + col, width)

    def updateList():
        # Update the found addons list.
        foundList.clear()
        dialog.disableWidget(actionButton)
        extensions = ao.getAddonExtensions() + ['manifest']

        # This should be done in addons.py.
        fileNames = os.listdir(pathField.getText())
        for name in fileNames:
            type = ''
            for ext in extensions:
                if paths.hasExtension(ext, name):
                    type = ext
                    break

            if not type:
                # Unknown files are skipped.
                continue

            # Manifests don't appear in the list if the corresponding
            # addon is in the same directory.
            if paths.hasExtension('manifest', name):
                foundSame = False

                # Identifier of the addon the manifest belongs to.
                manifestId = paths.getBase(name)

                # See if the addon is in the list.
                for other in fileNames:
                    if other == name:
                        continue
                    if manifestId == ao.formIdentifier(other)[0]:
                        foundSame = True
                        break
                if foundSame:
                    # Don't add it.
                    continue

            foundList.addItemWithColumns(
                name, name, language.translate('addon-dialog-type-' + type))

    # Update reactions.
    def pathChanged():
        if os.path.exists(pathField.getText()):
            updateList()
            if pathField.getText() != paths.getUserPath(paths.UNINSTALLED):
                addToMyButton.enable()
        else:
            addToMyButton.disable()

    def browseAction():
        # Show a directory browser.
        selection = sb.util.dialog.chooseFolder('addon-dialog-browse-prompt',
                                                pathField.getText())
        if len(selection):
            pathField.setText(selection)
            pathField.select()

    # The initial contents of the list.
    updateList()

    pathField.addReaction(pathChanged)
    browseButton.addReaction(browseAction)

    dialog.addEndCommand(actionButton)
    result = dialog.run()
    if result == actionButton:
        addonFiles = map(lambda name: os.path.join(pathField.getText(), name),
                         foundList.getSelectedItems())

        # Include any associated manifests.
        for name in addonFiles:
            manifest = ao.formIdentifier(name)[0] + '.manifest'
            manifestFile = os.path.join(pathField.getText(), manifest)
            if manifest not in addonFiles and os.path.exists(manifestFile):
                addonFiles.append(manifestFile)
                #print 'including ' + manifestFile + ' due to ' + name

        return addonFiles

    elif result == 'addon-dialog-add-to-custom-folders':
        paths.addAddonPath(pathField.getText())
        events.send(events.Notify('addon-paths-changed'))
        ao.refresh()
        return []

    # The dialog was canceled.
    return []