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()); |