Example #1
0
 def __init__(self, kit, emptyDrums = None, parent = None, directory = None):
     '''
     Constructor
     '''
     super(QEditKitDialog, self).__init__(parent)
     self.setupUi(self)
     self.muteButton.setChecked(DBMidi.isMuted())
     if emptyDrums is None:
         emptyDrums = []
         self.deleteEmptyButton.setEnabled(False)
     self._scoreDirectory = directory
     self._emptyDrums = emptyDrums
     self._currentKit = []
     self._oldLines = {}
     self._initialKit = kit
     self._initialize()
     self.kitTable.currentRowChanged.connect(self._drumChanged)
     self.upButton.clicked.connect(self._moveDrumUp)
     self.downButton.clicked.connect(self._moveDrumDown)
     self.addButton.clicked.connect(self._addDrum)
     self.deleteButton.clicked.connect(self._removeDrum)
     self.deleteEmptyButton.clicked.connect(self._deleteEmpty)
     self.clearButton.clicked.connect(self._clearKit)
     self.resetButton.clicked.connect(self._resetKit)
     self.defaultKitButton.clicked.connect(self._manageDefaultKits)
     self.loadButton.clicked.connect(self._loadKit)
     self.saveButton.clicked.connect(self._saveKit)
     self.drumName.textEdited.connect(self._drumNameEdited)
     self.drumAbbr.editingFinished.connect(self._drumAbbrEdited)
     self.oldDrum.currentIndexChanged.connect(self._oldDrumChanged)
     self.currentNoteHead.currentIndexChanged.connect(self._headEdited)
     self.noteHeadTable.currentRowChanged.connect(self._noteHeadChanged)
     self.addHeadButton.clicked.connect(self._addNoteHead)
     self.headUpButton.clicked.connect(self._moveNoteHeadUp)
     self.setDefaultHeadButton.clicked.connect(self._setDefaultHead)
     self.headDownButton.clicked.connect(self._moveNoteHeadDown)
     self.deleteHeadButton.clicked.connect(self._removeNoteHead)
     self.noteHeadBox.currentIndexChanged.connect(self._notationHeadChanged)
     self.effectBox.currentIndexChanged.connect(self._notationEffectChanged)
     self.stemUpDownBox.stateChanged.connect(self._stemDirectionChanged)
     self.noteUpButton.clicked.connect(self._moveNotationUp)
     self.noteDownButton.clicked.connect(self._moveNotationDown)
     self.shortcutCombo.currentIndexChanged.connect(self._shortcutEdited)
     self._populateMidiCombo()
     self.midiNoteCombo.currentIndexChanged.connect(self._midiNoteChanged)
     self.volumeSlider.valueChanged.connect(self._midiVolumeChanged)
     for effect in self.effectsGroup.children():
         if isinstance(effect, QRadioButton):
             effect.toggled.connect(self._effectChanged)
     self.lockedCheckBox.stateChanged.connect(self._lockChanged)
     self._notationScene = QNotationScene(self)
     self.noteView.setScene(self._notationScene)
     self.noteView.centerOn(*self._notationScene.getCenter())
     self._populate()
Example #2
0
class QEditKitDialog(QDialog, Ui_editKitDialog):
    '''
    classdocs
    '''

    def __init__(self, kit, emptyDrums = None, parent = None, directory = None):
        '''
        Constructor
        '''
        super(QEditKitDialog, self).__init__(parent)
        self.setupUi(self)
        self.muteButton.setChecked(DBMidi.isMuted())
        if emptyDrums is None:
            emptyDrums = []
            self.deleteEmptyButton.setEnabled(False)
        self._scoreDirectory = directory
        self._emptyDrums = emptyDrums
        self._currentKit = []
        self._oldLines = {}
        self._initialKit = kit
        self._initialize()
        self.kitTable.currentRowChanged.connect(self._drumChanged)
        self.upButton.clicked.connect(self._moveDrumUp)
        self.downButton.clicked.connect(self._moveDrumDown)
        self.addButton.clicked.connect(self._addDrum)
        self.deleteButton.clicked.connect(self._removeDrum)
        self.deleteEmptyButton.clicked.connect(self._deleteEmpty)
        self.clearButton.clicked.connect(self._clearKit)
        self.resetButton.clicked.connect(self._resetKit)
        self.defaultKitButton.clicked.connect(self._manageDefaultKits)
        self.loadButton.clicked.connect(self._loadKit)
        self.saveButton.clicked.connect(self._saveKit)
        self.drumName.textEdited.connect(self._drumNameEdited)
        self.drumAbbr.editingFinished.connect(self._drumAbbrEdited)
        self.oldDrum.currentIndexChanged.connect(self._oldDrumChanged)
        self.currentNoteHead.currentIndexChanged.connect(self._headEdited)
        self.noteHeadTable.currentRowChanged.connect(self._noteHeadChanged)
        self.addHeadButton.clicked.connect(self._addNoteHead)
        self.headUpButton.clicked.connect(self._moveNoteHeadUp)
        self.setDefaultHeadButton.clicked.connect(self._setDefaultHead)
        self.headDownButton.clicked.connect(self._moveNoteHeadDown)
        self.deleteHeadButton.clicked.connect(self._removeNoteHead)
        self.noteHeadBox.currentIndexChanged.connect(self._notationHeadChanged)
        self.effectBox.currentIndexChanged.connect(self._notationEffectChanged)
        self.stemUpDownBox.stateChanged.connect(self._stemDirectionChanged)
        self.noteUpButton.clicked.connect(self._moveNotationUp)
        self.noteDownButton.clicked.connect(self._moveNotationDown)
        self.shortcutCombo.currentIndexChanged.connect(self._shortcutEdited)
        self._populateMidiCombo()
        self.midiNoteCombo.currentIndexChanged.connect(self._midiNoteChanged)
        self.volumeSlider.valueChanged.connect(self._midiVolumeChanged)
        for effect in self.effectsGroup.children():
            if isinstance(effect, QRadioButton):
                effect.toggled.connect(self._effectChanged)
        self.lockedCheckBox.stateChanged.connect(self._lockChanged)
        self._notationScene = QNotationScene(self)
        self.noteView.setScene(self._notationScene)
        self.noteView.centerOn(*self._notationScene.getCenter())
        self._populate()


    def _initialize(self):
        self.oldDrum.addItem("None", userData = QVariant(-1))
        for drumIndex, drum in enumerate(reversed(self._initialKit)):
            drum = copy.deepcopy(drum)
            self._currentKit.append(drum)
            self.oldDrum.addItem(drum.name, userData = QVariant(drumIndex))
            self._oldLines[drum] = drumIndex

    def _populate(self):
        self.kitTable.blockSignals(True)
        self.kitTable.clear()
        for drum in self._currentKit:
            self.kitTable.addItem(drum.name)
        self.kitTable.blockSignals(False)
        self.kitTable.setCurrentRow(0)
        self._checkAbbrs()

    @property
    def _currentDrumIndex(self):
        return self.kitTable.currentRow()

    @property
    def _currentDrum(self):
        drumIndex = self._currentDrumIndex
        return self._currentKit[drumIndex]

    def _checkDrumButtons(self):
        self.deleteButton.setEnabled(len(self._currentKit) > 1)
        index = self._currentDrumIndex
        self.upButton.setEnabled(index > 0)
        self.downButton.setEnabled(index < len(self._currentKit) - 1)

    def _drumChanged(self):
        drum = self._currentDrum
        self.drumName.setText(drum.name)
        self.drumAbbr.setText(drum.abbr)
        self.oldDrum.setCurrentIndex(self._oldLines[drum] + 1)
        self.lockedCheckBox.setChecked(drum.locked)
        self._populateHeadTable()
        self._checkDrumButtons()


    def _addDrum(self):
        drum = Drum("New drum", "XX", "o")
        drum.guessHeadData()
        drum.checkShortcuts()
        self._currentKit.append(drum)
        self._oldLines[drum] = -1
        self.kitTable.addItem(drum.name)
        self.kitTable.setCurrentRow(len(self._currentKit) - 1)
        self._checkDrumButtons()
        self._checkAbbrs()
        self.drumName.setFocus()
        self.drumName.selectAll()

    def _removeDrum(self):
        index = self._currentDrumIndex
        drum = self._currentDrum
        self._currentKit = (self._currentKit[:index]
                            + self._currentKit[index + 1:])
        self._oldLines.pop(drum)
        if index < len(self._currentKit) - 1:
            self._drumChanged()
        else:
            self.kitTable.setCurrentRow(index - 1)
        self.kitTable.takeItem(index)
        self._checkDrumButtons()
        self._checkAbbrs()

    def _moveDrumUp(self):
        idx = self._currentDrumIndex
        druma, drumb = self._currentKit[idx - 1], self._currentKit[idx]
        self._currentKit[idx - 1], self._currentKit[idx] = drumb, druma
        self.kitTable.item(idx).setText(self._currentKit[idx].name)
        self.kitTable.item(idx - 1).setText(self._currentKit[idx - 1].name)
        self.kitTable.setCurrentRow(idx - 1)

    def _moveDrumDown(self):
        idx = self._currentDrumIndex
        druma, drumb = self._currentKit[idx], self._currentKit[idx + 1]
        self._currentKit[idx], self._currentKit[idx + 1] = drumb, druma
        self.kitTable.item(idx).setText(self._currentKit[idx].name)
        self.kitTable.item(idx + 1).setText(self._currentKit[idx + 1].name)
        self.kitTable.setCurrentRow(idx + 1)

    def _clearKit(self):
        self._currentKit = []
        self._oldLines.clear()
        self.kitTable.blockSignals(True)
        self.kitTable.clear()
        self.kitTable.blockSignals(False)
        self._addDrum()

    def _deleteEmpty(self):
        newKit = []
        toDelete = []
        for drum in self._currentKit:
            oldIndex = self._oldLines[drum]
            if oldIndex == -1:
                newKit.append(drum)
                continue
            oldDrum = self._initialKit[len(self._initialKit)
                                       - 1 - self._oldLines[drum]]
            if oldDrum in self._emptyDrums:
                toDelete.append(drum)
            else:
                newKit.append(drum)
        for drum in toDelete:
            self._oldLines.pop(drum)
        self._currentKit = newKit
        self._populate()

    def _resetKit(self):
        self._currentKit = []
        self._oldLines = {}
        for drumIndex, drum in enumerate(reversed(self._initialKit)):
            drum = copy.deepcopy(drum)
            self._currentKit.append(drum)
            self._oldLines[drum] = drumIndex
        self._populate()

    def _loadKit(self):
        directory = self._scoreDirectory
        if directory is None:
            home = QDesktopServices.HomeLocation
            directory = unicode(QDesktopServices.storageLocation(home))
        fname = QFileDialog.getOpenFileName(parent = self,
                                            caption = "Load DrumBurp kit",
                                            directory = directory,
                                            filter = _KIT_FILTER)
        if len(fname) == 0:
            return
        with open(fname, 'rU') as handle:
            fileIterator = fileUtils.dbFileIterator(handle)
            newKit = DrumKit.DrumKit()
            newKit.read(fileIterator)
        self._currentKit = list(reversed(newKit))
        self._oldLines.clear()
        for drum in self._currentKit:
            self._oldLines[drum] = -1
        self._populate()

    def _manageDefaultKits(self):
        currentKit, unused_ = self.getNewKit()
        dialog = QDefaultKitManager(currentKit, self)
        if dialog.exec_():
            newKit = dialog.getKit()
            self._currentKit = list(reversed(newKit))
            self._oldLines.clear()
            for drum in self._currentKit:
                self._oldLines[drum] = -1
            self._populate()

    def _saveKit(self):
        directory = self._scoreDirectory
        if directory is None:
            home = QDesktopServices.HomeLocation
            directory = unicode(QDesktopServices.storageLocation(home))
        fname = QFileDialog.getSaveFileName(parent = self,
                                            caption = "Save DrumBurp kit",
                                            directory = directory,
                                            filter = _KIT_FILTER)
        if len(fname) == 0:
            return
        fname = unicode(fname)
        newKit, unused = self.getNewKit()
        with open(fname, 'w') as handle:
            indenter = fileUtils.Indenter(handle)
            newKit.write(indenter)
        QMessageBox.information(self, "Kit saved", "Successfully saved drumkit")


    def _drumNameEdited(self):
        self._currentDrum.name = unicode(self.drumName.text())
        drumIndex = self._currentDrumIndex
        self.kitTable.item(drumIndex).setText(self._currentDrum.name)

    def _drumAbbrEdited(self):
        self._currentDrum.abbr = unicode(self.drumAbbr.text())
        self._checkAbbrs()

    def _checkAbbrs(self):
        # Check that there is not more than one drum with the same
        # abbreviation. If there is, highlight them and disable the OK button 
        # and accept action.
        drumIndicesByAbbr = {}
        for index, drum in enumerate(self._currentKit):
            if drum.abbr not in drumIndicesByAbbr:
                drumIndicesByAbbr[drum.abbr] = []
            drumIndicesByAbbr[drum.abbr].append(index)
        ok = True
        for indices in drumIndicesByAbbr.itervalues():
            if len(indices) > 1:
                ok = False
                for index in indices:
                    self.kitTable.item(index).setTextColor(_BAD_ABBR_COLOR)
            else:
                for index in indices:
                    self.kitTable.item(index).setTextColor(_GOOD_ABBR_COLOR)
        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(ok)
        self.saveButton.setEnabled(ok)
        return ok


    def _oldDrumChanged(self):
        drum = self._currentDrum
        newOldDrumIndex = self.oldDrum.currentIndex()
        newOldDrumIndex = self.oldDrum.itemData(newOldDrumIndex).toInt()[0]
        self._oldLines[drum] = newOldDrumIndex

    def _populateHeadTable(self):
        self.noteHeadTable.blockSignals(True)
        drum = self._currentDrum
        self.noteHeadTable.clear()
        for head in drum:
            headString = head
            if head == drum.head:
                headString += " (Default)"
            self.noteHeadTable.addItem(headString)
        self.noteHeadTable.setCurrentRow(-1)
        self.noteHeadTable.blockSignals(False)
        self.noteHeadTable.setCurrentRow(0)


    @property
    def _currentHead(self):
        drum = self._currentDrum
        row = self.noteHeadTable.currentRow()
        head = drum[row]
        return head

    @property
    def _currentHeadData(self):
        drum = self._currentDrum
        row = self.noteHeadTable.currentRow()
        head = drum[row]
        return drum.headData(head)

    def _headEdited(self):
        noteHead = str(self.currentNoteHead.currentText())
        row = self.noteHeadTable.currentRow()
        drum = self._currentDrum
        oldHead = drum[row]
        drum.renameHead(oldHead, noteHead)
        headString = noteHead
        if noteHead == drum.head:
            headString += " (Default)"
        self.noteHeadTable.item(row).setText(headString)
        self._populateCurrentNoteHead()

    def _noteHeadChanged(self):
        self._populateCurrentNoteHead()
        headData = self._currentHeadData
        self.volumeSlider.setValue(headData.midiVolume)
        midiIndex = self.midiNoteCombo.findData(QVariant(headData.midiNote))
        self.midiNoteCombo.setCurrentIndex(midiIndex)
        self._setEffect(headData.effect)
        if not self.muteButton.isChecked():
            DBMidi.playHeadData(self._currentHeadData)
        self._checkHeadButtons()
        self._setNotation()

    def _shortcutEdited(self):
        shortcut = str(self.shortcutCombo.currentText())
        self._currentHeadData.shortcut = shortcut

    def _populateCurrentNoteHead(self):
        self.currentNoteHead.blockSignals(True)
        self.shortcutCombo.blockSignals(True)
        try:
            self.currentNoteHead.clear()
            badNotes = set(self._currentDrum)
            badNotes.remove(self._currentHead)
            badNotes.update(["-", "|"])
            for head in string.printable:
                head = head.strip()
                if not head or head in badNotes:
                    continue
                self.currentNoteHead.addItem(head)
            headIndex = self.currentNoteHead.findText(self._currentHead)
            self.currentNoteHead.setCurrentIndex(headIndex)
            self.shortcutCombo.clear()
            availableShortcuts = set('abcdefghijklmnopqrstuvwxyz')
            for head in self._currentDrum:
                if head != self._currentHead:
                    shortcut = self._currentDrum.headData(head).shortcut
                    availableShortcuts.remove(shortcut)
            for okShortcut in sorted(list(availableShortcuts)):
                self.shortcutCombo.addItem(okShortcut)
            shortcut = self._currentHeadData.shortcut
            shortIndex = self.shortcutCombo.findText(shortcut)
            self.shortcutCombo.setCurrentIndex(shortIndex)
        finally:
            self.shortcutCombo.blockSignals(False)
            self.currentNoteHead.blockSignals(False)

    def _addNoteHead(self):
        badNotes = set(self._currentDrum)
        badNotes.update(["-", "|"])
        head = "?"
        if head in badNotes:
            candidates = string.printable
            for head in candidates:
                if head not in badNotes:
                    break
        self._currentDrum.addNoteHead(head)
        self._populateHeadTable()
        self.noteHeadTable.setCurrentRow(len(self._currentDrum) - 1)
        self._checkHeadButtons()
        self.currentNoteHead.setFocus()

    def _removeNoteHead(self):
        row = self.noteHeadTable.currentRow()
        head = self._currentHead
        self._currentDrum.removeNoteHead(head)
        self._populateHeadTable()
        if row >= len(self._currentDrum):
            self.noteHeadTable.setCurrentRow(row - 1)
        else:
            self.noteHeadTable.setCurrentRow(row)
        self._checkHeadButtons()

    def _checkHeadButtons(self):
        isDefault = (self._currentHead == self._currentDrum.head)
        self.deleteHeadButton.setEnabled(not isDefault)
        if isDefault:
            self.headUpButton.setEnabled(False)
            self.headDownButton.setEnabled(False)
        else:
            index = self.noteHeadTable.currentRow()
            self.headUpButton.setEnabled(index > 1)
            self.headDownButton.setEnabled(index <
                                           len(self._currentDrum) - 1)

    def _moveNoteHeadUp(self):
        index = self.noteHeadTable.currentRow()
        self._currentDrum.moveHeadUp(self._currentHead)
        self._populateHeadTable()
        self.noteHeadTable.setCurrentRow(index - 1)

    def _moveNoteHeadDown(self):
        index = self.noteHeadTable.currentRow()
        self._currentDrum.moveHeadDown(self._currentHead)
        self._populateHeadTable()
        self.noteHeadTable.setCurrentRow(index + 1)

    def _setDefaultHead(self):
        self.noteHeadTable.blockSignals(True)
        self._currentDrum.setDefaultHead(self._currentHead)
        self._populateHeadTable()
        self.noteHeadTable.blockSignals(False)
        self.noteHeadTable.setCurrentRow(0)


    def _midiNoteChanged(self):
        midiNote = self.midiNoteCombo.currentIndex()
        midiNote = self.midiNoteCombo.itemData(midiNote).toInt()[0]
        self._currentHeadData.midiNote = midiNote
        if not self.muteButton.isChecked():
            DBMidi.playHeadData(self._currentHeadData)

    def _midiVolumeChanged(self):
        self._currentHeadData.midiVolume = self.volumeSlider.value()

    def _setEffect(self, effect):
        effectMap = {"normal":self.normalEffect,
                     "accent":self.accentEffect,
                     "ghost":self.ghostEffect,
                     "flam":self.flamEffect,
                     "choke":self.chokeEffect,
                     "drag":self.dragEffect}
        effect = effectMap[effect]
        effect.setChecked(True)

    def _effectChanged(self):
        for effect in self.effectsGroup.children():
            if not isinstance(effect, QRadioButton):
                continue
            if effect.isChecked():
                self._currentHeadData.effect = str(effect.text()).lower()
                if not self.muteButton.isChecked():
                    DBMidi.playHeadData(self._currentHeadData)
                break

    def _lockChanged(self):
        self._currentDrum.locked = self.lockedCheckBox.isChecked()

    def _populateMidiCombo(self):
        for midiNote, midiName in _MIDIDATA:
            self.midiNoteCombo.addItem(midiName, userData = QVariant(midiNote))

    def _checkNotationButtons(self):
        headData = self._currentHeadData
        line = headData.notationLine
        self.noteUpButton.setDisabled(line >= 9)
        self.noteDownButton.setDisabled(line <= -7)


    def _setNotation(self):
        headData = self._currentHeadData
        self.stemUpDownBox.setChecked(headData.stemDirection
                                      == DrumKit.STEM_UP)
        effectIndex = self.effectBox.findText(headData.notationEffect)
        self.effectBox.setCurrentIndex(effectIndex)
        headIndex = self.noteHeadBox.findText(headData.notationHead)
        self.noteHeadBox.setCurrentIndex(headIndex)
        self._notationScene.setHeadData(headData)
        self._checkNotationButtons()

    def _notationEffectChanged(self):
        self._currentHeadData.notationEffect = str(self.effectBox.currentText())
        self._notationScene.setHeadData(self._currentHeadData)

    def _notationHeadChanged(self):
        self._currentHeadData.notationHead = str(self.noteHeadBox.currentText())
        self._notationScene.setHeadData(self._currentHeadData)

    def _stemDirectionChanged(self):
        if self.stemUpDownBox.isChecked():
            self._currentHeadData.stemDirection = DrumKit.STEM_UP
        else:
            self._currentHeadData.stemDirection = DrumKit.STEM_DOWN
        self._notationScene.setHeadData(self._currentHeadData)

    def _moveNotationUp(self):
        self._currentHeadData.notationLine += 1
        self._notationScene.setHeadData(self._currentHeadData)
        self._checkNotationButtons()

    def _moveNotationDown(self):
        self._currentHeadData.notationLine -= 1
        self._notationScene.setHeadData(self._currentHeadData)
        self._checkNotationButtons()

    def accept(self):
        if all(old == -1 for old in self._oldLines.itervalues()):
            qtext = ("Discard all existing notes?",
                     "Warning! You have changed the kit, "
                     "but none of the old drums are being "
                     "converted to new drums. This will discard "
                     "all notes currently in the score. Are you "
                     "sure you want to proceed?")
            question = QMessageBox.question(self.parent(), qtext,
                                            buttons = (QMessageBox.Yes
                                                       | QMessageBox.No))
            if question == QMessageBox.No:
                return
        super(QEditKitDialog, self).accept()

    def getNewKit(self):
        newKit = DrumKit.DrumKit()
        oldLines = []
        for drum in reversed(self._currentKit):
            newKit.addDrum(drum)
            if self._oldLines[drum] == -1:
                oldLines.append(-1)
            else:
                oldLines.append(len(self._initialKit)
                                - self._oldLines[drum] - 1)
        return newKit, oldLines