|
35 | 35 | #include <dspxmodel/Track.h> |
36 | 36 | #include <dspxmodel/TrackList.h> |
37 | 37 | #include <dspxmodel/BusControl.h> |
| 38 | +#include <dspxmodel/NoteSelectionModel.h> |
| 39 | +#include <dspxmodel/Note.h> |
| 40 | +#include <dspxmodel/NoteSequence.h> |
38 | 41 |
|
39 | 42 | #include <coreplugin/DspxDocument.h> |
40 | 43 | #include <coreplugin/ProjectTimeline.h> |
@@ -222,7 +225,7 @@ namespace Core { |
222 | 225 | return; |
223 | 226 |
|
224 | 227 | auto selectionModel = document()->selectionModel(); |
225 | | - auto trackSelectionModel = selectionModel ? selectionModel->trackSelectionModel() : nullptr; |
| 228 | + auto trackSelectionModel = selectionModel->trackSelectionModel(); |
226 | 229 | auto currentTrack = trackSelectionModel ? trackSelectionModel->currentItem() : nullptr; |
227 | 230 | if (!currentTrack) { |
228 | 231 | if (auto currentClip = qobject_cast<dspx::Clip *>(selectionModel ? selectionModel->currentItem() : nullptr)) { |
@@ -292,9 +295,66 @@ namespace Core { |
292 | 295 | }); |
293 | 296 |
|
294 | 297 | if (success && newClip) { |
295 | | - if (selectionModel) { |
296 | | - selectionModel->select(newClip, dspx::SelectionModel::Select | dspx::SelectionModel::SetCurrentItem | dspx::SelectionModel::ClearPreviousSelection); |
| 298 | + selectionModel->select(newClip, dspx::SelectionModel::Select | dspx::SelectionModel::SetCurrentItem | dspx::SelectionModel::ClearPreviousSelection); |
| 299 | + } |
| 300 | + } |
| 301 | + |
| 302 | + void InsertItemScenario::insertNote() const { |
| 303 | + Q_D(const InsertItemScenario); |
| 304 | + if (!document() || !d->projectTimeline || !window()) |
| 305 | + return; |
| 306 | + |
| 307 | + auto model = document()->model(); |
| 308 | + auto selectionModel = document()->selectionModel(); |
| 309 | + auto noteSelectionModel = selectionModel->noteSelectionModel(); |
| 310 | + |
| 311 | + auto noteSequence = noteSelectionModel->noteSequenceWithSelectedItems(); |
| 312 | + if (!noteSequence) |
| 313 | + return; |
| 314 | + |
| 315 | + auto clip = noteSequence->singingClip(); |
| 316 | + |
| 317 | + // Calculate initial position: playback position - clip position |
| 318 | + const int clipPosition = clip->position(); |
| 319 | + const int initialPosition = qMax(0, d->projectTimeline->position() - clipPosition); |
| 320 | + |
| 321 | + QQmlComponent component(RuntimeInterface::qmlEngine(), "DiffScope.Core", "InsertNoteDialog"); |
| 322 | + QVariantMap properties; |
| 323 | + properties.insert("timeline", QVariant::fromValue(d->projectTimeline->musicTimeline())); |
| 324 | + properties.insert("notePosition", initialPosition); |
| 325 | + properties.insert("noteLength", 480); |
| 326 | + properties.insert("notePitch", 60); // Default to middle C (C4) |
| 327 | + properties.insert("noteLyric", QString()); // TODO: determine initial lyric |
| 328 | + auto dialog = createAndPositionDialog(&component, properties); |
| 329 | + if (!DocumentEditScenarioPrivate::execDialog(dialog)) |
| 330 | + return; |
| 331 | + |
| 332 | + const auto notePosition = qMax(0, dialog->property("notePosition").toInt()); |
| 333 | + const auto noteLength = qMax(1, dialog->property("noteLength").toInt()); |
| 334 | + const auto notePitch = qBound(0, dialog->property("notePitch").toInt(), 127); |
| 335 | + const auto noteLyric = dialog->property("noteLyric").toString(); |
| 336 | + |
| 337 | + dspx::Note *newNote = nullptr; |
| 338 | + bool success = false; |
| 339 | + document()->transactionController()->beginScopedTransaction(tr("Inserting note"), [=, &newNote, &success] { |
| 340 | + newNote = model->createNote(); |
| 341 | + newNote->setPos(notePosition); |
| 342 | + newNote->setLength(noteLength); |
| 343 | + newNote->setKeyNum(notePitch); |
| 344 | + newNote->setLyric(noteLyric); |
| 345 | + if (!noteSequence->insertItem(newNote)) { |
| 346 | + model->destroyItem(newNote); |
| 347 | + newNote = nullptr; |
| 348 | + return false; |
297 | 349 | } |
| 350 | + success = true; |
| 351 | + return true; |
| 352 | + }, [] { |
| 353 | + qCCritical(lcInsertItemScenario) << "Failed to insert note in exclusive transaction"; |
| 354 | + }); |
| 355 | + |
| 356 | + if (success && newNote) { |
| 357 | + selectionModel->select(newNote, dspx::SelectionModel::Select | dspx::SelectionModel::SetCurrentItem | dspx::SelectionModel::ClearPreviousSelection); |
298 | 358 | } |
299 | 359 | } |
300 | 360 |
|
|
0 commit comments