예제 #1
0
파일: algwin.py 프로젝트: korala1968/tago
class SetDialog(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self,parent)
        winsettings('setdialog', self)
        vbox = QVBoxLayout()
        self._previndex = 0
        self.setscombo = QComboBox()
        setlabel = QLabel('&Sets')
        setlabel.setBuddy(self.setscombo)
        vbox.addWidget(setlabel)

        comboadd = QToolButton()
        comboadd.setIcon(QIcon(':/filenew.png'))
        comboadd.setToolTip('Add set')
        self.connect(comboadd, SIGNAL('clicked()'), self.addSet)

        hbox = QHBoxLayout()
        hbox.addWidget(self.setscombo)
        hbox.addWidget(comboadd)

        vbox.addLayout(hbox)

        conditions = QLabel('&Conditions')
        vbox.addWidget(conditions)

        self.listbox = ListBox()
        conditions.setBuddy(self.listbox)
        listbuttons = ListButtons()

        listhbox = QHBoxLayout()
        listhbox.addWidget(self.listbox)
        listhbox.addLayout(listbuttons)
        vbox.addLayout(listhbox)

        label = QLabel('Retrieve values via: ')
        self.maintag = QComboBox()
        self.maintag.addItems(['artist', 'title', 'genre', 'album', 'year'])
        maintaghbox = QHBoxLayout()
        maintaghbox.addWidget(label)
        maintaghbox.addWidget(self.maintag)
        maintaghbox.addStretch()
        vbox.addLayout(maintaghbox)

        dispformat = QLabel('Display Format')
        vbox.addWidget(dispformat)
        self.texts = [QLineEdit(), QLineEdit()]
        t = ['Original', 'Duplicates']
        for i, text in enumerate(self.texts):
            label = QLabel(t[i])
            label.setBuddy(text)
            dispbox = QHBoxLayout()
            dispbox.addWidget(label)
            dispbox.addWidget(text)
            vbox.addLayout(dispbox)

        okcancel = OKCancel()
        vbox.addLayout(okcancel)
        self.connect(okcancel, SIGNAL('ok'), self.okClicked)
        self.connect(okcancel, SIGNAL('cancel'), self.cancelClicked)
        self.setLayout(vbox)

        self.fill(loadsets())
        listbuttons.connectToWidget(self)

    def addSet(self):
        def gettext():
            (text, ok) = QInputDialog.getText (self, 'puddletag', 'Enter a name'
                                'for the set', QLineEdit.Normal)
            if ok:
                if self.setscombo.findText(text) > -1:
                    QMessageBox.information (self, 'puddletag', 'The name entered already exists.')
                    return gettext()
                return text
        text = gettext()
        if text:
            self.setscombo.addItem(text)
            self._sets.append([unicode(text), ['', ''], []])
            self.setscombo.setCurrentIndex(self.setscombo.count() - 1)

    def fill(self, sets):
        if not sets:
            return
        self._sets = sets
        self.setscombo.clear()
        self.setscombo.addItems([z[0] for z in sets])
        self.currentSet = sets[0]
        self.setscombo.setCurrentIndex(0)
        self.connect(self.setscombo, SIGNAL('currentIndexChanged (int)'),
                        self.changeSet)

    def _setCurrentSet(self, s):
        [text.setText(disp) for text, disp in zip(self.texts, s[1])]
        self.listbox.clear()
        [self.listbox.addItem(alg.pprint()) for alg in s[2]]
        index = self.maintag.findText(s[3])
        if index > -1:
            self.maintag.setCurrentIndex(index)
        else:
            self.maintag.addItem(s[3])
            self.maintag.setCurrentIndex(self.maintag.count() - 1)

    def _getCurrentSet(self):
        return self._sets[self.setscombo.currentIndex()]

    currentSet = property(_getCurrentSet, _setCurrentSet)

    def changeSet(self, index):
        i = self._previndex
        prevset = {'setname': self._sets[i][0],
                   'disp': [unicode(text.text()) for text in self.texts],
                   'algs': self._sets[i][2],
                   'maintag': unicode(self.maintag.currentText())}
        self._sets[i][1] = prevset['disp']
        self._sets[i][2] = prevset['algs']
        self._sets[i][3] = prevset['maintag']
        saveset(**prevset)
        self.currentSet = self._sets[index]
        self._previndex = index

    def add(self):
        win = AlgWin(self)
        win.setModal(True)
        self.connect(win, SIGNAL('okClicked'), self.addBuddy)
        win.show()

    def addBuddy(self, alg):
        self.listbox.addItem(alg.pprint())
        self.currentSet[2].append(alg)

    def edit(self):
        win = AlgWin(self, self.currentSet[2][self.listbox.currentRow()])
        win.setModal(True)
        self.connect(win, SIGNAL('okClicked'), self.editBuddy)
        win.show()

    def editBuddy(self, alg):
        self.listbox.item(self.listbox.currentRow()).setText(alg.pprint())
        self._sets[self._previndex][2][self.listbox.currentRow()] = alg

    def moveUp(self):
        self.listbox.moveUp(self.currentSet[2])

    def moveDown(self):
        self.listbox.moveDown(self.currentSet[2])

    def remove(self):
        del(self.currentSet[2][self.listbox.currentRow()])
        self.listbox.takeItem(self.listbox.currentRow())

    def okClicked(self):
        i = self.setscombo.currentIndex()
        prevset = {'setname': self._sets[i][0],
                   'disp': [unicode(text.text()) for text in self.texts],
                   'algs': self._sets[i][2],
                   'maintag': unicode(self.maintag.currentText())}
        saveset(**prevset)
        self.close()
        self.emit(SIGNAL('setAvailable'), *self.currentSet)

    def cancelClicked(self):
        self.close()
예제 #2
0
파일: dialogs.py 프로젝트: korala1968/tago
class MassTagEdit(QDialog):
    def __init__(self, tag_sources, profiles=None, parent = None):
        super(MassTagEdit, self).__init__(parent)

        self.setWindowTitle(translate('Profile Config',
            'Configure Mass Tagging Profiles'))
        winsettings('masstag_edit', self)

        self.listbox = ListBox()
        self.tag_sources = tag_sources

        okcancel = OKCancel()
        okcancel.ok.setDefault(True)

        self.buttonlist = ListButtons()

        connect = lambda control, signal, slot: self.connect(
            control, SIGNAL(signal), slot)

        connect(okcancel, "ok" , self.okClicked)
        connect(okcancel, "cancel",self.close)
        connect(self.buttonlist, "add", self.addClicked)
        connect(self.buttonlist, "edit", self.editClicked)
        connect(self.buttonlist, "moveup", self.moveUp)
        connect(self.buttonlist, "movedown", self.moveDown)
        connect(self.buttonlist, "remove", self.remove)
        connect(self.buttonlist, "duplicate", self.dupClicked)
        connect(self.listbox, "itemDoubleClicked (QListWidgetItem *)",
            self.editClicked)
        connect(self.listbox, "currentRowChanged(int)", self.enableListButtons)

        self.enableListButtons(self.listbox.currentRow())

        layout = QVBoxLayout()
        self.setLayout(layout)

        layout.addWidget(QLabel(translate('Profile Config',
            'Masstagging Profiles')))

        list_layout = QHBoxLayout()
        list_layout.addWidget(self.listbox, 1)
        list_layout.addLayout(self.buttonlist)

        layout.addLayout(list_layout)
        layout.addLayout(okcancel)
        if profiles is not None:
            self.setProfiles(profiles)

    def addClicked(self):
        win = MTProfileEdit(self.tag_sources, parent=self)
        win.setModal(True)
        self.connect(win, SIGNAL('profileChanged'), self.addProfile)
        win.show()

    def addProfile(self, profile):
        row = self.listbox.count()
        self.listbox.addItem(profile.name)
        self._profiles.append(profile)

    def dupClicked(self):
        row = self.listbox.currentRow()
        if row == -1:
            return
        win = MTProfileEdit(self.tag_sources, deepcopy(self._profiles[row]), self)
        win.setModal(True)
        self.connect(win, SIGNAL('profileChanged'), self.addProfile)
        win.show()

    def editClicked(self, item=None):
        if item:
            row = self.listbox.row(item)
        else:
            row = self.listbox.currentRow()

        if row == -1:
            return
        win = MTProfileEdit(self.tag_sources, self._profiles[row], self)
        win.setModal(True)
        self.connect(win, SIGNAL('profileChanged'),
            partial(self.replaceProfile, row))
        win.show()

    def enableListButtons(self, val):
        if val == -1:
            [button.setEnabled(False) for button in self.buttonlist.widgets[1:]]
        else:
            [button.setEnabled(True) for button in self.buttonlist.widgets[1:]]

    def loadProfiles(self, dirpath=PROFILEDIR):
        profiles = load_all_mtps(dirpath, self.tag_sources)
        self.setProfiles(filter(None, profiles))

    def moveDown(self):
        self.listbox.moveDown(self._profiles)

    def moveUp(self):
        self.listbox.moveUp(self._profiles)

    def okClicked(self):
        self.emit(SIGNAL('profilesChanged'), self._profiles)
        self.saveProfiles(PROFILEDIR, self._profiles)
        self.close()

    def remove(self):
        row = self.listbox.currentRow()
        if row == -1:
            return
        del(self._profiles[row])
        self.listbox.takeItem(row)

    def replaceProfile(self, row, profile):
        self._profiles[row] = profile
        self.listbox.item(row).setText(profile.name)

    def saveProfiles(self, dirpath, profiles):
        filenames = {}
        order = []
        for profile in profiles:
            filename = profile.name + u'.mtp'
            i = 0
            while filename in filenames:
                filename = u'%s_%d%s' % (profile.name, i, u'.mtp')
                i += 1
            filenames[filename] = profile
            order.append(profile.name)
        files = glob.glob(os.path.join(dirpath, '*.mtp'))
        for f in files:
            if f not in filenames:
                try:
                    os.remove(f)
                except EnvironmentError:
                    pass
        for filename, profile in filenames.items():
            save_mtp(profile, os.path.join(dirpath, filename))
        f = open(os.path.join(dirpath, 'order'), 'w')
        f.write(u'\n'.join(order))
        f.close()

    def setProfiles(self, profiles):
        self._profiles = profiles
        for profile in self._profiles:
            self.listbox.addItem(profile.name)
예제 #3
0
class SettingsWin(QFrame):
    def __init__(self, parent = None, cenwid = None, status=None):
        QFrame.__init__(self, parent)
        self.title = translate('Settings', "Patterns")
        connect = lambda c, signal, s: self.connect(c, SIGNAL(signal), s)
        self.setFrameStyle(QFrame.Box)
        self.listbox = ListBox()
        self.listbox.setSelectionMode(self.listbox.ExtendedSelection)
        buttons = ListButtons()

        self.listbox.addItems(status['patterns'])
        hbox = QHBoxLayout()
        hbox.addWidget(self.listbox)
        self.setLayout(hbox)

        vbox = QVBoxLayout()
        sortlistbox = QPushButton(translate("Pattern Settings", '&Sort'))
        self._sortOrder = Qt.AscendingOrder
        connect(sortlistbox, 'clicked()', self._sortListBox)
        vbox.addWidget(sortlistbox)
        vbox.addLayout(buttons)
        vbox.addStretch()

        hbox.addLayout(vbox)

        connect(buttons, "add", self.addPattern)
        connect(buttons, "edit", self.editItem)
        buttons.duplicate.setVisible(False)
        self.listbox.connectToListButtons(buttons)
        self.listbox.editButton = buttons.edit
        connect(self.listbox, 'itemDoubleClicked(QListWidgetItem *)',
                    self._doubleClicked)

    def _sortListBox(self):
        if self._sortOrder == Qt.AscendingOrder:
            self.listbox.sortItems(Qt.DescendingOrder)
            self._sortOrder = Qt.DescendingOrder
        else:
            self.listbox.sortItems(Qt.AscendingOrder)
            self._sortOrder = Qt.AscendingOrder

    def saveSettings(self):
        patterns = [unicode(self.listbox.item(row).text()) for row in xrange(self.listbox.count())]
        cparser = PuddleConfig()
        cparser.setSection('editor', 'patterns', patterns)

    def addPattern(self):
        l = self.listbox.item
        patterns = [unicode(l(z).text()) for z in range(self.listbox.count())]
        row = self.listbox.currentRow()
        if row < 0:
            row = 0
        (text, ok) = QInputDialog().getItem(self, 'puddletag', 
            translate("Pattern Settings", 'Enter a pattern'), patterns, row)
        if ok:
            self.listbox.clearSelection()
            self.listbox.addItem(text)
            self.listbox.setCurrentRow(self.listbox.count() - 1)

    def _doubleClicked(self, item):
        self.editItem()

    def editItem(self, row=None):
        if row is None:
            row = self.listbox.currentRow()
        l = self.listbox.item
        patterns = [unicode(l(z).text()) for z in range(self.listbox.count())]
        (text, ok) = QInputDialog().getItem (self, 'puddletag', 
            translate("Pattern Settings", 'Enter a pattern'),
            patterns, row)
        if ok:
            item = l(row)
            item.setText(text)
            self.listbox.setItemSelected(item, True)

    def applySettings(self, control):
        item = self.listbox.item
        patterns = [item(row).text() for row in xrange(self.listbox.count())]
        control.setItems(patterns)
예제 #4
0
class ShortcutEditor(QDialog):
    def __init__(self, load=False, parent=None, buttons=False):
        super(ShortcutEditor, self).__init__(parent)
        self._names = []
        self._hotkeys = []

        self._listbox = ListBox()

        listbuttons = ListButtons()
        listbuttons.insertStretch(0)
        self.connect(listbuttons, SIGNAL('add'), self._addShortcut)
        self.connect(listbuttons, SIGNAL('edit'), self._editShortcut)
        self.connect(listbuttons, SIGNAL('duplicate'), self._duplicate)
        self.connect(self._listbox,
                     SIGNAL('itemDoubleClicked (QListWidgetItem *)'),
                     self._editShortcut)

        self._listbox.connectToListButtons(listbuttons)

        hbox = QHBoxLayout()
        hbox.addLayout(create_buddy('Shortcuts', self._listbox, QVBoxLayout()))
        hbox.addLayout(listbuttons)

        okcancel = OKCancel()

        vbox = QVBoxLayout()
        vbox.addLayout(hbox)
        if buttons:
            vbox.addLayout(okcancel)
        self.setLayout(vbox)

        self.connect(okcancel, SIGNAL('ok'), self.okClicked)
        self.connect(okcancel, SIGNAL('cancel'), self.close)

        if load:
            self.loadSettings()

    def _addShortcut(self):
        shortcuts = get_shortcuts().difference(self._hotkeys).union(
            i.shortcut for i in self._listbox.items() if i.shortcut)

        win = Editor('Add Shortcut', u'', self._actions, self.names(),
                     shortcuts, self)
        win.setModal(True)
        self.connect(win, SIGNAL('actionChanged'), self.addShortcut)
        win.show()

    def addShortcut(self, name, filenames, shortcut=u'', select=True):
        item = QListWidgetItem(name)
        item.actionName = name
        item.filenames = filenames[::]
        item.shortcut = shortcut
        self._listbox.addItem(item)
        if select:
            self._listbox.setCurrentItem(item,
                                         QItemSelectionModel.ClearAndSelect)

    def applySettings(self, control=None):
        from puddlestuff.puddletag import remove_shortcuts, add_shortcuts
        remove_shortcuts('&Actions', self._names)

        f = open(FILENAME, 'w')
        f.close()

        cparser = PuddleConfig(FILENAME)
        for i, item in enumerate(self._listbox.items()):
            section = SHORTCUT_SECTION + unicode(i)
            cparser.set(section, NAME, item.actionName)
            cparser.set(section, FILENAMES, item.filenames)

        from puddlestuff.mainwin.funcs import applyaction

        shortcuts = create_action_shortcuts(applyaction, control)
        for item, shortcut in zip(self._listbox.items(), shortcuts):
            if item.shortcut:
                shortcut.setShortcut(item.shortcut)
        add_shortcuts('&Actions', shortcuts, save=True)

    def okClicked(self):
        self.applySettings()
        self.close()

    def _duplicate(self):
        try:
            item = self._listbox.selectedItems()[0]
        except IndexError:
            return
        shortcuts = get_shortcuts().difference(self._hotkeys).union(
            i.shortcut for i in self._listbox.items() if i.shortcut)
        win = Editor('Duplicate Shortcut', u'', self._actions, self.names(),
                     shortcuts, self)
        win.setAttrs(item.actionName, self._actions, item.filenames, u'')
        win.setModal(True)
        self.connect(win, SIGNAL('actionChanged'), self.addShortcut)
        win.show()

    def _editShortcut(self):
        try:
            item = self._listbox.selectedItems()[0]
        except IndexError:
            return
        shortcuts = get_shortcuts().difference(self._hotkeys).union(
            i.shortcut for i in self._listbox.items() if i.shortcut)

        names = self.names()
        names.remove(item.actionName)
        win = Editor('Edit Shortcut', item.shortcut, self._actions, names,
                     shortcuts, self)
        win.setAttrs(item.actionName, self._actions, item.filenames,
                     item.shortcut)
        win.setModal(True)
        self.connect(win, SIGNAL('actionChanged'),
                     partial(self.editShortcut, item))
        win.show()

    def editShortcut(self, item, name, filenames, shortcut):
        item.actionName = name
        item.filenames = filenames[::]
        item.shortcut = shortcut
        item.setText(name)

    def loadSettings(self, filename=None, actions=None):
        self._names = []
        self._hotkeys = []

        if filename is None:
            filename = os.path.join(ACTIONDIR, 'action_shortcuts')

        self._listbox.clear()
        cparser = PuddleConfig(filename)

        if actions is None:
            self._actions = load_actions()
        else:
            self._actions = actions

        from puddlestuff.puddletag import status
        if status['actions']:
            shortcuts = dict(
                (unicode(a.text()), unicode(a.shortcut().toString()))
                for a in status['actions'])
        else:
            shortcuts = {}

        for section in sorted(cparser.sections()):
            if section.startswith('Shortcut'):
                name = cparser.get(section, NAME, 'Default')
                self._names.append(name)
                filenames = cparser.get(section, FILENAMES, [])
                shortcut = shortcuts.get(name, u'')
                self.addShortcut(name, filenames, shortcut, select=False)
                self._hotkeys.append(shortcut)

    def names(self):
        return [item.actionName for item in self._listbox.items()]
예제 #5
0
파일: dialogs.py 프로젝트: korala1968/tago
class MTProfileEdit(QDialog):
    def __init__(self, tag_sources, profile=None, parent=None):
        super(MTProfileEdit, self).__init__(parent)

        self.setWindowTitle(translate('Profile Editor', 'Edit Masstagging Profile'))
        winsettings('masstag_profile', self)
        self._configs = []
        self.tag_sources = tag_sources
        self._tsps = []

        self._name = QLineEdit(translate('Profile Editor',
            'Masstagging Profile'))

        self._desc = QLineEdit()

        self.listbox = ListBox()

        self.okcancel = OKCancel()
        self.okcancel.ok.setDefault(True)

        self.buttonlist = ListButtons()

        self.pattern = QLineEdit('%artist% - %album%/%track% - %title%')
        self.pattern.setToolTip(translate('Profile Editor',
            "<p>If no tag information is found in a file, "
            "the tags retrieved using this pattern will be used instead.</p>"))

        self.albumBound = QSpinBox()
        self.albumBound.setRange(0,100)
        self.albumBound.setValue(70)
        self.albumBound.setToolTip(translate('Profile Editor',
            "<p>The artist and album fields will be used in "
            "determining whether an album matches the retrieved one. "
            "Each field will be compared using a fuzzy matching algorithm. "
            "If the resulting average match percentage is greater "
            "or equal than what you specify here it'll be "
            "considered to match.</p>"))

        self.matchFields = QLineEdit('artist, title')
        self.matchFields.setToolTip(translate('Profile Editor',
            '<p>The fields listed here will be used in '
            'determining whether a file matches a retrieved track. '
            'Each field will be compared using a fuzzy matching '
            'algorithm. If the resulting average match '
            'percentage is greater than the "Minimum Percentage" '
            'it\'ll be considered to match.</p>'))

        self.trackBound = QSpinBox()
        self.trackBound.setRange(0,100)
        self.trackBound.setValue(80)

        self.jfdi = QCheckBox(translate('Profile Editor',
            'Brute force unmatched files.'))
        self.jfdi.setToolTip(translate('Profile Editor',
            "<p>Check to enable brute forcing matches. "
            " If a proper match isn't found for a file, "
            'the files will get sorted by filename, '
            'the retrieved tag sources by filename and '
            'corresponding (unmatched) tracks will matched.</p>'))

        self.existing = QCheckBox(translate('Profile Editor',
            'Update empty fields only.'))

        self.grid = QGridLayout()
        self.setLayout(self.grid)

        self.grid.addLayout(create_buddy(
            translate('Profile Editor', '&Name:'), self._name), 0, 0, 1, 2)
        self.grid.addLayout(create_buddy(
            translate('Profile Editor', '&Description'), self._desc), 1, 0, 1, 2)
        self.grid.addWidget(self.listbox, 2, 0)
        self.grid.setRowStretch(2, 1)
        self.grid.addLayout(self.buttonlist, 2, 1)
        self.grid.addLayout(create_buddy(translate('Profile Editor',
                'Pattern to match filenames against.'),
            self.pattern, QVBoxLayout()), 3, 0, 1, 2)
        self.grid.addLayout(create_buddy(translate('Profile Editor',
                'Minimum percentage required for album matches.'),
            self.albumBound), 4, 0, 1, 2)
        self.grid.addLayout(create_buddy(translate('Profile Editor',
                'Match tracks using fields: '),
            self.matchFields, QVBoxLayout()), 5, 0, 1, 2)
        self.grid.addLayout(create_buddy(translate('Profile Editor',
                'Minimum percentage required for track match.'),
            self.trackBound), 6, 0, 1, 2)
        self.grid.addWidget(self.jfdi, 7, 0, 1, 2)
        self.grid.addWidget(self.existing, 8, 0, 1, 2)
        self.grid.addLayout(self.okcancel, 9, 0, 1, 2)

        connect = lambda control, signal, slot: self.connect(
            control, SIGNAL(signal), slot)

        connect(self.okcancel, "ok" , self.okClicked)
        connect(self.okcancel, "cancel",self.close)
        connect(self.buttonlist, "add", self.addClicked)
        connect(self.buttonlist, "edit", self.editClicked)
        connect(self.buttonlist, "moveup", self.moveUp)
        connect(self.buttonlist, "movedown", self.moveDown)
        connect(self.buttonlist, "remove", self.remove)
        connect(self.buttonlist, "duplicate", self.dupClicked)
        connect(self.listbox, "itemDoubleClicked (QListWidgetItem *)",
            self.editClicked)
        connect(self.listbox, "currentRowChanged(int)", self.enableListButtons)

        if profile is not None:
            self.setProfile(profile)
        self.enableListButtons(self.listbox.currentRow())

    def addClicked(self):
        win = TSProfileEdit(self.tag_sources, None, self)
        win.setModal(True)
        self.connect(win, SIGNAL('profileChanged'), self.addTSProfile)
        win.show()

    def addTSProfile(self, profile):
        row = self.listbox.count()
        self.listbox.addItem(profile.tag_source.name)
        self._tsps.append(profile)

    def dupClicked(self):
        row = self.listbox.currentRow()
        if row == -1:
            return
        win = TSProfileEdit(self.tag_sources, self._tsps[row], self)
        win.setModal(True)
        self.connect(win, SIGNAL('profileChanged'), self.addTSProfile)
        win.show()

    def editClicked(self, item=None):
        if item:
            row = self.listbox.row(item)
        else:
            row = self.listbox.currentRow()

        if row == -1:
            return
        win = TSProfileEdit(self.tag_sources, self._tsps[row], self)
        win.setModal(True)
        self.connect(win, SIGNAL('profileChanged'),
            partial(self.replaceTSProfile, row))
        win.show()

    def replaceTSProfile(self, row, profile):
        self._tsps[row] = profile
        self.listbox.item(row).setText(profile.tag_source.name)

    def enableListButtons(self, val):
        if val == -1:
            [button.setEnabled(False) for button in self.buttonlist.widgets[1:]]
        else:
            [button.setEnabled(True) for button in self.buttonlist.widgets[1:]]

    def moveDown(self):
        self.listbox.moveDown(self._tsps)

    def moveUp(self):
        self.listbox.moveUp(self._tsps)

    def okClicked(self):
        fields = [z.strip() for z in
            unicode(self.matchFields.text()).split(u',')]

        mtp = MassTagProfile(unicode(self._name.text()),
            unicode(self._desc.text()), fields, None,
            unicode(self.pattern.text()), self._tsps,
            self.albumBound.value() / 100.0,
            self.trackBound.value() / 100.0, self.jfdi.isChecked(),
            self.existing.isChecked(), u'')

        self.emit(SIGNAL('profileChanged'), mtp)
        self.close()

    def remove(self):
        row = self.listbox.currentRow()
        if row == -1:
            return
        del(self._tsps[row])
        self.listbox.takeItem(row)

    def setProfile(self, profile):
        self._tsps = [tsp for tsp in profile.profiles if tsp.tag_source]
        [self.listbox.addItem(tsp.tag_source.name) for tsp in self._tsps]
        self.albumBound.setValue(profile.album_bound * 100)
        self.pattern.setText(profile.file_pattern)
        self.matchFields.setText(u', '.join(profile.fields))
        self.trackBound.setValue(profile.track_bound * 100)
        self.jfdi.setChecked(profile.jfdi)
        self._name.setText(profile.name)
        self._desc.setText(profile.desc)
        self.existing.setChecked(profile.leave_existing)
예제 #6
0
class ButtonsAndList(QFrame):
    def __init__(self,
                 parent=None,
                 title=u'',
                 add_text=ADD_TEXT,
                 help_text=u''):

        QFrame.__init__(self, parent)
        self.title = title
        connect = lambda c, signal, s: self.connect(c, SIGNAL(signal), s)
        self.setFrameStyle(QFrame.Box)
        self.listbox = ListBox()
        self.listbox.setSelectionMode(self.listbox.ExtendedSelection)
        buttons = ListButtons()

        hbox = QHBoxLayout()
        hbox.addWidget(self.listbox)

        vbox = QVBoxLayout()
        sortlistbox = QPushButton(translate("Defaults", '&Sort'))
        self._sortOrder = Qt.AscendingOrder
        connect(sortlistbox, 'clicked()', self._sortListBox)
        vbox.addWidget(sortlistbox)
        vbox.addLayout(buttons)
        vbox.addStretch()

        hbox.addLayout(vbox)

        if help_text:
            label = QLabel(help_text)
            layout = QVBoxLayout()
            layout.addWidget(label)
            layout.addLayout(hbox, 1)
            self.setLayout(layout)
        else:
            self.setLayout(hbox)

        connect(buttons, "add", self.addItem)
        connect(buttons, "edit", self.editItem)
        buttons.duplicate.setVisible(False)
        self.listbox.connectToListButtons(buttons)
        self.listbox.editButton = buttons.edit
        connect(self.listbox, 'itemDoubleClicked(QListWidgetItem *)',
                self._doubleClicked)
        self.addText = add_text

    def _doubleClicked(self, item):
        self.editItem()

    def _sortListBox(self):
        if self._sortOrder == Qt.AscendingOrder:
            self.listbox.sortItems(Qt.DescendingOrder)
            self._sortOrder = Qt.DescendingOrder
        else:
            self.listbox.sortItems(Qt.AscendingOrder)
            self._sortOrder = Qt.AscendingOrder

    def addItem(self):
        l = self.listbox.item
        patterns = [unicode(l(z).text()) for z in range(self.listbox.count())]
        row = self.listbox.currentRow()
        if row < 0:
            row = 0
        (text, ok) = QInputDialog().getItem(self, 'puddletag', self.addText,
                                            patterns, row)
        if ok:
            self.listbox.clearSelection()
            self.listbox.addItem(text)
            self.listbox.setCurrentRow(self.listbox.count() - 1)

    def addItems(self, items):
        self.listbox.addItems(items)

    def editItem(self, row=None):
        if row is None:
            row = self.listbox.currentRow()
        l = self.listbox.item
        patterns = [unicode(l(z).text()) for z in range(self.listbox.count())]
        (text, ok) = QInputDialog().getItem(self, 'puddletag', self.addText,
                                            patterns, row)
        if ok:
            item = l(row)
            item.setText(text)
            self.listbox.setItemSelected(item, True)

    def getItems(self):
        return [item.text() for item in self.listbox.items()]
예제 #7
0
class Editor(QDialog):
    def __init__(self,
                 title='Add Action',
                 shortcut=u'',
                 actions=None,
                 names=None,
                 shortcuts=None,
                 parent=None):
        super(Editor, self).__init__(parent)
        self.setWindowTitle(title)

        self._items = {}

        self._name = QLineEdit('Name')

        if shortcut and shortcut in shortcuts:
            shortcuts.remove(shortcut)

        self._shortcut = puddleobjects.ShortcutEditor(shortcuts)
        self._shortcut.setText(shortcut)
        clear = QPushButton(translate('Shortcuts', '&Clear'))
        self.connect(clear, SIGNAL('clicked()'), self._shortcut.clear)

        if names is None:
            names = []
        self._names = names

        self._actionList = ListBox()
        self.connect(self._actionList,
                     SIGNAL('itemDoubleClicked (QListWidgetItem *)'),
                     self._addAction)
        self._newActionList = ListBox()
        listbuttons = ListButtons()
        listbuttons.duplicate.hide()
        listbuttons.insertStretch(0)
        self.connect(listbuttons, SIGNAL('add'), self._addAction)

        self._newActionList.connectToListButtons(listbuttons)

        okcancel = OKCancel()
        self.connect(okcancel, SIGNAL('ok'), self.okClicked)
        self.connect(okcancel, SIGNAL('cancel'), self.close)
        self._ok = okcancel.ok
        self.connect(self._name, SIGNAL('textChanged(const QString)'),
                     self.enableOk)
        scut_status = QLabel('')
        self.connect(
            self._shortcut, SIGNAL('validityChanged'),
            lambda v: scut_status.setText(u'')
            if v or (not self._shortcut.text()) else scut_status.setText(
                translate('Shortcuts', "Invalid shortcut sequence.")))
        okcancel.insertWidget(0, scut_status)

        hbox = QHBoxLayout()
        hbox.addLayout(
            create_buddy('Actions', self._actionList, QVBoxLayout()), 1)
        hbox.addLayout(listbuttons, 0)
        hbox.addLayout(
            create_buddy('Actions to run for shortcut', self._newActionList,
                         QVBoxLayout()), 1)

        layout = QVBoxLayout()
        layout.addLayout(create_buddy('Shortcut &Name: ', self._name))
        scut_layout = create_buddy('&Keyboard Shortcut: ', self._shortcut)
        scut_layout.addWidget(clear)
        layout.addLayout(scut_layout)
        layout.addLayout(hbox)
        layout.addLayout(okcancel)
        self.setLayout(layout)

        if actions:
            self.setActions(actions)

    def _addAction(self, item=None):
        if item is None:
            for item in self._actionList.selectedItems():
                self._addAction(item)
            return
        new_item = QListWidgetItem(item)
        new_item._action = item._action
        self._newActionList.addItem(new_item)
        self._newActionList.setCurrentItem(new_item,
                                           QItemSelectionModel.ClearAndSelect)

    def enableOk(self, text):
        if not text or text in self._names:
            self._ok.setEnabled(False)
        else:
            self._ok.setEnabled(True)

    def okClicked(self):
        alist = self._newActionList
        items = map(alist.item, xrange(alist.count()))
        actions = [item._action[1] for item in items]
        self.emit(
            SIGNAL('actionChanged'), unicode(self._name.text()), actions,
            unicode(self._shortcut.text()) if self._shortcut.valid else u'')
        self.close()

    def setActions(self, actions):
        self._actionList.clear()
        self._actions = []
        for funcs, name, filename in actions:
            item = QListWidgetItem(name)
            item.setToolTip(u'\n'.join([func.description() for func in funcs]))
            item._action = [name, filename]
            self._actionList.addItem(item)

    def setName(self, name):
        self._name.setText(name)

    def setAttrs(self, name, actions, filenames, shortcut=u''):
        names = dict([(z[2], z[1]) for z in actions])
        self.setActions(actions)
        self.setName(name)
        self._newActionList.clear()
        self.setShortcut(shortcut)
        if filenames:
            for filename in filenames:
                item = QListWidgetItem(
                    names.get(filename, translate('Shortcuts', '(Deleted)')))
                item._action = [names.get(filename, u''), filename]
                self._newActionList.addItem(item)

    def setShortcut(self, text):
        self._shortcut.setText(text)
예제 #8
0
class SettingsWin(QFrame):
    def __init__(self, parent=None, cenwid=None, status=None):
        QFrame.__init__(self, parent)
        self.title = translate('Settings', "Patterns")
        connect = lambda c, signal, s: self.connect(c, SIGNAL(signal), s)
        self.setFrameStyle(QFrame.Box)
        self.listbox = ListBox()
        self.listbox.setSelectionMode(self.listbox.ExtendedSelection)
        buttons = ListButtons()

        self.listbox.addItems(status['patterns'])
        hbox = QHBoxLayout()
        hbox.addWidget(self.listbox)
        self.setLayout(hbox)

        vbox = QVBoxLayout()
        sortlistbox = QPushButton(translate("Pattern Settings", '&Sort'))
        self._sortOrder = Qt.AscendingOrder
        connect(sortlistbox, 'clicked()', self._sortListBox)
        vbox.addWidget(sortlistbox)
        vbox.addLayout(buttons)
        vbox.addStretch()

        hbox.addLayout(vbox)

        connect(buttons, "add", self.addPattern)
        connect(buttons, "edit", self.editItem)
        buttons.duplicate.setVisible(False)
        self.listbox.connectToListButtons(buttons)
        self.listbox.editButton = buttons.edit
        connect(self.listbox, 'itemDoubleClicked(QListWidgetItem *)',
                self._doubleClicked)

    def _sortListBox(self):
        if self._sortOrder == Qt.AscendingOrder:
            self.listbox.sortItems(Qt.DescendingOrder)
            self._sortOrder = Qt.DescendingOrder
        else:
            self.listbox.sortItems(Qt.AscendingOrder)
            self._sortOrder = Qt.AscendingOrder

    def saveSettings(self):
        patterns = [
            unicode(self.listbox.item(row).text())
            for row in xrange(self.listbox.count())
        ]
        cparser = PuddleConfig()
        cparser.setSection('editor', 'patterns', patterns)

    def addPattern(self):
        l = self.listbox.item
        patterns = [unicode(l(z).text()) for z in range(self.listbox.count())]
        row = self.listbox.currentRow()
        if row < 0:
            row = 0
        (text, ok) = QInputDialog().getItem(
            self, 'puddletag', translate("Pattern Settings",
                                         'Enter a pattern'), patterns, row)
        if ok:
            self.listbox.clearSelection()
            self.listbox.addItem(text)
            self.listbox.setCurrentRow(self.listbox.count() - 1)

    def _doubleClicked(self, item):
        self.editItem()

    def editItem(self, row=None):
        if row is None:
            row = self.listbox.currentRow()
        l = self.listbox.item
        patterns = [unicode(l(z).text()) for z in range(self.listbox.count())]
        (text, ok) = QInputDialog().getItem(
            self, 'puddletag', translate("Pattern Settings",
                                         'Enter a pattern'), patterns, row)
        if ok:
            item = l(row)
            item.setText(text)
            self.listbox.setItemSelected(item, True)

    def applySettings(self, control):
        item = self.listbox.item
        patterns = [item(row).text() for row in xrange(self.listbox.count())]
        control.setItems(patterns)
예제 #9
0
class ShortcutEditor(QDialog):
    def __init__(self, load=False, parent=None, buttons=False):
        super(ShortcutEditor, self).__init__(parent)
        self._names = []
        self._hotkeys = []

        self._listbox = ListBox()

        listbuttons = ListButtons()
        listbuttons.insertStretch(0)
        self.connect(listbuttons, SIGNAL('add'), self._addShortcut)
        self.connect(listbuttons, SIGNAL('edit'), self._editShortcut)
        self.connect(listbuttons, SIGNAL('duplicate'), self._duplicate)
        self.connect(self._listbox,
            SIGNAL('itemDoubleClicked (QListWidgetItem *)'), self._editShortcut)
        
        self._listbox.connectToListButtons(listbuttons)

        hbox = QHBoxLayout()
        hbox.addLayout(create_buddy('Shortcuts', self._listbox, QVBoxLayout()))
        hbox.addLayout(listbuttons)

        okcancel = OKCancel()

        vbox = QVBoxLayout()
        vbox.addLayout(hbox)
        if buttons:
            vbox.addLayout(okcancel)
        self.setLayout(vbox)

        self.connect(okcancel, SIGNAL('ok'), self.okClicked)
        self.connect(okcancel, SIGNAL('cancel'), self.close)

        if load:
            self.loadSettings()

    def _addShortcut(self):
        shortcuts = get_shortcuts().difference(self._hotkeys).union(
            i.shortcut for i in self._listbox.items() if i.shortcut)
            
        win = Editor('Add Shortcut', u'', self._actions, self.names(), shortcuts, self)
        win.setModal(True)
        self.connect(win, SIGNAL('actionChanged'), self.addShortcut)
        win.show()

    def addShortcut(self, name, filenames, shortcut=u'', select=True):
        item = QListWidgetItem(name)
        item.actionName = name
        item.filenames = filenames[::]
        item.shortcut = shortcut
        self._listbox.addItem(item)
        if select:
            self._listbox.setCurrentItem(item, QItemSelectionModel.ClearAndSelect)

    def applySettings(self, control = None):
        from puddlestuff.puddletag import remove_shortcuts, add_shortcuts
        remove_shortcuts('&Actions', self._names)

        f = open(FILENAME, 'w')
        f.close()
        
        cparser = PuddleConfig(FILENAME)
        for i, item in enumerate(self._listbox.items()):
            section = SHORTCUT_SECTION + unicode(i)
            cparser.set(section, NAME, item.actionName)
            cparser.set(section, FILENAMES, item.filenames)

        from puddlestuff.mainwin.funcs import applyaction

        shortcuts = create_action_shortcuts(applyaction, control)
        for item, shortcut in zip(self._listbox.items(), shortcuts):
            if item.shortcut:
                shortcut.setShortcut(item.shortcut)
        add_shortcuts('&Actions', shortcuts, save=True)

    def okClicked(self):
        self.applySettings()
        self.close()

    def _duplicate(self):
        try:
            item = self._listbox.selectedItems()[0]
        except IndexError:
            return
        shortcuts = get_shortcuts().difference(self._hotkeys).union(
            i.shortcut for i in self._listbox.items() if i.shortcut)
        win = Editor('Duplicate Shortcut', u'', self._actions, self.names(), shortcuts, self)
        win.setAttrs(item.actionName, self._actions, item.filenames, u'')
        win.setModal(True)
        self.connect(win, SIGNAL('actionChanged'), self.addShortcut)
        win.show()

    def _editShortcut(self):
        try:
            item = self._listbox.selectedItems()[0]
        except IndexError:
            return
        shortcuts = get_shortcuts().difference(self._hotkeys).union(
            i.shortcut for i in self._listbox.items() if i.shortcut)

        names = self.names()
        names.remove(item.actionName)
        win = Editor('Edit Shortcut', item.shortcut, self._actions, names, shortcuts, self)
        win.setAttrs(item.actionName, self._actions, item.filenames, item.shortcut)
        win.setModal(True)
        self.connect(win, SIGNAL('actionChanged'),
            partial(self.editShortcut, item))
        win.show()

    def editShortcut(self, item, name, filenames, shortcut):
        item.actionName = name
        item.filenames = filenames[::]
        item.shortcut = shortcut
        item.setText(name)

    def loadSettings(self, filename=None, actions=None):
        self._names = []
        self._hotkeys = []

        if filename is None:
            filename = os.path.join(ACTIONDIR, 'action_shortcuts')

        self._listbox.clear()
        cparser = PuddleConfig(filename)

        if actions is None:
            self._actions = load_actions()
        else:
            self._actions = actions

        from puddlestuff.puddletag import status
        if status['actions']:
            shortcuts = dict((unicode(a.text()), unicode(a.shortcut().toString()))
                for a in status['actions'])
        else:
            shortcuts = {}

        for section in sorted(cparser.sections()):
            if section.startswith('Shortcut'):
                name = cparser.get(section, NAME, 'Default')
                self._names.append(name)
                filenames = cparser.get(section, FILENAMES, [])
                shortcut = shortcuts.get(name, u'')
                self.addShortcut(name, filenames, shortcut, select=False)
                self._hotkeys.append(shortcut)

    def names(self):
        return [item.actionName for item in self._listbox.items()]
예제 #10
0
class Editor(QDialog):
    def __init__(self, title='Add Action', shortcut=u'', actions=None, names=None, shortcuts=None, parent=None):
        super(Editor, self).__init__(parent)
        self.setWindowTitle(title)

        self._items = {}

        self._name = QLineEdit('Name')
        
        if shortcut and shortcut in shortcuts:
            shortcuts.remove(shortcut)

        self._shortcut = puddleobjects.ShortcutEditor(shortcuts)
        self._shortcut.setText(shortcut)
        clear = QPushButton(translate('Shortcuts', '&Clear'))
        self.connect(clear, SIGNAL('clicked()'), self._shortcut.clear)
        
        if names is None:
            names = []
        self._names = names
        
        self._actionList = ListBox()
        self.connect(self._actionList,
            SIGNAL('itemDoubleClicked (QListWidgetItem *)'), self._addAction)
        self._newActionList = ListBox()
        listbuttons = ListButtons()
        listbuttons.duplicate.hide()
        listbuttons.insertStretch(0)
        self.connect(listbuttons, SIGNAL('add'), self._addAction)

        self._newActionList.connectToListButtons(listbuttons)

        okcancel = OKCancel()
        self.connect(okcancel, SIGNAL('ok'), self.okClicked)
        self.connect(okcancel, SIGNAL('cancel'), self.close)
        self._ok = okcancel.ok
        self.connect(self._name, SIGNAL('textChanged(const QString)'), self.enableOk)
        scut_status = QLabel('')
        self.connect(self._shortcut, SIGNAL('validityChanged'),
            lambda v: scut_status.setText(u'') if v or (not self._shortcut.text()) else
                scut_status.setText(translate('Shortcuts', "Invalid shortcut sequence.")))
        okcancel.insertWidget(0, scut_status)

        hbox = QHBoxLayout()
        hbox.addLayout(
            create_buddy('Actions', self._actionList, QVBoxLayout()), 1)
        hbox.addLayout(listbuttons, 0)
        hbox.addLayout(create_buddy('Actions to run for shortcut',
            self._newActionList, QVBoxLayout()), 1)

        layout = QVBoxLayout()
        layout.addLayout(create_buddy('Shortcut &Name: ', self._name))
        scut_layout = create_buddy('&Keyboard Shortcut: ', self._shortcut)
        scut_layout.addWidget(clear)
        layout.addLayout(scut_layout)
        layout.addLayout(hbox)
        layout.addLayout(okcancel)
        self.setLayout(layout)

        if actions:
            self.setActions(actions)

    def _addAction(self, item=None):
        if item is None:
            for item in self._actionList.selectedItems():
                self._addAction(item)
            return
        new_item = QListWidgetItem(item)
        new_item._action = item._action
        self._newActionList.addItem(new_item)
        self._newActionList.setCurrentItem(new_item,
            QItemSelectionModel.ClearAndSelect)

    def enableOk(self, text):
        if not text or text in self._names:
            self._ok.setEnabled(False)
        else:
            self._ok.setEnabled(True)

    def okClicked(self):
        alist = self._newActionList
        items = map(alist.item, xrange(alist.count()))
        actions = [item._action[1] for item in items]
        self.emit(SIGNAL('actionChanged'), unicode(self._name.text()), actions,
            unicode(self._shortcut.text()) if self._shortcut.valid else u'')
        self.close()

    def setActions(self, actions):
        self._actionList.clear()
        self._actions = []
        for funcs, name, filename in actions:
            item = QListWidgetItem(name)
            item.setToolTip(u'\n'.join([func.description() for func in funcs]))
            item._action = [name, filename]
            self._actionList.addItem(item)

    def setName(self, name):
        self._name.setText(name)

    def setAttrs(self, name, actions, filenames, shortcut=u''):
        names = dict([(z[2], z[1]) for z in actions])
        self.setActions(actions)
        self.setName(name)
        self._newActionList.clear()
        self.setShortcut(shortcut)
        if filenames:
            for filename in filenames:
                item = QListWidgetItem(names.get(filename, translate('Shortcuts', '(Deleted)')))
                item._action = [names.get(filename, u''), filename]
                self._newActionList.addItem(item)

    def setShortcut(self, text):
        self._shortcut.setText(text)
예제 #11
0
class ButtonsAndList(QFrame):
    def __init__(self, parent=None, title=u'', add_text=ADD_TEXT,
        help_text=u''):
            
        QFrame.__init__(self, parent)
        self.title = title
        connect = lambda c, signal, s: self.connect(c, SIGNAL(signal), s)
        self.setFrameStyle(QFrame.Box)
        self.listbox = ListBox()
        self.listbox.setSelectionMode(self.listbox.ExtendedSelection)
        buttons = ListButtons()

        hbox = QHBoxLayout()
        hbox.addWidget(self.listbox)

        vbox = QVBoxLayout()
        sortlistbox = QPushButton(translate("Defaults", '&Sort'))
        self._sortOrder = Qt.AscendingOrder
        connect(sortlistbox, 'clicked()', self._sortListBox)
        vbox.addWidget(sortlistbox)
        vbox.addLayout(buttons)
        vbox.addStretch()

        hbox.addLayout(vbox)

        if help_text:
            label = QLabel(help_text)
            layout = QVBoxLayout()
            layout.addWidget(label)
            layout.addLayout(hbox, 1)
            self.setLayout(layout)
        else:
            self.setLayout(hbox)

        connect(buttons, "add", self.addItem)
        connect(buttons, "edit", self.editItem)
        buttons.duplicate.setVisible(False)
        self.listbox.connectToListButtons(buttons)
        self.listbox.editButton = buttons.edit
        connect(self.listbox, 'itemDoubleClicked(QListWidgetItem *)',
                    self._doubleClicked)
        self.addText = add_text

    def _doubleClicked(self, item):
        self.editItem()

    def _sortListBox(self):
        if self._sortOrder == Qt.AscendingOrder:
            self.listbox.sortItems(Qt.DescendingOrder)
            self._sortOrder = Qt.DescendingOrder
        else:
            self.listbox.sortItems(Qt.AscendingOrder)
            self._sortOrder = Qt.AscendingOrder

    def addItem(self):
        l = self.listbox.item
        patterns = [unicode(l(z).text()) for z in range(self.listbox.count())]
        row = self.listbox.currentRow()
        if row < 0:
            row = 0
        (text, ok) = QInputDialog().getItem(self, 'puddletag',
            self.addText, patterns, row)
        if ok:
            self.listbox.clearSelection()
            self.listbox.addItem(text)
            self.listbox.setCurrentRow(self.listbox.count() - 1)

    def addItems(self, items):
        self.listbox.addItems(items)

    def editItem(self, row=None):
        if row is None:
            row = self.listbox.currentRow()
        l = self.listbox.item
        patterns = [unicode(l(z).text()) for z in range(self.listbox.count())]
        (text, ok) = QInputDialog().getItem (self, 'puddletag',
            self.addText, patterns, row)
        if ok:
            item = l(row)
            item.setText(text)
            self.listbox.setItemSelected(item, True)

    def getItems(self):
        return [item.text() for item in self.listbox.items()]
예제 #12
0
class SetDialog(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self,parent)
        winsettings('setdialog', self)
        vbox = QVBoxLayout()
        self._previndex = 0
        self.setscombo = QComboBox()
        setlabel = QLabel('&Sets')
        setlabel.setBuddy(self.setscombo)
        vbox.addWidget(setlabel)

        comboadd = QToolButton()
        comboadd.setIcon(QIcon(':/filenew.png'))
        comboadd.setToolTip('Add set')
        self.connect(comboadd, SIGNAL('clicked()'), self.addSet)

        hbox = QHBoxLayout()
        hbox.addWidget(self.setscombo)
        hbox.addWidget(comboadd)
        
        vbox.addLayout(hbox)
        
        conditions = QLabel('&Conditions')
        vbox.addWidget(conditions)
        
        self.listbox = ListBox()
        conditions.setBuddy(self.listbox)
        listbuttons = ListButtons()
        
        listhbox = QHBoxLayout()
        listhbox.addWidget(self.listbox)
        listhbox.addLayout(listbuttons)
        vbox.addLayout(listhbox)

        label = QLabel('Retrieve values via: ')
        self.maintag = QComboBox()
        self.maintag.addItems(['artist', 'title', 'genre', 'album', 'year'])
        maintaghbox = QHBoxLayout()
        maintaghbox.addWidget(label)
        maintaghbox.addWidget(self.maintag)
        maintaghbox.addStretch()
        vbox.addLayout(maintaghbox)
        
        dispformat = QLabel('Display Format')
        vbox.addWidget(dispformat)
        self.texts = [QLineEdit(), QLineEdit()]
        t = ['Original', 'Duplicates']
        for i, text in enumerate(self.texts):
            label = QLabel(t[i])
            label.setBuddy(text)
            dispbox = QHBoxLayout()
            dispbox.addWidget(label)
            dispbox.addWidget(text)
            vbox.addLayout(dispbox)

        okcancel = OKCancel()
        vbox.addLayout(okcancel)
        self.connect(okcancel, SIGNAL('ok'), self.okClicked)
        self.connect(okcancel, SIGNAL('cancel'), self.cancelClicked)
        self.setLayout(vbox)

        self.fill(loadsets())
        listbuttons.connectToWidget(self)

    def addSet(self):
        def gettext():
            (text, ok) = QInputDialog.getText (self, 'puddletag', 'Enter a name'
                                'for the set', QLineEdit.Normal)
            if ok:
                if self.setscombo.findText(text) > -1:
                    QMessageBox.information (self, 'puddletag', 'The name entered already exists.')
                    return gettext()
                return text
        text = gettext()
        if text:
            self.setscombo.addItem(text)
            self._sets.append([unicode(text), ['', ''], []])
            self.setscombo.setCurrentIndex(self.setscombo.count() - 1)

    def fill(self, sets):
        if not sets:
            return
        self._sets = sets
        self.setscombo.clear()
        self.setscombo.addItems([z[0] for z in sets])
        self.currentSet = sets[0]
        self.setscombo.setCurrentIndex(0)
        self.connect(self.setscombo, SIGNAL('currentIndexChanged (int)'),
                        self.changeSet)

    def _setCurrentSet(self, s):
        [text.setText(disp) for text, disp in zip(self.texts, s[1])]
        self.listbox.clear()
        [self.listbox.addItem(alg.pprint()) for alg in s[2]]
        index = self.maintag.findText(s[3])
        if index > -1:
            self.maintag.setCurrentIndex(index)
        else:
            self.maintag.addItem(s[3])
            self.maintag.setCurrentIndex(self.maintag.count() - 1)

    def _getCurrentSet(self):
        return self._sets[self.setscombo.currentIndex()]

    currentSet = property(_getCurrentSet, _setCurrentSet)

    def changeSet(self, index):
        i = self._previndex
        prevset = {'setname': self._sets[i][0],
                   'disp': [unicode(text.text()) for text in self.texts],
                   'algs': self._sets[i][2],
                   'maintag': unicode(self.maintag.currentText())}
        self._sets[i][1] = prevset['disp']
        self._sets[i][2] = prevset['algs']
        self._sets[i][3] = prevset['maintag']
        saveset(**prevset)
        self.currentSet = self._sets[index]
        self._previndex = index

    def add(self):
        win = AlgWin(self)
        win.setModal(True)
        self.connect(win, SIGNAL('okClicked'), self.addBuddy)
        win.show()

    def addBuddy(self, alg):
        self.listbox.addItem(alg.pprint())
        self.currentSet[2].append(alg)

    def edit(self):
        win = AlgWin(self, self.currentSet[2][self.listbox.currentRow()])
        win.setModal(True)
        self.connect(win, SIGNAL('okClicked'), self.editBuddy)
        win.show()

    def editBuddy(self, alg):
        self.listbox.item(self.listbox.currentRow()).setText(alg.pprint())
        self._sets[self._previndex][2][self.listbox.currentRow()] = alg

    def moveUp(self):
        self.listbox.moveUp(self.currentSet[2])

    def moveDown(self):
        self.listbox.moveDown(self.currentSet[2])

    def remove(self):
        del(self.currentSet[2][self.listbox.currentRow()])
        self.listbox.takeItem(self.listbox.currentRow())

    def okClicked(self):
        i = self.setscombo.currentIndex()
        prevset = {'setname': self._sets[i][0],
                   'disp': [unicode(text.text()) for text in self.texts],
                   'algs': self._sets[i][2],
                   'maintag': unicode(self.maintag.currentText())}
        saveset(**prevset)
        self.close()
        self.emit(SIGNAL('setAvailable'), *self.currentSet)

    def cancelClicked(self):
        self.close()