From 5db9edf0f5dbc99a82a76a714a5fa921398267fe Mon Sep 17 00:00:00 2001 From: "Andrey M. Tokarev" Date: Fri, 19 Jul 2013 18:47:11 +0400 Subject: [PATCH 1/5] Fix tuplet filtering --- mscore/importmidi.cpp | 2 +- mscore/importmidi_tuplet.cpp | 29 ++- mscore/importmidi_tuplet.h | 2 +- mtest/importmidi/inner_func_decl.h | 6 + mtest/importmidi/tst_importmidi.cpp | 81 ++++++- ...ed_3_5.mid => tuplet_tied_3_5_tuplets.mid} | Bin ..._3_5.mscx => tuplet_tied_3_5_tuplets.mscx} | 0 mtest/importmidi/tuplet_tied_3_5_tuplets2.mid | Bin 0 -> 142 bytes .../importmidi/tuplet_tied_3_5_tuplets2.mscx | 220 ++++++++++++++++++ .../importmidi/tuplet_triplet_first_tied2.mid | Bin 0 -> 114 bytes .../tuplet_triplet_first_tied2.mscx | 162 +++++++++++++ 11 files changed, 491 insertions(+), 11 deletions(-) rename mtest/importmidi/{tuplet_tied_3_5.mid => tuplet_tied_3_5_tuplets.mid} (100%) rename mtest/importmidi/{tuplet_tied_3_5.mscx => tuplet_tied_3_5_tuplets.mscx} (100%) create mode 100644 mtest/importmidi/tuplet_tied_3_5_tuplets2.mid create mode 100644 mtest/importmidi/tuplet_tied_3_5_tuplets2.mscx create mode 100644 mtest/importmidi/tuplet_triplet_first_tied2.mid create mode 100644 mtest/importmidi/tuplet_triplet_first_tied2.mscx diff --git a/mscore/importmidi.cpp b/mscore/importmidi.cpp index b3c2d513e5034..ab5a04481ebd3 100644 --- a/mscore/importmidi.cpp +++ b/mscore/importmidi.cpp @@ -244,7 +244,7 @@ void sortNotesByLength(std::multimap &chords) // find notes of each chord that have different durations // and separate them into different chords -// so all chords will have notes with equal lengths +// so all notes inside every chord will have equal lengths void splitUnequalChords(QList &tracks) { diff --git a/mscore/importmidi_tuplet.cpp b/mscore/importmidi_tuplet.cpp index 8149edba739fb..29a5bc5ef27dc 100644 --- a/mscore/importmidi_tuplet.cpp +++ b/mscore/importmidi_tuplet.cpp @@ -151,7 +151,7 @@ Fraction maxNoteLen(const QList ¬es) std::vector findTupletsForDuration(int voice, - const Fraction &barTick, + const Fraction &barStartTick, const Fraction &durationOnTime, const Fraction &durationLen, const std::multimap &tuplets) @@ -168,7 +168,7 @@ findTupletsForDuration(int voice, // if tuplet and duration intersect each other auto tupletData = tupletIt->second; // convert tuplet onTime to local bar ticks - tupletData.onTime -= barTick; + tupletData.onTime -= barStartTick; tupletsData.push_back(tupletData); } if (tupletIt == tuplets.begin()) @@ -308,7 +308,7 @@ std::tuple validateTuplets(std::list &indexes, const std::vector &tuplets) { if (tuplets.empty()) - return std::make_tuple(0.0, 0, Fraction()); + return std::make_tuple(0.0, 0, Fraction(0)); // structure of map: std::map *, int> usedFirstTupletNotes; // chord IDs of already used chords @@ -373,7 +373,7 @@ minimizeQuantError(std::vector> &indexGroups, for (const auto &i: iIndexGroups) { const auto &group = indexGroups[i]; for (const auto &ii: group) - indexesToValidate.push_back(ii); + indexesToValidate.push_back(ii); } auto result = validateTuplets(indexesToValidate, tuplets); @@ -394,6 +394,8 @@ minimizeQuantError(std::vector> &indexGroups, bool haveCommonChords(int i, int j, const std::vector &tuplets) { + if (tuplets.empty()) + return false; std::set *> chordsI; for (const auto &chord: tuplets[i].chords) chordsI.insert(&*chord.second); @@ -411,13 +413,16 @@ std::list findTupletsWithCommonChords(std::list &restTuplets, return tupletGroup; QQueue q; + { auto it = restTuplets.begin(); tupletGroup.push_back(*it); q.enqueue(*it); - it = restTuplets.erase(it); + restTuplets.erase(it); + } while (!q.isEmpty() && !restTuplets.empty()) { int index = q.dequeue(); + auto it = restTuplets.begin(); while (it != restTuplets.end()) { if (haveCommonChords(index, *it, tuplets)) { tupletGroup.push_back(*it); @@ -832,6 +837,8 @@ void optimizeVoices(std::multimap::iterator startBarChordIt void addFirstTiedTupletNotes(std::multimap &chords, const std::vector &tuplets) { + // if more than one tuplet can have first tied note - choose + // the case with min quantization error std::map *, Fraction> tiedTupletErrors; for (const auto &tupletInfo: tuplets) { @@ -845,7 +852,8 @@ void addFirstTiedTupletNotes(std::multimap &chords, + tupletInfo.len / tupletInfo.tupletNumber * firstNoteIndex; Fraction chordOffTime = chord.first + maxLen; // if chord offTime is outside tuplet - discard chord - if (chordOffTime <= tupletInfo.onTime + if (chord.first + tupletInfo.tupletQuantValue >= tupletInfo.onTime + || chordOffTime <= tupletInfo.onTime || chordOffTime >= tupletFreeEnd + tupletInfo.tupletQuantValue) continue; @@ -857,7 +865,14 @@ void addFirstTiedTupletNotes(std::multimap &chords, bool found = (it != tiedTupletErrors.end()); if (tupletError < chordError && (!found || (found && tupletError < it->second))) { // include chord in first tuplet notes as tied chord - chord.second.voice = tupletInfo.chords.begin()->second->second.voice; + int chordVoice = chord.second.voice; + int tupletVoice = tupletInfo.chords.begin()->second->second.voice; + if (chordVoice != tupletVoice) { + for (auto &ch: chords) { + if (ch.second.voice == chordVoice) + ch.second.voice = tupletVoice; + } + } tiedTupletErrors.insert({&chord, tupletError}); } } diff --git a/mscore/importmidi_tuplet.h b/mscore/importmidi_tuplet.h index 7b845c0a755f3..42899e1985536 100644 --- a/mscore/importmidi_tuplet.h +++ b/mscore/importmidi_tuplet.h @@ -52,7 +52,7 @@ std::vector findTuplets(const Fraction &startBarTick, std::multimap &chords); std::vector findTupletsForDuration(int voice, - const Fraction &barTick, + const Fraction &barStartTick, const Fraction &durationOnTime, const Fraction &durationLen, const std::multimap &tuplets); diff --git a/mtest/importmidi/inner_func_decl.h b/mtest/importmidi/inner_func_decl.h index c7077efc0c059..4ce726aab1bcb 100644 --- a/mtest/importmidi/inner_func_decl.h +++ b/mtest/importmidi/inner_func_decl.h @@ -43,6 +43,12 @@ int separateTupletVoices(std::vector &tuplets, std::multimap &chords, const Fraction &endBarTick); +std::list findTupletsWithCommonChords(std::list &restTuplets, + const std::vector &tuplets); + +std::vector findTupletsWithNoCommonChords(std::list &commonTuplets, + const std::vector &tuplets); + } // namespace MidiTuplet namespace Meter { diff --git a/mtest/importmidi/tst_importmidi.cpp b/mtest/importmidi/tst_importmidi.cpp index aeaae13d44452..b5173aa1ed39a 100644 --- a/mtest/importmidi/tst_importmidi.cpp +++ b/mtest/importmidi/tst_importmidi.cpp @@ -66,6 +66,7 @@ class TestImportMidi : public QObject, public MTest void findOnTimeRegularError(); void findTupletApproximation(); void separateTupletVoices(); + void findTupletsWithCommonChords(); // metric bar analysis void metricDivisionsOfTuplet(); @@ -123,13 +124,22 @@ class TestImportMidi : public QObject, public MTest void tupletTripletsMixed() { mf("tuplet_triplets_mixed"); } void tupletTriplet() { mf("tuplet_triplet"); } void tupletTripletFirstTied() { mf("tuplet_triplet_first_tied"); } + void tupletTripletFirstTied2() { mf("tuplet_triplet_first_tied2"); } void tupletTripletLastTied() { mf("tuplet_triplet_last_tied"); } void tupletTied3_5() { // requires 1/32 quantization int defaultQuant = preferences.shortestNote; preferences.shortestNote = MScore::division / 8; // midi quantization: 1/32 - mf("tuplet_tied_3_5"); + mf("tuplet_tied_3_5_tuplets"); + preferences.shortestNote = defaultQuant; + } + void tupletTied3_5_2() + { + // requires 1/32 quantization + int defaultQuant = preferences.shortestNote; + preferences.shortestNote = MScore::division / 8; // midi quantization: 1/32 + mf("tuplet_tied_3_5_tuplets2"); preferences.shortestNote = defaultQuant; } @@ -605,6 +615,74 @@ void TestImportMidi::separateTupletVoices() } } +void TestImportMidi::findTupletsWithCommonChords() + { + std::vector tuplets; + + std::multimap chords; + chords.insert({Fraction(0), MidiChord()}); + chords.insert({Fraction(1, 12), MidiChord()}); + chords.insert({Fraction(1, 6), MidiChord()}); + chords.insert({Fraction(3, 10), MidiChord()}); + chords.insert({Fraction(7, 20), MidiChord()}); + chords.insert({Fraction(2, 5), MidiChord()}); + chords.insert({Fraction(9, 20), MidiChord()}); + + MidiTuplet::TupletInfo tupletData; + // triplet, total len = 1/8 + tupletData.chords.clear(); + tupletData.chords.insert({0, chords.find(Fraction(0))}); + tupletData.chords.insert({2, chords.find(Fraction(1, 12))}); + tuplets.push_back(tupletData); + // second triplet, total len = 1/8 + tupletData.chords.clear(); + tupletData.chords.insert({1, chords.find(Fraction(1, 6))}); + tuplets.push_back(tupletData); + // third triplet, total len = 1/4 + tupletData.chords.clear(); + tupletData.chords.insert({0, chords.find(Fraction(0))}); + tupletData.chords.insert({1, chords.find(Fraction(1, 12))}); + tupletData.chords.insert({2, chords.find(Fraction(1, 6))}); + tuplets.push_back(tupletData); + // quintuplet, total len = 1/4 + tupletData.chords.clear(); + tupletData.chords.insert({1, chords.find(Fraction(3, 10))}); + tupletData.chords.insert({2, chords.find(Fraction(7, 20))}); + tupletData.chords.insert({3, chords.find(Fraction(2, 5))}); + tupletData.chords.insert({4, chords.find(Fraction(9, 20))}); + tuplets.push_back(tupletData); + // second quintuplet, total len = 1/2 + tupletData.chords.clear(); + tupletData.chords.insert({0, chords.find(Fraction(0))}); + tupletData.chords.insert({1, chords.find(Fraction(1, 12))}); + tupletData.chords.insert({3, chords.find(Fraction(3, 10))}); + tupletData.chords.insert({4, chords.find(Fraction(2, 5))}); + tuplets.push_back(tupletData); + + QVERIFY(tuplets.size() == 5); + std::list restTupletIndexes = {0, 1, 2, 3, 4}; + + std::list commonTuplets = MidiTuplet::findTupletsWithCommonChords(restTupletIndexes, tuplets); + commonTuplets.sort(); + QVERIFY(restTupletIndexes.empty()); + QVERIFY(commonTuplets == std::list({0, 1, 2, 3, 4})); + + std::vector uncommonTuplets = MidiTuplet::findTupletsWithNoCommonChords(commonTuplets, tuplets); + std::sort(uncommonTuplets.begin(), uncommonTuplets.end()); + QVERIFY(uncommonTuplets == std::vector({0, 1, 3})); + QVERIFY(commonTuplets == std::list({2, 4})); + // process the rest tuplets with common chords + uncommonTuplets = MidiTuplet::findTupletsWithNoCommonChords(commonTuplets, tuplets); + std::sort(uncommonTuplets.begin(), uncommonTuplets.end()); + QVERIFY(uncommonTuplets == std::vector({2})); + QVERIFY(commonTuplets == std::list({4})); + // process the rest tuplets with common chords + uncommonTuplets = MidiTuplet::findTupletsWithNoCommonChords(commonTuplets, tuplets); + std::sort(uncommonTuplets.begin(), uncommonTuplets.end()); + QVERIFY(uncommonTuplets == std::vector({4})); + QVERIFY(commonTuplets.empty()); + } + //--------------------------------------------------------- // metric bar analysis @@ -701,7 +779,6 @@ void TestImportMidi::maxLevelBetween() startTickInBar = Fraction::fromTicks(0); endTickInBar = tupletData.onTime; level = Meter::findMaxLevelBetween(startTickInBar, endTickInBar, divInfo); - qDebug() << level.level; QVERIFY(level.level == -3); QCOMPARE(level.lastPos, (startTickInBar + tupletData.onTime) / 2); QCOMPARE(level.levelCount, 1); diff --git a/mtest/importmidi/tuplet_tied_3_5.mid b/mtest/importmidi/tuplet_tied_3_5_tuplets.mid similarity index 100% rename from mtest/importmidi/tuplet_tied_3_5.mid rename to mtest/importmidi/tuplet_tied_3_5_tuplets.mid diff --git a/mtest/importmidi/tuplet_tied_3_5.mscx b/mtest/importmidi/tuplet_tied_3_5_tuplets.mscx similarity index 100% rename from mtest/importmidi/tuplet_tied_3_5.mscx rename to mtest/importmidi/tuplet_tied_3_5_tuplets.mscx diff --git a/mtest/importmidi/tuplet_tied_3_5_tuplets2.mid b/mtest/importmidi/tuplet_tied_3_5_tuplets2.mid new file mode 100644 index 0000000000000000000000000000000000000000..441df08f0351dbe7a6a2c75892eaf0c62381fa32 GIT binary patch literal 142 zcmXYqu?fOJ6hPlU&qT!mEZx8r5{_^QB=7|bLF_IdXk{&lZjcq+AR{=Eon?$*_g?c} zwL1kMLNIc#cGvT07y26NmKXGKV3BZuBMf_M&1%N5oy5;I?`hM{q9svs i>m0^w<1x8D${cZ8IIP#wBdHcCHq$a2gB$)&`{OUG+aHPm literal 0 HcmV?d00001 diff --git a/mtest/importmidi/tuplet_tied_3_5_tuplets2.mscx b/mtest/importmidi/tuplet_tied_3_5_tuplets2.mscx new file mode 100644 index 0000000000000..1cbc40a9c6ab3 --- /dev/null +++ b/mtest/importmidi/tuplet_tied_3_5_tuplets2.mscx @@ -0,0 +1,220 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + + + + + + + + + 0 + + Grand Piano + + + +

Grand Piano

+
+ + + + +
+
+ + + + 0 + + + 4 + 4 + 1 + + + 2 + 3 + eighth + + + 1 + eighth + + + + 0 + 0 + 666 + + + 67 + 15 + 80 + user + + + + 1 + eighth + + + + 0 + 0 + 666 + + + 71 + 19 + 80 + user + + + + 1 + eighth + + + + + + 0 + 0 + 666 + + + 72 + 14 + 80 + user + + + + 4 + 5 + 16th + + + 2 + 16th + + + + 0 + 0 + 800 + + + 72 + 14 + 80 + user + + + + 2 + 16th + + + + 0 + 0 + 800 + + + 67 + 15 + 80 + user + + + + 2 + 16th + + + + 0 + 0 + 800 + + + 71 + 19 + 80 + user + + + + 2 + 16th + + + + 0 + 0 + 800 + + + 65 + 13 + 80 + user + + + + 2 + 16th + + + + 0 + 0 + 800 + + + 69 + 17 + 80 + user + + + + half + + + +
+
diff --git a/mtest/importmidi/tuplet_triplet_first_tied2.mid b/mtest/importmidi/tuplet_triplet_first_tied2.mid new file mode 100644 index 0000000000000000000000000000000000000000..37222b6c897aed66938defeeb9bfd2c2d2fae574 GIT binary patch literal 114 zcmeYb$w*;fU|?flWME`$@C_--2J&JUHl#8zq}DSWU|`t5p2EQ8z!1&A5X->uKZ1pY zNrHpne;_maLIs8otabIAjNch1cmyzRNMU41sb^&4VPJD;w4LC=z~maxWb4Yn + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + + + + + + + + + 0 + + Grand Piano + + + +

Grand Piano

+
+ + + + +
+
+ + + + 0 + + + 4 + 4 + 1 + + + eighth + + + + 0 + 0 + 1000 + + + 72 + 14 + 80 + user + + + + eighth + + + + + + 0 + 0 + 1000 + + + 69 + 17 + 80 + user + + + + 2 + 3 + eighth + + + 1 + eighth + + + + 0 + 0 + 666 + + + 69 + 17 + 80 + user + + + + 1 + eighth + + + + 0 + 0 + 666 + + + 74 + 16 + 80 + user + + + + 1 + eighth + + + + 0 + 0 + 666 + + + 71 + 19 + 80 + user + + + + half + + + +
+
From 0bc05b1877f185e62bd4d29f60f0b4e2f7ab94f8 Mon Sep 17 00:00:00 2001 From: "Andrey M. Tokarev" Date: Sun, 21 Jul 2013 18:33:31 +0400 Subject: [PATCH 2/5] Fix issue #21533 (MIDI file causes crash) --- libmscore/sig.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libmscore/sig.cpp b/libmscore/sig.cpp index 4b0e968e8e79a..5f9e21537f5e2 100644 --- a/libmscore/sig.cpp +++ b/libmscore/sig.cpp @@ -93,13 +93,13 @@ void TimeSigMap::normalize() int z = 4; int n = 4; int tick = 0; - int bar = 0; + Fraction bar; int tm = ticks_measure(Fraction(z, n)); for (auto i = begin(); i != end(); ++i) { SigEvent& e = i->second; - e.setBar(bar + (i->first - tick) / tm); - bar = e.bar(); + bar += Fraction(i->first - tick, tm).reduced(); + e.setBar(bar.numerator() / bar.denominator()); tick = i->first; tm = ticks_measure(e.timesig()); } From 9f0087d38c8f29e433c733ae3e6fbc5d9edc2da9 Mon Sep 17 00:00:00 2001 From: "Andrey M. Tokarev" Date: Mon, 22 Jul 2013 03:33:56 +0400 Subject: [PATCH 3/5] Individual MIDI panel settings for different MIDI files --- mscore/CMakeLists.txt | 3 +- mscore/file.cpp | 3 +- mscore/importmidi_data.cpp | 25 +++++++++++++++++ mscore/importmidi_data.h | 23 ++++++++++++++++ mscore/importmidi_panel.cpp | 52 +++++++++++++++++++++++------------ mscore/importmidi_panel.h | 12 ++++++-- mscore/importmidi_trmodel.cpp | 10 ++++++- mscore/importmidi_trmodel.h | 4 ++- mscore/musescore.cpp | 38 +++++++++++++++++++------ mscore/musescore.h | 5 ++-- 10 files changed, 141 insertions(+), 34 deletions(-) create mode 100644 mscore/importmidi_data.cpp create mode 100644 mscore/importmidi_data.h diff --git a/mscore/CMakeLists.txt b/mscore/CMakeLists.txt index b0859c1fc94fb..2443f406e3f8a 100644 --- a/mscore/CMakeLists.txt +++ b/mscore/CMakeLists.txt @@ -151,7 +151,7 @@ QT4_WRAP_CPP (mocs importmidi_panel.h importmidi_operations.h importmidi_opmodel.h importmidi_trmodel.h importmidi_opdelegate.h importmidi_meter.h importmidi_operation.h importmidi_quant.h importmidi_chord.h - importmidi_tuplet.h importmidi_inner.h + importmidi_tuplet.h importmidi_inner.h importmidi_data.h debugger/debugger.h ${OMR_MOCS} ${SCRIPT_MOCS} @@ -266,6 +266,7 @@ add_executable ( ${ExecutableName} importmidi_panel.cpp importmidi_operations.cpp miconengine.cpp importmidi_opmodel.cpp importmidi_trmodel.cpp importmidi_opdelegate.cpp importmidi_meter.cpp importmidi_quant.cpp importmidi_tuplet.cpp importmidi_chord.cpp + importmidi_data.cpp ${OMR_FILES} ${AUDIO} diff --git a/mscore/file.cpp b/mscore/file.cpp index 467fd348b9779..cb9a86e8a064d 100644 --- a/mscore/file.cpp +++ b/mscore/file.cpp @@ -323,7 +323,8 @@ Score* MuseScore::readScore(const QString& name) delete score; score = 0; } - showPanelIfMidiFile(name); + allowShowMidiPanel(name); + return score; } diff --git a/mscore/importmidi_data.cpp b/mscore/importmidi_data.cpp new file mode 100644 index 0000000000000..c7b02726cb596 --- /dev/null +++ b/mscore/importmidi_data.cpp @@ -0,0 +1,25 @@ +#include "importmidi_data.h" +#include "importmidi_operations.h" + + +namespace Ms { + +void MidiData::setFileData(const QString &fileName, const QList &fileData) + { + data[fileName] = fileData; + } + +void MidiData::excludeFile(const QString &fileName) + { + data.remove(fileName); + } + +QList MidiData::fileData(const QString &fileName) const + { + auto it = data.find(fileName); + if (it == data.end()) + return QList(); + return it.value(); + } + +} // namespace Ms diff --git a/mscore/importmidi_data.h b/mscore/importmidi_data.h new file mode 100644 index 0000000000000..39eb294a86654 --- /dev/null +++ b/mscore/importmidi_data.h @@ -0,0 +1,23 @@ +#ifndef IMPORTMIDI_DATA_H +#define IMPORTMIDI_DATA_H + + +namespace Ms { + +struct TrackData; + +class MidiData + { + public: + void setFileData(const QString &fileName, const QList &fileData); + void excludeFile(const QString &fileName); + QList fileData(const QString &fileName) const; + + private: + QMap> data; // + }; + +} // namespace Ms + + +#endif // IMPORTMIDI_DATA_H diff --git a/mscore/importmidi_panel.cpp b/mscore/importmidi_panel.cpp index 0072e16ab90d5..4e9d3e119c9de 100644 --- a/mscore/importmidi_panel.cpp +++ b/mscore/importmidi_panel.cpp @@ -7,6 +7,7 @@ #include "importmidi_trmodel.h" #include "importmidi_opmodel.h" #include "importmidi_opdelegate.h" +#include "importmidi_data.h" namespace Ms { @@ -22,6 +23,8 @@ ImportMidiPanel::ImportMidiPanel(QWidget *parent) , ui(new Ui::ImportMidiPanel) , updateUiTimer(new QTimer) , isMidiFileExists(false) + , importInProgress(false) + , prefferedVisible_(false) { ui->setupUi(this); tracksModel = new TracksModel(); @@ -79,7 +82,7 @@ class CustomHorizHeaderView : public QHeaderView void ImportMidiPanel::tweakUi() { connect(updateUiTimer, SIGNAL(timeout()), this, SLOT(updateUi())); - connect(ui->pushButtonImport, SIGNAL(clicked()), SLOT(importMidi())); + connect(ui->pushButtonImport, SIGNAL(clicked()), SLOT(doMidiImport())); connect(ui->pushButtonUp, SIGNAL(clicked()), SLOT(moveTrackUp())); connect(ui->pushButtonDown, SIGNAL(clicked()), SLOT(moveTrackDown())); connect(ui->toolButtonHideMidiPanel, SIGNAL(clicked()), SLOT(hidePanel())); @@ -115,7 +118,7 @@ void ImportMidiPanel::hidePanel() { if (isVisible()) { setVisible(false); - getAction("toggle-midiimportpanel")->setChecked(false); + prefferedVisible_ = false; } } @@ -174,21 +177,26 @@ void ImportMidiPanel::updateUi() ui->pushButtonDown->setEnabled(canMoveTrackDown(visualIndex)); } -void ImportMidiPanel::importMidi() +void ImportMidiPanel::doMidiImport() { if (!canImportMidi()) return; + importInProgress = true; preferences.midiImportOperations.clear(); int trackCount = tracksModel->trackCount(); + QList trackData; for (int i = 0; i != trackCount; ++i) { int visIndex = tracksModel->rowFromTrackIndex(i); int logIndex = ui->tableViewTracks->verticalHeader()->logicalIndex(visIndex); int trackIndex = tracksModel->trackIndexFromRow(logIndex); TrackData data(tracksModel->trackData(trackIndex)); preferences.midiImportOperations.appendTrackOperations(data.opers); + trackData.push_back(data); } mscore->openScore(midiFile); + midiData.setFileData(midiFile, trackData); preferences.midiImportOperations.clear(); + importInProgress = false; } bool ImportMidiPanel::isMidiFile(const QString &file) @@ -199,32 +207,40 @@ bool ImportMidiPanel::isMidiFile(const QString &file) void ImportMidiPanel::setMidiFile(const QString &file) { - if (midiFile == file) + if (midiFile == file || importInProgress) return; midiFile = file; ui->lineEditMidiFile->setText(QFileInfo(file).fileName()); updateUi(); if (isMidiFileExists) { - QList tracksMeta(extractMidiTracksMeta(file)); - tracksModel->reset(tracksMeta); - operationsModel->reset(tracksMeta.size()); + QList data = midiData.fileData(file); + if (data.isEmpty()) { + QList tracksMeta(extractMidiTracksMeta(file)); + tracksModel->reset(tracksMeta); + operationsModel->reset(tracksMeta.size()); + for (int i = 0; i != tracksModel->trackCount(); ++i) + data.push_back(tracksModel->trackData(i)); + midiData.setFileData(file, data); + } + else { + tracksModel->reset(data); + } ui->tableViewTracks->selectRow(0); } } +void ImportMidiPanel::excludeMidiFile(const QString &file) + { + // because button "Apply" of MIDI import operations + // causes reopen of the current score + // we need prevent MIDI import panel from closing at that moment + if (!importInProgress) + midiData.excludeFile(file); + } -//--------- MuseScore --------- - -void MuseScore::showMidiImportPanel(bool visible) +void ImportMidiPanel::setPrefferedVisible(bool visible) { - if (visible) { - if (!importmidi_panel) { - importmidi_panel = new ImportMidiPanel(this); - } - } - if (importmidi_panel) - importmidi_panel->setVisible(visible); - getAction("toggle-midiimportpanel")->setChecked(visible); + prefferedVisible_ = visible; } } // namespace Ms diff --git a/mscore/importmidi_panel.h b/mscore/importmidi_panel.h index 72a894bfad3f3..d37ffea6e9516 100644 --- a/mscore/importmidi_panel.h +++ b/mscore/importmidi_panel.h @@ -1,6 +1,8 @@ #ifndef IMPORTMIDI_PANEL_H #define IMPORTMIDI_PANEL_H +#include "importmidi_data.h" + namespace Ui { class ImportMidiPanel; @@ -24,12 +26,15 @@ class ImportMidiPanel : public QWidget ~ImportMidiPanel(); static bool isMidiFile(const QString &file); void setMidiFile(const QString &file); + void excludeMidiFile(const QString &file); + bool prefferedVisible() const { return prefferedVisible_; } + void setPrefferedVisible(bool visible); -private slots: + private slots: void updateUi(); void onCurrentTrackChanged(const QModelIndex ¤tIndex); void onOperationChanged(const QModelIndex &index); - void importMidi(); + void doMidiImport(); void hidePanel(); void moveTrackUp(); void moveTrackDown(); @@ -48,6 +53,9 @@ private slots: TracksModel *tracksModel; OperationsModel *operationsModel; OperationsDelegate *operationsDelegate; + MidiData midiData; + bool importInProgress; + bool prefferedVisible_; }; } // namespace Ms diff --git a/mscore/importmidi_trmodel.cpp b/mscore/importmidi_trmodel.cpp index 50d560413b2fd..01fea2368dd83 100644 --- a/mscore/importmidi_trmodel.cpp +++ b/mscore/importmidi_trmodel.cpp @@ -28,6 +28,14 @@ void TracksModel::reset(const QList &tracksMeta) endResetModel(); } +void TracksModel::reset(const QList &tracksData) + { + beginResetModel(); + trackCount_ = tracksData.size(); + tracksData_ = tracksData; + endResetModel(); + } + void TracksModel::setOperation(int row, MidiOperation::Type operType, const QVariant &operValue) { int trackIndex = trackIndexFromRow(row); @@ -312,7 +320,7 @@ QVariant TracksModel::data(const QModelIndex &index, int role) const case TrackCol::TRACK_NUMBER: if (trackIndex == -1) return "All"; - return trackIndex + 1; + return tracksData_[trackIndex].opers.trackIndex + 1; case TrackCol::TRACK_NAME: if (trackIndex == -1) return ""; diff --git a/mscore/importmidi_trmodel.h b/mscore/importmidi_trmodel.h index b3122747b5d39..9afccaa19fe77 100644 --- a/mscore/importmidi_trmodel.h +++ b/mscore/importmidi_trmodel.h @@ -27,7 +27,9 @@ class TracksModel : public QAbstractTableModel TracksModel(); void reset(const QList &tracksMeta); + void reset(const QList &tracksData); void setOperation(int row, MidiOperation::Type operType, const QVariant &operValue); + TrackData trackData(int trackIndex) const; DefinedTrackOperations trackOperations(int row) const; int trackCount() const { return trackCount_; } @@ -43,7 +45,7 @@ class TracksModel : public QAbstractTableModel bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); private: - std::vector tracksData_; + QList tracksData_; int trackCount_; int colCount_; diff --git a/mscore/musescore.cpp b/mscore/musescore.cpp index 78939f64b3b61..b9a1d7dd686ba 100644 --- a/mscore/musescore.cpp +++ b/mscore/musescore.cpp @@ -531,11 +531,11 @@ MuseScore::MuseScore() QLayout* envlayout = new QVBoxLayout; envlayout->setMargin(0); envlayout->setSpacing(0); -// envelope->setLayout(envlayout); envelope->addWidget(mainWindow); importmidi_panel = new ImportMidiPanel(this); - showMidiImportPanel(false); + importmidi_panel->setVisible(false); + envelope->addWidget(importmidi_panel); { @@ -1446,6 +1446,11 @@ void MuseScore::setCurrentScoreView(ScoreView* view) } else cs = 0; + + // set midi import panel + QString fileName = cs ? cs->fileInfo()->filePath() : ""; + midiPanelOnSwitchToFile(fileName); + updateLayer(); updatePlayMode(); if (seq) @@ -1530,16 +1535,31 @@ void MuseScore::showMessage(const QString& s, int timeout) } //--------------------------------------------------------- -// setIfMidiFile +// midiPanel //--------------------------------------------------------- -void MuseScore::showPanelIfMidiFile(const QString &file) +void MuseScore::midiPanelOnSwitchToFile(const QString &file) { - if (ImportMidiPanel::isMidiFile(file)) { + bool isMidiFile = ImportMidiPanel::isMidiFile(file); + if (isMidiFile) { importmidi_panel->setMidiFile(file); - if (!importmidi_panel->isVisible()) - showMidiImportPanel(true); + if (importmidi_panel->prefferedVisible()) + importmidi_panel->setVisible(true); } + else + importmidi_panel->setVisible(false); + } + +void MuseScore::midiPanelOnCloseFile(const QString &file) + { + if (ImportMidiPanel::isMidiFile(file)) + importmidi_panel->excludeMidiFile(file); + } + +void MuseScore::allowShowMidiPanel(const QString &file) + { + if (ImportMidiPanel::isMidiFile(file)) + importmidi_panel->setPrefferedVisible(true); } //--------------------------------------------------------- @@ -1895,7 +1915,9 @@ void MuseScore::removeTab(int i) int idx1 = tab1->currentIndex(); bool firstTab = tab1->view(idx1) == cv; + midiPanelOnCloseFile(score->fileInfo()->filePath()); scoreList.removeAt(i); + tab1->blockSignals(true); tab1->removeTab(i); tab1->blockSignals(false); @@ -3979,7 +4001,7 @@ void MuseScore::cmd(QAction* a, const QString& cmd) else if (cmd == "toggle-navigator") showNavigator(a->isChecked()); else if (cmd == "toggle-midiimportpanel") - showMidiImportPanel(a->isChecked()); + importmidi_panel->setVisible(a->isChecked()); else if (cmd == "toggle-mixer") showMixer(a->isChecked()); else if (cmd == "synth-control") diff --git a/mscore/musescore.h b/mscore/musescore.h index fe8f47d0a71d0..2e270496f5c6b 100644 --- a/mscore/musescore.h +++ b/mscore/musescore.h @@ -375,7 +375,6 @@ class MuseScore : public QMainWindow, public MuseScoreCore { void showOmrPanel(bool); void showPlayPanel(bool); void showNavigator(bool); - void showMidiImportPanel(bool); void showMixer(bool); void showSynthControl(bool); void showSearchDialog(); @@ -608,7 +607,9 @@ class MuseScore : public QMainWindow, public MuseScoreCore { bool panDuringPlayback() const { return panAction->isChecked(); } void noteTooShortForTupletDialog(); void loadFiles(); - void showPanelIfMidiFile(const QString &file); + void midiPanelOnSwitchToFile(const QString &file); + void midiPanelOnCloseFile(const QString &file); + void allowShowMidiPanel(const QString &file); static Palette* newTextPalette(); static Palette* newTimePalette(); From 5e17160e17d5fccbceb462a2a7c7a5fde902ba71 Mon Sep 17 00:00:00 2001 From: "Andrey M. Tokarev" Date: Mon, 22 Jul 2013 16:03:23 +0400 Subject: [PATCH 4/5] Fix MIDI track reordering --- mscore/importmidi.cpp | 144 ++++++++++++++++--------------- mscore/importmidi_data.cpp | 49 ++++++++++- mscore/importmidi_data.h | 14 ++- mscore/importmidi_operations.cpp | 15 ---- mscore/importmidi_operations.h | 4 +- mscore/importmidi_panel.cpp | 26 ++++-- mscore/importmidi_trmodel.cpp | 13 ++- mscore/importmidi_trmodel.h | 1 + 8 files changed, 159 insertions(+), 107 deletions(-) diff --git a/mscore/importmidi.cpp b/mscore/importmidi.cpp index ab5a04481ebd3..c3daffce92c53 100644 --- a/mscore/importmidi.cpp +++ b/mscore/importmidi.cpp @@ -61,6 +61,7 @@ class MTrack { MidiTrack* mtrack = 0; QString name; bool hasKey = false; + int indexOfOperation = 0; std::multimap chords; std::multimap tuplets; // @@ -82,10 +83,10 @@ class MTrack { // remove overlapping notes with the same pitch -void removeOverlappingNotes(QList &tracks) +void removeOverlappingNotes(std::multimap &tracks) { for (auto &track: tracks) { - auto &chords = track.chords; + auto &chords = track.second.chords; for (auto it = chords.begin(); it != chords.end(); ++it) { auto &firstChord = it->second; const auto &firstOnTime = it->first; @@ -142,14 +143,14 @@ void removeOverlappingNotes(QList &tracks) // in the object's inlet in the "fudge" time zone // threshExtTime = 20 ms -void collectChords(QList &tracks, const Fraction &minNoteDuration) +void collectChords(std::multimap &tracks, const Fraction &minNoteDuration) { for (auto &track: tracks) { - auto &chords = track.chords; + auto &chords = track.second.chords; if (chords.empty()) continue; - Drumset* drumset = track.mtrack->drumTrack() ? smDrumset : 0; + Drumset* drumset = track.second.mtrack->drumTrack() ? smDrumset : 0; Fraction threshTime = minNoteDuration / 2; Fraction fudgeTime = threshTime / 4; @@ -280,20 +281,22 @@ void splitUnequalChords(QList &tracks) } -void quantizeAllTracks(QList& tracks, TimeSigMap* sigmap, const Fraction &lastTick) +void quantizeAllTracks(std::multimap &tracks, + TimeSigMap *sigmap, + const Fraction &lastTick) { auto &opers = preferences.midiImportOperations; - if (tracks.size() == 1 && opers.trackOperations(0).quantize.humanPerformance) { + if (opers.count() == 1 && opers.trackOperations(0).quantize.humanPerformance) { opers.setCurrentTrack(0); - Quantize::applyAdaptiveQuant(tracks[0].chords, sigmap, lastTick); - Quantize::applyGridQuant(tracks[0].chords, sigmap, lastTick); + Quantize::applyAdaptiveQuant(tracks.begin()->second.chords, sigmap, lastTick); + Quantize::applyGridQuant(tracks.begin()->second.chords, sigmap, lastTick); } else { - for (int i = 0; i < tracks.size(); ++i) { + for (auto &track: tracks) { // pass current track index through MidiImportOperations // for further usage - opers.setCurrentTrack(i); - Quantize::quantizeChordsAndTuplets(tracks[i].tuplets, tracks[i].chords, + opers.setCurrentTrack(track.second.indexOfOperation); + Quantize::quantizeChordsAndTuplets(track.second.tuplets, track.second.chords, sigmap, lastTick); } } @@ -675,9 +678,8 @@ void MTrack::convertTrack(const Fraction &lastTick) Score* score = staff->score(); int key = 0; // TODO-LIB findKey(mtrack, score->sigmap()); int track = staff->idx() * VOICES; - int voices = VOICES; - for (int voice = 0; voice < voices; ++voice) { + for (int voice = 0; voice < VOICES; ++voice) { // startChordTick is onTime value of all simultaneous notes // chords here are consist of notes with equal durations // several chords may have the same onTime value @@ -797,31 +799,29 @@ Fraction metaTimeSignature(const MidiEvent& e) return Fraction(z, n); } -void insertNewLeftHandTrack(QList &tracks, - int &trackIndex, +void insertNewLeftHandTrack(std::multimap &tracks, + std::multimap::iterator &it, const std::multimap &leftHandChords) { - auto leftHandTrack = tracks[trackIndex]; + auto leftHandTrack = it->second; leftHandTrack.chords = leftHandChords; - tracks.insert(trackIndex + 1, leftHandTrack); - // synchronize operations length and tracks list length - preferences.midiImportOperations.duplicateTrackOperations(trackIndex); - ++trackIndex; + it = tracks.insert({it->first, leftHandTrack}); } void addNewLeftHandChord(std::multimap &leftHandChords, const QList &leftHandNotes, - const std::multimap::iterator &i) + const std::multimap::iterator &it) { - MidiChord leftHandChord = i->second; + MidiChord leftHandChord = it->second; leftHandChord.notes = leftHandNotes; - leftHandChords.insert({i->first, leftHandChord}); + leftHandChords.insert({it->first, leftHandChord}); } -void splitIntoLRHands_FixedPitch(QList &tracks, int &trackIndex) +void splitIntoLRHands_FixedPitch(std::multimap &tracks, + std::multimap::iterator &it) { - auto &srcTrack = tracks[trackIndex]; - auto trackOpers = preferences.midiImportOperations.trackOperations(trackIndex); + auto &srcTrack = it->second; + auto trackOpers = preferences.midiImportOperations.trackOperations(srcTrack.indexOfOperation); int splitPitch = 12 * (int)trackOpers.LHRH.splitPitchOctave + (int)trackOpers.LHRH.splitPitchNote; std::multimap leftHandChords; @@ -842,12 +842,13 @@ void splitIntoLRHands_FixedPitch(QList &tracks, int &trackIndex) addNewLeftHandChord(leftHandChords, leftHandNotes, i); } if (!leftHandChords.empty()) - insertNewLeftHandTrack(tracks, trackIndex, leftHandChords); + insertNewLeftHandTrack(tracks, it, leftHandChords); } -void splitIntoLRHands_HandWidth(QList &tracks, int &trackIndex) +void splitIntoLRHands_HandWidth(std::multimap &tracks, + std::multimap::iterator &it) { - auto &srcTrack = tracks[trackIndex]; + auto &srcTrack = it->second; sortNotesByPitch(srcTrack.chords); const int OCTAVE = 12; std::multimap leftHandChords; @@ -859,8 +860,8 @@ void splitIntoLRHands_HandWidth(QList &tracks, int &trackIndex) int maxPitch = notes.back().pitch; if (maxPitch - minPitch > OCTAVE) { // need both hands - // assign all chords in range [minPitch .. minPitch + OCTAVE] to left hand - // and assign all other chords to right hand + // assign all chords in range [minPitch .. minPitch + OCTAVE] + // to left hand and all other chords - to right hand for (auto j = notes.begin(); j != notes.end(); ) { auto ¬e = *j; if (note.pitch <= minPitch + OCTAVE) { @@ -869,8 +870,8 @@ void splitIntoLRHands_HandWidth(QList &tracks, int &trackIndex) continue; } ++j; - // maybe todo later: if range of right-hand chords > OCTAVE => assign all bottom right-hand - // chords to another, third track + // maybe todo later: if range of right-hand chords > OCTAVE + // => assign all bottom right-hand chords to another, third track } } else { // check - use two hands or one hand will be enough (right or left?) @@ -884,41 +885,42 @@ void splitIntoLRHands_HandWidth(QList &tracks, int &trackIndex) addNewLeftHandChord(leftHandChords, leftHandNotes, i); } if (!leftHandChords.empty()) - insertNewLeftHandTrack(tracks, trackIndex, leftHandChords); + insertNewLeftHandTrack(tracks, it, leftHandChords); } -void splitIntoLeftRightHands(QList &tracks) +void splitIntoLeftRightHands(std::multimap &tracks) { - for (int i = 0; i < tracks.size(); ++i) { - auto operations = preferences.midiImportOperations.trackOperations(i); + for (auto it = tracks.begin(); it != tracks.end(); ++it) { + auto operations = preferences.midiImportOperations.trackOperations( + it->second.indexOfOperation); if (!operations.LHRH.doIt) continue; + // iterator 'it' will change after track split to ++it + // C++11 guarantees that newely inserted item with equal key will go after: + // "The relative ordering of elements with equivalent keys is preserved, + // and newly inserted elements follow those with equivalent keys + // already in the container" switch (operations.LHRH.method) { case MidiOperation::LHRHMethod::HAND_WIDTH: - splitIntoLRHands_HandWidth(tracks, i); + splitIntoLRHands_HandWidth(tracks, it); break; case MidiOperation::LHRHMethod::SPECIFIED_PITCH: - splitIntoLRHands_FixedPitch(tracks, i); + splitIntoLRHands_FixedPitch(tracks, it); break; } } } -void reorderTracks(QList &tracks) +QList prepareTrackList(const std::multimap &tracks) { - const auto &operations = preferences.midiImportOperations; - if (operations.count() == 0) - return; - QList newTracks; - for (int i = 0; i != tracks.size(); ++i) { - auto op = operations.trackOperations(i); - newTracks.push_back(tracks[op.trackIndex]); - } - std::swap(tracks, newTracks); + QList trackList; + for (const auto &track: tracks) + trackList.push_back(track.second); + return trackList; } void createMTrackList(Fraction &lastTick, TimeSigMap *sigmap, - QList &tracks, MidiFile *mf) + std::multimap &tracks, MidiFile *mf) { sigmap->clear(); sigmap->add(0, Fraction(4, 4)); // default time signature @@ -972,10 +974,9 @@ void createMTrackList(Fraction &lastTick, TimeSigMap *sigmap, = preferences.midiImportOperations.trackOperations(++trackIndex); if (trackOperations.doImport) { track.medPitch /= events; - tracks.push_back(track); + track.indexOfOperation = trackIndex; + tracks.insert({trackOperations.reorderedIndex, track}); } - else - preferences.midiImportOperations.eraseTrackOperations(trackIndex--); } } } @@ -1155,45 +1156,46 @@ void createNotes(const Fraction &lastTick, QList &tracks, MidiFile *mf) } } -QList getTracksMeta(QList &tracks, MidiFile *mf) +QList getTracksMeta(const std::multimap &tracks, + const MidiFile *mf) { QList tracksMeta; - for (int i = 0; i < tracks.size(); ++i) { - MTrack &mt = tracks[i]; - MidiTrack *track = mt.mtrack; - - for (auto ie : track->events()) { - const MidiEvent& e = ie.second; + for (const auto &track: tracks) { + const MTrack &mt = track.second; + const MidiTrack *midiTrack = mt.mtrack; + QString trackName; + for (const auto &ie: midiTrack->events()) { + const MidiEvent &e = ie.second; if ((e.type() == ME_META) && (e.metaType() == META_TRACK_NAME)) - mt.name = (const char*)e.edata(); + trackName = (const char*)e.edata(); } MidiType midiType = mf->midiType(); if (midiType == MT_UNKNOWN) midiType = MT_GM; - QString name = instrumentName(midiType, mt.program); - tracksMeta.push_back({mt.name, name}); + QString instrName = instrumentName(midiType, mt.program); + tracksMeta.push_back({trackName, instrName}); } return tracksMeta; } void convertMidi(Score *score, MidiFile *mf) { - QList tracks; + std::multimap tracks; // Fraction lastTick; auto sigmap = score->sigmap(); mf->separateChannel(); createMTrackList(lastTick, sigmap, tracks, mf); - reorderTracks(tracks); collectChords(tracks, Fraction::fromTicks(MScore::division) / 32); // tol = 1/128 note quantizeAllTracks(tracks, sigmap, lastTick); removeOverlappingNotes(tracks); splitIntoLeftRightHands(tracks); - splitUnequalChords(tracks); - - createInstruments(score, tracks); + // no more track insertion/reordering/deletion from now + QList trackList = prepareTrackList(tracks); + splitUnequalChords(trackList); + createInstruments(score, trackList); createMeasures(lastTick, score); - createNotes(lastTick, tracks, mf); + createNotes(lastTick, trackList, mf); createTimeSignatures(score); score->connectTies(); } @@ -1216,7 +1218,7 @@ QList extractMidiTracksMeta(const QString &fileName) fp.close(); Score mockScore; - QList tracks; + std::multimap tracks; Fraction lastTick; mf.separateChannel(); diff --git a/mscore/importmidi_data.cpp b/mscore/importmidi_data.cpp index c7b02726cb596..349c468d9ddd0 100644 --- a/mscore/importmidi_data.cpp +++ b/mscore/importmidi_data.cpp @@ -4,9 +4,29 @@ namespace Ms { -void MidiData::setFileData(const QString &fileName, const QList &fileData) +MidiData::MidiData() { - data[fileName] = fileData; + } + +MidiData::~MidiData() + { + } + +struct MidiData::MidiDataStore + { + QByteArray tableViewData; + QList tracksData; + int selectedRow = 0; + }; + +void MidiData::setTracksData(const QString &fileName, const QList &tracksData) + { + data[fileName].tracksData = tracksData; + } + +void MidiData::setTableViewData(const QString &fileName, const QByteArray &tableViewData) + { + data[fileName].tableViewData = tableViewData; } void MidiData::excludeFile(const QString &fileName) @@ -14,12 +34,33 @@ void MidiData::excludeFile(const QString &fileName) data.remove(fileName); } -QList MidiData::fileData(const QString &fileName) const +QList MidiData::tracksData(const QString &fileName) const { auto it = data.find(fileName); if (it == data.end()) return QList(); - return it.value(); + return it.value().tracksData; + } + +QByteArray MidiData::tableViewData(const QString &fileName) const + { + auto it = data.find(fileName); + if (it == data.end()) + return QByteArray(); + return it.value().tableViewData; + } + +int MidiData::selectedRow(const QString &fileName) const + { + auto it = data.find(fileName); + if (it == data.end()) + return 0; + return it.value().selectedRow; + } + +void MidiData::setSelectedRow(const QString &fileName, int row) + { + data[fileName].selectedRow = row; } } // namespace Ms diff --git a/mscore/importmidi_data.h b/mscore/importmidi_data.h index 39eb294a86654..032c72fecec41 100644 --- a/mscore/importmidi_data.h +++ b/mscore/importmidi_data.h @@ -9,12 +9,20 @@ struct TrackData; class MidiData { public: - void setFileData(const QString &fileName, const QList &fileData); + MidiData(); + ~MidiData(); + + void setTracksData(const QString &fileName, const QList &tracksData); + void setTableViewData(const QString &fileName, const QByteArray &tableViewData); void excludeFile(const QString &fileName); - QList fileData(const QString &fileName) const; + QList tracksData(const QString &fileName) const; + QByteArray tableViewData(const QString &fileName) const; + int selectedRow(const QString &fileName) const; + void setSelectedRow(const QString &fileName, int row); private: - QMap> data; // + struct MidiDataStore; + QMap data; // }; } // namespace Ms diff --git a/mscore/importmidi_operations.cpp b/mscore/importmidi_operations.cpp index 74438dc00bb0d..4d176446cae4b 100644 --- a/mscore/importmidi_operations.cpp +++ b/mscore/importmidi_operations.cpp @@ -15,21 +15,6 @@ void MidiImportOperations::appendTrackOperations(const TrackOperations &operatio currentTrack_ = 0; } -void MidiImportOperations::duplicateTrackOperations(int trackIndex) - { - if (!isValidIndex(trackIndex)) - return; - operations_.insert(trackIndex + 1, operations_[trackIndex]); - ++currentTrack_; - } - -void MidiImportOperations::eraseTrackOperations(int trackIndex) - { - if (!isValidIndex(trackIndex)) - return; - operations_.removeAt(trackIndex); - } - void MidiImportOperations::clear() { operations_.clear(); diff --git a/mscore/importmidi_operations.h b/mscore/importmidi_operations.h index 169a94e021770..99972770c2b4c 100644 --- a/mscore/importmidi_operations.h +++ b/mscore/importmidi_operations.h @@ -43,7 +43,7 @@ struct LHRHSeparation // bool and enum-like elementary operations (itself and inside structs) allowed struct TrackOperations { - int trackIndex = 0; + int reorderedIndex = 0; bool doImport = true; Quantization quantize; bool useDots = true; @@ -74,8 +74,6 @@ class MidiImportOperations { public: void appendTrackOperations(const TrackOperations& operations); - void duplicateTrackOperations(int trackIndex); - void eraseTrackOperations(int trackIndex); void clear(); void setCurrentTrack(int trackIndex); int currentTrack() const { return currentTrack_; } diff --git a/mscore/importmidi_panel.cpp b/mscore/importmidi_panel.cpp index 4e9d3e119c9de..f21165c71a1e4 100644 --- a/mscore/importmidi_panel.cpp +++ b/mscore/importmidi_panel.cpp @@ -49,6 +49,7 @@ void ImportMidiPanel::onCurrentTrackChanged(const QModelIndex ¤tIndex) tracksModel->index(row, TrackCol::TRACK_NUMBER)).toString(); operationsModel->setTrackData(trackLabel, tracksModel->trackOperations(row)); ui->treeViewOperations->expandAll(); + midiData.setSelectedRow(midiFile, row); } } @@ -185,16 +186,20 @@ void ImportMidiPanel::doMidiImport() preferences.midiImportOperations.clear(); int trackCount = tracksModel->trackCount(); QList trackData; + for (int i = 0; i != trackCount; ++i) { - int visIndex = tracksModel->rowFromTrackIndex(i); - int logIndex = ui->tableViewTracks->verticalHeader()->logicalIndex(visIndex); - int trackIndex = tracksModel->trackIndexFromRow(logIndex); - TrackData data(tracksModel->trackData(trackIndex)); + int trackRow = tracksModel->rowFromTrackIndex(i); + int reorderedRow = ui->tableViewTracks->verticalHeader()->logicalIndex(trackRow); + int reorderedIndex = tracksModel->trackIndexFromRow(reorderedRow); + tracksModel->setTrackReorderedIndex(i, reorderedIndex); + auto data = tracksModel->trackData(i); preferences.midiImportOperations.appendTrackOperations(data.opers); trackData.push_back(data); } mscore->openScore(midiFile); - midiData.setFileData(midiFile, trackData); + midiData.setTracksData(midiFile, trackData); + QByteArray tableViewData = ui->tableViewTracks->verticalHeader()->saveState(); + midiData.setTableViewData(midiFile, tableViewData); preferences.midiImportOperations.clear(); importInProgress = false; } @@ -212,20 +217,25 @@ void ImportMidiPanel::setMidiFile(const QString &file) midiFile = file; ui->lineEditMidiFile->setText(QFileInfo(file).fileName()); updateUi(); + if (isMidiFileExists) { - QList data = midiData.fileData(file); + QList data = midiData.tracksData(file); if (data.isEmpty()) { QList tracksMeta(extractMidiTracksMeta(file)); tracksModel->reset(tracksMeta); operationsModel->reset(tracksMeta.size()); for (int i = 0; i != tracksModel->trackCount(); ++i) data.push_back(tracksModel->trackData(i)); - midiData.setFileData(file, data); + midiData.setTracksData(file, data); + QByteArray tableViewData = ui->tableViewTracks->verticalHeader()->saveState(); + midiData.setTableViewData(file, tableViewData); } else { tracksModel->reset(data); + QByteArray tableViewData = midiData.tableViewData(file); + ui->tableViewTracks->verticalHeader()->restoreState(tableViewData); } - ui->tableViewTracks->selectRow(0); + ui->tableViewTracks->selectRow(midiData.selectedRow(midiFile)); } } diff --git a/mscore/importmidi_trmodel.cpp b/mscore/importmidi_trmodel.cpp index 01fea2368dd83..613e3d81c7e4e 100644 --- a/mscore/importmidi_trmodel.cpp +++ b/mscore/importmidi_trmodel.cpp @@ -22,7 +22,7 @@ void TracksModel::reset(const QList &tracksMeta) QString instrumentName = meta.instrumentName.isEmpty() ? "-" : meta.instrumentName; TrackOperations ops; // initialized by default values - see ctor - ops.trackIndex = i++; + ops.reorderedIndex = i++; tracksData_.push_back({{trackName, instrumentName}, ops}); } endResetModel(); @@ -45,6 +45,13 @@ void TracksModel::setOperation(int row, MidiOperation::Type operType, const QVar setTrackOperation(trackIndex, operType, operValue); } +void TracksModel::setTrackReorderedIndex(int trackIndex, int reorderIndex) + { + if (!isTrackIndexValid(trackIndex)) + return; + tracksData_[trackIndex].opers.reorderedIndex = reorderIndex; + } + void TracksModel::setOperationForAllTracks(MidiOperation::Type operType, const QVariant &operValue) { @@ -55,7 +62,7 @@ void TracksModel::setOperationForAllTracks(MidiOperation::Type operType, void TracksModel::setTrackOperation(int trackIndex, MidiOperation::Type operType, const QVariant &operValue) { - if (!operValue.isValid()) + if (!operValue.isValid() || !isTrackIndexValid(trackIndex)) return; TrackData &trackData = tracksData_[trackIndex]; @@ -320,7 +327,7 @@ QVariant TracksModel::data(const QModelIndex &index, int role) const case TrackCol::TRACK_NUMBER: if (trackIndex == -1) return "All"; - return tracksData_[trackIndex].opers.trackIndex + 1; + return trackIndex + 1; case TrackCol::TRACK_NAME: if (trackIndex == -1) return ""; diff --git a/mscore/importmidi_trmodel.h b/mscore/importmidi_trmodel.h index 9afccaa19fe77..b999435551d9a 100644 --- a/mscore/importmidi_trmodel.h +++ b/mscore/importmidi_trmodel.h @@ -29,6 +29,7 @@ class TracksModel : public QAbstractTableModel void reset(const QList &tracksMeta); void reset(const QList &tracksData); void setOperation(int row, MidiOperation::Type operType, const QVariant &operValue); + void setTrackReorderedIndex(int trackIndex, int reorderIndex); TrackData trackData(int trackIndex) const; DefinedTrackOperations trackOperations(int row) const; From fa7c622a871e821d0d08cc7a0ef23d0dd20e0c95 Mon Sep 17 00:00:00 2001 From: "Andrey M. Tokarev" Date: Mon, 22 Jul 2013 21:50:42 +0400 Subject: [PATCH 5/5] Center align of track numbers in MIDI panel --- mscore/importmidi_trmodel.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/mscore/importmidi_trmodel.cpp b/mscore/importmidi_trmodel.cpp index 613e3d81c7e4e..d0d20f958ebee 100644 --- a/mscore/importmidi_trmodel.cpp +++ b/mscore/importmidi_trmodel.cpp @@ -352,15 +352,7 @@ QVariant TracksModel::data(const QModelIndex &index, int role) const } break; case Qt::TextAlignmentRole: - if (trackIndex == -1) - break; - switch (index.column()) { - case TrackCol::TRACK_NAME: - case TrackCol::INSTRUMENT: - return Qt::AlignCenter; - default: - break; - } + return Qt::AlignCenter; break; default: break;