comparison framework/MainWindowBase.cpp @ 684:5e9b1956b609 by-id

ModelId updates
author Chris Cannam
date Wed, 03 Jul 2019 14:21:05 +0100
parents 331be52cd473
children 7540733f5480
comparison
equal deleted inserted replaced
683:0736beb8b852 684:5e9b1956b609
103 #include <QDateTime> 103 #include <QDateTime>
104 #include <QProcess> 104 #include <QProcess>
105 #include <QCheckBox> 105 #include <QCheckBox>
106 #include <QRegExp> 106 #include <QRegExp>
107 #include <QScrollArea> 107 #include <QScrollArea>
108 #include <QDesktopWidget> 108 #include <QScreen>
109 #include <QSignalMapper> 109 #include <QSignalMapper>
110 110
111 #include <iostream> 111 #include <iostream>
112 #include <cstdio> 112 #include <cstdio>
113 #include <errno.h> 113 #include <errno.h>
505 } 505 }
506 506
507 void 507 void
508 MainWindowBase::resizeConstrained(QSize size) 508 MainWindowBase::resizeConstrained(QSize size)
509 { 509 {
510 QDesktopWidget *desktop = QApplication::desktop(); 510 QScreen *screen = QApplication::primaryScreen();
511 QRect available = desktop->availableGeometry(); 511 QRect available = screen->availableGeometry();
512 QSize actual(std::min(size.width(), available.width()), 512 QSize actual(std::min(size.width(), available.width()),
513 std::min(size.height(), available.height())); 513 std::min(size.height(), available.height()));
514 resize(actual); 514 resize(actual);
515 } 515 }
516 516
573 MainWindowBase::getOpenFileName(FileFinder::FileType type) 573 MainWindowBase::getOpenFileName(FileFinder::FileType type)
574 { 574 {
575 FileFinder *ff = FileFinder::getInstance(); 575 FileFinder *ff = FileFinder::getInstance();
576 576
577 if (type == FileFinder::AnyFile) { 577 if (type == FileFinder::AnyFile) {
578 if (getMainModel() != nullptr && 578 if (!getMainModelId().isNone() &&
579 m_paneStack != nullptr && 579 m_paneStack != nullptr &&
580 m_paneStack->getCurrentPane() != nullptr) { // can import a layer 580 m_paneStack->getCurrentPane() != nullptr) { // can import a layer
581 return ff->getOpenFileName(FileFinder::AnyFile, m_sessionFile); 581 return ff->getOpenFileName(FileFinder::AnyFile, m_sessionFile);
582 } else { 582 } else {
583 return ff->getOpenFileName(FileFinder::SessionOrAudioFile, 583 return ff->getOpenFileName(FileFinder::SessionOrAudioFile,
666 (currentPane != nullptr); 666 (currentPane != nullptr);
667 bool haveCurrentLayer = 667 bool haveCurrentLayer =
668 (haveCurrentPane && 668 (haveCurrentPane &&
669 (currentLayer != nullptr)); 669 (currentLayer != nullptr));
670 bool haveMainModel = 670 bool haveMainModel =
671 (getMainModel() != nullptr); 671 (!getMainModelId().isNone());
672 bool havePlayTarget = 672 bool havePlayTarget =
673 (m_playTarget != nullptr || m_audioIO != nullptr); 673 (m_playTarget != nullptr || m_audioIO != nullptr);
674 bool haveSelection = 674 bool haveSelection =
675 (m_viewManager && 675 (m_viewManager &&
676 !m_viewManager->getSelections().empty()); 676 !m_viewManager->getSelections().empty());
691 bool haveClipboardContents = 691 bool haveClipboardContents =
692 (m_viewManager && 692 (m_viewManager &&
693 !m_viewManager->getClipboard().empty()); 693 !m_viewManager->getClipboard().empty());
694 bool haveTabularLayer = 694 bool haveTabularLayer =
695 (haveCurrentLayer && 695 (haveCurrentLayer &&
696 dynamic_cast<TabularModel *>(currentLayer->getModel())); 696 ModelById::isa<TabularModel>(currentLayer->getModel()));
697 697
698 emit canAddPane(haveMainModel); 698 emit canAddPane(haveMainModel);
699 emit canDeleteCurrentPane(haveCurrentPane); 699 emit canDeleteCurrentPane(haveCurrentPane);
700 emit canZoom(haveMainModel && haveCurrentPane); 700 emit canZoom(haveMainModel && haveCurrentPane);
701 emit canScroll(haveMainModel && haveCurrentPane); 701 emit canScroll(haveMainModel && haveCurrentPane);
837 } 837 }
838 838
839 if (m_viewManager->getPlaySoloMode()) { 839 if (m_viewManager->getPlaySoloMode()) {
840 currentPaneChanged(m_paneStack->getCurrentPane()); 840 currentPaneChanged(m_paneStack->getCurrentPane());
841 } else { 841 } else {
842 m_viewManager->setPlaybackModel(nullptr); 842 m_viewManager->setPlaybackModel({});
843 if (m_playSource) { 843 if (m_playSource) {
844 m_playSource->clearSoloModelSet(); 844 m_playSource->clearSoloModelSet();
845 } 845 }
846 } 846 }
847 } 847 }
855 if (!p) return; 855 if (!p) return;
856 856
857 if (!(m_viewManager && 857 if (!(m_viewManager &&
858 m_playSource && 858 m_playSource &&
859 m_viewManager->getPlaySoloMode())) { 859 m_viewManager->getPlaySoloMode())) {
860 if (m_viewManager) m_viewManager->setPlaybackModel(nullptr); 860 if (m_viewManager) {
861 m_viewManager->setPlaybackModel(ModelId());
862 }
861 return; 863 return;
862 } 864 }
863 865
864 Model *prevPlaybackModel = m_viewManager->getPlaybackModel(); 866 ModelId prevPlaybackModel = m_viewManager->getPlaybackModel();
865 867
866 // What we want here is not the currently playing frame (unless we 868 // What we want here is not the currently playing frame (unless we
867 // are about to clear out the audio playback buffers -- which may 869 // are about to clear out the audio playback buffers -- which may
868 // or may not be possible, depending on the audio driver). What 870 // or may not be possible, depending on the audio driver). What
869 // we want is the frame that was last committed to the soundcard 871 // we want is the frame that was last committed to the soundcard
876 cerr << "currentPaneChanged: current frame (in ref model) = " << frame << endl; 878 cerr << "currentPaneChanged: current frame (in ref model) = " << frame << endl;
877 879
878 View::ModelSet soloModels = p->getModels(); 880 View::ModelSet soloModels = p->getModels();
879 881
880 View::ModelSet sources; 882 View::ModelSet sources;
881 for (View::ModelSet::iterator mi = soloModels.begin(); 883 for (ModelId modelId: sources) {
882 mi != soloModels.end(); ++mi) {
883 // If a model in this pane is derived from something else, 884 // If a model in this pane is derived from something else,
884 // then we want to play that model as well -- if the model 885 // then we want to play that model as well -- if the model
885 // that's derived from it is not something that is itself 886 // that's derived from it is not something that is itself
886 // individually playable (e.g. a waveform) 887 // individually playable (e.g. a waveform)
887 if (*mi && 888 if (auto model = ModelById::get(modelId)) {
888 !dynamic_cast<RangeSummarisableTimeValueModel *>(*mi) && 889 if (!ModelById::isa<RangeSummarisableTimeValueModel>(modelId) &&
889 (*mi)->getSourceModel()) { 890 !model->getSourceModel().isNone()) {
890 sources.insert((*mi)->getSourceModel()); 891 sources.insert(model->getSourceModel());
891 } 892 }
892 } 893 }
893 for (View::ModelSet::iterator mi = sources.begin(); 894 }
894 mi != sources.end(); ++mi) { 895 for (ModelId modelId: sources) {
895 soloModels.insert(*mi); 896 soloModels.insert(modelId);
896 } 897 }
897 898
898 //!!! Need an "atomic" way of telling the play source that the 899 //!!! Need an "atomic" way of telling the play source that the
899 //playback model has changed, and changing it on ViewManager -- 900 //playback model has changed, and changing it on ViewManager --
900 //the play source should be making the setPlaybackModel call to 901 //the play source should be making the setPlaybackModel call to
901 //ViewManager 902 //ViewManager
902 903
903 for (View::ModelSet::iterator mi = soloModels.begin(); 904 ModelId newPlaybackModel;
904 mi != soloModels.end(); ++mi) { 905
905 if (dynamic_cast<RangeSummarisableTimeValueModel *>(*mi)) { 906 for (ModelId modelId: soloModels) {
906 m_viewManager->setPlaybackModel(*mi); 907 if (ModelById::isa<RangeSummarisableTimeValueModel>(modelId)) {
907 } 908 m_viewManager->setPlaybackModel(modelId);
908 } 909 newPlaybackModel = modelId;
909 910 }
910 RangeSummarisableTimeValueModel *a = 911 }
911 dynamic_cast<RangeSummarisableTimeValueModel *>(prevPlaybackModel);
912 RangeSummarisableTimeValueModel *b =
913 dynamic_cast<RangeSummarisableTimeValueModel *>(m_viewManager->
914 getPlaybackModel());
915 912
916 m_playSource->setSoloModelSet(soloModels); 913 m_playSource->setSoloModelSet(soloModels);
917 914
918 if (a && b && (a != b)) { 915 if (!prevPlaybackModel.isNone() && !newPlaybackModel.isNone() &&
919 if (m_playSource->isPlaying()) m_playSource->play(frame); 916 prevPlaybackModel != newPlaybackModel) {
917 if (m_playSource->isPlaying()) {
918 m_playSource->play(frame);
919 }
920 } 920 }
921 } 921 }
922 922
923 void 923 void
924 MainWindowBase::currentLayerChanged(Pane *p, Layer *) 924 MainWindowBase::currentLayerChanged(Pane *p, Layer *)
956 } 956 }
957 957
958 void 958 void
959 MainWindowBase::selectAll() 959 MainWindowBase::selectAll()
960 { 960 {
961 if (!getMainModel()) return;
962 m_viewManager->setSelection(Selection(getModelsStartFrame(), 961 m_viewManager->setSelection(Selection(getModelsStartFrame(),
963 getModelsEndFrame())); 962 getModelsEndFrame()));
964 } 963 }
965 964
966 void 965 void
967 MainWindowBase::selectToStart() 966 MainWindowBase::selectToStart()
968 { 967 {
969 if (!getMainModel()) return; 968 m_viewManager->setSelection(Selection(getModelsStartFrame(),
970 m_viewManager->setSelection(Selection(getMainModel()->getStartFrame(),
971 m_viewManager->getGlobalCentreFrame())); 969 m_viewManager->getGlobalCentreFrame()));
972 } 970 }
973 971
974 void 972 void
975 MainWindowBase::selectToEnd() 973 MainWindowBase::selectToEnd()
976 { 974 {
977 if (!getMainModel()) return;
978 m_viewManager->setSelection(Selection(m_viewManager->getGlobalCentreFrame(), 975 m_viewManager->setSelection(Selection(m_viewManager->getGlobalCentreFrame(),
979 getMainModel()->getEndFrame())); 976 getModelsEndFrame()));
980 } 977 }
981 978
982 void 979 void
983 MainWindowBase::selectVisible() 980 MainWindowBase::selectVisible()
984 { 981 {
985 Model *model = getMainModel(); 982 auto model = getMainModel();
986 if (!model) return; 983 if (!model) return;
987 984
988 Pane *currentPane = m_paneStack->getCurrentPane(); 985 Pane *currentPane = m_paneStack->getCurrentPane();
989 if (!currentPane) return; 986 if (!currentPane) return;
990 987
991 sv_frame_t startFrame, endFrame; 988 sv_frame_t startFrame, endFrame;
992 989
993 if (currentPane->getStartFrame() < 0) startFrame = 0; 990 if (currentPane->getStartFrame() < 0) {
994 else startFrame = currentPane->getStartFrame(); 991 startFrame = 0;
995 992 } else {
996 if (currentPane->getEndFrame() > model->getEndFrame()) endFrame = model->getEndFrame(); 993 startFrame = currentPane->getStartFrame();
997 else endFrame = currentPane->getEndFrame(); 994 }
995
996 if (currentPane->getEndFrame() > model->getEndFrame()) {
997 endFrame = model->getEndFrame();
998 } else {
999 endFrame = currentPane->getEndFrame();
1000 }
998 1001
999 m_viewManager->setSelection(Selection(startFrame, endFrame)); 1002 m_viewManager->setSelection(Selection(startFrame, endFrame));
1000 } 1003 }
1001 1004
1002 void 1005 void
1206 } 1209 }
1207 } 1210 }
1208 1211
1209 if (layer) { 1212 if (layer) {
1210 1213
1211 Model *model = layer->getModel(); 1214 ModelId model = layer->getModel();
1212 SparseOneDimensionalModel *sodm = 1215 auto sodm = ModelById::getAs<SparseOneDimensionalModel>(model);
1213 dynamic_cast<SparseOneDimensionalModel *>(model);
1214 1216
1215 if (sodm) { 1217 if (sodm) {
1216 Event point(frame, ""); 1218 Event point(frame, "");
1217 Event prevPoint(0); 1219 Event prevPoint(0);
1218 bool havePrevPoint = false; 1220 bool havePrevPoint = false;
1219 1221
1220 ChangeEventsCommand *command = 1222 ChangeEventsCommand *command =
1221 new ChangeEventsCommand(sodm, tr("Add Point")); 1223 new ChangeEventsCommand(model.untyped, tr("Add Point"));
1222 1224
1223 if (m_labeller) { 1225 if (m_labeller) {
1224 1226
1225 if (m_labeller->requiresPrevPoint()) { 1227 if (m_labeller->requiresPrevPoint()) {
1226 1228
1253 (frame, 1255 (frame,
1254 sodm->getSampleRate()) 1256 sodm->getSampleRate())
1255 .toText(false).c_str())); 1257 .toText(false).c_str()));
1256 1258
1257 Command *c = command->finish(); 1259 Command *c = command->finish();
1258 if (c) CommandHistory::getInstance()->addCommand(c, false); 1260 if (c) {
1261 CommandHistory::getInstance()->addCommand(c, false);
1262 }
1259 } 1263 }
1260 } 1264 }
1261 } 1265 }
1262 1266
1263 void 1267 void
1298 .toText(false).c_str()); 1302 .toText(false).c_str());
1299 1303
1300 Layer *layer = pane->getSelectedLayer(); 1304 Layer *layer = pane->getSelectedLayer();
1301 if (!layer) return; 1305 if (!layer) return;
1302 1306
1303 RegionModel *rm = dynamic_cast<RegionModel *>(layer->getModel()); 1307 auto rm = ModelById::getAs<RegionModel>(layer->getModel());
1304 if (rm) { 1308 if (rm) {
1305 Event point(alignedStart, 1309 Event point(alignedStart,
1306 rm->getValueMaximum() + 1, 1310 rm->getValueMaximum() + 1,
1307 alignedDuration, 1311 alignedDuration,
1308 ""); 1312 "");
1309 ChangeEventsCommand *command = new ChangeEventsCommand(rm, name); 1313 ChangeEventsCommand *command = new ChangeEventsCommand
1314 (rm->getId().untyped, name);
1310 command->add(point); 1315 command->add(point);
1311 c = command->finish(); 1316 c = command->finish();
1312 } 1317 }
1313 1318
1314 if (c) { 1319 if (c) {
1315 CommandHistory::getInstance()->addCommand(c, false); 1320 CommandHistory::getInstance()->addCommand(c, false);
1316 return; 1321 return;
1317 } 1322 }
1318 1323
1319 NoteModel *nm = dynamic_cast<NoteModel *>(layer->getModel()); 1324 auto nm = ModelById::getAs<NoteModel>(layer->getModel());
1320 if (nm) { 1325 if (nm) {
1321 Event point(alignedStart, 1326 Event point(alignedStart,
1322 nm->getValueMinimum(), 1327 nm->getValueMinimum(),
1323 alignedDuration, 1328 alignedDuration,
1324 1.f, 1329 1.f,
1325 ""); 1330 "");
1326 ChangeEventsCommand *command = new ChangeEventsCommand(nm, name); 1331 ChangeEventsCommand *command = new ChangeEventsCommand
1332 (nm->getId().untyped, name);
1327 command->add(point); 1333 command->add(point);
1328 c = command->finish(); 1334 c = command->finish();
1329 } 1335 }
1330 1336
1331 if (c) { 1337 if (c) {
1343 Layer *layer = dynamic_cast<TimeInstantLayer *>(pane->getSelectedLayer()); 1349 Layer *layer = dynamic_cast<TimeInstantLayer *>(pane->getSelectedLayer());
1344 if (!layer) return; 1350 if (!layer) return;
1345 1351
1346 MultiSelection ms(m_viewManager->getSelection()); 1352 MultiSelection ms(m_viewManager->getSelection());
1347 1353
1348 Model *model = layer->getModel(); 1354 auto sodm = ModelById::getAs<SparseOneDimensionalModel>(layer->getModel());
1349 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
1350 (model);
1351 if (!sodm) return; 1355 if (!sodm) return;
1352 1356
1353 if (!m_labeller) return; 1357 if (!m_labeller) return;
1354 1358
1355 Labeller labeller(*m_labeller); 1359 Labeller labeller(*m_labeller);
1356 labeller.setSampleRate(sodm->getSampleRate()); 1360 labeller.setSampleRate(sodm->getSampleRate());
1357 /*!!! to be updated after SODM API update 1361
1358 Command *c = labeller.labelAll<SparseOneDimensionalModel::Point>(*sodm, &ms); 1362 /*!!!
1363 Command *c = labeller.labelAll(sodm->getId().untyped, &ms);
1359 if (c) CommandHistory::getInstance()->addCommand(c, false); 1364 if (c) CommandHistory::getInstance()->addCommand(c, false);
1360 */ 1365 */
1361 } 1366 }
1362 1367
1363 void 1368 void
1369 Layer *layer = dynamic_cast<TimeInstantLayer *>(pane->getSelectedLayer()); 1374 Layer *layer = dynamic_cast<TimeInstantLayer *>(pane->getSelectedLayer());
1370 if (!layer) return; 1375 if (!layer) return;
1371 1376
1372 MultiSelection ms(m_viewManager->getSelection()); 1377 MultiSelection ms(m_viewManager->getSelection());
1373 1378
1374 Model *model = layer->getModel(); 1379 auto sodm = ModelById::getAs<SparseOneDimensionalModel>(layer->getModel());
1375 SparseOneDimensionalModel *sodm =
1376 dynamic_cast<SparseOneDimensionalModel *>(model);
1377 if (!sodm) return; 1380 if (!sodm) return;
1378 1381
1379 if (!m_labeller) return; 1382 if (!m_labeller) return;
1380 1383
1381 Labeller labeller(*m_labeller); 1384 Labeller labeller(*m_labeller);
1382 labeller.setSampleRate(sodm->getSampleRate()); 1385 labeller.setSampleRate(sodm->getSampleRate());
1383 1386
1384 (void)n; 1387 (void)n;
1385 /*!!! to be updated after SODM API update 1388 /*!!!
1386 Command *c = labeller.subdivide<SparseOneDimensionalModel::Point> 1389 Command *c = labeller.subdivide(sodm->getId().untyped, &ms, n);
1387 (*sodm, &ms, n);
1388 if (c) CommandHistory::getInstance()->addCommand(c, false); 1390 if (c) CommandHistory::getInstance()->addCommand(c, false);
1389 */ 1391 */
1390 } 1392 }
1391 1393
1392 void 1394 void
1393 MainWindowBase::winnowInstantsBy(int n) 1395 MainWindowBase::winnowInstantsBy(int n)
1394 { 1396 {
1398 Layer *layer = dynamic_cast<TimeInstantLayer *>(pane->getSelectedLayer()); 1400 Layer *layer = dynamic_cast<TimeInstantLayer *>(pane->getSelectedLayer());
1399 if (!layer) return; 1401 if (!layer) return;
1400 1402
1401 MultiSelection ms(m_viewManager->getSelection()); 1403 MultiSelection ms(m_viewManager->getSelection());
1402 1404
1403 Model *model = layer->getModel(); 1405 auto sodm = ModelById::getAs<SparseOneDimensionalModel>(layer->getModel());
1404 SparseOneDimensionalModel *sodm =
1405 dynamic_cast<SparseOneDimensionalModel *>(model);
1406 if (!sodm) return; 1406 if (!sodm) return;
1407 1407
1408 if (!m_labeller) return; 1408 if (!m_labeller) return;
1409 1409
1410 Labeller labeller(*m_labeller); 1410 Labeller labeller(*m_labeller);
1411 labeller.setSampleRate(sodm->getSampleRate()); 1411 labeller.setSampleRate(sodm->getSampleRate());
1412 1412
1413 (void)n; 1413 (void)n;
1414 /*!!! to be updated after SODM API update 1414 //!!! to update: (and the above two functions)
1415 Command *c = labeller.winnow<SparseOneDimensionalModel::Point> 1415 /*
1416 (*sodm, &ms, n); 1416 Command *c = labeller.winnow(sodm->getId.untyped, &ms, n);
1417 if (c) CommandHistory::getInstance()->addCommand(c, false); 1417 if (c) CommandHistory::getInstance()->addCommand(c, false);
1418 */ 1418 */
1419 } 1419 }
1420 1420
1421 MainWindowBase::FileOpenStatus 1421 MainWindowBase::FileOpenStatus
1422 MainWindowBase::openPath(QString fileOrUrl, AudioFileOpenMode mode) 1422 MainWindowBase::openPath(QString fileOrUrl, AudioFileOpenMode mode)
1423 { 1423 {
1563 1563
1564 if (rate == 0) { 1564 if (rate == 0) {
1565 SVDEBUG << "Yes, preserving incoming file rate" << endl; 1565 SVDEBUG << "Yes, preserving incoming file rate" << endl;
1566 } 1566 }
1567 1567
1568 ReadOnlyWaveFileModel *newModel = new ReadOnlyWaveFileModel(source, rate); 1568 auto newModel = std::make_shared<ReadOnlyWaveFileModel>(source, rate);
1569
1570 if (!newModel->isOK()) { 1569 if (!newModel->isOK()) {
1571 delete newModel;
1572 m_openingAudioFile = false; 1570 m_openingAudioFile = false;
1573 if (source.wasCancelled()) { 1571 if (source.wasCancelled()) {
1574 return FileOpenCancelled; 1572 return FileOpenCancelled;
1575 } else { 1573 } else {
1576 return FileOpenFailed; 1574 return FileOpenFailed;
1577 } 1575 }
1578 } 1576 }
1579 1577
1580 return addOpenedAudioModel(source, newModel, mode, templateName, true); 1578 ModelById::add(newModel);
1579
1580 return addOpenedAudioModel(source, newModel->getId(),
1581 mode, templateName, true);
1581 } 1582 }
1582 1583
1583 MainWindowBase::FileOpenStatus 1584 MainWindowBase::FileOpenStatus
1584 MainWindowBase::addOpenedAudioModel(FileSource source, 1585 MainWindowBase::addOpenedAudioModel(FileSource source,
1585 WaveFileModel *newModel, 1586 ModelId newModel,
1586 AudioFileOpenMode mode, 1587 AudioFileOpenMode mode,
1587 QString templateName, 1588 QString templateName,
1588 bool registerSource) 1589 bool registerSource)
1589 { 1590 {
1590 if (mode == AskUser) { 1591 if (mode == AskUser) {
1606 (this, tr("Select target for import"), 1607 (this, tr("Select target for import"),
1607 tr("<b>Select a target for import</b><p>You already have an audio file loaded.<br>What would you like to do with the new audio file?"), 1608 tr("<b>Select a target for import</b><p>You already have an audio file loaded.<br>What would you like to do with the new audio file?"),
1608 items, lastMode, &ok); 1609 items, lastMode, &ok);
1609 1610
1610 if (!ok || item.isEmpty()) { 1611 if (!ok || item.isEmpty()) {
1611 delete newModel; 1612 ModelById::release(newModel);
1612 m_openingAudioFile = false; 1613 m_openingAudioFile = false;
1613 return FileOpenCancelled; 1614 return FileOpenCancelled;
1614 } 1615 }
1615 1616
1616 for (int i = 0; i < items.size(); ++i) { 1617 for (int i = 0; i < items.size(); ++i) {
1633 1634
1634 Pane *pane = m_paneStack->getCurrentPane(); 1635 Pane *pane = m_paneStack->getCurrentPane();
1635 if (pane) { 1636 if (pane) {
1636 if (getMainModel()) { 1637 if (getMainModel()) {
1637 View::ModelSet models(pane->getModels()); 1638 View::ModelSet models(pane->getModels());
1638 if (models.find(getMainModel()) != models.end()) { 1639 if (models.find(getMainModelId()) != models.end()) {
1639 // Current pane contains main model: replace that 1640 // Current pane contains main model: replace that
1640 mode = ReplaceMainModel; 1641 mode = ReplaceMainModel;
1641 } 1642 }
1642 // Otherwise the current pane has a non-default model, 1643 // Otherwise the current pane has a non-default model,
1643 // which we will deal with later 1644 // which we will deal with later
1650 // We seem to have no current pane! Oh well 1651 // We seem to have no current pane! Oh well
1651 mode = CreateAdditionalModel; 1652 mode = CreateAdditionalModel;
1652 } 1653 }
1653 } 1654 }
1654 1655
1655 if (mode == CreateAdditionalModel && !getMainModel()) { 1656 if (mode == CreateAdditionalModel && getMainModelId().isNone()) {
1656 SVDEBUG << "Mode is CreateAdditionalModel but we have no main model, switching to ReplaceSession mode" << endl; 1657 SVDEBUG << "Mode is CreateAdditionalModel but we have no main model, switching to ReplaceSession mode" << endl;
1657 mode = ReplaceSession; 1658 mode = ReplaceSession;
1658 } 1659 }
1659 1660
1660 bool loadedTemplate = false; 1661 bool loadedTemplate = false;
1688 1689
1689 emit activity(tr("Import audio file \"%1\"").arg(source.getLocation())); 1690 emit activity(tr("Import audio file \"%1\"").arg(source.getLocation()));
1690 1691
1691 if (mode == ReplaceMainModel) { 1692 if (mode == ReplaceMainModel) {
1692 1693
1693 Model *prevMain = getMainModel(); 1694 ModelId prevMain = getMainModelId();
1694 if (prevMain) { 1695 if (!prevMain.isNone()) {
1695 m_playSource->removeModel(prevMain); 1696 m_playSource->removeModel(prevMain);
1696 PlayParameterRepository::getInstance()->removePlayable(prevMain); 1697 //!!! shouldn't this stuff be handled by Document?
1697 } 1698 PlayParameterRepository::getInstance()->removePlayable
1698 PlayParameterRepository::getInstance()->addPlayable(newModel); 1699 (prevMain.untyped);
1700 }
1701 PlayParameterRepository::getInstance()->addPlayable(newModel.untyped);
1699 1702
1700 SVDEBUG << "SV about to call setMainModel(" << newModel << "): prevMain is " << prevMain << endl; 1703 SVDEBUG << "SV about to call setMainModel(" << newModel << "): prevMain is " << prevMain << endl;
1701 1704
1702 m_document->setMainModel(newModel); 1705 m_document->setMainModel(newModel);
1703 1706
1930 1933
1931 try { 1934 try {
1932 1935
1933 MIDIFileImportDialog midiDlg(this); 1936 MIDIFileImportDialog midiDlg(this);
1934 1937
1935 Model *model = DataFileReaderFactory::loadNonCSV 1938 Model *newModelPtr = DataFileReaderFactory::loadNonCSV
1936 (path, &midiDlg, getMainModel()->getSampleRate()); 1939 (path, &midiDlg, getMainModel()->getSampleRate());
1937 1940
1938 if (!model) { 1941 if (!newModelPtr) {
1939 CSVFormatDialog *dialog = 1942 CSVFormatDialog *dialog =
1940 new CSVFormatDialog(this, 1943 new CSVFormatDialog(this,
1941 path, 1944 path,
1942 getMainModel()->getSampleRate(), 1945 getMainModel()->getSampleRate(),
1943 5); 1946 5);
1944 if (dialog->exec() == QDialog::Accepted) { 1947 if (dialog->exec() == QDialog::Accepted) {
1945 model = DataFileReaderFactory::loadCSV 1948 newModelPtr = DataFileReaderFactory::loadCSV
1946 (path, dialog->getFormat(), 1949 (path, dialog->getFormat(),
1947 getMainModel()->getSampleRate()); 1950 getMainModel()->getSampleRate());
1948 } 1951 }
1949 delete dialog; 1952 delete dialog;
1950 } 1953 }
1951 1954
1952 if (model) { 1955 if (newModelPtr) {
1953 1956
1954 SVDEBUG << "MainWindowBase::openLayer: Have model" << endl; 1957 SVDEBUG << "MainWindowBase::openLayer: Have model" << endl;
1955 1958
1956 emit activity(tr("Import MIDI file \"%1\"").arg(source.getLocation())); 1959 emit activity(tr("Import MIDI file \"%1\"").arg(source.getLocation()));
1957 1960
1958 Layer *newLayer = m_document->createImportedLayer(model); 1961 ModelId modelId = newModelPtr->getId();
1962 ModelById::add(std::shared_ptr<Model>(newModelPtr));
1963
1964 Layer *newLayer = m_document->createImportedLayer(modelId);
1959 1965
1960 if (newLayer) { 1966 if (newLayer) {
1961 1967
1962 m_document->addLayerToView(pane, newLayer); 1968 m_document->addLayerToView(pane, newLayer);
1963 m_paneStack->setCurrentLayer(pane, newLayer); 1969 m_paneStack->setCurrentLayer(pane, newLayer);
1994 // shouldn't happen, as the menu action should have been disabled 2000 // shouldn't happen, as the menu action should have been disabled
1995 cerr << "WARNING: MainWindowBase::openImage: no current pane" << endl; 2001 cerr << "WARNING: MainWindowBase::openImage: no current pane" << endl;
1996 return FileOpenWrongMode; 2002 return FileOpenWrongMode;
1997 } 2003 }
1998 2004
1999 if (!m_document->getMainModel()) { 2005 if (!getMainModel()) {
2000 return FileOpenWrongMode; 2006 return FileOpenWrongMode;
2001 } 2007 }
2002 2008
2003 bool newLayer = false; 2009 bool newLayer = false;
2004 2010
2367 .arg(source.getLocation()).arg(importer.getErrorString())); 2373 .arg(source.getLocation()).arg(importer.getErrorString()));
2368 } 2374 }
2369 return FileOpenFailed; 2375 return FileOpenFailed;
2370 } 2376 }
2371 2377
2372 std::vector<Model *> models = importer.getDataModels(&dialog); 2378 std::vector<Model *> modelPtrs = importer.getDataModels(&dialog);
2373 2379
2374 dialog.setMessage(tr("Importing from RDF...")); 2380 dialog.setMessage(tr("Importing from RDF..."));
2375 2381
2376 if (models.empty()) { 2382 if (modelPtrs.empty()) {
2377 QMessageBox::critical 2383 QMessageBox::critical
2378 (this, tr("Failed to import RDF"), 2384 (this, tr("Failed to import RDF"),
2379 tr("<b>Failed to import RDF</b><p>No suitable data models found for import from RDF document at \"%1\"</p>").arg(source.getLocation())); 2385 tr("<b>Failed to import RDF</b><p>No suitable data models found for import from RDF document at \"%1\"</p>").arg(source.getLocation()));
2380 return FileOpenFailed; 2386 return FileOpenFailed;
2381 } 2387 }
2382 2388
2383 emit activity(tr("Import RDF document \"%1\"").arg(source.getLocation())); 2389 emit activity(tr("Import RDF document \"%1\"").arg(source.getLocation()));
2384 2390
2385 std::set<Model *> added; 2391 std::set<ModelId> modelIds;
2386 2392
2387 for (int i = 0; i < (int)models.size(); ++i) { 2393 for (Model *modelPtr: modelPtrs) {
2388 2394 modelIds.insert(modelPtr->getId());
2389 Model *m = models[i]; 2395 ModelById::add(std::shared_ptr<Model>(modelPtr));
2390 WaveFileModel *w = dynamic_cast<WaveFileModel *>(m); 2396 }
2391 2397
2392 if (w) { 2398 std::set<ModelId> added;
2399
2400 for (auto modelId: modelIds) {
2401
2402 if (ModelById::isa<WaveFileModel>(modelId)) {
2393 2403
2394 Pane *pane = addPaneToStack(); 2404 Pane *pane = addPaneToStack();
2395 Layer *layer = nullptr; 2405 Layer *layer = nullptr;
2396 2406
2397 if (m_timeRulerLayer) { 2407 if (m_timeRulerLayer) {
2398 m_document->addLayerToView(pane, m_timeRulerLayer); 2408 m_document->addLayerToView(pane, m_timeRulerLayer);
2399 } 2409 }
2400 2410
2401 if (!getMainModel()) { 2411 if (!getMainModel()) {
2402 m_document->setMainModel(w); 2412 m_document->setMainModel(modelId);
2403 layer = m_document->createMainModelLayer(LayerFactory::Waveform); 2413 layer = m_document->createMainModelLayer(LayerFactory::Waveform);
2404 } else { 2414 } else {
2405 layer = m_document->createImportedLayer(w); 2415 layer = m_document->createImportedLayer(modelId);
2406 } 2416 }
2407 2417
2408 m_document->addLayerToView(pane, layer); 2418 m_document->addLayerToView(pane, layer);
2409 2419
2410 added.insert(w); 2420 added.insert(modelId);
2411 2421
2412 for (int j = 0; j < (int)models.size(); ++j) { 2422 for (auto otherId: modelIds) {
2413 2423
2414 Model *dm = models[j]; 2424 if (otherId == modelId) continue;
2415 2425
2416 if (dm == m) continue; 2426 bool isDependent = false;
2417 if (dm->getSourceModel() != m) continue; 2427 if (auto dm = ModelById::get(otherId)) {
2418 2428 if (dm->getSourceModel() == modelId) {
2419 layer = m_document->createImportedLayer(dm); 2429 isDependent = true;
2430 }
2431 }
2432 if (!isDependent) continue;
2433
2434 layer = m_document->createImportedLayer(otherId);
2420 2435
2421 if (layer->isLayerOpaque() || 2436 if (layer->isLayerOpaque() ||
2422 dynamic_cast<Colour3DPlotLayer *>(layer)) { 2437 dynamic_cast<Colour3DPlotLayer *>(layer)) {
2423 2438
2424 // these always go in a new pane, with nothing 2439 // these always go in a new pane, with nothing
2460 } 2475 }
2461 2476
2462 m_document->addLayerToView(pane, layer); 2477 m_document->addLayerToView(pane, layer);
2463 } 2478 }
2464 2479
2465 added.insert(dm); 2480 added.insert(otherId);
2466 } 2481 }
2467 } 2482 }
2468 } 2483 }
2469 2484
2470 for (int i = 0; i < (int)models.size(); ++i) { 2485 for (auto modelId : modelIds) {
2471 2486
2472 Model *m = models[i]; 2487 if (added.find(modelId) == added.end()) {
2473
2474 if (added.find(m) == added.end()) {
2475 2488
2476 Layer *layer = m_document->createImportedLayer(m); 2489 Layer *layer = m_document->createImportedLayer(modelId);
2477 if (!layer) return FileOpenFailed; 2490 if (!layer) return FileOpenFailed;
2478 2491
2479 Pane *singleLayerPane = addPaneToStack(); 2492 Pane *singleLayerPane = addPaneToStack();
2480 if (m_timeRulerLayer) { 2493 if (m_timeRulerLayer) {
2481 m_document->addLayerToView(singleLayerPane, m_timeRulerLayer); 2494 m_document->addLayerToView(singleLayerPane, m_timeRulerLayer);
2649 SVCERR << "MainWindowBase::audioChannelCountIncreased: we were recording already, so resuming IO now" << endl; 2662 SVCERR << "MainWindowBase::audioChannelCountIncreased: we were recording already, so resuming IO now" << endl;
2650 m_audioIO->resume(); 2663 m_audioIO->resume();
2651 } 2664 }
2652 } 2665 }
2653 2666
2654 WaveFileModel * 2667 ModelId
2668 MainWindowBase::getMainModelId()
2669 {
2670 if (!m_document) return {};
2671 return m_document->getMainModel();
2672 }
2673
2674 std::shared_ptr<WaveFileModel>
2655 MainWindowBase::getMainModel() 2675 MainWindowBase::getMainModel()
2656 { 2676 {
2657 if (!m_document) return nullptr; 2677 return ModelById::getAs<WaveFileModel>(getMainModelId());
2658 return m_document->getMainModel();
2659 }
2660
2661 const WaveFileModel *
2662 MainWindowBase::getMainModel() const
2663 {
2664 if (!m_document) return nullptr;
2665 return m_document->getMainModel();
2666 } 2678 }
2667 2679
2668 void 2680 void
2669 MainWindowBase::createDocument() 2681 MainWindowBase::createDocument()
2670 { 2682 {
2677 connect(m_document, SIGNAL(layerAboutToBeDeleted(Layer *)), 2689 connect(m_document, SIGNAL(layerAboutToBeDeleted(Layer *)),
2678 this, SLOT(layerAboutToBeDeleted(Layer *))); 2690 this, SLOT(layerAboutToBeDeleted(Layer *)));
2679 connect(m_document, SIGNAL(layerInAView(Layer *, bool)), 2691 connect(m_document, SIGNAL(layerInAView(Layer *, bool)),
2680 this, SLOT(layerInAView(Layer *, bool))); 2692 this, SLOT(layerInAView(Layer *, bool)));
2681 2693
2682 connect(m_document, SIGNAL(modelAdded(Model *)), 2694 connect(m_document, SIGNAL(modelAdded(ModelId )),
2683 this, SLOT(modelAdded(Model *))); 2695 this, SLOT(modelAdded(ModelId )));
2684 connect(m_document, SIGNAL(mainModelChanged(WaveFileModel *)), 2696 connect(m_document, SIGNAL(mainModelChanged(WaveFileModel *)),
2685 this, SLOT(mainModelChanged(WaveFileModel *))); 2697 this, SLOT(mainModelChanged(WaveFileModel *)));
2686 connect(m_document, SIGNAL(modelAboutToBeDeleted(Model *)), 2698 connect(m_document, SIGNAL(modelAboutToBeDeleted(ModelId )),
2687 this, SLOT(modelAboutToBeDeleted(Model *))); 2699 this, SLOT(modelAboutToBeDeleted(ModelId )));
2688 2700
2689 connect(m_document, SIGNAL(modelGenerationFailed(QString, QString)), 2701 connect(m_document, SIGNAL(modelGenerationFailed(QString, QString)),
2690 this, SLOT(modelGenerationFailed(QString, QString))); 2702 this, SLOT(modelGenerationFailed(QString, QString)));
2691 connect(m_document, SIGNAL(modelRegenerationWarning(QString, QString, QString)), 2703 connect(m_document, SIGNAL(modelRegenerationWarning(QString, QString, QString)),
2692 this, SLOT(modelRegenerationWarning(QString, QString, QString))); 2704 this, SLOT(modelRegenerationWarning(QString, QString, QString)));
2789 { 2801 {
2790 if (QFileInfo(path).suffix() == "") path += ".svl"; 2802 if (QFileInfo(path).suffix() == "") path += ".svl";
2791 2803
2792 QString suffix = QFileInfo(path).suffix().toLower(); 2804 QString suffix = QFileInfo(path).suffix().toLower();
2793 2805
2794 Model *model = layer->getModel(); 2806 auto model = ModelById::get(layer->getModel());
2807 if (!model) {
2808 error = tr("Internal error: unknown model");
2809 return false;
2810 }
2795 2811
2796 if (suffix == "xml" || suffix == "svl") { 2812 if (suffix == "xml" || suffix == "svl") {
2797 2813
2798 QFile file(path); 2814 QFile file(path);
2799 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { 2815 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
2817 << "</sv>\n"; 2833 << "</sv>\n";
2818 } 2834 }
2819 2835
2820 } else if (suffix == "mid" || suffix == "midi") { 2836 } else if (suffix == "mid" || suffix == "midi") {
2821 2837
2822 NoteModel *nm = dynamic_cast<NoteModel *>(model); 2838 auto nm = ModelById::getAs<NoteModel>(layer->getModel());
2823 2839
2824 if (!nm) { 2840 if (!nm) {
2825 error = tr("Can't export non-note layers to MIDI"); 2841 error = tr("Can't export non-note layers to MIDI");
2826 } else { 2842 } else {
2827 MIDIFileWriter writer(path, nm, nm->getSampleRate()); 2843 MIDIFileWriter writer(path, nm.get(), nm->getSampleRate());
2828 writer.write(); 2844 writer.write();
2829 if (!writer.isOK()) { 2845 if (!writer.isOK()) {
2830 error = writer.getError(); 2846 error = writer.getError();
2831 } 2847 }
2832 } 2848 }
2833 2849
2834 } else if (suffix == "ttl" || suffix == "n3") { 2850 } else if (suffix == "ttl" || suffix == "n3") {
2835 2851
2836 if (!RDFExporter::canExportModel(model)) { 2852 if (!RDFExporter::canExportModel(model.get())) {
2837 error = tr("Sorry, cannot export this layer type to RDF (supported types are: region, note, text, time instants, time values)"); 2853 error = tr("Sorry, cannot export this layer type to RDF (supported types are: region, note, text, time instants, time values)");
2838 } else { 2854 } else {
2839 RDFExporter exporter(path, model); 2855 RDFExporter exporter(path, model.get());
2840 exporter.write(); 2856 exporter.write();
2841 if (!exporter.isOK()) { 2857 if (!exporter.isOK()) {
2842 error = exporter.getError(); 2858 error = exporter.getError();
2843 } 2859 }
2844 } 2860 }
2845 2861
2846 } else { 2862 } else {
2847 2863
2848 CSVFileWriter writer(path, model, 2864 CSVFileWriter writer(path, model.get(),
2849 ((suffix == "csv") ? "," : "\t")); 2865 ((suffix == "csv") ? "," : "\t"));
2850 writer.write(); 2866 writer.write();
2851 2867
2852 if (!writer.isOK()) { 2868 if (!writer.isOK()) {
2853 error = writer.getError(); 2869 error = writer.getError();
2921 MainWindowBase::zoomToFit() 2937 MainWindowBase::zoomToFit()
2922 { 2938 {
2923 Pane *currentPane = m_paneStack->getCurrentPane(); 2939 Pane *currentPane = m_paneStack->getCurrentPane();
2924 if (!currentPane) return; 2940 if (!currentPane) return;
2925 2941
2926 Model *model = getMainModel(); 2942 auto model = getMainModel();
2927 if (!model) return; 2943 if (!model) return;
2928 2944
2929 sv_frame_t start = model->getStartFrame(); 2945 sv_frame_t start = model->getStartFrame();
2930 sv_frame_t end = model->getEndFrame(); 2946 sv_frame_t end = model->getEndFrame();
2931 if (m_playSource) end = std::max(end, m_playSource->getPlayEndFrame()); 2947 if (m_playSource) end = std::max(end, m_playSource->getPlayEndFrame());
3241 if (m_viewManager) m_viewManager->setGlobalCentreFrame(0); 3257 if (m_viewManager) m_viewManager->setGlobalCentreFrame(0);
3242 3258
3243 SVCERR << "MainWindowBase::record: about to resume" << endl; 3259 SVCERR << "MainWindowBase::record: about to resume" << endl;
3244 m_audioIO->resume(); 3260 m_audioIO->resume();
3245 3261
3246 WritableWaveFileModel *model = m_recordTarget->startRecording(); 3262 WritableWaveFileModel *modelPtr = m_recordTarget->startRecording();
3247 if (!model) { 3263 if (!modelPtr) {
3248 SVCERR << "ERROR: MainWindowBase::record: Recording failed" << endl; 3264 SVCERR << "ERROR: MainWindowBase::record: Recording failed" << endl;
3249 QMessageBox::critical 3265 QMessageBox::critical
3250 (this, tr("Recording failed"), 3266 (this, tr("Recording failed"),
3251 tr("<b>Recording failed</b><p>Failed to switch to record mode (some internal problem?)</p>")); 3267 tr("<b>Recording failed</b><p>Failed to switch to record mode (some internal problem?)</p>"));
3252 if (action) action->setChecked(false); 3268 if (action) action->setChecked(false);
3253 return; 3269 return;
3254 } 3270 }
3255 3271
3256 if (!model->isOK()) { 3272 if (!modelPtr->isOK()) {
3257 SVCERR << "MainWindowBase::record: Model not OK, stopping and suspending" << endl; 3273 SVCERR << "MainWindowBase::record: Model not OK, stopping and suspending" << endl;
3258 m_recordTarget->stopRecording(); 3274 m_recordTarget->stopRecording();
3259 m_audioIO->suspend(); 3275 m_audioIO->suspend();
3260 if (action) action->setChecked(false); 3276 if (action) action->setChecked(false);
3261 delete model; 3277 delete modelPtr;
3262 return; 3278 return;
3263 } 3279 }
3264 3280
3265 SVCERR << "MainWindowBase::record: Model is OK, continuing..." << endl; 3281 SVCERR << "MainWindowBase::record: Model is OK, continuing..." << endl;
3266 3282
3267 PlayParameterRepository::getInstance()->addPlayable(model); 3283 QString location = modelPtr->getLocation();
3284
3285 auto modelId = modelPtr->getId();
3286 ModelById::add(std::shared_ptr<Model>(modelPtr));
3287 PlayParameterRepository::getInstance()->addPlayable(modelId.untyped);
3268 3288
3269 if (m_audioRecordMode == RecordReplaceSession || !getMainModel()) { 3289 if (m_audioRecordMode == RecordReplaceSession || !getMainModel()) {
3270 3290
3271 //!!! duplication with openAudio here 3291 //!!! duplication with openAudio here
3272 3292
3277 FileOpenStatus tplStatus = openSessionTemplate(templateName); 3297 FileOpenStatus tplStatus = openSessionTemplate(templateName);
3278 if (tplStatus == FileOpenCancelled) { 3298 if (tplStatus == FileOpenCancelled) {
3279 SVCERR << "MainWindowBase::record: Session template open cancelled, stopping and suspending" << endl; 3299 SVCERR << "MainWindowBase::record: Session template open cancelled, stopping and suspending" << endl;
3280 m_recordTarget->stopRecording(); 3300 m_recordTarget->stopRecording();
3281 m_audioIO->suspend(); 3301 m_audioIO->suspend();
3282 PlayParameterRepository::getInstance()->removePlayable(model); 3302 PlayParameterRepository::getInstance()->removePlayable
3303 (modelId.untyped);
3304 ModelById::release(modelId);
3283 return; 3305 return;
3284 } 3306 }
3285 if (tplStatus != FileOpenFailed) { 3307 if (tplStatus != FileOpenFailed) {
3286 loadedTemplate = true; 3308 loadedTemplate = true;
3287 } 3309 }
3290 if (!loadedTemplate) { 3312 if (!loadedTemplate) {
3291 closeSession(); 3313 closeSession();
3292 createDocument(); 3314 createDocument();
3293 } 3315 }
3294 3316
3295 Model *prevMain = getMainModel(); 3317 ModelId prevMain = getMainModelId();
3296 if (prevMain) { 3318 if (!prevMain.isNone()) {
3297 m_playSource->removeModel(prevMain); 3319 m_playSource->removeModel(prevMain);
3298 PlayParameterRepository::getInstance()->removePlayable(prevMain); 3320 PlayParameterRepository::getInstance()->removePlayable
3321 (prevMain.untyped);
3299 } 3322 }
3300 3323
3301 m_document->setMainModel(model); 3324 m_document->setMainModel(modelId);
3302 setupMenus(); 3325 setupMenus();
3303 findTimeRulerLayer(); 3326 findTimeRulerLayer();
3304 3327
3305 m_originalLocation = model->getLocation(); 3328 m_originalLocation = location;
3306 3329
3307 if (loadedTemplate || (m_sessionFile == "")) { 3330 if (loadedTemplate || (m_sessionFile == "")) {
3308 CommandHistory::getInstance()->clear(); 3331 CommandHistory::getInstance()->clear();
3309 CommandHistory::getInstance()->documentSaved(); 3332 CommandHistory::getInstance()->documentSaved();
3310 } 3333 }
3315 } else { 3338 } else {
3316 3339
3317 CommandHistory::getInstance()->startCompoundOperation 3340 CommandHistory::getInstance()->startCompoundOperation
3318 (tr("Import Recorded Audio"), true); 3341 (tr("Import Recorded Audio"), true);
3319 3342
3320 m_document->addImportedModel(model); 3343 m_document->addImportedModel(modelId);
3321 3344
3322 AddPaneCommand *command = new AddPaneCommand(this); 3345 AddPaneCommand *command = new AddPaneCommand(this);
3323 CommandHistory::getInstance()->addCommand(command); 3346 CommandHistory::getInstance()->addCommand(command);
3324 3347
3325 Pane *pane = command->getPane(); 3348 Pane *pane = command->getPane();
3326 3349
3327 if (m_timeRulerLayer) { 3350 if (m_timeRulerLayer) {
3328 m_document->addLayerToView(pane, m_timeRulerLayer); 3351 m_document->addLayerToView(pane, m_timeRulerLayer);
3329 } 3352 }
3330 3353
3331 Layer *newLayer = m_document->createImportedLayer(model); 3354 Layer *newLayer = m_document->createImportedLayer(modelId);
3332 3355
3333 if (newLayer) { 3356 if (newLayer) {
3334 m_document->addLayerToView(pane, newLayer); 3357 m_document->addLayerToView(pane, newLayer);
3335 } 3358 }
3336 3359
3337 CommandHistory::getInstance()->endCompoundOperation(); 3360 CommandHistory::getInstance()->endCompoundOperation();
3338 } 3361 }
3339 3362
3340 updateMenuStates(); 3363 updateMenuStates();
3341 m_recentFiles.addFile(model->getLocation()); 3364 m_recentFiles.addFile(location);
3342 currentPaneChanged(m_paneStack->getCurrentPane()); 3365 currentPaneChanged(m_paneStack->getCurrentPane());
3343 3366
3344 emit audioFileLoaded(); 3367 emit audioFileLoaded();
3345 } 3368 }
3346 3369
3722 Layer *layer = nullptr; 3745 Layer *layer = nullptr;
3723 Pane *pane = m_paneStack->getCurrentPane(); 3746 Pane *pane = m_paneStack->getCurrentPane();
3724 if (pane) layer = pane->getSelectedLayer(); 3747 if (pane) layer = pane->getSelectedLayer();
3725 if (!layer) return; 3748 if (!layer) return;
3726 3749
3727 Model *model = layer->getModel(); 3750 auto tabular = ModelById::getAs<TabularModel>(layer->getModel());
3728 if (!model) return;
3729
3730 TabularModel *tabular = dynamic_cast<TabularModel *>(model);
3731 if (!tabular) { 3751 if (!tabular) {
3732 //!!! how to prevent this function from being active if not 3752 //!!! how to prevent this function from being active if not
3733 //appropriate model type? or will we ultimately support 3753 //appropriate model type? or will we ultimately support
3734 //tabular display for all editable models? 3754 //tabular display for all editable models?
3735 SVDEBUG << "NOTE: Not a tabular model" << endl; 3755 SVDEBUG << "NOTE: Not a tabular model" << endl;
3744 } 3764 }
3745 } 3765 }
3746 3766
3747 QString title = layer->getLayerPresentationName(); 3767 QString title = layer->getLayerPresentationName();
3748 3768
3749 ModelDataTableDialog *dialog = new ModelDataTableDialog(tabular, title, this); 3769 ModelDataTableDialog *dialog = new ModelDataTableDialog
3770 (layer->getModel(), title, this);
3750 dialog->setAttribute(Qt::WA_DeleteOnClose); 3771 dialog->setAttribute(Qt::WA_DeleteOnClose);
3751 3772
3752 connectLayerEditDialog(dialog); 3773 connectLayerEditDialog(dialog);
3753 3774
3754 m_layerDataDialogMap[layer] = dialog; 3775 m_layerDataDialogMap[layer] = dialog;
4003 // SVDEBUG << "MainWindowBase::layerInAView(" << layer << "," << inAView << ")" << endl; 4024 // SVDEBUG << "MainWindowBase::layerInAView(" << layer << "," << inAView << ")" << endl;
4004 4025
4005 if (!inAView) removeLayerEditDialog(layer); 4026 if (!inAView) removeLayerEditDialog(layer);
4006 4027
4007 // Check whether we need to add or remove model from play source 4028 // Check whether we need to add or remove model from play source
4008 Model *model = layer->getModel(); 4029 ModelId modelId = layer->getModel();
4009 if (model) { 4030 if (!modelId.isNone()) {
4010 if (inAView) { 4031 if (inAView) {
4011 m_playSource->addModel(model); 4032 m_playSource->addModel(modelId);
4012 } else { 4033 } else {
4013 bool found = false; 4034 bool found = false;
4014 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) { 4035 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
4015 Pane *pane = m_paneStack->getPane(i); 4036 Pane *pane = m_paneStack->getPane(i);
4016 if (!pane) continue; 4037 if (!pane) continue;
4017 for (int j = 0; j < pane->getLayerCount(); ++j) { 4038 for (int j = 0; j < pane->getLayerCount(); ++j) {
4018 Layer *pl = pane->getLayer(j); 4039 Layer *pl = pane->getLayer(j);
4019 if (pl && 4040 if (pl &&
4020 !dynamic_cast<TimeRulerLayer *>(pl) && 4041 !dynamic_cast<TimeRulerLayer *>(pl) &&
4021 (pl->getModel() == model)) { 4042 (pl->getModel() == modelId)) {
4022 found = true; 4043 found = true;
4023 break; 4044 break;
4024 } 4045 }
4025 } 4046 }
4026 if (found) break; 4047 if (found) break;
4027 } 4048 }
4028 if (!found) { 4049 if (!found) {
4029 m_playSource->removeModel(model); 4050 m_playSource->removeModel(modelId);
4030 } 4051 }
4031 } 4052 }
4032 } 4053 }
4033 4054
4034 updateMenuStates(); 4055 updateMenuStates();
4050 delete dialog; 4071 delete dialog;
4051 } 4072 }
4052 } 4073 }
4053 4074
4054 void 4075 void
4055 MainWindowBase::modelAdded(Model *model) 4076 MainWindowBase::modelAdded(ModelId model)
4056 { 4077 {
4057 // SVDEBUG << "MainWindowBase::modelAdded(" << model << ")" << endl; 4078 // SVDEBUG << "MainWindowBase::modelAdded(" << model << ")" << endl;
4058 std::cerr << "\nAdding model " << model->getTypeName() << " to playsource " << std::endl; 4079 std::cerr << "\nAdding model " << model << " to playsource " << std::endl;
4059 m_playSource->addModel(model); 4080 m_playSource->addModel(model);
4060 } 4081 }
4061 4082
4062 void 4083 void
4063 MainWindowBase::mainModelChanged(WaveFileModel *model) 4084 MainWindowBase::mainModelChanged(ModelId modelId)
4064 { 4085 {
4065 // SVDEBUG << "MainWindowBase::mainModelChanged(" << model << ")" << endl; 4086 // SVDEBUG << "MainWindowBase::mainModelChanged(" << model << ")" << endl;
4066 updateDescriptionLabel(); 4087 updateDescriptionLabel();
4088 auto model = ModelById::getAs<WaveFileModel>(modelId);
4067 if (model) m_viewManager->setMainModelSampleRate(model->getSampleRate()); 4089 if (model) m_viewManager->setMainModelSampleRate(model->getSampleRate());
4068 if (model && !(m_playTarget || m_audioIO) && 4090 if (model && !(m_playTarget || m_audioIO) &&
4069 (m_soundOptions & WithAudioOutput)) { 4091 (m_soundOptions & WithAudioOutput)) {
4070 createAudioIO(); 4092 createAudioIO();
4071 } 4093 }
4072 } 4094 }
4073 4095
4074 void 4096 void
4075 MainWindowBase::modelAboutToBeDeleted(Model *model) 4097 MainWindowBase::modelAboutToBeDeleted(ModelId model)
4076 { 4098 {
4077 // SVDEBUG << "MainWindowBase::modelAboutToBeDeleted(" << model << ")" << endl;
4078 if (model == m_viewManager->getPlaybackModel()) { 4099 if (model == m_viewManager->getPlaybackModel()) {
4079 m_viewManager->setPlaybackModel(nullptr); 4100 m_viewManager->setPlaybackModel({});
4080 } 4101 }
4081 m_playSource->removeModel(model); 4102 m_playSource->removeModel(model);
4082 } 4103 }
4083 4104
4084 void 4105 void
4116 4137
4117 updateMenuStates(); 4138 updateMenuStates();
4118 } 4139 }
4119 4140
4120 void 4141 void
4121 MainWindowBase::alignmentComplete(AlignmentModel *model) 4142 MainWindowBase::alignmentComplete(ModelId alignmentModelId)
4122 { 4143 {
4123 cerr << "MainWindowBase::alignmentComplete(" << model << ")" << endl; 4144 cerr << "MainWindowBase::alignmentComplete(" << alignmentModelId << ")" << endl;
4124 } 4145 }
4125 4146
4126 void 4147 void
4127 MainWindowBase::pollOSC() 4148 MainWindowBase::pollOSC()
4128 { 4149 {