comparison main/MainWindow.cpp @ 245:fc542303eda2 1.2-stable

* merge from trunk (1.2 ended up being tracked from trunk, but we may want this branch for fixes later)
author Chris Cannam
date Wed, 27 Feb 2008 10:32:45 +0000
parents 0ebfc1e392f1
children
comparison
equal deleted inserted replaced
223:35e438b612ff 245:fc542303eda2
131 m_soloAction(0), 131 m_soloAction(0),
132 m_soloModified(false), 132 m_soloModified(false),
133 m_prevSolo(false), 133 m_prevSolo(false),
134 m_ffwdAction(0), 134 m_ffwdAction(0),
135 m_rwdAction(0), 135 m_rwdAction(0),
136 m_playControlsSpacer(0),
137 m_playControlsWidth(0),
136 m_preferencesDialog(0), 138 m_preferencesDialog(0),
137 m_layerTreeDialog(0), 139 m_layerTreeDialog(0),
138 m_keyReference(new KeyReference()) 140 m_keyReference(new KeyReference())
139 { 141 {
140 setWindowTitle(tr("Sonic Visualiser")); 142 setWindowTitle(tr("Sonic Visualiser"));
218 connect(m_playSpeed, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget())); 220 connect(m_playSpeed, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
219 connect(m_playSpeed, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget())); 221 connect(m_playSpeed, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
220 222
221 IconLoader il; 223 IconLoader il;
222 224
223 #ifndef HAVE_RUBBERBAND
224 m_playSharpen = new NotifyingPushButton(frame);
225 m_playSharpen->setToolTip(tr("Sharpen percussive transients"));
226 m_playSharpen->setFixedSize(20, 20);
227 m_playSharpen->setEnabled(false);
228 m_playSharpen->setCheckable(true);
229 m_playSharpen->setChecked(false);
230 m_playSharpen->setIcon(il.load("sharpen"));
231 connect(m_playSharpen, SIGNAL(clicked()), this, SLOT(playSharpenToggled()));
232 connect(m_playSharpen, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
233 connect(m_playSharpen, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
234
235 m_playMono = new NotifyingPushButton(frame);
236 m_playMono->setToolTip(tr("Run time stretcher in mono only"));
237 m_playMono->setFixedSize(20, 20);
238 m_playMono->setEnabled(false);
239 m_playMono->setCheckable(true);
240 m_playMono->setChecked(false);
241 m_playMono->setIcon(il.load("mono"));
242 connect(m_playMono, SIGNAL(clicked()), this, SLOT(playMonoToggled()));
243 connect(m_playMono, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
244 connect(m_playMono, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
245 #endif
246
247 QSettings settings; 225 QSettings settings;
248 settings.beginGroup("MainWindow"); 226 settings.beginGroup("MainWindow");
249 #ifndef HAVE_RUBBERBAND
250 m_playSharpen->setChecked(settings.value("playsharpen", true).toBool());
251 m_playMono->setChecked(settings.value("playmono", false).toBool());
252 #endif
253 settings.endGroup(); 227 settings.endGroup();
228
229 m_playControlsSpacer = new QFrame;
254 230
255 layout->setSpacing(4); 231 layout->setSpacing(4);
256 layout->addWidget(scroll, 0, 0, 1, 5); 232 layout->addWidget(scroll, 0, 0, 1, 5);
257 layout->addWidget(m_overview, 1, 0); 233 layout->addWidget(m_overview, 1, 1);
258 layout->addWidget(m_fader, 1, 1); 234 layout->addWidget(m_playControlsSpacer, 1, 2);
259 layout->addWidget(m_playSpeed, 1, 2); 235 layout->addWidget(m_playSpeed, 1, 3);
260 #ifndef HAVE_RUBBERBAND 236 layout->addWidget(m_fader, 1, 4);
261 layout->addWidget(m_playSharpen, 1, 3); 237
262 layout->addWidget(m_playMono, 1, 4); 238 m_playControlsWidth =
263 #endif 239 m_fader->width() + m_playSpeed->width() + layout->spacing() * 2;
264 240
265 m_paneStack->setPropertyStackMinWidth 241 layout->setColumnMinimumWidth(0, 14);
266 (m_fader->width() + m_playSpeed->width() 242 layout->setColumnStretch(0, 0);
267 #ifndef HAVE_RUBBERBAND 243
268 + m_playSharpen->width() 244 m_paneStack->setPropertyStackMinWidth(m_playControlsWidth
269 + m_playMono->width() 245 + 2 + layout->spacing());
270 #endif 246 m_playControlsSpacer->setFixedSize(QSize(2, 2));
271 + layout->spacing() * 4); 247
272 248 layout->setColumnStretch(1, 10);
273 layout->setColumnStretch(0, 10); 249
250 connect(m_paneStack, SIGNAL(propertyStacksResized(int)),
251 this, SLOT(propertyStacksResized(int)));
274 252
275 frame->setLayout(layout); 253 frame->setLayout(layout);
276 254
277 setupMenus(); 255 setupMenus();
278 setupToolbars(); 256 setupToolbars();
601 connect(this, SIGNAL(canInsertInstantsAtBoundaries(bool)), action, SLOT(setEnabled(bool))); 579 connect(this, SIGNAL(canInsertInstantsAtBoundaries(bool)), action, SLOT(setEnabled(bool)));
602 m_keyReference->registerShortcut(action); 580 m_keyReference->registerShortcut(action);
603 menu->addAction(action); 581 menu->addAction(action);
604 582
605 QMenu *numberingMenu = menu->addMenu(tr("Number New Instants with")); 583 QMenu *numberingMenu = menu->addMenu(tr("Number New Instants with"));
584 numberingMenu->setTearOffEnabled(true);
606 QActionGroup *numberingGroup = new QActionGroup(this); 585 QActionGroup *numberingGroup = new QActionGroup(this);
607 586
608 Labeller::TypeNameMap types = m_labeller->getTypeNames(); 587 Labeller::TypeNameMap types = m_labeller->getTypeNames();
609 for (Labeller::TypeNameMap::iterator i = types.begin(); i != types.end(); ++i) { 588 for (Labeller::TypeNameMap::iterator i = types.begin(); i != types.end(); ++i) {
610 589
622 if (i->first == Labeller::ValueFromTwoLevelCounter) { 601 if (i->first == Labeller::ValueFromTwoLevelCounter) {
623 602
624 QMenu *cycleMenu = numberingMenu->addMenu(tr("Cycle size")); 603 QMenu *cycleMenu = numberingMenu->addMenu(tr("Cycle size"));
625 QActionGroup *cycleGroup = new QActionGroup(this); 604 QActionGroup *cycleGroup = new QActionGroup(this);
626 605
627 int cycles[] = { 2, 3, 4, 5, 6, 7, 8, 10, 12, 16 }; 606 int cycles[] = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 16 };
628 for (int i = 0; i < int(sizeof(cycles)/sizeof(cycles[0])); ++i) { 607 for (int i = 0; i < int(sizeof(cycles)/sizeof(cycles[0])); ++i) {
629 action = new QAction(QString("%1").arg(cycles[i]), this); 608 action = new QAction(QString("%1").arg(cycles[i]), this);
630 connect(action, SIGNAL(triggered()), this, SLOT(setInstantsCounterCycle())); 609 connect(action, SIGNAL(triggered()), this, SLOT(setInstantsCounterCycle()));
631 action->setCheckable(true); 610 action->setCheckable(true);
632 action->setChecked(cycles[i] == m_labeller->getCounterCycleSize()); 611 action->setChecked(cycles[i] == m_labeller->getCounterCycleSize());
633 cycleGroup->addAction(action); 612 cycleGroup->addAction(action);
634 cycleMenu->addAction(action); 613 cycleMenu->addAction(action);
635 } 614 }
636
637 action = new QAction(tr("Reset Counters..."), this);
638 connect(action, SIGNAL(triggered()), this, SLOT(resetInstantsCounters()));
639 numberingMenu->addAction(action);
640 } 615 }
641 616
642 if (i->first == Labeller::ValueNone || 617 if (i->first == Labeller::ValueNone ||
643 i->first == Labeller::ValueFromTwoLevelCounter || 618 i->first == Labeller::ValueFromTwoLevelCounter ||
644 i->first == Labeller::ValueFromRealTime) { 619 i->first == Labeller::ValueFromRealTime) {
645 numberingMenu->addSeparator(); 620 numberingMenu->addSeparator();
646 } 621 }
647 } 622 }
648 623
649 action = new QAction(tr("Re-Number Selected Instants"), this); 624 action = new QAction(tr("Set Numbering Counters..."), this);
650 action->setStatusTip(tr("Re-number the selected instants using the current labelling scheme")); 625 action->setStatusTip(tr("Set the counters used for counter-based labelling"));
626 connect(action, SIGNAL(triggered()), this, SLOT(resetInstantsCounters()));
627 menu->addAction(action);
628
629 action = new QAction(tr("Renumber Selected Instants"), this);
630 action->setStatusTip(tr("Renumber the selected instants using the current labelling scheme"));
651 connect(action, SIGNAL(triggered()), this, SLOT(renumberInstants())); 631 connect(action, SIGNAL(triggered()), this, SLOT(renumberInstants()));
652 connect(this, SIGNAL(canRenumberInstants(bool)), action, SLOT(setEnabled(bool))); 632 connect(this, SIGNAL(canRenumberInstants(bool)), action, SLOT(setEnabled(bool)));
653 // m_keyReference->registerShortcut(action); 633 // m_keyReference->registerShortcut(action);
654 menu->addAction(action); 634 menu->addAction(action);
655 } 635 }
856 QAction *action = new QAction(il.load("pane"), tr("Add &New Pane"), this); 836 QAction *action = new QAction(il.load("pane"), tr("Add &New Pane"), this);
857 action->setShortcut(tr("N")); 837 action->setShortcut(tr("N"));
858 action->setStatusTip(tr("Add a new pane containing only a time ruler")); 838 action->setStatusTip(tr("Add a new pane containing only a time ruler"));
859 connect(action, SIGNAL(triggered()), this, SLOT(addPane())); 839 connect(action, SIGNAL(triggered()), this, SLOT(addPane()));
860 connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool))); 840 connect(this, SIGNAL(canAddPane(bool)), action, SLOT(setEnabled(bool)));
861 m_paneActions[action] = PaneConfiguration(LayerFactory::TimeRuler); 841 m_paneActions[action] = LayerConfiguration(LayerFactory::TimeRuler);
862 m_keyReference->registerShortcut(action); 842 m_keyReference->registerShortcut(action);
863 menu->addAction(action); 843 menu->addAction(action);
864 844
865 menu->addSeparator(); 845 menu->addSeparator();
866 846
892 m_keyReference->registerShortcut(action); 872 m_keyReference->registerShortcut(action);
893 } 873 }
894 874
895 connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); 875 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
896 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); 876 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
897 m_layerActions[action] = type; 877 m_layerActions[action] = LayerConfiguration(type);
898 menu->addAction(action); 878 menu->addAction(action);
899 m_rightButtonLayerMenu->addAction(action); 879 m_rightButtonLayerMenu->addAction(action);
900 } 880 }
901 881
902 m_rightButtonLayerMenu->addSeparator(); 882 m_rightButtonLayerMenu->addSeparator();
909 LayerFactory::PeakFrequencySpectrogram, 889 LayerFactory::PeakFrequencySpectrogram,
910 LayerFactory::Spectrum 890 LayerFactory::Spectrum
911 }; 891 };
912 892
913 std::vector<Model *> models; 893 std::vector<Model *> models;
914 if (m_document) models = m_document->getTransformerInputModels(); //!!! not well named for this! 894 if (m_document) models = m_document->getTransformInputModels();
915 bool plural = (models.size() > 1); 895 bool plural = (models.size() > 1);
916 if (models.empty()) { 896 if (models.empty()) {
917 models.push_back(getMainModel()); // probably 0 897 models.push_back(getMainModel()); // probably 0
918 } 898 }
919 899
920 for (unsigned int i = 0; 900 for (unsigned int i = 0;
921 i < sizeof(backgroundTypes)/sizeof(backgroundTypes[0]); ++i) { 901 i < sizeof(backgroundTypes)/sizeof(backgroundTypes[0]); ++i) {
922 902
923 for (int menuType = 0; menuType <= 1; ++menuType) { // pane, layer 903 const int paneMenuType = 0, layerMenuType = 1;
924 904
925 if (menuType == 0) menu = m_paneMenu; 905 for (int menuType = paneMenuType; menuType <= layerMenuType; ++menuType) {
906
907 if (menuType == paneMenuType) menu = m_paneMenu;
926 else menu = m_layerMenu; 908 else menu = m_layerMenu;
927 909
928 QMenu *submenu = 0; 910 QMenu *submenu = 0;
929 911
930 QIcon icon; 912 QIcon icon;
935 switch (type) { 917 switch (type) {
936 918
937 case LayerFactory::Waveform: 919 case LayerFactory::Waveform:
938 icon = il.load("waveform"); 920 icon = il.load("waveform");
939 mainText = tr("Add &Waveform"); 921 mainText = tr("Add &Waveform");
940 if (menuType == 0) { 922 if (menuType == paneMenuType) {
941 shortcutText = tr("W"); 923 shortcutText = tr("W");
942 tipText = tr("Add a new pane showing a waveform view"); 924 tipText = tr("Add a new pane showing a waveform view");
943 } else { 925 } else {
944 tipText = tr("Add a new layer showing a waveform view"); 926 tipText = tr("Add a new layer showing a waveform view");
945 } 927 }
947 break; 929 break;
948 930
949 case LayerFactory::Spectrogram: 931 case LayerFactory::Spectrogram:
950 icon = il.load("spectrogram"); 932 icon = il.load("spectrogram");
951 mainText = tr("Add Spectro&gram"); 933 mainText = tr("Add Spectro&gram");
952 if (menuType == 0) { 934 if (menuType == paneMenuType) {
953 shortcutText = tr("G"); 935 shortcutText = tr("G");
954 tipText = tr("Add a new pane showing a spectrogram"); 936 tipText = tr("Add a new pane showing a spectrogram");
955 } else { 937 } else {
956 tipText = tr("Add a new layer showing a spectrogram"); 938 tipText = tr("Add a new layer showing a spectrogram");
957 } 939 }
958 break; 940 break;
959 941
960 case LayerFactory::MelodicRangeSpectrogram: 942 case LayerFactory::MelodicRangeSpectrogram:
961 icon = il.load("spectrogram"); 943 icon = il.load("spectrogram");
962 mainText = tr("Add &Melodic Range Spectrogram"); 944 mainText = tr("Add &Melodic Range Spectrogram");
963 if (menuType == 0) { 945 if (menuType == paneMenuType) {
964 shortcutText = tr("M"); 946 shortcutText = tr("M");
965 tipText = tr("Add a new pane showing a spectrogram set up for an overview of note pitches"); 947 tipText = tr("Add a new pane showing a spectrogram set up for an overview of note pitches");
966 } else { 948 } else {
967 tipText = tr("Add a new layer showing a spectrogram set up for an overview of note pitches"); 949 tipText = tr("Add a new layer showing a spectrogram set up for an overview of note pitches");
968 } 950 }
969 break; 951 break;
970 952
971 case LayerFactory::PeakFrequencySpectrogram: 953 case LayerFactory::PeakFrequencySpectrogram:
972 icon = il.load("spectrogram"); 954 icon = il.load("spectrogram");
973 mainText = tr("Add Pea&k Frequency Spectrogram"); 955 mainText = tr("Add Pea&k Frequency Spectrogram");
974 if (menuType == 0) { 956 if (menuType == paneMenuType) {
975 shortcutText = tr("K"); 957 shortcutText = tr("K");
976 tipText = tr("Add a new pane showing a spectrogram set up for tracking frequencies"); 958 tipText = tr("Add a new pane showing a spectrogram set up for tracking frequencies");
977 } else { 959 } else {
978 tipText = tr("Add a new layer showing a spectrogram set up for tracking frequencies"); 960 tipText = tr("Add a new layer showing a spectrogram set up for tracking frequencies");
979 } 961 }
980 break; 962 break;
981 963
982 case LayerFactory::Spectrum: 964 case LayerFactory::Spectrum:
983 icon = il.load("spectrum"); 965 icon = il.load("spectrum");
984 mainText = tr("Add Spectr&um"); 966 mainText = tr("Add Spectr&um");
985 if (menuType == 0) { 967 if (menuType == paneMenuType) {
986 shortcutText = tr("U"); 968 shortcutText = tr("U");
987 tipText = tr("Add a new pane showing a frequency spectrum"); 969 tipText = tr("Add a new pane showing a frequency spectrum");
988 } else { 970 } else {
989 tipText = tr("Add a new layer showing a frequency spectrum"); 971 tipText = tr("Add a new layer showing a frequency spectrum");
990 } 972 }
992 974
993 default: break; 975 default: break;
994 } 976 }
995 977
996 std::vector<Model *> candidateModels; 978 std::vector<Model *> candidateModels;
997 if (menuType == 0) { 979 // if (menuType == paneMenuType) {
998 candidateModels = models; 980 candidateModels = models;
999 } else { 981 // } else {
1000 candidateModels.push_back(0); 982 // candidateModels.push_back(0);
1001 } 983 // }
1002 984
1003 for (std::vector<Model *>::iterator mi = 985 for (std::vector<Model *>::iterator mi =
1004 candidateModels.begin(); 986 candidateModels.begin();
1005 mi != candidateModels.end(); ++mi) { 987 mi != candidateModels.end(); ++mi) {
1006 988
1021 1003
1022 if (c == 1 && channels == 1) continue; 1004 if (c == 1 && channels == 1) continue;
1023 bool isDefault = (c == 0); 1005 bool isDefault = (c == 0);
1024 bool isOnly = (isDefault && (channels == 1)); 1006 bool isOnly = (isDefault && (channels == 1));
1025 1007
1026 if (menuType == 1) { 1008 // if (menuType == layerMenuType) {
1027 if (isDefault) isOnly = true; 1009 // if (isDefault) isOnly = true;
1028 else continue; 1010 // else continue;
1029 } 1011 // }
1030 1012
1031 if (isOnly && (!plural || menuType == 1)) { 1013 if (isOnly && (!plural /*|| menuType == layerMenuType*/)) {
1032 1014
1033 if (menuType == 1 && type != LayerFactory::Waveform) { 1015 // if (menuType == layerMenuType && type != LayerFactory::Waveform) {
1034 action = new QAction(mainText, this); 1016 // action = new QAction(mainText, this);
1035 } else { 1017 // } else {
1036 action = new QAction(icon, mainText, this); 1018 action = new QAction(icon, mainText, this);
1037 } 1019 // }
1038 1020
1039 action->setShortcut(shortcutText); 1021 action->setShortcut(shortcutText);
1040 action->setStatusTip(tipText); 1022 action->setStatusTip(tipText);
1041 if (menuType == 0) { 1023 if (menuType == paneMenuType) {
1042 connect(action, SIGNAL(triggered()), 1024 connect(action, SIGNAL(triggered()),
1043 this, SLOT(addPane())); 1025 this, SLOT(addPane()));
1044 connect(this, SIGNAL(canAddPane(bool)), 1026 connect(this, SIGNAL(canAddPane(bool)),
1045 action, SLOT(setEnabled(bool))); 1027 action, SLOT(setEnabled(bool)));
1046 m_paneActions[action] = PaneConfiguration(type); 1028 m_paneActions[action] = LayerConfiguration(type);
1047 } else { 1029 } else {
1048 connect(action, SIGNAL(triggered()), 1030 connect(action, SIGNAL(triggered()),
1049 this, SLOT(addLayer())); 1031 this, SLOT(addLayer()));
1050 connect(this, SIGNAL(canAddLayer(bool)), 1032 connect(this, SIGNAL(canAddLayer(bool)),
1051 action, SLOT(setEnabled(bool))); 1033 action, SLOT(setEnabled(bool)));
1052 m_layerActions[action] = type; 1034 m_layerActions[action] = LayerConfiguration(type);
1053 } 1035 }
1054 if (shortcutText != "") { 1036 if (shortcutText != "") {
1055 m_keyReference->registerShortcut(action); 1037 m_keyReference->registerShortcut(action);
1056 } 1038 }
1057 menu->addAction(action); 1039 menu->addAction(action);
1091 action = new QAction(actionText, this); 1073 action = new QAction(actionText, this);
1092 } 1074 }
1093 1075
1094 action->setStatusTip(tipText); 1076 action->setStatusTip(tipText);
1095 1077
1096 if (menuType == 0) { 1078 if (menuType == paneMenuType) {
1097 connect(action, SIGNAL(triggered()), 1079 connect(action, SIGNAL(triggered()),
1098 this, SLOT(addPane())); 1080 this, SLOT(addPane()));
1099 connect(this, SIGNAL(canAddPane(bool)), 1081 connect(this, SIGNAL(canAddPane(bool)),
1100 action, SLOT(setEnabled(bool))); 1082 action, SLOT(setEnabled(bool)));
1101 m_paneActions[action] = 1083 m_paneActions[action] =
1102 PaneConfiguration(type, model, c - 1); 1084 LayerConfiguration(type, model, c - 1);
1103 } else { 1085 } else {
1104 connect(action, SIGNAL(triggered()), 1086 connect(action, SIGNAL(triggered()),
1105 this, SLOT(addLayer())); 1087 this, SLOT(addLayer()));
1106 connect(this, SIGNAL(canAddLayer(bool)), 1088 connect(this, SIGNAL(canAddLayer(bool)),
1107 action, SLOT(setEnabled(bool))); 1089 action, SLOT(setEnabled(bool)));
1108 m_layerActions[action] = type; 1090 m_layerActions[action] =
1091 LayerConfiguration(type, model, c - 1);
1109 } 1092 }
1110 1093
1111 submenu->addAction(action); 1094 submenu->addAction(action);
1112 } 1095 }
1113 } 1096 }
1114 } 1097 }
1115 } 1098 }
1116 } 1099 }
1117 1100
1118 menu = m_paneMenu; 1101 menu = m_paneMenu;
1102 menu->addSeparator();
1103
1104 action = new QAction(tr("Switch to Previous Pane"), this);
1105 action->setShortcut(tr("["));
1106 action->setStatusTip(tr("Make the next pane up in the pane stack current"));
1107 connect(action, SIGNAL(triggered()), this, SLOT(previousPane()));
1108 connect(this, SIGNAL(canSelectPreviousPane(bool)), action, SLOT(setEnabled(bool)));
1109 m_keyReference->registerShortcut(action);
1110 menu->addAction(action);
1111
1112 action = new QAction(tr("Switch to Next Pane"), this);
1113 action->setShortcut(tr("]"));
1114 action->setStatusTip(tr("Make the next pane down in the pane stack current"));
1115 connect(action, SIGNAL(triggered()), this, SLOT(nextPane()));
1116 connect(this, SIGNAL(canSelectNextPane(bool)), action, SLOT(setEnabled(bool)));
1117 m_keyReference->registerShortcut(action);
1118 menu->addAction(action);
1119 1119
1120 menu->addSeparator(); 1120 menu->addSeparator();
1121 1121
1122 action = new QAction(il.load("editdelete"), tr("&Delete Pane"), this); 1122 action = new QAction(il.load("editdelete"), tr("&Delete Pane"), this);
1123 action->setShortcut(tr("Ctrl+Shift+D")); 1123 action->setShortcut(tr("Ctrl+Shift+D"));
1131 1131
1132 action = new QAction(il.load("timeruler"), tr("Add &Time Ruler"), this); 1132 action = new QAction(il.load("timeruler"), tr("Add &Time Ruler"), this);
1133 action->setStatusTip(tr("Add a new layer showing a time ruler")); 1133 action->setStatusTip(tr("Add a new layer showing a time ruler"));
1134 connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); 1134 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
1135 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool))); 1135 connect(this, SIGNAL(canAddLayer(bool)), action, SLOT(setEnabled(bool)));
1136 m_layerActions[action] = LayerFactory::TimeRuler; 1136 m_layerActions[action] = LayerConfiguration(LayerFactory::TimeRuler);
1137 menu->addAction(action); 1137 menu->addAction(action);
1138 1138
1139 menu->addSeparator(); 1139 menu->addSeparator();
1140 1140
1141 m_existingLayersMenu = menu->addMenu(tr("Add &Existing Layer")); 1141 m_existingLayersMenu = menu->addMenu(tr("Add &Existing Layer"));
1146 m_sliceMenu->setTearOffEnabled(true); 1146 m_sliceMenu->setTearOffEnabled(true);
1147 m_rightButtonLayerMenu->addMenu(m_sliceMenu); 1147 m_rightButtonLayerMenu->addMenu(m_sliceMenu);
1148 1148
1149 setupExistingLayersMenus(); 1149 setupExistingLayersMenus();
1150 1150
1151 /*!!! These don't work correctly -- fix or omit
1152 menu->addSeparator();
1153
1154 action = new QAction(tr("Switch to Previous Layer"), this);
1155 action->setShortcut(tr("{"));
1156 action->setStatusTip(tr("Make the previous layer in the pane current"));
1157 connect(action, SIGNAL(triggered()), this, SLOT(previousLayer()));
1158 connect(this, SIGNAL(canSelectPreviousLayer(bool)), action, SLOT(setEnabled(bool)));
1159 m_keyReference->registerShortcut(action);
1160 menu->addAction(action);
1161
1162 action = new QAction(tr("Switch to Next Layer"), this);
1163 action->setShortcut(tr("}"));
1164 action->setStatusTip(tr("Make the next layer in the pane current"));
1165 connect(action, SIGNAL(triggered()), this, SLOT(nextLayer()));
1166 connect(this, SIGNAL(canSelectNextLayer(bool)), action, SLOT(setEnabled(bool)));
1167 m_keyReference->registerShortcut(action);
1168 menu->addAction(action);
1169 */
1151 m_rightButtonLayerMenu->addSeparator(); 1170 m_rightButtonLayerMenu->addSeparator();
1152 menu->addSeparator(); 1171 menu->addSeparator();
1153 1172
1154 QAction *raction = new QAction(tr("&Rename Layer..."), this); 1173 QAction *raction = new QAction(tr("&Rename Layer..."), this);
1155 raction->setShortcut(tr("R")); 1174 raction->setShortcut(tr("R"));
1182 m_transformsMenu = menuBar()->addMenu(tr("&Transform")); 1201 m_transformsMenu = menuBar()->addMenu(tr("&Transform"));
1183 m_transformsMenu->setTearOffEnabled(true); 1202 m_transformsMenu->setTearOffEnabled(true);
1184 } 1203 }
1185 1204
1186 TransformList transforms = 1205 TransformList transforms =
1187 TransformFactory::getInstance()->getAllTransforms(); 1206 TransformFactory::getInstance()->getAllTransformDescriptions();
1188 1207
1189 vector<QString> types = 1208 vector<QString> types =
1190 TransformFactory::getInstance()->getAllTransformTypes(); 1209 TransformFactory::getInstance()->getAllTransformTypes();
1191 1210
1192 map<QString, map<QString, SubdividingMenu *> > categoryMenus; 1211 map<QString, map<QString, SubdividingMenu *> > categoryMenus;
1288 byMakerMenu->addMenu(makerMenus[*i][maker]); 1307 byMakerMenu->addMenu(makerMenus[*i][maker]);
1289 pendingMenus.insert(makerMenus[*i][maker]); 1308 pendingMenus.insert(makerMenus[*i][maker]);
1290 } 1309 }
1291 } 1310 }
1292 1311
1312 // Names should only be duplicated here if they have the same
1313 // plugin name, output name and maker but are in different library
1314 // .so names -- that won't happen often I hope
1315 std::map<QString, QString> idNameSonameMap;
1316 std::set<QString> seenNames, duplicateNames;
1317 for (unsigned int i = 0; i < transforms.size(); ++i) {
1318 QString name = transforms[i].name;
1319 if (seenNames.find(name) != seenNames.end()) {
1320 duplicateNames.insert(name);
1321 } else {
1322 seenNames.insert(name);
1323 }
1324 }
1325
1293 for (unsigned int i = 0; i < transforms.size(); ++i) { 1326 for (unsigned int i = 0; i < transforms.size(); ++i) {
1294 1327
1295 QString name = transforms[i].name; 1328 QString name = transforms[i].name;
1296 if (name == "") name = transforms[i].identifier; 1329 if (name == "") name = transforms[i].identifier;
1297 1330
1306 if (maker == "") maker = tr("Unknown"); 1339 if (maker == "") maker = tr("Unknown");
1307 maker.replace(QRegExp(tr(" [\\(<].*$")), ""); 1340 maker.replace(QRegExp(tr(" [\\(<].*$")), "");
1308 1341
1309 QString pluginName = name.section(": ", 0, 0); 1342 QString pluginName = name.section(": ", 0, 0);
1310 QString output = name.section(": ", 1); 1343 QString output = name.section(": ", 1);
1344
1345 if (duplicateNames.find(pluginName) != duplicateNames.end()) {
1346 pluginName = QString("%1 <%2>")
1347 .arg(pluginName)
1348 .arg(transforms[i].identifier.section(':', 1, 1));
1349 if (output == "") name = pluginName;
1350 else name = QString("%1: %2")
1351 .arg(pluginName)
1352 .arg(output);
1353 }
1311 1354
1312 QAction *action = new QAction(tr("%1...").arg(name), this); 1355 QAction *action = new QAction(tr("%1...").arg(name), this);
1313 connect(action, SIGNAL(triggered()), this, SLOT(addLayer())); 1356 connect(action, SIGNAL(triggered()), this, SLOT(addLayer()));
1314 m_transformActions[action] = transforms[i].identifier; 1357 m_transformActions[action] = transforms[i].identifier;
1315 m_transformActionsReverse[transforms[i].identifier] = action; 1358 m_transformActionsReverse[transforms[i].identifier] = action;
2521 m_preferencesDialog->isVisible()) { 2564 m_preferencesDialog->isVisible()) {
2522 closeSession(); // otherwise we'll have to wait for prefs changes 2565 closeSession(); // otherwise we'll have to wait for prefs changes
2523 m_preferencesDialog->applicationClosing(false); 2566 m_preferencesDialog->applicationClosing(false);
2524 } 2567 }
2525 2568
2526 if (m_layerTreeDialog &&
2527 m_layerTreeDialog->isVisible()) {
2528 delete m_layerTreeDialog;
2529 }
2530
2531 closeSession(); 2569 closeSession();
2532 2570
2533 e->accept(); 2571 e->accept();
2534 return; 2572 return;
2535 } 2573 }
2672 } 2710 }
2673 } 2711 }
2674 } 2712 }
2675 2713
2676 void 2714 void
2715 MainWindow::propertyStacksResized(int width)
2716 {
2717 std::cerr << "MainWindow::propertyStacksResized(" << width << ")" << std::endl;
2718
2719 if (!m_playControlsSpacer) return;
2720
2721 int spacerWidth = width - m_playControlsWidth - 4;
2722
2723 std::cerr << "resizing spacer from " << m_playControlsSpacer->width() << " to " << spacerWidth << std::endl;
2724
2725 m_playControlsSpacer->setFixedSize(QSize(spacerWidth, 2));
2726 }
2727
2728 void
2677 MainWindow::addPane() 2729 MainWindow::addPane()
2678 { 2730 {
2679 QObject *s = sender(); 2731 QObject *s = sender();
2680 QAction *action = dynamic_cast<QAction *>(s); 2732 QAction *action = dynamic_cast<QAction *>(s);
2681 2733
2695 2747
2696 addPane(i->second, action->text()); 2748 addPane(i->second, action->text());
2697 } 2749 }
2698 2750
2699 void 2751 void
2700 MainWindow::addPane(const PaneConfiguration &configuration, QString text) 2752 MainWindow::addPane(const LayerConfiguration &configuration, QString text)
2701 { 2753 {
2702 CommandHistory::getInstance()->startCompoundOperation(text, true); 2754 CommandHistory::getInstance()->startCompoundOperation(text, true);
2703 2755
2704 AddPaneCommand *command = new AddPaneCommand(this); 2756 AddPaneCommand *command = new AddPaneCommand(this);
2705 CommandHistory::getInstance()->addCommand(command); 2757 CommandHistory::getInstance()->addCommand(command);
2732 Model *model = 0; 2784 Model *model = 0;
2733 2785
2734 if (suggestedModel) { 2786 if (suggestedModel) {
2735 2787
2736 // check its validity 2788 // check its validity
2737 std::vector<Model *> inputModels = m_document->getTransformerInputModels(); 2789 std::vector<Model *> inputModels = m_document->getTransformInputModels();
2738 for (size_t j = 0; j < inputModels.size(); ++j) { 2790 for (size_t j = 0; j < inputModels.size(); ++j) {
2739 if (inputModels[j] == suggestedModel) { 2791 if (inputModels[j] == suggestedModel) {
2740 model = suggestedModel; 2792 model = suggestedModel;
2741 break; 2793 break;
2742 } 2794 }
2826 std::cerr << "WARNING: MainWindow::addLayer: unknown action " 2878 std::cerr << "WARNING: MainWindow::addLayer: unknown action "
2827 << action->objectName().toStdString() << std::endl; 2879 << action->objectName().toStdString() << std::endl;
2828 return; 2880 return;
2829 } 2881 }
2830 2882
2831 LayerFactory::LayerType type = i->second; 2883 LayerFactory::LayerType type = i->second.layer;
2832 2884
2833 LayerFactory::LayerTypeSet emptyTypes = 2885 LayerFactory::LayerTypeSet emptyTypes =
2834 LayerFactory::getInstance()->getValidEmptyLayerTypes(); 2886 LayerFactory::getInstance()->getValidEmptyLayerTypes();
2835 2887
2836 Layer *newLayer; 2888 Layer *newLayer;
2842 m_toolActions[ViewManager::DrawMode]->trigger(); 2894 m_toolActions[ViewManager::DrawMode]->trigger();
2843 } 2895 }
2844 2896
2845 } else { 2897 } else {
2846 2898
2847 newLayer = m_document->createMainModelLayer(type); 2899 if (!i->second.sourceModel) {
2848 } 2900 // e.g. time ruler
2901 newLayer = m_document->createMainModelLayer(type);
2902 } else {
2903 newLayer = m_document->createLayer(type);
2904 if (m_document->isKnownModel(i->second.sourceModel)) {
2905 m_document->setChannel(newLayer, i->second.channel);
2906 m_document->setModel(newLayer, i->second.sourceModel);
2907 } else {
2908 std::cerr << "WARNING: MainWindow::addLayer: unknown model "
2909 << i->second.sourceModel
2910 << " (\""
2911 << (i->second.sourceModel ? i->second.sourceModel->objectName().toStdString() : "")
2912 << "\") in layer action map"
2913 << std::endl;
2914 }
2915 }
2916 }
2849 2917
2850 if (newLayer) { 2918 if (newLayer) {
2851 m_document->addLayerToView(pane, newLayer); 2919 m_document->addLayerToView(pane, newLayer);
2852 m_paneStack->setCurrentLayer(pane, newLayer); 2920 m_paneStack->setCurrentLayer(pane, newLayer);
2853 } 2921 }
2854 2922
2855 return; 2923 return;
2856 } 2924 }
2857 2925
2858 TransformId transform = i->second; 2926 //!!! want to do something like this, but it's not supported in
2859 ModelTransformerFactory *factory = ModelTransformerFactory::getInstance(); 2927 //ModelTransformerFactory yet
2860 2928 /*
2861 QString configurationXml;
2862
2863 int channel = -1; 2929 int channel = -1;
2864 // pick up the default channel from any existing layers on the same pane 2930 // pick up the default channel from any existing layers on the same pane
2865 for (int j = 0; j < pane->getLayerCount(); ++j) { 2931 for (int j = 0; j < pane->getLayerCount(); ++j) {
2866 int c = LayerFactory::getInstance()->getChannel(pane->getLayer(j)); 2932 int c = LayerFactory::getInstance()->getChannel(pane->getLayer(j));
2867 if (c != -1) { 2933 if (c != -1) {
2868 channel = c; 2934 channel = c;
2869 break; 2935 break;
2870 } 2936 }
2871 } 2937 }
2938 */
2872 2939
2873 // We always ask for configuration, even if the plugin isn't 2940 // We always ask for configuration, even if the plugin isn't
2874 // supposed to be configurable, because we need to let the user 2941 // supposed to be configurable, because we need to let the user
2875 // change the execution context (block size etc). 2942 // change the execution context (block size etc).
2876 2943
2877 PluginTransformer::ExecutionContext context(channel); 2944 QString transformId = i->second;
2945 Transform transform = TransformFactory::getInstance()->
2946 getDefaultTransformFor(transformId);
2878 2947
2879 std::vector<Model *> candidateInputModels = 2948 std::vector<Model *> candidateInputModels =
2880 m_document->getTransformerInputModels(); 2949 m_document->getTransformInputModels();
2881 2950
2882 Model *defaultInputModel = 0; 2951 Model *defaultInputModel = 0;
2883 for (int j = 0; j < pane->getLayerCount(); ++j) { 2952 for (int j = 0; j < pane->getLayerCount(); ++j) {
2884 Layer *layer = pane->getLayer(j); 2953 Layer *layer = pane->getLayer(j);
2885 if (!layer) continue; 2954 if (!layer) continue;
2955 if (LayerFactory::getInstance()->getLayerType(layer) !=
2956 LayerFactory::Waveform &&
2957 !layer->isLayerOpaque()) continue;
2886 Model *model = layer->getModel(); 2958 Model *model = layer->getModel();
2887 if (!model) continue; 2959 if (!model) continue;
2888 for (size_t k = 0; k < candidateInputModels.size(); ++k) { 2960 for (size_t k = 0; k < candidateInputModels.size(); ++k) {
2889 if (candidateInputModels[k] == model) { 2961 if (candidateInputModels[k] == model) {
2890 defaultInputModel = model; 2962 defaultInputModel = model;
2898 size_t endFrame = 0; 2970 size_t endFrame = 0;
2899 m_viewManager->getSelection().getExtents(startFrame, endFrame); 2971 m_viewManager->getSelection().getExtents(startFrame, endFrame);
2900 if (endFrame > startFrame) duration = endFrame - startFrame; 2972 if (endFrame > startFrame) duration = endFrame - startFrame;
2901 else startFrame = 0; 2973 else startFrame = 0;
2902 2974
2903 Model *inputModel = factory->getConfigurationForTransformer 2975 ModelTransformer::Input input = ModelTransformerFactory::getInstance()->
2976 getConfigurationForTransform
2904 (transform, 2977 (transform,
2905 candidateInputModels, 2978 candidateInputModels,
2906 defaultInputModel, 2979 defaultInputModel,
2907 context,
2908 configurationXml,
2909 m_playSource, 2980 m_playSource,
2910 startFrame, 2981 startFrame,
2911 duration); 2982 duration);
2912 2983
2913 if (!inputModel) return; 2984 if (!input.getModel()) return;
2914 2985
2915 // std::cerr << "MainWindow::addLayer: Input model is " << inputModel << " \"" << inputModel->objectName().toStdString() << "\"" << std::endl; 2986 // std::cerr << "MainWindow::addLayer: Input model is " << input.getModel() << " \"" << input.getModel()->objectName().toStdString() << "\"" << std::endl;
2916 2987
2917 Layer *newLayer = m_document->createDerivedLayer(transform, 2988 Layer *newLayer = m_document->createDerivedLayer(transform, input);
2918 inputModel,
2919 context,
2920 configurationXml);
2921 2989
2922 if (newLayer) { 2990 if (newLayer) {
2923 m_document->addLayerToView(pane, newLayer); 2991 m_document->addLayerToView(pane, newLayer);
2924 m_document->setChannel(newLayer, context.channel); 2992 m_document->setChannel(newLayer, input.getChannel());
2925 m_recentTransforms.add(transform); 2993 m_recentTransforms.add(transformId);
2926 m_paneStack->setCurrentLayer(pane, newLayer); 2994 m_paneStack->setCurrentLayer(pane, newLayer);
2927 } 2995 }
2928 2996
2929 updateMenuStates(); 2997 updateMenuStates();
2930 } 2998 }
2940 QString newName = QInputDialog::getText 3008 QString newName = QInputDialog::getText
2941 (this, tr("Rename Layer"), 3009 (this, tr("Rename Layer"),
2942 tr("New name for this layer:"), 3010 tr("New name for this layer:"),
2943 QLineEdit::Normal, layer->objectName(), &ok); 3011 QLineEdit::Normal, layer->objectName(), &ok);
2944 if (ok) { 3012 if (ok) {
2945 layer->setObjectName(newName); 3013 layer->setPresentationName(newName);
2946 setupExistingLayersMenus(); 3014 setupExistingLayersMenus();
2947 } 3015 }
2948 } 3016 }
2949 } 3017 }
2950 } 3018 }
3019 contextHelpChanged(tr("Playback speed: %1%2%") 3087 contextHelpChanged(tr("Playback speed: %1%2%")
3020 .arg(position > 100 ? "+" : "") 3088 .arg(position > 100 ? "+" : "")
3021 .arg(pc)); 3089 .arg(pc));
3022 } 3090 }
3023 3091
3024 #ifdef HAVE_RUBBERBAND 3092 m_playSource->setTimeStretch(factor);
3025 bool mono = false;
3026 bool sharpen = true;
3027 #else
3028 m_playSharpen->setEnabled(something);
3029 bool sharpen = (something && m_playSharpen->isChecked());
3030 m_playMono->setEnabled(something);
3031 bool mono = (something && m_playMono->isChecked());
3032 #endif
3033
3034 m_playSource->setTimeStretch(factor, sharpen, mono);
3035 3093
3036 updateMenuStates(); 3094 updateMenuStates();
3037 } 3095 }
3038
3039 #ifndef HAVE_RUBBERBAND
3040 void
3041 MainWindow::playSharpenToggled()
3042 {
3043 QSettings settings;
3044 settings.beginGroup("MainWindow");
3045 settings.setValue("playsharpen", m_playSharpen->isChecked());
3046 settings.endGroup();
3047
3048 playSpeedChanged(m_playSpeed->value());
3049 }
3050
3051 void
3052 MainWindow::playMonoToggled()
3053 {
3054 QSettings settings;
3055 settings.beginGroup("MainWindow");
3056 settings.setValue("playmono", m_playMono->isChecked());
3057 settings.endGroup();
3058
3059 playSpeedChanged(m_playSpeed->value());
3060 }
3061 #endif
3062 3096
3063 void 3097 void
3064 MainWindow::speedUpPlayback() 3098 MainWindow::speedUpPlayback()
3065 { 3099 {
3066 int value = m_playSpeed->value(); 3100 int value = m_playSpeed->value();
3080 3114
3081 void 3115 void
3082 MainWindow::restoreNormalPlayback() 3116 MainWindow::restoreNormalPlayback()
3083 { 3117 {
3084 m_playSpeed->setValue(m_playSpeed->defaultValue()); 3118 m_playSpeed->setValue(m_playSpeed->defaultValue());
3119 }
3120
3121 void
3122 MainWindow::currentPaneChanged(Pane *pane)
3123 {
3124 MainWindowBase::currentPaneChanged(pane);
3125
3126 if (!pane || !m_panLayer) return;
3127 for (int i = pane->getLayerCount(); i > 0; ) {
3128 --i;
3129 Layer *layer = pane->getLayer(i);
3130 if (LayerFactory::getInstance()->getLayerType(layer) ==
3131 LayerFactory::Waveform) {
3132 RangeSummarisableTimeValueModel *tvm =
3133 dynamic_cast<RangeSummarisableTimeValueModel *>(layer->getModel());
3134 if (tvm) {
3135 m_panLayer->setModel(tvm);
3136 return;
3137 }
3138 }
3139 }
3085 } 3140 }
3086 3141
3087 void 3142 void
3088 MainWindow::updateVisibleRangeDisplay(Pane *p) const 3143 MainWindow::updateVisibleRangeDisplay(Pane *p) const
3089 { 3144 {
3235 3290
3236 void 3291 void
3237 MainWindow::resetInstantsCounters() 3292 MainWindow::resetInstantsCounters()
3238 { 3293 {
3239 LabelCounterInputDialog dialog(m_labeller, this); 3294 LabelCounterInputDialog dialog(m_labeller, this);
3295 dialog.setWindowTitle(tr("Reset Counters"));
3240 dialog.exec(); 3296 dialog.exec();
3241 } 3297 }
3242 3298
3243 void 3299 void
3244 MainWindow::modelGenerationFailed(QString transformName) 3300 MainWindow::modelGenerationFailed(QString transformName, QString message)
3301 {
3302 if (message != "") {
3303
3304 QMessageBox::warning
3305 (this,
3306 tr("Failed to generate layer"),
3307 tr("<b>Layer generation failed</b><p>Failed to generate derived layer.<p>The layer transform \"%1\" failed:<p>%2")
3308 .arg(transformName).arg(message),
3309 QMessageBox::Ok);
3310 } else {
3311 QMessageBox::warning
3312 (this,
3313 tr("Failed to generate layer"),
3314 tr("<b>Layer generation failed</b><p>Failed to generate a derived layer.<p>The layer transform \"%1\" failed.<p>No error information is available.")
3315 .arg(transformName),
3316 QMessageBox::Ok);
3317 }
3318 }
3319
3320 void
3321 MainWindow::modelGenerationWarning(QString transformName, QString message)
3322 {
3323 QMessageBox::warning
3324 (this, tr("Warning"), message, QMessageBox::Ok);
3325 }
3326
3327 void
3328 MainWindow::modelRegenerationFailed(QString layerName,
3329 QString transformName, QString message)
3330 {
3331 if (message != "") {
3332
3333 QMessageBox::warning
3334 (this,
3335 tr("Failed to regenerate layer"),
3336 tr("<b>Layer generation failed</b><p>Failed to regenerate derived layer \"%1\" using new data model as input.<p>The layer transform \"%2\" failed:<p>%3")
3337 .arg(layerName).arg(transformName).arg(message),
3338 QMessageBox::Ok);
3339 } else {
3340 QMessageBox::warning
3341 (this,
3342 tr("Failed to regenerate layer"),
3343 tr("<b>Layer generation failed</b><p>Failed to regenerate derived layer \"%1\" using new data model as input.<p>The layer transform \"%2\" failed.<p>No error information is available.")
3344 .arg(layerName).arg(transformName),
3345 QMessageBox::Ok);
3346 }
3347 }
3348
3349 void
3350 MainWindow::modelRegenerationWarning(QString layerName,
3351 QString transformName, QString message)
3352 {
3353 QMessageBox::warning
3354 (this, tr("Warning"), tr("<b>Warning when regenerating layer</b><p>When regenerating the derived layer \"%1\" using new data model as input:<p>%2").arg(layerName).arg(message), QMessageBox::Ok);
3355 }
3356
3357 void
3358 MainWindow::alignmentFailed(QString transformName, QString message)
3245 { 3359 {
3246 QMessageBox::warning 3360 QMessageBox::warning
3247 (this, 3361 (this,
3248 tr("Failed to generate layer"), 3362 tr("Failed to calculate alignment"),
3249 tr("<b>Layer generation failed</b><p>Failed to generate a derived layer.<p>The layer transform \"%1\" failed.<p>This may mean that a plugin failed to initialise, perhaps because it rejected the processing block size that was requested.") 3363 tr("<b>Alignment calculation failed</b><p>Failed to calculate an audio alignment using transform \"%1\":<p>%2")
3250 .arg(transformName), 3364 .arg(transformName).arg(message),
3251 QMessageBox::Ok);
3252 }
3253
3254 void
3255 MainWindow::modelRegenerationFailed(QString layerName, QString transformName)
3256 {
3257 QMessageBox::warning
3258 (this,
3259 tr("Failed to regenerate layer"),
3260 tr("<b>Layer generation failed</b><p>Failed to regenerate derived layer \"%1\".<p>The layer transform \"%2\" failed to run.<p>This may mean that the layer used a plugin that is not currently available.")
3261 .arg(layerName).arg(transformName),
3262 QMessageBox::Ok); 3365 QMessageBox::Ok);
3263 } 3366 }
3264 3367
3265 void 3368 void
3266 MainWindow::rightButtonMenuRequested(Pane *pane, QPoint position) 3369 MainWindow::rightButtonMenuRequested(Pane *pane, QPoint position)
3278 m_layerTreeDialog->raise(); 3381 m_layerTreeDialog->raise();
3279 return; 3382 return;
3280 } 3383 }
3281 3384
3282 m_layerTreeDialog = new LayerTreeDialog(m_paneStack); 3385 m_layerTreeDialog = new LayerTreeDialog(m_paneStack);
3386 m_layerTreeDialog->setAttribute(Qt::WA_DeleteOnClose); // see below
3283 m_layerTreeDialog->show(); 3387 m_layerTreeDialog->show();
3284 } 3388 }
3285 3389
3286 void 3390 void
3287 MainWindow::preferences() 3391 MainWindow::preferences()
3313 3417
3314 if (w == m_fader) { 3418 if (w == m_fader) {
3315 contextHelpChanged(tr("Adjust the master playback level")); 3419 contextHelpChanged(tr("Adjust the master playback level"));
3316 } else if (w == m_playSpeed) { 3420 } else if (w == m_playSpeed) {
3317 contextHelpChanged(tr("Adjust the master playback speed")); 3421 contextHelpChanged(tr("Adjust the master playback speed"));
3318 #ifndef HAVE_RUBBERBAND
3319 } else if (w == m_playSharpen && w->isEnabled()) {
3320 contextHelpChanged(tr("Toggle transient sharpening for playback time scaling"));
3321 } else if (w == m_playMono && w->isEnabled()) {
3322 contextHelpChanged(tr("Toggle mono mode for playback time scaling"));
3323 #endif
3324 } 3422 }
3325 } 3423 }
3326 3424
3327 void 3425 void
3328 MainWindow::mouseLeftWidget() 3426 MainWindow::mouseLeftWidget()
3337 } 3435 }
3338 3436
3339 void 3437 void
3340 MainWindow::help() 3438 MainWindow::help()
3341 { 3439 {
3342 openHelpUrl(tr("http://www.sonicvisualiser.org/doc/reference/1.0/en/")); 3440 openHelpUrl(tr("http://www.sonicvisualiser.org/doc/reference/1.2/en/"));
3343 } 3441 }
3344 3442
3345 void 3443 void
3346 MainWindow::about() 3444 MainWindow::about()
3347 { 3445 {
3364 #endif 3462 #endif
3365 3463
3366 QString aboutText; 3464 QString aboutText;
3367 3465
3368 aboutText += tr("<h3>About Sonic Visualiser</h3>"); 3466 aboutText += tr("<h3>About Sonic Visualiser</h3>");
3369 aboutText += tr("<p>Sonic Visualiser is a program for viewing and exploring audio data for<br>semantic music analysis and annotation.</p>"); 3467 aboutText += tr("<p>Sonic Visualiser is a program for viewing and exploring audio data for semantic music analysis and annotation.</p>");
3370 aboutText += tr("<p>%1 : %2 configuration</p>") 3468 aboutText += tr("<p>%1 : %2 configuration</p>")
3371 .arg(version) 3469 .arg(version)
3372 .arg(debug ? tr("Debug") : tr("Release")); 3470 .arg(debug ? tr("Debug") : tr("Release"));
3373 3471
3374 #ifndef BUILD_STATIC 3472 #ifndef BUILD_STATIC
3446 #endif 3544 #endif
3447 aboutText += "</p>"; 3545 aboutText += "</p>";
3448 #endif 3546 #endif
3449 3547
3450 aboutText += 3548 aboutText +=
3451 "<p>Sonic Visualiser Copyright &copy; 2005 - 2007 Chris Cannam and<br>" 3549 "<p>Sonic Visualiser Copyright &copy; 2005 - 2008 Chris Cannam and "
3452 "Queen Mary, University of London.</p>" 3550 "Queen Mary, University of London.</p>"
3453 "<p>This program is free software; you can redistribute it and/or<br>" 3551 "<p>This program is free software; you can redistribute it and/or "
3454 "modify it under the terms of the GNU General Public License as<br>" 3552 "modify it under the terms of the GNU General Public License as "
3455 "published by the Free Software Foundation; either version 2 of the<br>" 3553 "published by the Free Software Foundation; either version 2 of the "
3456 "License, or (at your option) any later version.<br>See the file " 3554 "License, or (at your option) any later version.<br>See the file "
3457 "COPYING included with this distribution for more information.</p>"; 3555 "COPYING included with this distribution for more information.</p>";
3458 3556
3459 QMessageBox::about(this, tr("About Sonic Visualiser"), aboutText); 3557 QMessageBox::about(this, tr("About Sonic Visualiser"), aboutText);
3460 } 3558 }