1 //=============================================================================
2 // MuseScore
3 // Linux Music Score Editor
4 //
5 // Copyright (C) 2008 Werner Schweer and others
6 //
7 // This program is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License version 2.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //=============================================================================
19
20 #include "excerptsdialog.h"
21 #include "musescore.h"
22 #include "libmscore/score.h"
23 #include "libmscore/part.h"
24 #include "libmscore/undo.h"
25 #include "icons.h"
26
27 namespace Ms {
28
29 //---------------------------------------------------------
30 // StaffItem
31 //---------------------------------------------------------
32
StaffItem(int firstTrack,int idx1,int idx2,const QMultiMap<int,int> tracks,bool disabled,PartItem * parent)33 StaffItem::StaffItem(int firstTrack, int idx1, int idx2, const QMultiMap<int, int> tracks, bool disabled, PartItem* parent)
34 : QTreeWidgetItem(parent)
35 {
36 _firstTrack = -1; // Indicates initialising.
37
38 setFlags(Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable));
39
40 for (int i = 0; i < VOICES; ++i) {
41 bool inRange { true };
42 if (idx1 >= 0) {
43 int checkTrack = tracks.value(firstTrack + i, -1);
44 inRange = ((idx1 * VOICES) <= checkTrack) && ((checkTrack < (idx2 + 1) * VOICES));
45 }
46 setCheckState(i + 1, inRange ? Qt::Checked : Qt::Unchecked);
47 setDisabled(disabled);
48 }
49
50 // By setting _firstTrack the check in setData is no longer bypassed.
51 _firstTrack = firstTrack;
52 }
53
54 //---------------------------------------------------------
55 // setLinkMaster
56 //---------------------------------------------------------
57
setLink(StaffItem * si)58 void StaffItem::setLink(StaffItem* si)
59 {
60 _linked.append(si);
61 si->setDisabled(true);
62 }
63
64 //---------------------------------------------------------
65 // setData
66 //---------------------------------------------------------
67
setData(int column,int role,const QVariant & value)68 void StaffItem::setData(int column, int role, const QVariant& value)
69 {
70 QTreeWidgetItem::setData(column, role, value);
71
72 if (_firstTrack < 0)
73 // Is initially set to -1 in the constructor to bypass
74 // the checked for all unchecked items during initialisation.
75 return;
76
77 // Make sure there is always one voice selected.
78 // Is bypassed during initialisation.
79
80 int unchecked = 0;
81 for (int i = 1; i <= VOICES; i++) {
82 if (checkState(i) == Qt::Unchecked)
83 unchecked += 1;
84 }
85 if (unchecked == VOICES)
86 setCheckState(column, Qt::Checked);
87
88 for (auto si : _linked)
89 si->setData(column, role, value);
90 }
91
92 //---------------------------------------------------------
93 // tracks
94 //---------------------------------------------------------
95
tracks(int & staff) const96 QMultiMap<int, int> StaffItem::tracks(int& staff) const
97 {
98 QMultiMap<int, int> tracks;
99 int voice = 0;
100 for (int i = 0; i < VOICES; ++i) {
101 if (checkState(i + 1) == Qt::Checked)
102 tracks.insert(_firstTrack + i, staff * VOICES + voice++);
103 }
104 staff++;
105 return tracks;
106 }
107
108 //---------------------------------------------------------
109 // PartItem
110 //---------------------------------------------------------
111
PartItem(Part * part,const QMultiMap<int,int> tracks,int & staffIdx,bool disabled,QTreeWidget * parent)112 PartItem::PartItem(Part* part, const QMultiMap<int, int> tracks, int& staffIdx, bool disabled, QTreeWidget* parent)
113 : QTreeWidgetItem(parent)
114 {
115 setFlags(Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable));
116 _part = part;
117 setText(0, _part->partName());
118
119 Staff* master { nullptr };
120 StaffItem* msli { nullptr };
121 int firstTrack = _part->startTrack();
122 for (int i = 0; i < _part->nstaves(); ++i) {
123 StaffItem* sli = new StaffItem(firstTrack, staffIdx, staffIdx + _part->nstaves() - 1, tracks, disabled, this);
124 _staffItems.append(sli);
125
126 // If the part contains linked staves they all must have the same
127 // selection. Make only the first editable.
128 Staff* s = _part->staves()->at(i);
129 if (!master) {
130 if (s->staffList().length() > 1) {
131 master = s;
132 msli = sli;
133 }
134 }
135 else if (master && !s->staffList().length()) {
136 master = nullptr;
137 msli = nullptr;
138 }
139 else {
140 if (master->staffList().contains(s))
141 msli->setLink(sli);
142 }
143 firstTrack += VOICES;
144 }
145
146 if (staffIdx >= 0)
147 staffIdx += _part->nstaves();
148 }
149
150 //---------------------------------------------------------
151 // ~PartItem
152 //---------------------------------------------------------
153
~PartItem()154 PartItem::~PartItem()
155 {
156 while (!_staffItems.isEmpty())
157 delete _staffItems.takeFirst();
158 _staffItems.clear();
159 }
160
161 //---------------------------------------------------------
162 // findStaffItem
163 //---------------------------------------------------------
164
findStaffItem(QTreeWidgetItem * widget) const165 StaffItem* PartItem::findStaffItem(QTreeWidgetItem* widget) const
166 {
167 for (StaffItem* si : _staffItems) {
168 if (si == widget)
169 return si;
170 }
171 return nullptr;
172 }
173
174 //---------------------------------------------------------
175 // tracks
176 //---------------------------------------------------------
177
tracks(int & staff) const178 QMultiMap<int, int> PartItem::tracks(int& staff) const
179 {
180 QMultiMap<int, int> tracks;
181 for (StaffItem* si : _staffItems)
182 tracks += si->tracks(staff);
183 return tracks;
184 }
185
186 //---------------------------------------------------------
187 // ExcerptItem
188 //---------------------------------------------------------
189
ExcerptItem(Excerpt * e,QListWidget * parent)190 ExcerptItem::ExcerptItem(Excerpt* e, QListWidget* parent)
191 : QListWidgetItem(parent)
192 {
193 _excerpt = e;
194 _tracks = _excerpt->tracks();
195 setText(_excerpt->title());
196
197 int staffIdx { 0 };
198 for (Part* part : _excerpt->parts())
199 _partItems.append(new PartItem(part, _excerpt->tracks(), staffIdx, _excerpt->partScore(), 0));
200 }
201
202 //---------------------------------------------------------
203 // ExcerptItem
204 //---------------------------------------------------------
205
~ExcerptItem()206 ExcerptItem::~ExcerptItem()
207 {
208 while (!_partItems.isEmpty())
209 delete _partItems.takeFirst();
210 _partItems.clear();
211 }
212
213 //---------------------------------------------------------
214 // addPartItem
215 //---------------------------------------------------------
216
addPartItem(PartItem * pi)217 void ExcerptItem::addPartItem(PartItem* pi)
218 {
219 _excerpt->parts().append(pi->part());
220 _partItems.append(pi);
221 }
222
223 //---------------------------------------------------------
224 // removePartItem
225 //---------------------------------------------------------
226
removePartItem(PartItem * pi)227 void ExcerptItem::removePartItem(PartItem* pi)
228 {
229 if (_partItems.contains(pi))
230 _partItems.removeAll(pi);
231 }
232
233 //---------------------------------------------------------
234 // findPartItem
235 //---------------------------------------------------------
236
findPartItem(QTreeWidgetItem * widget) const237 PartItem* ExcerptItem::findPartItem(QTreeWidgetItem* widget) const
238 {
239 for (PartItem* pi : _partItems) {
240 if ((pi == widget) || pi->findStaffItem(widget))
241 return pi;
242 }
243 return nullptr;
244 }
245
246 //---------------------------------------------------------
247 // tracks
248 //---------------------------------------------------------
249
tracks() const250 QMultiMap<int, int> ExcerptItem::tracks() const
251 {
252 QMultiMap<int, int> tracks;
253 int staff = 0;
254
255 for (PartItem* pi : _partItems)
256 tracks += pi->tracks(staff);
257 return tracks;
258 }
259
260 //---------------------------------------------------------
261 // setTitle
262 //---------------------------------------------------------
263
setTitle(const QString name)264 void ExcerptItem::setTitle(const QString name)
265 {
266 setText(name);
267 if (!isPartScore())
268 _excerpt->setTitle(name);
269 }
270
271 //---------------------------------------------------------
272 // InstrumentItem
273 //---------------------------------------------------------
274
InstrumentItem(Part * part,QListWidget * parent)275 InstrumentItem::InstrumentItem(Part* part, QListWidget* parent)
276 : QListWidgetItem(parent)
277 {
278 _part = part;
279 setFlags(Qt::ItemFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable));
280 setText(_part->partName().replace("/", "_"));
281 }
282
283 //---------------------------------------------------------
284 // newPartItem
285 //---------------------------------------------------------
286
newPartItem(int count) const287 PartItem* InstrumentItem::newPartItem(int count) const
288 {
289 QMultiMap<int, int> tracks;
290 for (int track = _part->startTrack(); track < _part->endTrack(); ++track)
291 tracks.insert(track, count * VOICES + track - _part->startTrack());
292
293 int staffIdx { -1 };
294 return new PartItem(_part, tracks, staffIdx, false, 0);
295 }
296
297 //---------------------------------------------------------
298 // ExcerptsDialog
299 //---------------------------------------------------------
300
ExcerptsDialog(MasterScore * s,QWidget * parent)301 ExcerptsDialog::ExcerptsDialog(MasterScore* s, QWidget* parent)
302 : QDialog(parent)
303 {
304 setObjectName("PartEditor");
305 setupUi(this);
306 setWindowFlags(this->windowFlags() & ~Qt::WindowContextHelpButtonHint);
307 setModal(true);
308
309 score = s->masterScore();
310
311 for (Part* p : score->parts())
312 instrumentList->addItem(new InstrumentItem(p));
313
314 for (Excerpt* e : score->excerpts())
315 excerptList->addItem(new ExcerptItem(e));
316
317
318 connect(singlePartButton, SIGNAL(clicked()), SLOT(singlePartClicked()));
319 connect(allPartsButton, SIGNAL(clicked()), SLOT(allPartsClicked()));
320 connect(deleteButton, SIGNAL(clicked()), SLOT(deleteClicked()));
321 connect(moveUpButton, SIGNAL(clicked()), SLOT(moveUpClicked()));
322 connect(moveDownButton, SIGNAL(clicked()), SLOT(moveDownClicked()));
323 connect(addButton, SIGNAL(clicked()), SLOT(addButtonClicked()));
324 connect(removeButton, SIGNAL(clicked()), SLOT(removeButtonClicked()));
325
326 connect(excerptList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
327 SLOT(excerptChanged(QListWidgetItem*, QListWidgetItem*)));
328 connect(partList, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
329 SLOT(partDoubleClicked(QTreeWidgetItem*, int)));
330 connect(partList, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
331 SLOT(partChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
332 connect(instrumentList, SIGNAL(itemDoubleClicked(QListWidgetItem*)),
333 SLOT(addButtonClicked()));
334 connect(instrumentList, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
335 SLOT(instrumentChanged(QListWidgetItem*, QListWidgetItem*)));
336 connect(title, SIGNAL(textChanged(const QString&)), SLOT(titleChanged(const QString&)));
337
338 moveUpButton->setIcon(*icons[int(Icons::arrowUp_ICON)]);
339 moveDownButton->setIcon(*icons[int(Icons::arrowDown_ICON)]);
340
341 for (int i = 1; i <= VOICES; i++)
342 partList->header()->resizeSection(i, 30);
343
344 if (excerptList->count())
345 excerptList->setCurrentRow(0);
346 }
347
348 //---------------------------------------------------------
349 // ~ExcerptsDialog
350 //---------------------------------------------------------
351
~ExcerptsDialog()352 ExcerptsDialog::~ExcerptsDialog()
353 {
354 // A delete of a QTreeWidget includes a delete of all item. But PartItem's in the
355 // partList are owned by ExcerptItem. So deleting excerptList will delete ExcerptItem's
356 // in the list **and** all its children (in ExcerptItem), leaving invalid pointer.
357 // So, just remove the item from partList and leave the delete to the owner.
358 clearPartList();
359 }
360
361 //---------------------------------------------------------
362 // startExcerptsDialog
363 //---------------------------------------------------------
364
startExcerptsDialog()365 void MuseScore::startExcerptsDialog()
366 {
367 if (cs == 0)
368 return;
369 ExcerptsDialog ed(cs->masterScore(), 0);
370 MuseScore::restoreGeometry(&ed);
371 ed.exec();
372 MuseScore::saveGeometry(&ed);
373 cs->setLayoutAll();
374 cs->update();
375 }
376
377 //---------------------------------------------------------
378 // singlePartClicked
379 //---------------------------------------------------------
380
singlePartClicked()381 void ExcerptsDialog::singlePartClicked()
382 {
383 QString name = createName("Part");
384 Excerpt* e = new Excerpt(score);
385 e->setTitle(name);
386 ExcerptItem* ei = new ExcerptItem(e);
387 excerptList->addItem(ei);
388 excerptList->selectionModel()->clearSelection();
389 excerptList->setCurrentItem(ei, QItemSelectionModel::SelectCurrent);
390
391 for (int i = 0; i < excerptList->count(); ++i) {
392 // if except score not created yet, change the UI title
393 // if already created, change back(see createName) the excerpt title
394 ExcerptItem* eii = getExcerptItemAt(i);
395 eii->setText(eii->excerpt()->title());
396 }
397 }
398
399 //---------------------------------------------------------
400 // allPartsClicked
401 //---------------------------------------------------------
402
allPartsClicked()403 void ExcerptsDialog::allPartsClicked()
404 {
405 ExcerptItem* ei = 0;
406 for (Excerpt* e : Excerpt::createAllExcerpt(score)) {
407 ei = new ExcerptItem(e);
408 excerptList->addItem(ei);
409 }
410 if (ei) {
411 excerptList->selectionModel()->clearSelection();
412 excerptList->setCurrentItem(ei, QItemSelectionModel::SelectCurrent);
413 }
414 }
415
416 //---------------------------------------------------------
417 // deleteClicked
418 //---------------------------------------------------------
419
deleteClicked()420 void ExcerptsDialog::deleteClicked()
421 {
422 ExcerptItem* ei = getCurrentExcerptItem();
423 if (ei == 0)
424 return;
425
426 delete ei;
427 setWidgetState();
428 }
429
430 //---------------------------------------------------------
431 // moveUpClicked
432 //---------------------------------------------------------
433
moveUpClicked()434 void ExcerptsDialog::moveUpClicked()
435 {
436 int currentRow = excerptList->currentRow();
437 if (currentRow <= 0)
438 return;
439 QListWidgetItem* currentItem = excerptList->takeItem(currentRow);
440 excerptList->insertItem(currentRow - 1, currentItem);
441 excerptList->setCurrentRow(currentRow - 1);
442 }
443
444 //---------------------------------------------------------
445 // moveDownClicked
446 //---------------------------------------------------------
447
moveDownClicked()448 void ExcerptsDialog::moveDownClicked()
449 {
450 int currentRow = excerptList->currentRow();
451 if (currentRow >= excerptList->count() - 1)
452 return;
453 QListWidgetItem* currentItem = excerptList->takeItem(currentRow);
454 excerptList->insertItem(currentRow + 1, currentItem);
455 excerptList->setCurrentRow(currentRow + 1);
456 }
457
458 //---------------------------------------------------------
459 // addButtonClicked
460 // add instrument to excerpt
461 //---------------------------------------------------------
462
addButtonClicked()463 void ExcerptsDialog::addButtonClicked()
464 {
465 InstrumentItem* ii = getCurrentInstrumentItem();
466 ExcerptItem* ei = getCurrentExcerptItem();
467
468 if (!ii || !ei || !partList->isEnabled())
469 return;
470
471 PartItem* pi = ii->newPartItem(partList->topLevelItemCount());
472 ei->addPartItem(pi);
473 partList->addTopLevelItem(pi);
474 partList->resizeColumnToContents(0);
475 }
476
477 //---------------------------------------------------------
478 // removeButtonClicked
479 // remove instrument from score
480 //---------------------------------------------------------
481
removeButtonClicked()482 void ExcerptsDialog::removeButtonClicked()
483 {
484 ExcerptItem* ei = getCurrentExcerptItem();
485 PartItem* pi = getCurrentPartItem();
486 if (!ei || !pi)
487 return;
488
489 ei->removePartItem(pi);
490 partList->takeTopLevelItem(partList->indexOfTopLevelItem(pi));
491
492 partList->resizeColumnToContents(0);
493 // removeButton->setEnabled(partList->topLevelItemCount() > 0);
494 }
495
496 //---------------------------------------------------------
497 // excerptChanged
498 //---------------------------------------------------------
499
excerptChanged(QListWidgetItem *,QListWidgetItem *)500 void ExcerptsDialog::excerptChanged(QListWidgetItem*, QListWidgetItem*)
501 {
502 clearPartList();
503 ExcerptItem* ei = getCurrentExcerptItem();
504 if (ei) {
505 title->setText(ei->text());
506 for (PartItem* pi : ei->partItems())
507 partList->addTopLevelItem(pi);
508 }
509 else {
510 title->setText("");
511 }
512
513 setWidgetState();
514 }
515
516 //---------------------------------------------------------
517 // partChanged
518 //---------------------------------------------------------
519
partChanged(QTreeWidgetItem *,QTreeWidgetItem *)520 void ExcerptsDialog::partChanged(QTreeWidgetItem*, QTreeWidgetItem*)
521 {
522 removeButton->setEnabled(getCurrentPartItem());
523 }
524
525 //---------------------------------------------------------
526 // instrumentChanged
527 //---------------------------------------------------------
528
instrumentChanged(QListWidgetItem *,QListWidgetItem *)529 void ExcerptsDialog::instrumentChanged(QListWidgetItem*, QListWidgetItem*)
530 {
531 addButton->setEnabled(getCurrentInstrumentItem());
532 }
533
534 //---------------------------------------------------------
535 // partDoubleClicked
536 //---------------------------------------------------------
537
partDoubleClicked(QTreeWidgetItem * item,int)538 void ExcerptsDialog::partDoubleClicked(QTreeWidgetItem* item, int)
539 {
540 if (!item->parent()) { // top level items are PartItem
541 PartItem* pi = static_cast<PartItem*>(item); // TODO
542 QString s = pi->part()->partName();
543 title->setText(s);
544 titleChanged(s);
545 }
546 }
547
548 //---------------------------------------------------------
549 // doubleClickedInstrument
550 //---------------------------------------------------------
551
doubleClickedInstrument(QTreeWidgetItem *)552 void ExcerptsDialog::doubleClickedInstrument(QTreeWidgetItem*)
553 {
554 addButtonClicked();
555 }
556
557 //---------------------------------------------------------
558 // titleChanged
559 //---------------------------------------------------------
560
titleChanged(const QString & s)561 void ExcerptsDialog::titleChanged(const QString& s)
562 {
563 ExcerptItem* ei = getCurrentExcerptItem();
564 if (ei)
565 ei->setTitle(s);
566
567 score->masterScore()->setExcerptsChanged(true);
568 }
569
570 //---------------------------------------------------------
571 // createName
572 //---------------------------------------------------------
573
createName(const QString & partName)574 QString ExcerptsDialog::createName(const QString& partName)
575 {
576 int count = excerptList->count();
577 QList<Excerpt*> excerpts;
578 for (int i = 0; i < count; ++i)
579 excerpts.append(getExcerptItemAt(i)->excerpt());
580
581 return Excerpt::createName(partName, excerpts);
582 }
583
584 //---------------------------------------------------------
585 // getCurrentPartItem
586 //---------------------------------------------------------
587
getCurrentPartItem() const588 PartItem* ExcerptsDialog::getCurrentPartItem() const
589 {
590 return static_cast<PartItem*>(partList->currentItem());
591 }
592
593 //---------------------------------------------------------
594 // getCurrentExcerptItem
595 //---------------------------------------------------------
596
getCurrentExcerptItem() const597 ExcerptItem* ExcerptsDialog::getCurrentExcerptItem() const
598 {
599 return static_cast<ExcerptItem*>(excerptList->currentItem());
600 }
601
602 //---------------------------------------------------------
603 // getExcerptItemAt
604 //---------------------------------------------------------
605
getExcerptItemAt(int index) const606 ExcerptItem* ExcerptsDialog::getExcerptItemAt(int index) const
607 {
608 return static_cast<ExcerptItem*>(excerptList->item(index));
609 }
610
611 //---------------------------------------------------------
612 // getInstrumentItemAt
613 //---------------------------------------------------------
614
getCurrentInstrumentItem() const615 InstrumentItem* ExcerptsDialog::getCurrentInstrumentItem() const
616 {
617 return static_cast<InstrumentItem*>(instrumentList->currentItem());
618 }
619
620 //---------------------------------------------------------
621 // clearPartList
622 //---------------------------------------------------------
623
clearPartList()624 void ExcerptsDialog::clearPartList()
625 {
626 // The clear method of QTreeWidget cannot be used because it will delete
627 // all items, leaving behind invalid pointer.
628 // takeTopLevelItem on the other hand will remove the item from the tree
629 // but will not delete it.
630 while (partList->takeTopLevelItem(0)) {}
631 }
632
633
634 //---------------------------------------------------------
635 // setWidgetState
636 //---------------------------------------------------------
637
setWidgetState()638 void ExcerptsDialog::setWidgetState()
639 {
640 ExcerptItem* ei = getCurrentExcerptItem();
641
642 const bool enable = ei && !ei->isPartScore();
643
644 instrumentList->setEnabled(enable);
645 title->setEnabled(ei);
646 deleteButton->setEnabled(ei);
647
648 addButton->setEnabled(ei && getCurrentInstrumentItem());
649 removeButton->setEnabled(ei && getCurrentPartItem());
650
651 int idx = excerptList->currentIndex().row();
652 moveUpButton->setEnabled(ei && (idx > 0));
653 moveDownButton->setEnabled(ei && (idx < (excerptList->count() - 1)));
654 }
655
656 //---------------------------------------------------------
657 // getExcerptItem
658 //---------------------------------------------------------
659
getExcerptItem(Excerpt * e)660 ExcerptItem* ExcerptsDialog::getExcerptItem(Excerpt* e)
661 {
662 for (int i = 0; i < excerptList->count(); ++i) {
663 ExcerptItem* ei = getExcerptItemAt(i);
664 if (ei && (ei->excerpt() == e))
665 return ei;
666 }
667 return 0;
668 }
669
670 //---------------------------------------------------------
671 // createNewExcerpt
672 //---------------------------------------------------------
673
createNewExcerpt(ExcerptItem * ei)674 void ExcerptsDialog::createNewExcerpt(ExcerptItem* ei)
675 {
676 Excerpt* e = ei->excerpt();
677 e->setTitle(ei->text());
678 if (e->partScore())
679 return;
680 if (e->parts().isEmpty()) {
681 qDebug("no parts");
682 return;
683 }
684
685 Score* nscore = new Score(e->oscore());
686 e->setPartScore(nscore);
687
688 qDebug() << " + Add part : " << e->title();
689 score->undo(new AddExcerpt(e));
690 e->setTracks(ei->tracks());
691 Excerpt::createExcerpt(e);
692
693 // a new excerpt is created in AddExcerpt, make sure the parts are filed
694 for (Excerpt* ee : e->oscore()->excerpts()) {
695 if (ee->partScore() == nscore && ee != e) {
696 ee->parts().clear();
697 ee->parts().append(e->parts());
698 }
699 }
700
701 partList->setEnabled(false);
702 title->setEnabled(false);
703 }
704
705 //---------------------------------------------------------
706 // accept
707 //---------------------------------------------------------
708
accept()709 void ExcerptsDialog::accept()
710 {
711 for (int i = 0; i < excerptList->count(); ++i)
712 excerptList->setCurrentRow(i);
713
714 score->startCmd();
715
716 // first pass : see if actual parts needs to be deleted or renamed
717 foreach (Excerpt* e, score->excerpts()) {
718 Score* partScore = e->partScore();
719 ExcerptItem* ei = getExcerptItem(e);
720 if (!getExcerptItem(e) && partScore) // Delete it because not in the list anymore
721 score->deleteExcerpt(e);
722 else if (ei->text() != e->title())
723 score->undo(new ChangeExcerptTitle(e, ei->text()));
724 }
725
726 // Second pass : Create new parts
727 for (int i = 0; i < excerptList->count(); ++i) {
728 ExcerptItem* ei = getExcerptItemAt(i);
729 if (ei && !ei->isEmpty())
730 createNewExcerpt(ei);
731 }
732
733 // Third pass : Remove empty parts.
734 int j = 0;
735 while (j < excerptList->count()) {
736 // This new part is empty, so we don't create an excerpt but remove it from the list.
737 // Necessary to order the parts later on.
738 ExcerptItem* ei = getExcerptItemAt(j);
739 if (ei->excerpt()->parts().isEmpty() && !ei->excerpt()->partScore()) {
740 qDebug() << " - Deleting empty parts : " << ei->text();
741 delete ei;
742 }
743 else
744 j++;
745 }
746
747 // Update the score parts order following excerptList widget
748 // The reference is the excerpt list. So we iterate following it and swap parts in the score accordingly
749 for (int i = 0; i < excerptList->count(); ++i) {
750 ExcerptItem* ei = getExcerptItemAt(i);
751
752 if (!ei || ei->isEmpty())
753 continue;
754
755 int position = 0; // Actual order position in score
756 bool found = false;
757
758 // Looks for the excerpt and its position.
759 foreach(Excerpt* e, score->excerpts()) {
760 if (ei->excerpt() == e) {
761 found = true;
762 break;
763 }
764 position++;
765 }
766 if (found && (position != i))
767 score->undo(new SwapExcerpt(score, i, position));
768 }
769 score->endCmd();
770 QDialog::accept();
771 }
772 }
773