Mercurial > hg > svapp
comparison framework/MainWindowBase.cpp @ 236:dd14baa45847
Merge from branch "templating"
| author | Chris Cannam |
|---|---|
| date | Sun, 26 Jun 2011 19:53:34 +0100 |
| parents | 8aace2d9f1c2 65d75297a37e |
| children | 1ebd8e13262d |
comparison
equal
deleted
inserted
replaced
| 233:8aace2d9f1c2 | 236:dd14baa45847 |
|---|---|
| 66 #include "base/XmlExportable.h" | 66 #include "base/XmlExportable.h" |
| 67 #include "base/Profiler.h" | 67 #include "base/Profiler.h" |
| 68 #include "base/Preferences.h" | 68 #include "base/Preferences.h" |
| 69 #include "base/TempWriteFile.h" | 69 #include "base/TempWriteFile.h" |
| 70 #include "base/Exceptions.h" | 70 #include "base/Exceptions.h" |
| 71 #include "base/ResourceFinder.h" | |
| 71 | 72 |
| 72 #include "data/osc/OSCQueue.h" | 73 #include "data/osc/OSCQueue.h" |
| 73 #include "data/midi/MIDIInput.h" | 74 #include "data/midi/MIDIInput.h" |
| 74 | 75 |
| 75 #include <QApplication> | 76 #include <QApplication> |
| 211 this, | 212 this, |
| 212 SLOT(preferenceChanged(PropertyContainer::PropertyName))); | 213 SLOT(preferenceChanged(PropertyContainer::PropertyName))); |
| 213 | 214 |
| 214 Labeller::ValueType labellerType = Labeller::ValueFromTwoLevelCounter; | 215 Labeller::ValueType labellerType = Labeller::ValueFromTwoLevelCounter; |
| 215 settings.beginGroup("MainWindow"); | 216 settings.beginGroup("MainWindow"); |
| 217 | |
| 216 labellerType = (Labeller::ValueType) | 218 labellerType = (Labeller::ValueType) |
| 217 settings.value("labellertype", (int)labellerType).toInt(); | 219 settings.value("labellertype", (int)labellerType).toInt(); |
| 218 int cycle = settings.value("labellercycle", 4).toInt(); | 220 int cycle = settings.value("labellercycle", 4).toInt(); |
| 221 | |
| 219 settings.endGroup(); | 222 settings.endGroup(); |
| 220 | 223 |
| 221 m_labeller = new Labeller(labellerType); | 224 m_labeller = new Labeller(labellerType); |
| 222 m_labeller->setCounterCycleSize(cycle); | 225 m_labeller->setCounterCycleSize(cycle); |
| 223 | 226 |
| 322 void | 325 void |
| 323 MainWindowBase::registerLastOpenedFilePath(FileFinder::FileType type, QString path) | 326 MainWindowBase::registerLastOpenedFilePath(FileFinder::FileType type, QString path) |
| 324 { | 327 { |
| 325 FileFinder *ff = FileFinder::getInstance(); | 328 FileFinder *ff = FileFinder::getInstance(); |
| 326 ff->registerLastOpenedFilePath(type, path); | 329 ff->registerLastOpenedFilePath(type, path); |
| 330 } | |
| 331 | |
| 332 QString | |
| 333 MainWindowBase::getDefaultSessionTemplate() const | |
| 334 { | |
| 335 QSettings settings; | |
| 336 settings.beginGroup("MainWindow"); | |
| 337 QString templateName = settings.value("sessiontemplate", "").toString(); | |
| 338 if (templateName == "") templateName = "default"; | |
| 339 return templateName; | |
| 327 } | 340 } |
| 328 | 341 |
| 329 void | 342 void |
| 330 MainWindowBase::updateMenuStates() | 343 MainWindowBase::updateMenuStates() |
| 331 { | 344 { |
| 688 Clipboard &clipboard = m_viewManager->getClipboard(); | 701 Clipboard &clipboard = m_viewManager->getClipboard(); |
| 689 if (!clipboard.empty()) { | 702 if (!clipboard.empty()) { |
| 690 long firstEventFrame = clipboard.getPoints()[0].getFrame(); | 703 long firstEventFrame = clipboard.getPoints()[0].getFrame(); |
| 691 long offset = 0; | 704 long offset = 0; |
| 692 if (firstEventFrame < 0) { | 705 if (firstEventFrame < 0) { |
| 693 offset = long(pos) - firstEventFrame; | 706 offset = (long)pos - firstEventFrame; |
| 694 } else if (firstEventFrame < pos) { | 707 } else if (firstEventFrame < pos) { |
| 695 offset = pos - firstEventFrame; | 708 offset = pos - (unsigned long)firstEventFrame; |
| 696 } else { | 709 } else { |
| 697 offset = -(firstEventFrame - pos); | 710 offset = -((unsigned long)firstEventFrame - pos); |
| 698 } | 711 } |
| 699 pasteRelative(offset); | 712 pasteRelative(offset); |
| 700 } | 713 } |
| 701 } | 714 } |
| 702 | 715 |
| 1069 return FileOpenFailed; | 1082 return FileOpenFailed; |
| 1070 } | 1083 } |
| 1071 } | 1084 } |
| 1072 | 1085 |
| 1073 MainWindowBase::FileOpenStatus | 1086 MainWindowBase::FileOpenStatus |
| 1074 MainWindowBase::openAudio(FileSource source, AudioFileOpenMode mode, QString templateName) | 1087 MainWindowBase::openAudio(FileSource source, AudioFileOpenMode mode, |
| 1088 QString templateName) | |
| 1075 { | 1089 { |
| 1076 // SVDEBUG << "MainWindowBase::openAudio(" << source.getLocation() << ")" << endl; | 1090 // SVDEBUG << "MainWindowBase::openAudio(" << source.getLocation() << ")" << endl; |
| 1091 | |
| 1092 if (templateName == "") { | |
| 1093 templateName = getDefaultSessionTemplate(); | |
| 1094 } | |
| 1095 | |
| 1096 std::cerr << "template is: \"" << templateName.toStdString() << "\"" << std::endl; | |
| 1077 | 1097 |
| 1078 if (!source.isAvailable()) return FileOpenFailed; | 1098 if (!source.isAvailable()) return FileOpenFailed; |
| 1079 source.waitForData(); | 1099 source.waitForData(); |
| 1080 | 1100 |
| 1081 m_openingAudioFile = true; | 1101 m_openingAudioFile = true; |
| 1099 if (mode == AskUser) { | 1119 if (mode == AskUser) { |
| 1100 if (getMainModel()) { | 1120 if (getMainModel()) { |
| 1101 | 1121 |
| 1102 QSettings settings; | 1122 QSettings settings; |
| 1103 settings.beginGroup("MainWindow"); | 1123 settings.beginGroup("MainWindow"); |
| 1104 bool prevSetAsMain = settings.value("newsessionforaudio", true).toBool(); | 1124 int lastMode = settings.value("lastaudioopenmode", 0).toBool(); |
| 1105 settings.endGroup(); | 1125 settings.endGroup(); |
| 1106 bool setAsMain = true; | 1126 int imode = 0; |
| 1107 | 1127 |
| 1108 QStringList items; | 1128 QStringList items; |
| 1109 items << tr("Replace the existing main waveform") | 1129 items << tr("Close the current session and start a new one") |
| 1110 << tr("Load this file into a new waveform pane"); | 1130 << tr("Replace the main audio file in this session") |
| 1131 << tr("Add the audio file to this session"); | |
| 1111 | 1132 |
| 1112 bool ok = false; | 1133 bool ok = false; |
| 1113 QString item = ListInputDialog::getItem | 1134 QString item = ListInputDialog::getItem |
| 1114 (this, tr("Select target for import"), | 1135 (this, tr("Select target for import"), |
| 1115 tr("<b>Select a target for import</b><p>You already have an audio waveform loaded.<br>What would you like to do with the new audio file?"), | 1136 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?"), |
| 1116 items, prevSetAsMain ? 0 : 1, &ok); | 1137 items, lastMode, &ok); |
| 1117 | 1138 |
| 1118 if (!ok || item.isEmpty()) { | 1139 if (!ok || item.isEmpty()) { |
| 1119 delete newModel; | 1140 delete newModel; |
| 1120 m_openingAudioFile = false; | 1141 m_openingAudioFile = false; |
| 1121 return FileOpenCancelled; | 1142 return FileOpenCancelled; |
| 1122 } | 1143 } |
| 1123 | 1144 |
| 1124 setAsMain = (item == items[0]); | 1145 for (int i = 0; i < items.size(); ++i) { |
| 1146 if (item == items[i]) imode = i; | |
| 1147 } | |
| 1148 | |
| 1125 settings.beginGroup("MainWindow"); | 1149 settings.beginGroup("MainWindow"); |
| 1126 settings.setValue("newsessionforaudio", setAsMain); | 1150 settings.setValue("lastaudioopenmode", imode); |
| 1127 settings.endGroup(); | 1151 settings.endGroup(); |
| 1128 | 1152 |
| 1129 if (setAsMain) mode = ReplaceMainModel; | 1153 mode = (AudioFileOpenMode)imode; |
| 1130 else mode = CreateAdditionalModel; | |
| 1131 | 1154 |
| 1132 } else { | 1155 } else { |
| 1133 mode = ReplaceMainModel; | 1156 // no main model: make a new session |
| 1157 mode = ReplaceSession; | |
| 1134 } | 1158 } |
| 1135 } | 1159 } |
| 1136 | 1160 |
| 1137 if (mode == ReplaceCurrentPane) { | 1161 if (mode == ReplaceCurrentPane) { |
| 1138 | 1162 |
| 1139 Pane *pane = m_paneStack->getCurrentPane(); | 1163 Pane *pane = m_paneStack->getCurrentPane(); |
| 1140 if (pane) { | 1164 if (pane) { |
| 1141 if (getMainModel()) { | 1165 if (getMainModel()) { |
| 1142 View::ModelSet models(pane->getModels()); | 1166 View::ModelSet models(pane->getModels()); |
| 1143 if (models.find(getMainModel()) != models.end()) { | 1167 if (models.find(getMainModel()) != models.end()) { |
| 1168 // Current pane contains main model: replace that | |
| 1144 mode = ReplaceMainModel; | 1169 mode = ReplaceMainModel; |
| 1145 } | 1170 } |
| 1171 // Otherwise the current pane has a non-default model, | |
| 1172 // which we will deal with later | |
| 1146 } else { | 1173 } else { |
| 1147 mode = ReplaceMainModel; | 1174 // We have no main model, so start a new session with |
| 1175 // optional template | |
| 1176 mode = ReplaceSession; | |
| 1148 } | 1177 } |
| 1149 } else { | 1178 } else { |
| 1179 // We seem to have no current pane! Oh well | |
| 1150 mode = CreateAdditionalModel; | 1180 mode = CreateAdditionalModel; |
| 1151 } | 1181 } |
| 1152 } | 1182 } |
| 1153 | 1183 |
| 1154 if (mode == CreateAdditionalModel && !getMainModel()) { | 1184 if (mode == CreateAdditionalModel && !getMainModel()) { |
| 1185 mode = ReplaceSession; | |
| 1186 } | |
| 1187 | |
| 1188 bool loadedTemplate = false; | |
| 1189 | |
| 1190 if (mode == ReplaceSession) { | |
| 1191 std::cerr << "SV looking for template " << tplPath << std::endl; | |
| 1192 if (templateName != "") { | |
| 1193 FileOpenStatus tplStatus = openSessionTemplate(templateName); | |
| 1194 if (tplStatus != FileOpenFailed) { | |
| 1195 std::cerr << "Template load succeeded" << std::endl; | |
| 1196 loadedTemplate = true; | |
| 1197 } | |
| 1198 } | |
| 1199 | |
| 1200 if (!loadedTemplate) { | |
| 1201 closeSession(); | |
| 1202 createDocument(); | |
| 1203 } | |
| 1204 | |
| 1155 mode = ReplaceMainModel; | 1205 mode = ReplaceMainModel; |
| 1156 } | |
| 1157 | |
| 1158 bool loadedTemplate = false; | |
| 1159 if ((mode == ReplaceMainModel) && (templateName.length() != 0)) { | |
| 1160 QString tplPath = "file::templates/" + templateName + ".xml"; | |
| 1161 std::cerr << "SV looking for template " << tplPath << std::endl; | |
| 1162 FileOpenStatus tplStatus = openSessionFile(tplPath); | |
| 1163 if(tplStatus != FileOpenFailed) { | |
| 1164 loadedTemplate = true; | |
| 1165 mode = ReplaceMainModel; | |
| 1166 } | |
| 1167 } | 1206 } |
| 1168 | 1207 |
| 1169 emit activity(tr("Import audio file \"%1\"").arg(source.getLocation())); | 1208 emit activity(tr("Import audio file \"%1\"").arg(source.getLocation())); |
| 1170 | 1209 |
| 1171 if (mode == ReplaceMainModel) { | 1210 if (mode == ReplaceMainModel) { |
| 1618 m_recentFiles.addFile(source.getLocation()); | 1657 m_recentFiles.addFile(source.getLocation()); |
| 1619 | 1658 |
| 1620 if (!source.isRemote()) { | 1659 if (!source.isRemote()) { |
| 1621 // for file dialog | 1660 // for file dialog |
| 1622 registerLastOpenedFilePath(FileFinder::SessionFile, | 1661 registerLastOpenedFilePath(FileFinder::SessionFile, |
| 1623 source.getLocalFilename()); | 1662 source.getLocalFilename()); |
| 1624 } | 1663 } |
| 1625 | 1664 |
| 1626 } else { | 1665 } else { |
| 1627 setWindowTitle(QApplication::applicationName()); | 1666 setWindowTitle(QApplication::applicationName()); |
| 1667 } | |
| 1668 | |
| 1669 return ok ? FileOpenSucceeded : FileOpenFailed; | |
| 1670 } | |
| 1671 | |
| 1672 MainWindowBase::FileOpenStatus | |
| 1673 MainWindowBase::openSessionTemplate(QString templateName) | |
| 1674 { | |
| 1675 // Template in the user's template directory takes | |
| 1676 // priority over a bundled one; we don't unbundle, but | |
| 1677 // open directly from the bundled file (where applicable) | |
| 1678 ResourceFinder rf; | |
| 1679 QString tfile = rf.getResourcePath("templates", templateName + ".svt"); | |
| 1680 if (tfile != "") { | |
| 1681 std::cerr << "SV loading template file " << tfile.toStdString() << std::endl; | |
| 1682 return openSessionTemplate(FileSource("file:" + tfile)); | |
| 1683 } else { | |
| 1684 return FileOpenFailed; | |
| 1685 } | |
| 1686 } | |
| 1687 | |
| 1688 MainWindowBase::FileOpenStatus | |
| 1689 MainWindowBase::openSessionTemplate(FileSource source) | |
| 1690 { | |
| 1691 std::cerr << "MainWindowBase::openSessionTemplate(" << source.getLocation().toStdString() << ")" << std::endl; | |
| 1692 | |
| 1693 if (!source.isAvailable()) return FileOpenFailed; | |
| 1694 source.waitForData(); | |
| 1695 | |
| 1696 QXmlInputSource *inputSource = 0; | |
| 1697 QFile *file = 0; | |
| 1698 bool isTemplate = false; | |
| 1699 | |
| 1700 file = new QFile(source.getLocalFilename()); | |
| 1701 inputSource = new QXmlInputSource(file); | |
| 1702 | |
| 1703 if (!checkSaveModified()) { | |
| 1704 delete inputSource; | |
| 1705 delete file; | |
| 1706 return FileOpenCancelled; | |
| 1707 } | |
| 1708 | |
| 1709 QString error; | |
| 1710 closeSession(); | |
| 1711 createDocument(); | |
| 1712 | |
| 1713 PaneCallback callback(this); | |
| 1714 m_viewManager->clearSelections(); | |
| 1715 | |
| 1716 SVFileReader reader(m_document, callback, source.getLocation()); | |
| 1717 connect | |
| 1718 (&reader, SIGNAL(modelRegenerationFailed(QString, QString, QString)), | |
| 1719 this, SLOT(modelRegenerationFailed(QString, QString, QString))); | |
| 1720 connect | |
| 1721 (&reader, SIGNAL(modelRegenerationWarning(QString, QString, QString)), | |
| 1722 this, SLOT(modelRegenerationWarning(QString, QString, QString))); | |
| 1723 | |
| 1724 reader.parse(*inputSource); | |
| 1725 | |
| 1726 if (!reader.isOK()) { | |
| 1727 error = tr("SV XML file read error:\n%1").arg(reader.getErrorString()); | |
| 1728 } | |
| 1729 | |
| 1730 delete inputSource; | |
| 1731 delete file; | |
| 1732 | |
| 1733 bool ok = (error == ""); | |
| 1734 | |
| 1735 setWindowTitle(QApplication::applicationName()); | |
| 1736 | |
| 1737 if (ok) { | |
| 1738 | |
| 1739 emit activity(tr("Open session template \"%1\"").arg(source.getLocation())); | |
| 1740 | |
| 1741 setupMenus(); | |
| 1742 | |
| 1743 CommandHistory::getInstance()->clear(); | |
| 1744 CommandHistory::getInstance()->documentSaved(); | |
| 1745 m_documentModified = false; | |
| 1746 updateMenuStates(); | |
| 1628 } | 1747 } |
| 1629 | 1748 |
| 1630 return ok ? FileOpenSucceeded : FileOpenFailed; | 1749 return ok ? FileOpenSucceeded : FileOpenFailed; |
| 1631 } | 1750 } |
| 1632 | 1751 |
| 1701 | 1820 |
| 1702 emit activity(tr("Import RDF document \"%1\"").arg(source.getLocation())); | 1821 emit activity(tr("Import RDF document \"%1\"").arg(source.getLocation())); |
| 1703 | 1822 |
| 1704 std::set<Model *> added; | 1823 std::set<Model *> added; |
| 1705 | 1824 |
| 1706 for (int i = 0; i < models.size(); ++i) { | 1825 for (int i = 0; i < (int)models.size(); ++i) { |
| 1707 | 1826 |
| 1708 Model *m = models[i]; | 1827 Model *m = models[i]; |
| 1709 WaveFileModel *w = dynamic_cast<WaveFileModel *>(m); | 1828 WaveFileModel *w = dynamic_cast<WaveFileModel *>(m); |
| 1710 | 1829 |
| 1711 if (w) { | 1830 if (w) { |
| 1726 | 1845 |
| 1727 m_document->addLayerToView(pane, layer); | 1846 m_document->addLayerToView(pane, layer); |
| 1728 | 1847 |
| 1729 added.insert(w); | 1848 added.insert(w); |
| 1730 | 1849 |
| 1731 for (int j = 0; j < models.size(); ++j) { | 1850 for (int j = 0; j < (int)models.size(); ++j) { |
| 1732 | 1851 |
| 1733 Model *dm = models[j]; | 1852 Model *dm = models[j]; |
| 1734 | 1853 |
| 1735 if (dm == m) continue; | 1854 if (dm == m) continue; |
| 1736 if (dm->getSourceModel() != m) continue; | 1855 if (dm->getSourceModel() != m) continue; |
| 1784 added.insert(dm); | 1903 added.insert(dm); |
| 1785 } | 1904 } |
| 1786 } | 1905 } |
| 1787 } | 1906 } |
| 1788 | 1907 |
| 1789 for (int i = 0; i < models.size(); ++i) { | 1908 for (int i = 0; i < (int)models.size(); ++i) { |
| 1790 | 1909 |
| 1791 Model *m = models[i]; | 1910 Model *m = models[i]; |
| 1792 | 1911 |
| 1793 if (added.find(m) == added.end()) { | 1912 if (added.find(m) == added.end()) { |
| 1794 | 1913 |
| 1906 } | 2025 } |
| 1907 | 2026 |
| 1908 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); | 2027 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); |
| 1909 | 2028 |
| 1910 QTextStream out(&bzFile); | 2029 QTextStream out(&bzFile); |
| 1911 toXml(out); | 2030 toXml(out, false); |
| 1912 out.flush(); | 2031 out.flush(); |
| 1913 | 2032 |
| 1914 QApplication::restoreOverrideCursor(); | 2033 QApplication::restoreOverrideCursor(); |
| 1915 | 2034 |
| 1916 if (!bzFile.isOK()) { | 2035 if (!bzFile.isOK()) { |
| 1932 .arg(path).arg(f.what())); | 2051 .arg(path).arg(f.what())); |
| 1933 return false; | 2052 return false; |
| 1934 } | 2053 } |
| 1935 } | 2054 } |
| 1936 | 2055 |
| 1937 void | 2056 bool |
| 1938 MainWindowBase::toXml(QTextStream &out) | 2057 MainWindowBase::saveSessionTemplate(QString path) |
| 2058 { | |
| 2059 try { | |
| 2060 | |
| 2061 TempWriteFile temp(path); | |
| 2062 | |
| 2063 QFile file(temp.getTemporaryFilename()); | |
| 2064 if (!file.open(QIODevice::WriteOnly)) { | |
| 2065 std::cerr << "Failed to open session template file \"" | |
| 2066 << temp.getTemporaryFilename().toStdString() | |
| 2067 << "\" for writing: " | |
| 2068 << file.errorString().toStdString() << std::endl; | |
| 2069 return false; | |
| 2070 } | |
| 2071 | |
| 2072 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); | |
| 2073 | |
| 2074 QTextStream out(&file); | |
| 2075 toXml(out, true); | |
| 2076 out.flush(); | |
| 2077 | |
| 2078 QApplication::restoreOverrideCursor(); | |
| 2079 | |
| 2080 file.close(); | |
| 2081 temp.moveToTarget(); | |
| 2082 return true; | |
| 2083 | |
| 2084 } catch (FileOperationFailed &f) { | |
| 2085 | |
| 2086 QMessageBox::critical(this, tr("Failed to write file"), | |
| 2087 tr("<b>Save failed</b><p>Failed to write to file \"%1\": %2") | |
| 2088 .arg(path).arg(f.what())); | |
| 2089 return false; | |
| 2090 } | |
| 2091 } | |
| 2092 | |
| 2093 void | |
| 2094 MainWindowBase::toXml(QTextStream &out, bool asTemplate) | |
| 1939 { | 2095 { |
| 1940 QString indent(" "); | 2096 QString indent(" "); |
| 1941 | 2097 |
| 1942 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; | 2098 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; |
| 1943 out << "<!DOCTYPE sonic-visualiser>\n"; | 2099 out << "<!DOCTYPE sonic-visualiser>\n"; |
| 1944 out << "<sv>\n"; | 2100 out << "<sv>\n"; |
| 1945 | 2101 |
| 1946 m_document->toXml(out, "", ""); | 2102 if (asTemplate) { |
| 2103 m_document->toXmlAsTemplate(out, "", ""); | |
| 2104 } else { | |
| 2105 m_document->toXml(out, "", ""); | |
| 2106 } | |
| 1947 | 2107 |
| 1948 out << "<display>\n"; | 2108 out << "<display>\n"; |
| 1949 | 2109 |
| 1950 out << QString(" <window width=\"%1\" height=\"%2\"/>\n") | 2110 out << QString(" <window width=\"%1\" height=\"%2\"/>\n") |
| 1951 .arg(width()).arg(height()); | 2111 .arg(width()).arg(height()); |
