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