def show(): """Show all the issues in a dialog. The list of issues will be automatically cleared. If there are no issues to report, nothing is done.""" global allIssues if len(allIssues) == 0: # Nothing to report. return import sb.util.dialog dialog, area = sb.util.dialog.createButtonDialog( 'issue-dialog', ['ok'], 'ok') message = area.createFormattedText() message.setMinSize(500, 300) msg = '' bgColor = ['#90E090', '#FFFF80', '#E05050'] fgColor = ['black', 'black', 'white'] severeName = ['Note', 'Warning', 'Error'] isFirst = True # Compose a HTML formatted version of each issue. for severe in [HIGH, MEDIUM, LOW]: # Show the important issues first. for issue in allIssues: if issue[0] != severe: continue if not isFirst: msg += '<hr>' isFirst = False msg += '<table width="100%" border=0 cellspacing=3 cellpadding=4>' msg += '<tr><td bgcolor="%s" width="20%%" align=center>' % \ bgColor[issue[0]] msg += '<font color="%s"><b>' % fgColor[issue[0]] + \ severeName[issue[0]] + '</b></font>' msg += '<td width="80%"><h3>' + language.expand( language.translate(issue[1]), *issue[2]) msg += '</h3>' + language.expand( language.translate(issue[1] + '-text'), *issue[2]) msg += '</table>' message.setText(msg) dialog.run() # Only show each issue once. allIssues = []
def show(): """Show all the issues in a dialog. The list of issues will be automatically cleared. If there are no issues to report, nothing is done.""" global allIssues if len(allIssues) == 0: # Nothing to report. return import sb.util.dialog dialog, area = sb.util.dialog.createButtonDialog('issue-dialog', ['ok'], 'ok') message = area.createFormattedText() message.setMinSize(500, 300) msg = '' bgColor = ['#90E090', '#FFFF80', '#E05050'] fgColor = ['black', 'black', 'white'] severeName = ['Note', 'Warning', 'Error'] isFirst = True # Compose a HTML formatted version of each issue. for severe in [HIGH, MEDIUM, LOW]: # Show the important issues first. for issue in allIssues: if issue[0] != severe: continue if not isFirst: msg += '<hr>' isFirst = False msg += '<table width="100%" border=0 cellspacing=3 cellpadding=4>' msg += '<tr><td bgcolor="%s" width="20%%" align=center>' % \ bgColor[issue[0]] msg += '<font color="%s"><b>' % fgColor[issue[0]] + \ severeName[issue[0]] + '</b></font>' msg += '<td width="80%"><h3>' + language.expand( language.translate(issue[1]), *issue[2]) msg += '</h3>' + language.expand( language.translate(issue[1] + '-text'), *issue[2]) msg += '</table>' message.setText(msg) dialog.run() # Only show each issue once. allIssues = []
def createConflictButtons(self, addonName): self.area.setWeight(0) self.choices = [] self.choices.append( resolving.area.createRadioButton('', True, True)) self.choices.append( resolving.area.createRadioButton('', False)) self.choices[0].setText(language.expand( language.translate('conflict-choice1'), addonName)) self.choices[1].setText(language.expand( language.translate('conflict-choice2'), addonName))
def getShortContentAnalysis(self): """Forms a short single line of text that describes the contents of the WAD.""" # The directory must already be read by this time. analysis = [] mapCount = 0 hasCustomTextures = False for lump in self.lumps: # Count the number of maps. if len(lump) == 4 and lump[0] == 'E' and lump[2] == 'M' and \ lump[1] in string.digits and lump[3] in string.digits: mapCount += 1 elif len(lump) == 5 and lump[:3] == 'MAP' and \ lump[3] in string.digits and lump[4] in string.digits: mapCount += 1 # Any custom textures? elif lump == 'PNAMES' or lump == 'TEXTURE1' or lump == 'TEXTURE2': hasCustomTextures = True if mapCount > 0: analysis.append( language.expand( language.translate('wad-analysis-maps'), str(mapCount)) ) if hasCustomTextures: analysis.append(language.translate('wad-analysis-custom-textures')) return string.join(analysis, ', ').capitalize()
def getShortContentAnalysis(self): """Forms a short single line of text that describes the contents of the WAD.""" # The directory must already be read by this time. analysis = [] mapCount = 0 hasCustomTextures = False for lump in self.lumps: # Count the number of maps. if len(lump) == 4 and lump[0] == 'E' and lump[2] == 'M' and \ lump[1] in string.digits and lump[3] in string.digits: mapCount += 1 elif len(lump) == 5 and lump[:3] == 'MAP' and \ lump[3] in string.digits and lump[4] in string.digits: mapCount += 1 # Any custom textures? elif lump == 'PNAMES' or lump == 'TEXTURE1' or lump == 'TEXTURE2': hasCustomTextures = True if mapCount > 0: analysis.append( language.expand(language.translate('wad-analysis-maps'), str(mapCount))) if hasCustomTextures: analysis.append(language.translate('wad-analysis-custom-textures')) return string.join(analysis, ', ').capitalize()
def showSettingInfo(setting): """Display information about the focused setting in the help panel. @param setting A settings.Setting object. """ # Values will be taken from the active profile. prof = pr.getActive() # The identifier of the setting. ident = setting.getId() msg = '<html>' # The name of the setting. msg += '<b><font size="+1">' + language.translate(ident) + \ '</font></b>' # The command line option. msg += '<br><table bgcolor="' + bgColor + '" width="100%"><tr><td>' + \ '<font size="-1"><tt>' + \ setting.getCommandLine(prof) + '</tt></font></table><p>' fromDefaults = False if prof.getValue(ident, False) == None: fromDefaults = True # The value comes from the default profile. msg += language.expand(language.translate('help-value-from-defaults'), pr.getDefaults().getName()) + '<p>' def valueToText(v): if language.isDefined(v): return language.translate(v) else: return v msg += tableBegin # The current value of the setting. value = prof.getValue(ident) if value: #msg += '<b>%s:</b><br>' % language.translate('help-value-current') #msg += valueToText(value.getValue()) #msg += '<p>' msg += tableRow + \ entryHeader(language.translate('help-value-current')) + \ entryContent(valueToText(value.getValue())) # Min and max for the range and slider settings. if setting.getType() == 'slider' or setting.getType() == 'range': #msg += '<b>' + language.translate('help-value-min') + ':</b><br>' + \ # str(setting.getMinimum()) #msg += '<p><b>' + language.translate('help-value-max') + \ # ':</b><br>' + str(setting.getMaximum()) #msg += '<p>' msg += tableRow + entryHeader(language.translate('help-value-min')) + \ entryContent(str(setting.getMinimum())) + \ tableRow + entryHeader(language.translate('help-value-max')) + \ entryContent(str(setting.getMaximum())) # The default. if prof.getValue(ident, False) != None and prof is pr.getDefaults(): if setting.getDefault() != None: #msg += '<b>%s:</b><br>' % language.translate('help-value-default') #msg += valueToText(str(setting.getDefault())) #msg += '<p>' msg += tableRow + \ entryHeader(language.translate('help-value-default')) + \ entryContent(valueToText(str(setting.getDefault()))) elif not fromDefaults and prof is not pr.getDefaults(): defValue = pr.getDefaults().getValue(ident) if defValue: #msg += '<b>%s:</b><br>' % language.translate('help-value-default') #msg += valueToText(defValue.getValue()) #msg += '<p>' msg += tableRow + \ entryHeader(language.translate('help-value-default')) + \ entryContent(valueToText(defValue.getValue())) msg += tableEnd # The help text of this setting. helpId = ident + '-help' if language.isDefined(helpId): msg += language.translate(helpId) msg += '</html>' # Display the setting information in the help panel. helpText.setText(msg) showLogo(False) # The info will be automatically updated in case it changes while # displayed. global currentSetting currentSetting = setting
def showAddonInfo(addon): """Display a summary of an addon in the help panel. @param addon An addons.Addon object. """ global currentAddon, currentSetting # No longer showing a setting. currentSetting = None # The current addon that is displayed in the help. currentAddon = addon oneLiners = (detailedAddonMode == False) ident = addon.getId() # Begin the page with a table that contains the basic info. msg = '<html>' def optLink(id, isLink): if isLink: return '<a href="%s">%s</a>' % (id, language.translate(id)) else: return language.translate(id) # The detail selection links. msg += '<center><font size="-1">' msg += optLink('help-addon-mode-brief', detailedAddonMode) + ' | ' msg += optLink('help-addon-mode-detailed', not detailedAddonMode) msg += '</font></center><br>' # Summary table. msg += tableBegin msg += '<tr><td colspan="2"><b><font size="+1">' + \ language.translate(ident) + \ '</font></b>' def makeField(msg, fieldId, oneLiner=True): title = language.translate('help-addon-' + fieldId) contentId = ident + '-' + fieldId text = '' if language.isDefined(contentId): # This information has been defined. text = language.translate(contentId) elif detailedAddonMode: # Force all fields to show. text = '-' if text: if oneLiner: msg += tableRow + entryHeader(title) + entryContent(text) else: msg += tableRow + entryHeader(title, 2) + \ tableRow + entryContent(text, 2) return msg msg = makeField(msg, 'version') if detailedAddonMode: # Get the last modification time from the addon. modTime = time.localtime(addon.getLastModified()) msg += tableRow + entryHeader(language.translate('help-addon-date')) \ + entryContent(time.strftime("%d %b %Y", modTime)) msg = makeField(msg, 'summary', oneLiners) if detailedAddonMode: msg = makeField(msg, 'contact', oneLiners) msg = makeField(msg, 'author', oneLiners) msg = makeField(msg, 'copyright', oneLiners) msg = makeField(msg, 'license', oneLiners) # Dependencies. deps = [] exCats = addon.getExcludedCategories() if len(exCats): deps.append((language.translate('help-addon-excluded-categories'), map(lambda c: language.translate(c.getLongId()), exCats))) for type, label in [(sb.addon.EXCLUDES, 'help-addon-excludes'), (sb.addon.REQUIRES, 'help-addon-requires'), (sb.addon.PROVIDES, 'help-addon-provides'), (sb.addon.OFFERS, 'help-addon-offers')]: # Make a copy of the list so we can modify it. keywords = [kw for kw in addon.getKeywords(type)] # In the Brief mode, hide the identifier of the addon in the # Provides field. if not detailedAddonMode and type == sb.addon.PROVIDES: keywords.remove(addon.getId()) if len(keywords) > 0: # Include this in the info. def xlate(key): if ao.exists(key): return '<a href="%s">%s</a>' % \ (key, language.translate(key)) else: return key deps.append((language.translate(label), map(xlate, keywords))) if len(deps): # Print a dependencies table. msg += tableRow + entryHeader( language.translate('help-addon-dependencies'), 2) content = "" for dep in deps: if dep is not deps[0]: content += '<br>' content += "<b>" + dep[0] + ":</b><ul><li>" content += string.join(dep[1], '<li>') content += '</ul>' msg += tableRow + entryContent(content, 2) msg += tableEnd # Inside a box? if addon.getBox(): box = addon.getBox() msg += language.expand(language.translate('help-addon-part-of-box'), box.getId(), language.translate( box.getId())) + '<p>' # The overview. if language.isDefined(ident + '-readme'): msg += language.translate(ident + '-readme') msg += '</html>' helpText.setText(msg) showLogo(False)
def createResolver(problem, addons): """Create the necessary widgets in the area to resolve the problem. @param area An ui.Area object. Will be cleared. @param problem The problem description as returned by addons.findConflicts. @param addons Set of Addon objects. This should be modified according to the user's selections. """ global resolving # Set the general parameters of the resolver. resolving.problem = problem resolving.addons = addons resolving.area.clear() resolving.area.setWeight(2) message = resolving.area.createFormattedText() message.setMinSize(250, 250) resolving.area.setWeight(1) # Enter this problem into the log. log(problem) # The name of the problem. problemName = problem[0] if problemName == 'exclusion-by-category': # The list of excluded addons. names = map(lambda a: language.translate(a.getId()), problem[2]) names.sort() msg = "<ul><li>" + string.join(names, '<li>') + "</ul>" message.setText(language.expand( language.translate('category-conflict-message'), language.translate(problem[1].getId()), msg)) # Create the radio buttons. resolving.createConflictButtons(language.translate(problem[1].getId())) elif problemName == 'exclusion-by-keyword': msg = '<ul>' for addon, key in problem[2]: msg += '<li>' if addon.getId() != key: msg += key + " in " msg += language.translate(addon.getId()) msg += '</ul>' message.setText(language.expand( language.translate('keyword-conflict-message'), language.translate(problem[1].getId()), msg)) # Create the radio buttons. resolving.createConflictButtons(language.translate(problem[1].getId())) elif problemName == 'exclusion-by-value': # The list of excluded values. names = [] for v in problem[2]: if language.isDefined(v): names.append(language.translate(v)) else: names.append(v) msg = "<ul><li>" + string.join(names, '<li>') + "</ul>" message.setText(language.expand( language.translate('value-conflict-message'), language.translate(problem[1].getId()), msg)) elif problemName == 'provide-conflict': # Collect the conflicting addons into a list. resolving.conflicted = [] keys = [] for a, b, key in problem[1]: if a not in resolving.conflicted: resolving.conflicted.append(a) if b not in resolving.conflicted: resolving.conflicted.append(b) if key not in keys: keys.append(key) #ao.sortIdentifiersByName(conflicting) message.setText(language.expand( language.translate('provide-conflict-message'), "<ul><li>" + string.join(keys, '<li>') + "</ul>")) resolving.list = resolving.area.createList('') for a in resolving.conflicted: resolving.list.addItem(a.getId()) elif problemName == 'missing-requirements': resolving.conflicted = problem[1] res = "<p><ul>" res += "<li>" + string.join(problem[2], '<li>') + "</ul>" msg = language.expand( language.translate('missing-requirements-message'), language.translate(problem[1].getId())) message.setText(msg + res) resolving.list = None resolving.area.updateLayout()
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]))
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
def refreshList(): """Refreshes the list of addons.""" addonList.freeze() # Try to keep the old selection, if there is one. oldSelections = addonList.getSelectedItems() addonList.clear() # Filtering parameters. profile = pr.getActive() isDefaults = profile is pr.getDefaults() if tree.getSelectedItem(): filterCategory = ao.getCategory(tree.getSelectedItem()) else: filterCategory = None # Which addons are currently attached? defaultAddons = pr.getDefaults().getAddons() if not isDefaults: profileAddons = pr.getActive().getAddons() else: profileAddons = None # Categories that will be in bold font in category-tree. boldCategories = [] # Determine filtering options. mode = listFilter.getSelectedItem() onlyCompatible = False onlyPWAD = False alsoBoxes = False if 'compatible' in mode: onlyCompatible = True if 'pwad' in mode: onlyPWAD = True if 'with-boxes' in mode: alsoBoxes = True for addon in ao.getAddons(): # Does this addon pass the filter? if not isDefaults and onlyCompatible: if not addon.isCompatibleWith(pr.getActive()): # Cannot be listed. continue if onlyPWAD and (addon.getType() != 'addon-type-wad' or not addon.isPWAD()): continue # Has a category been selected? if filterCategory and not filterCategory.isAncestorOf( addon.getCategory()): # Not in the category. continue # Addons in boxes are not listed unless the correct category is selected. if not alsoBoxes and addon.getBox(): # Addons in boxes are only visible if the selected category is a box category. boxCateg = addon.getBox().getContentCategoryLongId() if not filterCategory: continue if filterCategory.getLongId().find(boxCateg) != 0: # Not the right category. continue # Passed the filter! id = addon.getId() versionStr = '' icon = determineIcon(addon, profile, defaultAddons, profileAddons) if language.isDefined(id + '-version'): versionStr = language.translate(id + '-version') name = language.translate(id) if addon.getBox() and alsoBoxes: name += ' ' + language.translate('addon-list-in-box') addonList.addItemWithColumns(id, icon, name, versionStr) # Reselect old items. oldSelections.reverse() for sel in oldSelections: addonList.selectItem(sel) addonList.ensureVisible(sel) sortList() updateButtons() addonList.unfreeze() # Update the counter text. countText.setText( language.expand(language.translate('addon-counter'), str(len(addonList.getItems())), str(ao.getAddonCount()))) # Update boldings in category-tree. # --TODO!-- global mustRefreshList mustRefreshList = False
def showSettingInfo(setting): """Display information about the focused setting in the help panel. @param setting A settings.Setting object. """ # Values will be taken from the active profile. prof = pr.getActive() # The identifier of the setting. ident = setting.getId() msg = '<html>' # The name of the setting. msg += '<b><font size="+1">' + language.translate(ident) + \ '</font></b>' # The command line option. msg += '<br><table bgcolor="' + bgColor + '" width="100%"><tr><td>' + \ '<font size="-1"><tt>' + \ setting.getCommandLine(prof) + '</tt></font></table><p>' fromDefaults = False if prof.getValue(ident, False) == None: fromDefaults = True # The value comes from the default profile. msg += language.expand( language.translate('help-value-from-defaults'), pr.getDefaults().getName()) + '<p>' def valueToText(v): if language.isDefined(v): return language.translate(v) else: return v msg += tableBegin # The current value of the setting. value = prof.getValue(ident) if value: #msg += '<b>%s:</b><br>' % language.translate('help-value-current') #msg += valueToText(value.getValue()) #msg += '<p>' msg += tableRow + \ entryHeader(language.translate('help-value-current')) + \ entryContent(valueToText(value.getValue())) # Min and max for the range and slider settings. if setting.getType() == 'slider' or setting.getType() == 'range': #msg += '<b>' + language.translate('help-value-min') + ':</b><br>' + \ # str(setting.getMinimum()) #msg += '<p><b>' + language.translate('help-value-max') + \ # ':</b><br>' + str(setting.getMaximum()) #msg += '<p>' msg += tableRow + entryHeader(language.translate('help-value-min')) + \ entryContent(str(setting.getMinimum())) + \ tableRow + entryHeader(language.translate('help-value-max')) + \ entryContent(str(setting.getMaximum())) # The default. if prof.getValue(ident, False) != None and prof is pr.getDefaults(): if setting.getDefault() != None: #msg += '<b>%s:</b><br>' % language.translate('help-value-default') #msg += valueToText(str(setting.getDefault())) #msg += '<p>' msg += tableRow + \ entryHeader(language.translate('help-value-default')) + \ entryContent(valueToText(str(setting.getDefault()))) elif not fromDefaults and prof is not pr.getDefaults(): defValue = pr.getDefaults().getValue(ident) if defValue: #msg += '<b>%s:</b><br>' % language.translate('help-value-default') #msg += valueToText(defValue.getValue()) #msg += '<p>' msg += tableRow + \ entryHeader(language.translate('help-value-default')) + \ entryContent(valueToText(defValue.getValue())) msg += tableEnd # The help text of this setting. helpId = ident + '-help' if language.isDefined(helpId): msg += language.translate(helpId) msg += '</html>' # Display the setting information in the help panel. helpText.setText(msg) showLogo(False) # The info will be automatically updated in case it changes while # displayed. global currentSetting currentSetting = setting
def showAddonInfo(addon): """Display a summary of an addon in the help panel. @param addon An addons.Addon object. """ global currentAddon, currentSetting # No longer showing a setting. currentSetting = None # The current addon that is displayed in the help. currentAddon = addon oneLiners = (detailedAddonMode == False) ident = addon.getId() # Begin the page with a table that contains the basic info. msg = '<html>' def optLink(id, isLink): if isLink: return '<a href="%s">%s</a>' % (id, language.translate(id)) else: return language.translate(id) # The detail selection links. msg += '<center><font size="-1">' msg += optLink('help-addon-mode-brief', detailedAddonMode) + ' | ' msg += optLink('help-addon-mode-detailed', not detailedAddonMode) msg += '</font></center><br>' # Summary table. msg += tableBegin msg += '<tr><td colspan="2"><b><font size="+1">' + \ language.translate(ident) + \ '</font></b>' def makeField(msg, fieldId, oneLiner=True): title = language.translate('help-addon-' + fieldId) contentId = ident + '-' + fieldId text = '' if language.isDefined(contentId): # This information has been defined. text = language.translate(contentId) elif detailedAddonMode: # Force all fields to show. text = '-' if text: if oneLiner: msg += tableRow + entryHeader(title) + entryContent(text) else: msg += tableRow + entryHeader(title, 2) + \ tableRow + entryContent(text, 2) return msg msg = makeField(msg, 'version') if detailedAddonMode: # Get the last modification time from the addon. modTime = time.localtime(addon.getLastModified()) msg += tableRow + entryHeader(language.translate('help-addon-date')) \ + entryContent(time.strftime("%d %b %Y", modTime)) msg = makeField(msg, 'summary', oneLiners) if detailedAddonMode: msg = makeField(msg, 'contact', oneLiners) msg = makeField(msg, 'author', oneLiners) msg = makeField(msg, 'copyright', oneLiners) msg = makeField(msg, 'license', oneLiners) # Dependencies. deps = [] exCats = addon.getExcludedCategories() if len(exCats): deps.append((language.translate('help-addon-excluded-categories'), map(lambda c: language.translate(c.getLongId()), exCats))) for type, label in [(sb.addon.EXCLUDES, 'help-addon-excludes'), (sb.addon.REQUIRES, 'help-addon-requires'), (sb.addon.PROVIDES, 'help-addon-provides'), (sb.addon.OFFERS, 'help-addon-offers')]: # Make a copy of the list so we can modify it. keywords = [kw for kw in addon.getKeywords(type)] # In the Brief mode, hide the identifier of the addon in the # Provides field. if not detailedAddonMode and type == sb.addon.PROVIDES: keywords.remove(addon.getId()) if len(keywords) > 0: # Include this in the info. def xlate(key): if ao.exists(key): return '<a href="%s">%s</a>' % \ (key, language.translate(key)) else: return key deps.append((language.translate(label), map(xlate, keywords))) if len(deps): # Print a dependencies table. msg += tableRow + entryHeader( language.translate('help-addon-dependencies'), 2) content = "" for dep in deps: if dep is not deps[0]: content += '<br>' content += "<b>" + dep[0] + ":</b><ul><li>" content += string.join(dep[1], '<li>') content += '</ul>' msg += tableRow + entryContent(content, 2) msg += tableEnd # Inside a box? if addon.getBox(): box = addon.getBox() msg += language.expand( language.translate('help-addon-part-of-box'), box.getId(), language.translate(box.getId())) + '<p>' # The overview. if language.isDefined(ident + '-readme'): msg += language.translate(ident + '-readme') msg += '</html>' helpText.setText(msg) showLogo(False)
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]))
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
def refreshList(): """Refreshes the list of addons.""" addonList.freeze() # Try to keep the old selection, if there is one. oldSelections = addonList.getSelectedItems() addonList.clear() # Filtering parameters. profile = pr.getActive() isDefaults = profile is pr.getDefaults() if tree.getSelectedItem(): filterCategory = ao.getCategory(tree.getSelectedItem()) else: filterCategory = None # Which addons are currently attached? defaultAddons = pr.getDefaults().getAddons() if not isDefaults: profileAddons = pr.getActive().getAddons() else: profileAddons = None # Categories that will be in bold font in category-tree. boldCategories = [] # Determine filtering options. mode = listFilter.getSelectedItem() onlyCompatible = False onlyPWAD = False alsoBoxes = False if 'compatible' in mode: onlyCompatible = True if 'pwad' in mode: onlyPWAD = True if 'with-boxes' in mode: alsoBoxes = True for addon in ao.getAddons(): # Does this addon pass the filter? if not isDefaults and onlyCompatible: if not addon.isCompatibleWith(pr.getActive()): # Cannot be listed. continue if onlyPWAD and (addon.getType() != 'addon-type-wad' or not addon.isPWAD()): continue # Has a category been selected? if filterCategory and not filterCategory.isAncestorOf(addon.getCategory()): # Not in the category. continue # Addons in boxes are not listed unless the correct category is selected. if not alsoBoxes and addon.getBox(): # Addons in boxes are only visible if the selected category is a box category. boxCateg = addon.getBox().getContentCategoryLongId() if not filterCategory: continue if filterCategory.getLongId().find(boxCateg) != 0: # Not the right category. continue # Passed the filter! id = addon.getId() versionStr = '' icon = determineIcon(addon, profile, defaultAddons, profileAddons) if language.isDefined(id + '-version'): versionStr = language.translate(id + '-version') name = language.translate(id) if addon.getBox() and alsoBoxes: name += ' ' + language.translate('addon-list-in-box') addonList.addItemWithColumns(id, icon, name, versionStr) # Reselect old items. oldSelections.reverse() for sel in oldSelections: addonList.selectItem(sel) addonList.ensureVisible(sel) sortList() updateButtons() addonList.unfreeze() # Update the counter text. countText.setText(language.expand(language.translate('addon-counter'), str(len(addonList.getItems())), str(ao.getAddonCount()))) # Update boldings in category-tree. # --TODO!-- global mustRefreshList mustRefreshList = False