def __init__(self, parent): QSplitter.__init__(self, parent) parent.addPage(self, i18n("Parts")) # The part types overview widget. v = KVBox() self.addWidget(v) QLabel('<b>{0}</b>'.format(i18n("Available parts:")), v) allParts = QTreeWidget(v) addButton = KPushButton(KStandardGuiItem.add(), v) addButton.setToolTip(i18n("Add selected part to your score.")) # The listbox with selected parts v = KVBox() self.addWidget(v) QLabel('<b>{0}</b>'.format(i18n("Score:")), v) score = QListWidget(v) self.score = score # so the partList method can find us h = KHBox(v) removeButton = KPushButton(KStandardGuiItem.remove(), h) upButton = QToolButton(h) upButton.setIcon(KIcon("go-up")) downButton = QToolButton(h) downButton.setIcon(KIcon("go-down")) # The StackedWidget with settings partSettings = QStackedWidget() self.addWidget(partSettings) self.setStretchFactor(0, 1) self.setStretchFactor(1, 1) self.setStretchFactor(2, 1) self.setSizes((100, 100, 100)) allParts.setSelectionMode(QTreeWidget.ExtendedSelection) allParts.setRootIsDecorated(False) allParts.headerItem().setHidden(True) score.setSelectionMode(QListWidget.ExtendedSelection) score.setDragDropMode(QListWidget.InternalMove) class PartItem(QListWidgetItem): """ A part from the score, instantiating a config widget as well. """ def __init__(self, partClass): name = partClass.name() # partClass.name is a ki18n object QListWidgetItem.__init__(self, name, score) self.w = QGroupBox(name) partSettings.addWidget(self.w) self.part = partClass() layout = QVBoxLayout(self.w) self.part.widgets(layout) layout.addStretch(1) if score.count() == 1: score.setCurrentRow(0) self.setSelected(True) parent.enableButton(KPageDialog.Try, True) def showSettingsWidget(self): partSettings.setCurrentWidget(self.w) def remove(self): if score.count() == 1: parent.enableButton(KPageDialog.Try, False) sip.delete(self.w) sip.delete(self) # TODO: check if necessary @allParts.itemDoubleClicked.connect def addPart(item, col): if hasattr(item, "partClass"): PartItem(item.partClass) @allParts.itemClicked.connect def toggleExpand(item, col): item.setExpanded(not item.isExpanded()) @addButton.clicked.connect def addSelectedParts(): for item in allParts.selectedItems(): PartItem(item.partClass) @removeButton.clicked.connect def removeSelectedParts(): for item in score.selectedItems(): item.remove() def keepSel(func): """ Restore the selection and current element after reordering parts. """ def decorator(): selItems = score.selectedItems() curItem = score.currentItem() func() score.setCurrentItem(curItem) for i in selItems: i.setSelected(True) return decorator @upButton.clicked.connect @keepSel def moveUp(): """ Move selected parts up. """ for row in range(1, score.count()): if score.item(row).isSelected(): item = score.takeItem(row) score.insertItem(row - 1, item) @downButton.clicked.connect @keepSel def moveDown(): """ Move selected parts down. """ for row in range(score.count() - 1, -1, -1): if score.item(row).isSelected(): item = score.takeItem(row) score.insertItem(row + 1, item) @score.currentItemChanged.connect def showItem(cur, prev): if cur: cur.showSettingsWidget() from frescobaldi_app.scorewiz.parts import categories for name, parts in categories(): group = QTreeWidgetItem(allParts, [name]) group.setFlags(Qt.ItemIsEnabled) group.setIcon(0, KIcon("inode-directory")) for part in parts: p = QTreeWidgetItem(group, [part.name()]) p.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) p.partClass = part