Mercurial > hg > svapp
comparison framework/MainWindowBase.cpp @ 673:d62fd61082a1
Merge from branch tuning-difference
author | Chris Cannam |
---|---|
date | Fri, 17 May 2019 09:46:22 +0100 |
parents | 331be52cd473 |
children | 5e9b1956b609 |
comparison
equal
deleted
inserted
replaced
665:e19c609a7bec | 673:d62fd61082a1 |
---|---|
20 #include "view/PaneStack.h" | 20 #include "view/PaneStack.h" |
21 #include "data/model/ReadOnlyWaveFileModel.h" | 21 #include "data/model/ReadOnlyWaveFileModel.h" |
22 #include "data/model/WritableWaveFileModel.h" | 22 #include "data/model/WritableWaveFileModel.h" |
23 #include "data/model/SparseOneDimensionalModel.h" | 23 #include "data/model/SparseOneDimensionalModel.h" |
24 #include "data/model/NoteModel.h" | 24 #include "data/model/NoteModel.h" |
25 #include "data/model/FlexiNoteModel.h" | |
26 #include "data/model/Labeller.h" | 25 #include "data/model/Labeller.h" |
27 #include "data/model/TabularModel.h" | 26 #include "data/model/TabularModel.h" |
28 #include "view/ViewManager.h" | 27 #include "view/ViewManager.h" |
29 | 28 |
30 #include "layer/WaveformLayer.h" | 29 #include "layer/WaveformLayer.h" |
53 | 52 |
54 #include "data/fileio/DataFileReaderFactory.h" | 53 #include "data/fileio/DataFileReaderFactory.h" |
55 #include "data/fileio/PlaylistFileReader.h" | 54 #include "data/fileio/PlaylistFileReader.h" |
56 #include "data/fileio/WavFileWriter.h" | 55 #include "data/fileio/WavFileWriter.h" |
57 #include "data/fileio/MIDIFileWriter.h" | 56 #include "data/fileio/MIDIFileWriter.h" |
57 #include "data/fileio/CSVFileWriter.h" | |
58 #include "data/fileio/BZipFileDevice.h" | 58 #include "data/fileio/BZipFileDevice.h" |
59 #include "data/fileio/FileSource.h" | 59 #include "data/fileio/FileSource.h" |
60 #include "data/fileio/AudioFileReaderFactory.h" | 60 #include "data/fileio/AudioFileReaderFactory.h" |
61 #include "rdf/RDFImporter.h" | 61 #include "rdf/RDFImporter.h" |
62 #include "rdf/RDFExporter.h" | |
62 | 63 |
63 #include "base/RecentFiles.h" | 64 #include "base/RecentFiles.h" |
64 | 65 |
65 #include "base/PlayParameterRepository.h" | 66 #include "base/PlayParameterRepository.h" |
66 #include "base/XmlExportable.h" | 67 #include "base/XmlExportable.h" |
70 #include "base/Exceptions.h" | 71 #include "base/Exceptions.h" |
71 #include "base/ResourceFinder.h" | 72 #include "base/ResourceFinder.h" |
72 | 73 |
73 #include "data/osc/OSCQueue.h" | 74 #include "data/osc/OSCQueue.h" |
74 #include "data/midi/MIDIInput.h" | 75 #include "data/midi/MIDIInput.h" |
76 #include "OSCScript.h" | |
75 | 77 |
76 #include "system/System.h" | 78 #include "system/System.h" |
77 | 79 |
78 #include <bqaudioio/SystemPlaybackTarget.h> | 80 #include <bqaudioio/SystemPlaybackTarget.h> |
79 #include <bqaudioio/SystemAudioIO.h> | 81 #include <bqaudioio/SystemAudioIO.h> |
147 m_resamplerWrapper(nullptr), | 149 m_resamplerWrapper(nullptr), |
148 m_playTarget(nullptr), | 150 m_playTarget(nullptr), |
149 m_audioIO(nullptr), | 151 m_audioIO(nullptr), |
150 m_oscQueue(nullptr), | 152 m_oscQueue(nullptr), |
151 m_oscQueueStarter(nullptr), | 153 m_oscQueueStarter(nullptr), |
154 m_oscScript(nullptr), | |
152 m_midiInput(nullptr), | 155 m_midiInput(nullptr), |
153 m_recentFiles("RecentFiles", 20), | 156 m_recentFiles("RecentFiles", 20), |
154 m_recentTransforms("RecentTransforms", 20), | 157 m_recentTransforms("RecentTransforms", 20), |
155 m_documentModified(false), | 158 m_documentModified(false), |
156 m_openingAudioFile(false), | 159 m_openingAudioFile(false), |
325 delete m_playSource; | 328 delete m_playSource; |
326 delete m_recordTarget; | 329 delete m_recordTarget; |
327 | 330 |
328 delete m_viewManager; | 331 delete m_viewManager; |
329 delete m_midiInput; | 332 delete m_midiInput; |
333 | |
334 if (m_oscScript) { | |
335 disconnect(m_oscScript, nullptr, nullptr, nullptr); | |
336 m_oscScript->abandon(); | |
337 m_oscScript->wait(1000); | |
338 if (m_oscScript->isRunning()) { | |
339 m_oscScript->terminate(); | |
340 m_oscScript->wait(1000); | |
341 } | |
342 delete m_oscScript; | |
343 } | |
330 | 344 |
331 if (m_oscQueueStarter) { | 345 if (m_oscQueueStarter) { |
332 disconnect(m_oscQueueStarter, nullptr, nullptr, nullptr); | 346 disconnect(m_oscQueueStarter, nullptr, nullptr, nullptr); |
333 m_oscQueueStarter->wait(1000); | 347 m_oscQueueStarter->wait(1000); |
334 if (m_oscQueueStarter->isRunning()) { | 348 if (m_oscQueueStarter->isRunning()) { |
499 std::min(size.height(), available.height())); | 513 std::min(size.height(), available.height())); |
500 resize(actual); | 514 resize(actual); |
501 } | 515 } |
502 | 516 |
503 void | 517 void |
504 MainWindowBase::startOSCQueue() | 518 MainWindowBase::startOSCQueue(bool withNetworkPort) |
505 { | 519 { |
506 m_oscQueueStarter = new OSCQueueStarter(this); | 520 m_oscQueueStarter = new OSCQueueStarter(this, withNetworkPort); |
507 connect(m_oscQueueStarter, SIGNAL(finished()), this, SLOT(oscReady())); | 521 connect(m_oscQueueStarter, SIGNAL(finished()), this, SLOT(oscReady())); |
508 m_oscQueueStarter->start(); | 522 m_oscQueueStarter->start(); |
509 } | 523 } |
510 | 524 |
511 void | 525 void |
514 if (m_oscQueue && m_oscQueue->isOK()) { | 528 if (m_oscQueue && m_oscQueue->isOK()) { |
515 connect(m_oscQueue, SIGNAL(messagesAvailable()), this, SLOT(pollOSC())); | 529 connect(m_oscQueue, SIGNAL(messagesAvailable()), this, SLOT(pollOSC())); |
516 QTimer *oscTimer = new QTimer(this); | 530 QTimer *oscTimer = new QTimer(this); |
517 connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC())); | 531 connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC())); |
518 oscTimer->start(1000); | 532 oscTimer->start(1000); |
519 SVCERR << "Finished setting up OSC interface" << endl; | 533 |
520 } | 534 if (m_oscQueue->hasPort()) { |
535 SVDEBUG << "Finished setting up OSC interface" << endl; | |
536 } else { | |
537 SVDEBUG << "Finished setting up internal-only OSC queue" << endl; | |
538 } | |
539 | |
540 if (m_oscScriptFile != QString()) { | |
541 startOSCScript(); | |
542 } | |
543 } | |
544 } | |
545 | |
546 void | |
547 MainWindowBase::startOSCScript() | |
548 { | |
549 m_oscScript = new OSCScript(m_oscScriptFile, m_oscQueue); | |
550 connect(m_oscScript, SIGNAL(finished()), | |
551 this, SLOT(oscScriptFinished())); | |
552 m_oscScriptFile = QString(); | |
553 m_oscScript->start(); | |
554 } | |
555 | |
556 void | |
557 MainWindowBase::cueOSCScript(QString fileName) | |
558 { | |
559 m_oscScriptFile = fileName; | |
560 if (m_oscQueue && m_oscQueue->isOK()) { | |
561 startOSCScript(); | |
562 } | |
563 } | |
564 | |
565 void | |
566 MainWindowBase::oscScriptFinished() | |
567 { | |
568 delete m_oscScript; | |
569 m_oscScript = 0; | |
521 } | 570 } |
522 | 571 |
523 QString | 572 QString |
524 MainWindowBase::getOpenFileName(FileFinder::FileType type) | 573 MainWindowBase::getOpenFileName(FileFinder::FileType type) |
525 { | 574 { |
697 bool recordDeviceFailed = (m_playTarget != nullptr && m_audioIO == nullptr); | 746 bool recordDeviceFailed = (m_playTarget != nullptr && m_audioIO == nullptr); |
698 emit canRecord(!recordDisabled && !recordDeviceFailed); | 747 emit canRecord(!recordDisabled && !recordDeviceFailed); |
699 } | 748 } |
700 | 749 |
701 void | 750 void |
751 MainWindowBase::updateWindowTitle() | |
752 { | |
753 QString title; | |
754 | |
755 if (m_sessionFile != "") { | |
756 if (m_originalLocation != "" && | |
757 m_originalLocation != m_sessionFile) { // session + location | |
758 title = tr("%1: %2 [%3]") | |
759 .arg(QApplication::applicationName()) | |
760 .arg(QFileInfo(m_sessionFile).fileName()) | |
761 .arg(m_originalLocation); | |
762 } else { // session only | |
763 title = tr("%1: %2") | |
764 .arg(QApplication::applicationName()) | |
765 .arg(QFileInfo(m_sessionFile).fileName()); | |
766 } | |
767 } else { | |
768 if (m_originalLocation != "") { // location only | |
769 title = tr("%1: %2") | |
770 .arg(QApplication::applicationName()) | |
771 .arg(m_originalLocation); | |
772 } else { // neither | |
773 title = QApplication::applicationName(); | |
774 } | |
775 } | |
776 | |
777 if (m_documentModified) { | |
778 title = tr("%1 (modified)").arg(title); | |
779 } | |
780 | |
781 setWindowTitle(title); | |
782 } | |
783 | |
784 void | |
702 MainWindowBase::documentModified() | 785 MainWindowBase::documentModified() |
703 { | 786 { |
704 // SVDEBUG << "MainWindowBase::documentModified" << endl; | 787 // SVDEBUG << "MainWindowBase::documentModified" << endl; |
705 | 788 |
706 if (!m_documentModified) { | |
707 //!!! this in subclass implementation? | |
708 setWindowTitle(tr("%1 (modified)").arg(windowTitle())); | |
709 } | |
710 | |
711 m_documentModified = true; | 789 m_documentModified = true; |
790 updateWindowTitle(); | |
712 updateMenuStates(); | 791 updateMenuStates(); |
713 } | 792 } |
714 | 793 |
715 void | 794 void |
716 MainWindowBase::documentRestored() | 795 MainWindowBase::documentRestored() |
717 { | 796 { |
718 // SVDEBUG << "MainWindowBase::documentRestored" << endl; | 797 // SVDEBUG << "MainWindowBase::documentRestored" << endl; |
719 | 798 |
720 if (m_documentModified) { | |
721 //!!! this in subclass implementation? | |
722 QString wt(windowTitle()); | |
723 wt.replace(tr(" (modified)"), ""); | |
724 setWindowTitle(wt); | |
725 } | |
726 | |
727 m_documentModified = false; | 799 m_documentModified = false; |
800 updateWindowTitle(); | |
728 updateMenuStates(); | 801 updateMenuStates(); |
729 } | 802 } |
730 | 803 |
731 void | 804 void |
732 MainWindowBase::playLoopToggled() | 805 MainWindowBase::playLoopToggled() |
1134 } | 1207 } |
1135 | 1208 |
1136 if (layer) { | 1209 if (layer) { |
1137 | 1210 |
1138 Model *model = layer->getModel(); | 1211 Model *model = layer->getModel(); |
1139 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *> | 1212 SparseOneDimensionalModel *sodm = |
1140 (model); | 1213 dynamic_cast<SparseOneDimensionalModel *>(model); |
1141 | 1214 |
1142 if (sodm) { | 1215 if (sodm) { |
1143 SparseOneDimensionalModel::Point point(frame, ""); | 1216 Event point(frame, ""); |
1144 | 1217 Event prevPoint(0); |
1145 SparseOneDimensionalModel::Point prevPoint(0); | |
1146 bool havePrevPoint = false; | 1218 bool havePrevPoint = false; |
1147 | 1219 |
1148 SparseOneDimensionalModel::EditCommand *command = | 1220 ChangeEventsCommand *command = |
1149 new SparseOneDimensionalModel::EditCommand(sodm, tr("Add Point")); | 1221 new ChangeEventsCommand(sodm, tr("Add Point")); |
1150 | 1222 |
1151 if (m_labeller) { | 1223 if (m_labeller) { |
1152 | 1224 |
1153 if (m_labeller->requiresPrevPoint()) { | 1225 if (m_labeller->requiresPrevPoint()) { |
1154 | 1226 |
1155 SparseOneDimensionalModel::PointList prevPoints = | 1227 if (sodm->getNearestEventMatching |
1156 sodm->getPreviousPoints(frame); | 1228 (frame, |
1157 | 1229 [](Event) { return true; }, |
1158 if (!prevPoints.empty()) { | 1230 EventSeries::Backward, |
1159 prevPoint = *prevPoints.begin(); | 1231 prevPoint)) { |
1160 havePrevPoint = true; | 1232 havePrevPoint = true; |
1161 } | 1233 } |
1162 } | 1234 } |
1163 | 1235 |
1164 m_labeller->setSampleRate(sodm->getSampleRate()); | 1236 m_labeller->setSampleRate(sodm->getSampleRate()); |
1165 | 1237 |
1166 if (m_labeller->actingOnPrevPoint() && havePrevPoint) { | 1238 Labeller::Relabelling relabelling = m_labeller->label |
1167 command->deletePoint(prevPoint); | |
1168 } | |
1169 | |
1170 m_labeller->label<SparseOneDimensionalModel::Point> | |
1171 (point, havePrevPoint ? &prevPoint : nullptr); | 1239 (point, havePrevPoint ? &prevPoint : nullptr); |
1172 | 1240 |
1173 if (m_labeller->actingOnPrevPoint() && havePrevPoint) { | 1241 if (relabelling.first == Labeller::AppliesToPreviousEvent) { |
1174 command->addPoint(prevPoint); | 1242 command->remove(prevPoint); |
1243 command->add(relabelling.second); | |
1244 } else { | |
1245 point = relabelling.second; | |
1175 } | 1246 } |
1176 } | 1247 } |
1177 | 1248 |
1178 command->addPoint(point); | 1249 command->add(point); |
1179 | 1250 |
1180 command->setName(tr("Add Point at %1 s") | 1251 command->setName(tr("Add Point at %1 s") |
1181 .arg(RealTime::frame2RealTime | 1252 .arg(RealTime::frame2RealTime |
1182 (frame, | 1253 (frame, |
1183 sodm->getSampleRate()) | 1254 sodm->getSampleRate()) |
1229 Layer *layer = pane->getSelectedLayer(); | 1300 Layer *layer = pane->getSelectedLayer(); |
1230 if (!layer) return; | 1301 if (!layer) return; |
1231 | 1302 |
1232 RegionModel *rm = dynamic_cast<RegionModel *>(layer->getModel()); | 1303 RegionModel *rm = dynamic_cast<RegionModel *>(layer->getModel()); |
1233 if (rm) { | 1304 if (rm) { |
1234 RegionModel::Point point(alignedStart, | 1305 Event point(alignedStart, |
1235 rm->getValueMaximum() + 1, | 1306 rm->getValueMaximum() + 1, |
1236 alignedDuration, | 1307 alignedDuration, |
1237 ""); | 1308 ""); |
1238 RegionModel::EditCommand *command = | 1309 ChangeEventsCommand *command = new ChangeEventsCommand(rm, name); |
1239 new RegionModel::EditCommand(rm, tr("Add Point")); | 1310 command->add(point); |
1240 command->addPoint(point); | |
1241 command->setName(name); | |
1242 c = command->finish(); | 1311 c = command->finish(); |
1243 } | 1312 } |
1244 | 1313 |
1245 if (c) { | 1314 if (c) { |
1246 CommandHistory::getInstance()->addCommand(c, false); | 1315 CommandHistory::getInstance()->addCommand(c, false); |
1247 return; | 1316 return; |
1248 } | 1317 } |
1249 | 1318 |
1250 NoteModel *nm = dynamic_cast<NoteModel *>(layer->getModel()); | 1319 NoteModel *nm = dynamic_cast<NoteModel *>(layer->getModel()); |
1251 if (nm) { | 1320 if (nm) { |
1252 NoteModel::Point point(alignedStart, | 1321 Event point(alignedStart, |
1253 nm->getValueMinimum(), | 1322 nm->getValueMinimum(), |
1254 alignedDuration, | 1323 alignedDuration, |
1255 1.f, | 1324 1.f, |
1256 ""); | 1325 ""); |
1257 NoteModel::EditCommand *command = | 1326 ChangeEventsCommand *command = new ChangeEventsCommand(nm, name); |
1258 new NoteModel::EditCommand(nm, tr("Add Point")); | 1327 command->add(point); |
1259 command->addPoint(point); | |
1260 command->setName(name); | |
1261 c = command->finish(); | 1328 c = command->finish(); |
1262 } | 1329 } |
1263 | 1330 |
1264 if (c) { | |
1265 CommandHistory::getInstance()->addCommand(c, false); | |
1266 return; | |
1267 } | |
1268 | |
1269 FlexiNoteModel *fnm = dynamic_cast<FlexiNoteModel *>(layer->getModel()); | |
1270 if (fnm) { | |
1271 FlexiNoteModel::Point point(alignedStart, | |
1272 fnm->getValueMinimum(), | |
1273 alignedDuration, | |
1274 1.f, | |
1275 ""); | |
1276 FlexiNoteModel::EditCommand *command = | |
1277 new FlexiNoteModel::EditCommand(fnm, tr("Add Point")); | |
1278 command->addPoint(point); | |
1279 command->setName(name); | |
1280 c = command->finish(); | |
1281 } | |
1282 | |
1283 if (c) { | 1331 if (c) { |
1284 CommandHistory::getInstance()->addCommand(c, false); | 1332 CommandHistory::getInstance()->addCommand(c, false); |
1285 return; | 1333 return; |
1286 } | 1334 } |
1287 } | 1335 } |
1304 | 1352 |
1305 if (!m_labeller) return; | 1353 if (!m_labeller) return; |
1306 | 1354 |
1307 Labeller labeller(*m_labeller); | 1355 Labeller labeller(*m_labeller); |
1308 labeller.setSampleRate(sodm->getSampleRate()); | 1356 labeller.setSampleRate(sodm->getSampleRate()); |
1309 | 1357 /*!!! to be updated after SODM API update |
1310 Command *c = labeller.labelAll<SparseOneDimensionalModel::Point>(*sodm, &ms); | 1358 Command *c = labeller.labelAll<SparseOneDimensionalModel::Point>(*sodm, &ms); |
1311 if (c) CommandHistory::getInstance()->addCommand(c, false); | 1359 if (c) CommandHistory::getInstance()->addCommand(c, false); |
1360 */ | |
1312 } | 1361 } |
1313 | 1362 |
1314 void | 1363 void |
1315 MainWindowBase::subdivideInstantsBy(int n) | 1364 MainWindowBase::subdivideInstantsBy(int n) |
1316 { | 1365 { |
1330 if (!m_labeller) return; | 1379 if (!m_labeller) return; |
1331 | 1380 |
1332 Labeller labeller(*m_labeller); | 1381 Labeller labeller(*m_labeller); |
1333 labeller.setSampleRate(sodm->getSampleRate()); | 1382 labeller.setSampleRate(sodm->getSampleRate()); |
1334 | 1383 |
1384 (void)n; | |
1385 /*!!! to be updated after SODM API update | |
1335 Command *c = labeller.subdivide<SparseOneDimensionalModel::Point> | 1386 Command *c = labeller.subdivide<SparseOneDimensionalModel::Point> |
1336 (*sodm, &ms, n); | 1387 (*sodm, &ms, n); |
1337 if (c) CommandHistory::getInstance()->addCommand(c, false); | 1388 if (c) CommandHistory::getInstance()->addCommand(c, false); |
1389 */ | |
1338 } | 1390 } |
1339 | 1391 |
1340 void | 1392 void |
1341 MainWindowBase::winnowInstantsBy(int n) | 1393 MainWindowBase::winnowInstantsBy(int n) |
1342 { | 1394 { |
1356 if (!m_labeller) return; | 1408 if (!m_labeller) return; |
1357 | 1409 |
1358 Labeller labeller(*m_labeller); | 1410 Labeller labeller(*m_labeller); |
1359 labeller.setSampleRate(sodm->getSampleRate()); | 1411 labeller.setSampleRate(sodm->getSampleRate()); |
1360 | 1412 |
1413 (void)n; | |
1414 /*!!! to be updated after SODM API update | |
1361 Command *c = labeller.winnow<SparseOneDimensionalModel::Point> | 1415 Command *c = labeller.winnow<SparseOneDimensionalModel::Point> |
1362 (*sodm, &ms, n); | 1416 (*sodm, &ms, n); |
1363 if (c) CommandHistory::getInstance()->addCommand(c, false); | 1417 if (c) CommandHistory::getInstance()->addCommand(c, false); |
1418 */ | |
1364 } | 1419 } |
1365 | 1420 |
1366 MainWindowBase::FileOpenStatus | 1421 MainWindowBase::FileOpenStatus |
1367 MainWindowBase::openPath(QString fileOrUrl, AudioFileOpenMode mode) | 1422 MainWindowBase::openPath(QString fileOrUrl, AudioFileOpenMode mode) |
1368 { | 1423 { |
1630 SVDEBUG << "Now switching to ReplaceMainModel mode" << endl; | 1685 SVDEBUG << "Now switching to ReplaceMainModel mode" << endl; |
1631 mode = ReplaceMainModel; | 1686 mode = ReplaceMainModel; |
1632 } | 1687 } |
1633 | 1688 |
1634 emit activity(tr("Import audio file \"%1\"").arg(source.getLocation())); | 1689 emit activity(tr("Import audio file \"%1\"").arg(source.getLocation())); |
1635 | 1690 |
1636 if (mode == ReplaceMainModel) { | 1691 if (mode == ReplaceMainModel) { |
1637 | 1692 |
1638 Model *prevMain = getMainModel(); | 1693 Model *prevMain = getMainModel(); |
1639 if (prevMain) { | 1694 if (prevMain) { |
1640 m_playSource->removeModel(prevMain); | 1695 m_playSource->removeModel(prevMain); |
1646 | 1701 |
1647 m_document->setMainModel(newModel); | 1702 m_document->setMainModel(newModel); |
1648 | 1703 |
1649 setupMenus(); | 1704 setupMenus(); |
1650 | 1705 |
1706 m_originalLocation = source.getLocation(); | |
1707 | |
1651 if (loadedTemplate || (m_sessionFile == "")) { | 1708 if (loadedTemplate || (m_sessionFile == "")) { |
1652 //!!! shouldn't be dealing directly with title from here -- call a method | |
1653 setWindowTitle(tr("%1: %2") | |
1654 .arg(QApplication::applicationName()) | |
1655 .arg(source.getLocation())); | |
1656 CommandHistory::getInstance()->clear(); | 1709 CommandHistory::getInstance()->clear(); |
1657 CommandHistory::getInstance()->documentSaved(); | 1710 CommandHistory::getInstance()->documentSaved(); |
1658 m_documentModified = false; | 1711 m_documentModified = false; |
1659 } else { | 1712 } else { |
1660 setWindowTitle(tr("%1: %2 [%3]") | |
1661 .arg(QApplication::applicationName()) | |
1662 .arg(QFileInfo(m_sessionFile).fileName()) | |
1663 .arg(source.getLocation())); | |
1664 if (m_documentModified) { | 1713 if (m_documentModified) { |
1665 m_documentModified = false; | 1714 m_documentModified = false; |
1666 documentModified(); // so as to restore "(modified)" window title | |
1667 } | 1715 } |
1668 } | 1716 } |
1669 | 1717 |
1670 if (!source.isRemote() && registerSource) { | 1718 if (!source.isRemote() && registerSource) { |
1671 m_audioFile = source.getLocalFilename(); | 1719 m_audioFile = source.getLocalFilename(); |
1672 } | 1720 } |
1673 | 1721 |
1722 updateWindowTitle(); | |
1723 | |
1674 } else if (mode == CreateAdditionalModel) { | 1724 } else if (mode == CreateAdditionalModel) { |
1675 | 1725 |
1676 SVCERR << "Mode is CreateAdditionalModel" << endl; | 1726 SVCERR << "Mode is CreateAdditionalModel" << endl; |
1677 | 1727 |
1678 CommandHistory::getInstance()->startCompoundOperation | 1728 CommandHistory::getInstance()->startCompoundOperation |
2131 | 2181 |
2132 if (ok) { | 2182 if (ok) { |
2133 | 2183 |
2134 emit activity(tr("Import session file \"%1\"").arg(source.getLocation())); | 2184 emit activity(tr("Import session file \"%1\"").arg(source.getLocation())); |
2135 | 2185 |
2136 setWindowTitle(tr("%1: %2") | |
2137 .arg(QApplication::applicationName()) | |
2138 .arg(source.getLocation())); | |
2139 | |
2140 if (!source.isRemote() && !m_document->isIncomplete()) { | 2186 if (!source.isRemote() && !m_document->isIncomplete()) { |
2141 // Setting the session file path enables the Save (as | 2187 // Setting the session file path enables the Save (as |
2142 // opposed to Save As...) option. We can't do this if we | 2188 // opposed to Save As...) option. We can't do this if we |
2143 // don't have a local path to save to, but we also don't | 2189 // don't have a local path to save to, but we also don't |
2144 // want to do it if we failed to find an audio file or | 2190 // want to do it if we failed to find an audio file or |
2151 tr("Incomplete session loaded"), | 2197 tr("Incomplete session loaded"), |
2152 tr("Some of the audio content referred to by the original session file could not be loaded.\nIf you save this session, it will be saved without any reference to that audio, and information may be lost."), | 2198 tr("Some of the audio content referred to by the original session file could not be loaded.\nIf you save this session, it will be saved without any reference to that audio, and information may be lost."), |
2153 QMessageBox::Ok); | 2199 QMessageBox::Ok); |
2154 } | 2200 } |
2155 | 2201 |
2202 updateWindowTitle(); | |
2156 setupMenus(); | 2203 setupMenus(); |
2157 findTimeRulerLayer(); | 2204 findTimeRulerLayer(); |
2158 | 2205 |
2159 CommandHistory::getInstance()->clear(); | 2206 CommandHistory::getInstance()->clear(); |
2160 CommandHistory::getInstance()->documentSaved(); | 2207 CommandHistory::getInstance()->documentSaved(); |
2167 // for file dialog | 2214 // for file dialog |
2168 registerLastOpenedFilePath(FileFinder::SessionFile, | 2215 registerLastOpenedFilePath(FileFinder::SessionFile, |
2169 source.getLocalFilename()); | 2216 source.getLocalFilename()); |
2170 } | 2217 } |
2171 | 2218 |
2219 m_originalLocation = source.getLocation(); | |
2220 | |
2172 emit sessionLoaded(); | 2221 emit sessionLoaded(); |
2173 | 2222 |
2174 } else { | 2223 updateWindowTitle(); |
2175 setWindowTitle(QApplication::applicationName()); | 2224 } |
2176 } | 2225 |
2177 | |
2178 return ok ? FileOpenSucceeded : FileOpenFailed; | 2226 return ok ? FileOpenSucceeded : FileOpenFailed; |
2179 } | 2227 } |
2180 | 2228 |
2181 MainWindowBase::FileOpenStatus | 2229 MainWindowBase::FileOpenStatus |
2182 MainWindowBase::openSessionTemplate(QString templateName) | 2230 MainWindowBase::openSessionTemplate(QString templateName) |
2238 delete inputSource; | 2286 delete inputSource; |
2239 delete file; | 2287 delete file; |
2240 | 2288 |
2241 bool ok = (error == ""); | 2289 bool ok = (error == ""); |
2242 | 2290 |
2243 setWindowTitle(QApplication::applicationName()); | |
2244 | |
2245 if (ok) { | 2291 if (ok) { |
2246 | 2292 |
2247 emit activity(tr("Open session template \"%1\"").arg(source.getLocation())); | 2293 emit activity(tr("Open session template \"%1\"").arg(source.getLocation())); |
2248 | 2294 |
2249 setupMenus(); | 2295 setupMenus(); |
2255 updateMenuStates(); | 2301 updateMenuStates(); |
2256 | 2302 |
2257 emit sessionLoaded(); | 2303 emit sessionLoaded(); |
2258 } | 2304 } |
2259 | 2305 |
2306 updateWindowTitle(); | |
2307 | |
2260 return ok ? FileOpenSucceeded : FileOpenFailed; | 2308 return ok ? FileOpenSucceeded : FileOpenFailed; |
2261 } | 2309 } |
2262 | 2310 |
2263 MainWindowBase::FileOpenStatus | 2311 MainWindowBase::FileOpenStatus |
2264 MainWindowBase::openSessionFromRDF(FileSource source) | 2312 MainWindowBase::openSessionFromRDF(FileSource source) |
2277 | 2325 |
2278 FileOpenStatus status = openLayersFromRDF(source); | 2326 FileOpenStatus status = openLayersFromRDF(source); |
2279 | 2327 |
2280 setupMenus(); | 2328 setupMenus(); |
2281 findTimeRulerLayer(); | 2329 findTimeRulerLayer(); |
2282 | 2330 |
2283 setWindowTitle(tr("%1: %2") | |
2284 .arg(QApplication::applicationName()) | |
2285 .arg(source.getLocation())); | |
2286 CommandHistory::getInstance()->clear(); | 2331 CommandHistory::getInstance()->clear(); |
2287 CommandHistory::getInstance()->documentSaved(); | 2332 CommandHistory::getInstance()->documentSaved(); |
2288 m_documentModified = false; | 2333 m_documentModified = false; |
2334 updateWindowTitle(); | |
2289 | 2335 |
2290 emit sessionLoaded(); | 2336 emit sessionLoaded(); |
2291 | 2337 |
2292 return status; | 2338 return status; |
2293 } | 2339 } |
2647 connect(m_document, SIGNAL(alignmentComplete(AlignmentModel *)), | 2693 connect(m_document, SIGNAL(alignmentComplete(AlignmentModel *)), |
2648 this, SLOT(alignmentComplete(AlignmentModel *))); | 2694 this, SLOT(alignmentComplete(AlignmentModel *))); |
2649 connect(m_document, SIGNAL(alignmentFailed(QString)), | 2695 connect(m_document, SIGNAL(alignmentFailed(QString)), |
2650 this, SLOT(alignmentFailed(QString))); | 2696 this, SLOT(alignmentFailed(QString))); |
2651 | 2697 |
2698 m_document->setAutoAlignment(m_viewManager->getAlignMode()); | |
2699 | |
2652 emit replacedDocument(); | 2700 emit replacedDocument(); |
2653 } | 2701 } |
2654 | 2702 |
2655 bool | 2703 bool |
2656 MainWindowBase::saveSessionFile(QString path) | 2704 MainWindowBase::saveSessionFile(QString path) |
2732 QMessageBox::critical(this, tr("Failed to write file"), | 2780 QMessageBox::critical(this, tr("Failed to write file"), |
2733 tr("<b>Save failed</b><p>Failed to write to file \"%1\": %2") | 2781 tr("<b>Save failed</b><p>Failed to write to file \"%1\": %2") |
2734 .arg(path).arg(f.what())); | 2782 .arg(path).arg(f.what())); |
2735 return false; | 2783 return false; |
2736 } | 2784 } |
2785 } | |
2786 | |
2787 bool | |
2788 MainWindowBase::exportLayerTo(Layer *layer, QString path, QString &error) | |
2789 { | |
2790 if (QFileInfo(path).suffix() == "") path += ".svl"; | |
2791 | |
2792 QString suffix = QFileInfo(path).suffix().toLower(); | |
2793 | |
2794 Model *model = layer->getModel(); | |
2795 | |
2796 if (suffix == "xml" || suffix == "svl") { | |
2797 | |
2798 QFile file(path); | |
2799 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { | |
2800 error = tr("Failed to open file %1 for writing").arg(path); | |
2801 } else { | |
2802 QTextStream out(&file); | |
2803 out.setCodec(QTextCodec::codecForName("UTF-8")); | |
2804 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" | |
2805 << "<!DOCTYPE sonic-visualiser>\n" | |
2806 << "<sv>\n" | |
2807 << " <data>\n"; | |
2808 | |
2809 model->toXml(out, " "); | |
2810 | |
2811 out << " </data>\n" | |
2812 << " <display>\n"; | |
2813 | |
2814 layer->toXml(out, " "); | |
2815 | |
2816 out << " </display>\n" | |
2817 << "</sv>\n"; | |
2818 } | |
2819 | |
2820 } else if (suffix == "mid" || suffix == "midi") { | |
2821 | |
2822 NoteModel *nm = dynamic_cast<NoteModel *>(model); | |
2823 | |
2824 if (!nm) { | |
2825 error = tr("Can't export non-note layers to MIDI"); | |
2826 } else { | |
2827 MIDIFileWriter writer(path, nm, nm->getSampleRate()); | |
2828 writer.write(); | |
2829 if (!writer.isOK()) { | |
2830 error = writer.getError(); | |
2831 } | |
2832 } | |
2833 | |
2834 } else if (suffix == "ttl" || suffix == "n3") { | |
2835 | |
2836 if (!RDFExporter::canExportModel(model)) { | |
2837 error = tr("Sorry, cannot export this layer type to RDF (supported types are: region, note, text, time instants, time values)"); | |
2838 } else { | |
2839 RDFExporter exporter(path, model); | |
2840 exporter.write(); | |
2841 if (!exporter.isOK()) { | |
2842 error = exporter.getError(); | |
2843 } | |
2844 } | |
2845 | |
2846 } else { | |
2847 | |
2848 CSVFileWriter writer(path, model, | |
2849 ((suffix == "csv") ? "," : "\t")); | |
2850 writer.write(); | |
2851 | |
2852 if (!writer.isOK()) { | |
2853 error = writer.getError(); | |
2854 } | |
2855 } | |
2856 | |
2857 return (error == ""); | |
2737 } | 2858 } |
2738 | 2859 |
2739 void | 2860 void |
2740 MainWindowBase::toXml(QTextStream &out, bool asTemplate) | 2861 MainWindowBase::toXml(QTextStream &out, bool asTemplate) |
2741 { | 2862 { |
3179 | 3300 |
3180 m_document->setMainModel(model); | 3301 m_document->setMainModel(model); |
3181 setupMenus(); | 3302 setupMenus(); |
3182 findTimeRulerLayer(); | 3303 findTimeRulerLayer(); |
3183 | 3304 |
3305 m_originalLocation = model->getLocation(); | |
3306 | |
3184 if (loadedTemplate || (m_sessionFile == "")) { | 3307 if (loadedTemplate || (m_sessionFile == "")) { |
3185 //!!! shouldn't be dealing directly with title from here -- call a method | |
3186 setWindowTitle(tr("%1: %2") | |
3187 .arg(QApplication::applicationName()) | |
3188 .arg(model->getLocation())); | |
3189 CommandHistory::getInstance()->clear(); | 3308 CommandHistory::getInstance()->clear(); |
3190 CommandHistory::getInstance()->documentSaved(); | 3309 CommandHistory::getInstance()->documentSaved(); |
3191 m_documentModified = false; | 3310 } |
3192 } else { | 3311 |
3193 setWindowTitle(tr("%1: %2 [%3]") | 3312 m_documentModified = false; |
3194 .arg(QApplication::applicationName()) | 3313 updateWindowTitle(); |
3195 .arg(QFileInfo(m_sessionFile).fileName()) | |
3196 .arg(model->getLocation())); | |
3197 if (m_documentModified) { | |
3198 m_documentModified = false; | |
3199 documentModified(); // so as to restore "(modified)" window title | |
3200 } | |
3201 } | |
3202 | 3314 |
3203 } else { | 3315 } else { |
3204 | 3316 |
3205 CommandHistory::getInstance()->startCompoundOperation | 3317 CommandHistory::getInstance()->startCompoundOperation |
3206 (tr("Import Recorded Audio"), true); | 3318 (tr("Import Recorded Audio"), true); |