annotate src/MainWindow.cpp @ 198:bb391844e2aa

Switching pitch candidate no longer wraps around: you can't go higher than the highest or lower than the lowest (though you can go either "up" or "down" if none of the alternate candidates has been selected yet, regardless of whether the candidates are higher or lower than the actual pitch track)
author Chris Cannam
date Wed, 05 Mar 2014 11:39:28 +0000
parents 797395e56489
children 0ba33d6c0a71
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 Tony
Chris@0 5 An intonation analysis and annotation tool
Chris@0 6 Centre for Digital Music, Queen Mary, University of London.
Chris@0 7 This file copyright 2006-2012 Chris Cannam and QMUL.
Chris@0 8
Chris@0 9 This program is free software; you can redistribute it and/or
Chris@0 10 modify it under the terms of the GNU General Public License as
Chris@0 11 published by the Free Software Foundation; either version 2 of the
Chris@0 12 License, or (at your option) any later version. See the file
Chris@0 13 COPYING included with this distribution for more information.
Chris@0 14 */
Chris@0 15
Chris@0 16 #include "../version.h"
Chris@0 17
Chris@0 18 #include "MainWindow.h"
Chris@95 19 #include "NetworkPermissionTester.h"
Chris@6 20 #include "Analyser.h"
Chris@6 21
Chris@0 22 #include "framework/Document.h"
Chris@95 23 #include "framework/VersionTester.h"
Chris@0 24
Chris@0 25 #include "view/Pane.h"
Chris@0 26 #include "view/PaneStack.h"
Chris@0 27 #include "data/model/WaveFileModel.h"
matthiasm@26 28 #include "data/model/NoteModel.h"
matthiasm@26 29 #include "data/model/FlexiNoteModel.h"
matthiasm@42 30 #include "layer/FlexiNoteLayer.h"
matthiasm@26 31 #include "data/model/NoteModel.h"
Chris@0 32 #include "view/ViewManager.h"
Chris@0 33 #include "base/Preferences.h"
Chris@0 34 #include "layer/WaveformLayer.h"
Chris@0 35 #include "layer/TimeInstantLayer.h"
Chris@0 36 #include "layer/TimeValueLayer.h"
Chris@192 37 #include "layer/SpectrogramLayer.h"
Chris@0 38 #include "widgets/Fader.h"
Chris@0 39 #include "view/Overview.h"
Chris@0 40 #include "widgets/AudioDial.h"
Chris@0 41 #include "widgets/IconLoader.h"
Chris@0 42 #include "widgets/KeyReference.h"
Chris@0 43 #include "audioio/AudioCallbackPlaySource.h"
Chris@0 44 #include "audioio/AudioCallbackPlayTarget.h"
Chris@0 45 #include "audioio/PlaySpeedRangeMapper.h"
Chris@0 46 #include "base/Profiler.h"
Chris@0 47 #include "base/UnitDatabase.h"
Chris@0 48 #include "layer/ColourDatabase.h"
Chris@139 49 #include "base/Selection.h"
Chris@0 50
Chris@174 51 #include "rdf/RDFImporter.h"
Chris@174 52 #include "data/fileio/DataFileReaderFactory.h"
Chris@174 53 #include "data/fileio/CSVFormat.h"
matthiasm@26 54 #include "data/fileio/CSVFileWriter.h"
matthiasm@26 55 #include "data/fileio/MIDIFileWriter.h"
matthiasm@26 56 #include "rdf/RDFExporter.h"
matthiasm@26 57
Chris@0 58 // For version information
Chris@0 59 #include "vamp/vamp.h"
Chris@0 60 #include "vamp-sdk/PluginBase.h"
Chris@0 61 #include "plugin/api/ladspa.h"
Chris@0 62 #include "plugin/api/dssi.h"
Chris@0 63
Chris@0 64 #include <QApplication>
Chris@0 65 #include <QMessageBox>
Chris@0 66 #include <QGridLayout>
Chris@0 67 #include <QLabel>
Chris@0 68 #include <QMenuBar>
Chris@0 69 #include <QToolBar>
Chris@0 70 #include <QToolButton>
Chris@0 71 #include <QInputDialog>
Chris@0 72 #include <QStatusBar>
Chris@0 73 #include <QFileInfo>
Chris@0 74 #include <QDir>
Chris@0 75 #include <QProcess>
Chris@2 76 #include <QPushButton>
Chris@0 77 #include <QSettings>
Chris@0 78 #include <QScrollArea>
Chris@128 79 #include <QPainter>
Chris@0 80
Chris@0 81 #include <iostream>
Chris@0 82 #include <cstdio>
Chris@0 83 #include <errno.h>
Chris@0 84
Chris@0 85 using std::vector;
Chris@0 86
Chris@0 87
Chris@0 88 MainWindow::MainWindow(bool withAudioOutput, bool withOSCSupport) :
Chris@0 89 MainWindowBase(withAudioOutput, withOSCSupport, false),
Chris@0 90 m_overview(0),
Chris@0 91 m_mainMenusCreated(false),
Chris@0 92 m_playbackMenu(0),
gyorgyf@45 93 m_recentFilesMenu(0),
Chris@0 94 m_rightButtonMenu(0),
Chris@0 95 m_rightButtonPlaybackMenu(0),
Chris@0 96 m_deleteSelectedAction(0),
Chris@0 97 m_ffwdAction(0),
Chris@0 98 m_rwdAction(0),
Chris@168 99 m_intelligentActionOn(true), //GF: !!! temporary
Chris@0 100 m_keyReference(new KeyReference())
Chris@0 101 {
Chris@0 102 setWindowTitle(QApplication::applicationName());
Chris@0 103
Chris@0 104 UnitDatabase *udb = UnitDatabase::getInstance();
Chris@0 105 udb->registerUnit("Hz");
Chris@0 106 udb->registerUnit("dB");
Chris@0 107 udb->registerUnit("s");
Chris@0 108
Chris@0 109 ColourDatabase *cdb = ColourDatabase::getInstance();
Chris@0 110 cdb->addColour(Qt::black, tr("Black"));
Chris@0 111 cdb->addColour(Qt::darkRed, tr("Red"));
Chris@0 112 cdb->addColour(Qt::darkBlue, tr("Blue"));
Chris@0 113 cdb->addColour(Qt::darkGreen, tr("Green"));
Chris@0 114 cdb->addColour(QColor(200, 50, 255), tr("Purple"));
Chris@0 115 cdb->addColour(QColor(255, 150, 50), tr("Orange"));
Chris@120 116 cdb->addColour(QColor(180, 180, 180), tr("Grey"));
Chris@0 117 cdb->setUseDarkBackground(cdb->addColour(Qt::white, tr("White")), true);
Chris@0 118 cdb->setUseDarkBackground(cdb->addColour(Qt::red, tr("Bright Red")), true);
Chris@0 119 cdb->setUseDarkBackground(cdb->addColour(QColor(30, 150, 255), tr("Bright Blue")), true);
Chris@0 120 cdb->setUseDarkBackground(cdb->addColour(Qt::green, tr("Bright Green")), true);
Chris@0 121 cdb->setUseDarkBackground(cdb->addColour(QColor(225, 74, 255), tr("Bright Purple")), true);
Chris@0 122 cdb->setUseDarkBackground(cdb->addColour(QColor(255, 188, 80), tr("Bright Orange")), true);
Chris@0 123
Chris@0 124 Preferences::getInstance()->setResampleOnLoad(true);
Chris@0 125 Preferences::getInstance()->setSpectrogramSmoothing
Chris@0 126 (Preferences::SpectrogramInterpolated);
Chris@0 127
Chris@0 128 QSettings settings;
Chris@0 129
Chris@0 130 settings.beginGroup("MainWindow");
Chris@0 131 settings.setValue("showstatusbar", false);
Chris@0 132 settings.endGroup();
Chris@0 133
Chris@96 134 settings.beginGroup("Transformer");
Chris@96 135 settings.setValue("use-flexi-note-model", true);
Chris@96 136 settings.endGroup();
Chris@96 137
Chris@73 138 settings.beginGroup("LayerDefaults");
Chris@73 139 settings.setValue("waveform",
Chris@73 140 QString("<layer scale=\"%1\" channelMode=\"%2\"/>")
Chris@73 141 .arg(int(WaveformLayer::LinearScale))
Chris@73 142 .arg(int(WaveformLayer::MixChannels)));
Chris@73 143 settings.endGroup();
Chris@73 144
Chris@6 145 m_viewManager->setAlignMode(false);
Chris@6 146 m_viewManager->setPlaySoloMode(false);
Chris@0 147 m_viewManager->setToolMode(ViewManager::NavigateMode);
Chris@0 148 m_viewManager->setZoomWheelsEnabled(false);
Chris@6 149 m_viewManager->setIlluminateLocalFeatures(true);
Chris@0 150 m_viewManager->setShowWorkTitle(true);
Chris@6 151 m_viewManager->setShowCentreLine(false);
Chris@91 152 m_viewManager->setOverlayMode(ViewManager::MinimalOverlays);
Chris@0 153
Chris@192 154 connect(m_viewManager, SIGNAL(selectionChangedByUser()),
Chris@192 155 this, SLOT(selectionChangedByUser()));
Chris@164 156
Chris@0 157 QFrame *frame = new QFrame;
Chris@0 158 setCentralWidget(frame);
Chris@0 159
Chris@0 160 QGridLayout *layout = new QGridLayout;
Chris@0 161
Chris@0 162 QScrollArea *scroll = new QScrollArea(frame);
Chris@0 163 scroll->setWidgetResizable(true);
Chris@0 164 scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
Chris@0 165 scroll->setFrameShape(QFrame::NoFrame);
Chris@0 166
Chris@6 167 // We have a pane stack: it comes with the territory. However, we
Chris@120 168 // have a fixed and known number of panes in it -- it isn't
Chris@120 169 // variable
Chris@0 170 m_paneStack->setLayoutStyle(PaneStack::NoPropertyStacks);
Chris@137 171 m_paneStack->setShowPaneAccessories(false);
Chris@139 172 connect(m_paneStack, SIGNAL(doubleClickSelectInvoked(size_t)),
Chris@139 173 this, SLOT(doubleClickSelectInvoked(size_t)));
Chris@0 174 scroll->setWidget(m_paneStack);
Chris@6 175
Chris@0 176 m_overview = new Overview(frame);
Chris@0 177 m_overview->setViewManager(m_viewManager);
Chris@0 178 m_overview->setFixedHeight(40);
Chris@0 179 #ifndef _WIN32
Chris@0 180 // For some reason, the contents of the overview never appear if we
Chris@0 181 // make this setting on Windows. I have no inclination at the moment
Chris@0 182 // to track down the reason why.
Chris@0 183 m_overview->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
Chris@0 184 #endif
Chris@0 185 connect(m_overview, SIGNAL(contextHelpChanged(const QString &)),
Chris@0 186 this, SLOT(contextHelpChanged(const QString &)));
Chris@0 187
Chris@0 188 m_panLayer = new WaveformLayer;
Chris@0 189 m_panLayer->setChannelMode(WaveformLayer::MergeChannels);
Chris@0 190 m_panLayer->setAggressiveCacheing(true);
Chris@0 191 m_overview->addLayer(m_panLayer);
Chris@0 192
Chris@0 193 if (m_viewManager->getGlobalDarkBackground()) {
Chris@0 194 m_panLayer->setBaseColour
Chris@0 195 (ColourDatabase::getInstance()->getColourIndex(tr("Bright Green")));
Chris@0 196 } else {
Chris@0 197 m_panLayer->setBaseColour
matthiasm@13 198 (ColourDatabase::getInstance()->getColourIndex(tr("Blue")));
Chris@0 199 }
Chris@0 200
Chris@0 201 m_fader = new Fader(frame, false);
Chris@0 202 connect(m_fader, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
Chris@0 203 connect(m_fader, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
Chris@0 204
Chris@0 205 m_playSpeed = new AudioDial(frame);
Chris@0 206 m_playSpeed->setMinimum(0);
Chris@0 207 m_playSpeed->setMaximum(200);
Chris@0 208 m_playSpeed->setValue(100);
Chris@0 209 m_playSpeed->setFixedWidth(24);
Chris@0 210 m_playSpeed->setFixedHeight(24);
Chris@0 211 m_playSpeed->setNotchesVisible(true);
Chris@0 212 m_playSpeed->setPageStep(10);
Chris@0 213 m_playSpeed->setObjectName(tr("Playback Speedup"));
Chris@0 214 m_playSpeed->setDefaultValue(100);
Chris@0 215 m_playSpeed->setRangeMapper(new PlaySpeedRangeMapper(0, 200));
Chris@0 216 m_playSpeed->setShowToolTip(true);
Chris@0 217 connect(m_playSpeed, SIGNAL(valueChanged(int)),
gyorgyf@27 218 this, SLOT(playSpeedChanged(int)));
Chris@0 219 connect(m_playSpeed, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
Chris@0 220 connect(m_playSpeed, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
Chris@0 221
justin@159 222 // Gain controls
justin@159 223 m_gainAudio = new AudioDial(frame);
justin@159 224 m_gainAudio->setMinimum(-50);
justin@159 225 m_gainAudio->setMaximum(50);
justin@159 226 m_gainAudio->setValue(0);
justin@159 227 m_gainAudio->setDefaultValue(0);
justin@159 228 m_gainAudio->setFixedWidth(24);
justin@159 229 m_gainAudio->setFixedHeight(24);
justin@159 230 m_gainAudio->setNotchesVisible(true);
justin@159 231 m_gainAudio->setPageStep(10);
justin@159 232 m_gainAudio->setObjectName(tr("Audio Track Gain"));
justin@159 233 m_gainAudio->setRangeMapper(new LinearRangeMapper(-50, 50, -25, 25, tr("dB")));
justin@159 234 m_gainAudio->setShowToolTip(true);
justin@159 235 connect(m_gainAudio, SIGNAL(valueChanged(int)),
justin@159 236 this, SLOT(audioGainChanged(int)));
justin@159 237 connect(m_gainAudio, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
justin@159 238 connect(m_gainAudio, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
justin@159 239
justin@157 240 m_gainPitch = new AudioDial(frame);
Chris@158 241 m_gainPitch->setMinimum(-50);
Chris@158 242 m_gainPitch->setMaximum(50);
Chris@158 243 m_gainPitch->setValue(0);
Chris@158 244 m_gainPitch->setDefaultValue(0);
justin@157 245 m_gainPitch->setFixedWidth(24);
justin@157 246 m_gainPitch->setFixedHeight(24);
justin@157 247 m_gainPitch->setNotchesVisible(true);
justin@157 248 m_gainPitch->setPageStep(10);
Chris@158 249 m_gainPitch->setObjectName(tr("Pitch Track Gain"));
Chris@158 250 m_gainPitch->setRangeMapper(new LinearRangeMapper(-50, 50, -25, 25, tr("dB")));
justin@157 251 m_gainPitch->setShowToolTip(true);
justin@157 252 connect(m_gainPitch, SIGNAL(valueChanged(int)),
Chris@158 253 this, SLOT(pitchGainChanged(int)));
justin@157 254 connect(m_gainPitch, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
justin@157 255 connect(m_gainPitch, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
justin@157 256
justin@159 257 m_gainNotes = new AudioDial(frame);
justin@159 258 m_gainNotes->setMinimum(-50);
justin@159 259 m_gainNotes->setMaximum(50);
justin@159 260 m_gainNotes->setValue(0);
justin@159 261 m_gainNotes->setDefaultValue(0);
justin@159 262 m_gainNotes->setFixedWidth(24);
justin@159 263 m_gainNotes->setFixedHeight(24);
justin@159 264 m_gainNotes->setNotchesVisible(true);
justin@159 265 m_gainNotes->setPageStep(10);
justin@159 266 m_gainNotes->setObjectName(tr("Pitch Track Gain"));
justin@159 267 m_gainNotes->setRangeMapper(new LinearRangeMapper(-50, 50, -25, 25, tr("dB")));
justin@159 268 m_gainNotes->setShowToolTip(true);
justin@159 269 connect(m_gainNotes, SIGNAL(valueChanged(int)),
justin@159 270 this, SLOT(notesGainChanged(int)));
justin@159 271 connect(m_gainNotes, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
justin@159 272 connect(m_gainNotes, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
justin@159 273 // End of Gain controls
justin@159 274
justin@160 275 // Pan controls
justin@160 276 m_panAudio = new AudioDial(frame);
justin@160 277 m_panAudio->setMinimum(-100);
justin@160 278 m_panAudio->setMaximum(100);
justin@160 279 m_panAudio->setValue(-100);
justin@160 280 m_panAudio->setDefaultValue(-100);
justin@160 281 m_panAudio->setFixedWidth(24);
justin@160 282 m_panAudio->setFixedHeight(24);
justin@160 283 m_panAudio->setNotchesVisible(true);
justin@160 284 m_panAudio->setPageStep(10);
justin@160 285 m_panAudio->setObjectName(tr("Audio Track Pan"));
justin@160 286 m_panAudio->setRangeMapper(new LinearRangeMapper(-100, 100, -100, 100, tr("")));
justin@160 287 m_panAudio->setShowToolTip(true);
justin@160 288 connect(m_panAudio, SIGNAL(valueChanged(int)),
justin@160 289 this, SLOT(audioPanChanged(int)));
justin@160 290 connect(m_panAudio, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
justin@160 291 connect(m_panAudio, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
justin@160 292
justin@160 293 m_panPitch = new AudioDial(frame);
justin@160 294 m_panPitch->setMinimum(-100);
justin@160 295 m_panPitch->setMaximum(100);
justin@160 296 m_panPitch->setValue(100);
justin@160 297 m_panPitch->setDefaultValue(100);
justin@160 298 m_panPitch->setFixedWidth(24);
justin@160 299 m_panPitch->setFixedHeight(24);
justin@160 300 m_panPitch->setNotchesVisible(true);
justin@160 301 m_panPitch->setPageStep(10);
justin@160 302 m_panPitch->setObjectName(tr("Pitch Track Pan"));
justin@160 303 m_panPitch->setRangeMapper(new LinearRangeMapper(-100, 100, -100, 100, tr("")));
justin@160 304 m_panPitch->setShowToolTip(true);
justin@160 305 connect(m_panPitch, SIGNAL(valueChanged(int)),
justin@160 306 this, SLOT(pitchPanChanged(int)));
justin@160 307 connect(m_panPitch, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
justin@160 308 connect(m_panPitch, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
justin@160 309
justin@160 310 m_panNotes = new AudioDial(frame);
justin@160 311 m_panNotes->setMinimum(-100);
justin@160 312 m_panNotes->setMaximum(100);
justin@160 313 m_panNotes->setValue(100);
justin@160 314 m_panNotes->setDefaultValue(100);
justin@160 315 m_panNotes->setFixedWidth(24);
justin@160 316 m_panNotes->setFixedHeight(24);
justin@160 317 m_panNotes->setNotchesVisible(true);
justin@160 318 m_panNotes->setPageStep(10);
justin@160 319 m_panNotes->setObjectName(tr("Notes Track Pan"));
justin@160 320 m_panNotes->setRangeMapper(new LinearRangeMapper(-100, 100, -100, 100, tr("")));
justin@160 321 m_panNotes->setShowToolTip(true);
justin@160 322 connect(m_panNotes, SIGNAL(valueChanged(int)),
justin@160 323 this, SLOT(notesPanChanged(int)));
justin@160 324 connect(m_panNotes, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
justin@160 325 connect(m_panNotes, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
justin@160 326 // End of Pan controls
justin@160 327
Chris@0 328 layout->setSpacing(4);
Chris@6 329 layout->addWidget(m_overview, 0, 1);
Chris@6 330 layout->addWidget(scroll, 1, 1);
Chris@0 331
Chris@0 332 layout->setColumnStretch(1, 10);
Chris@0 333
Chris@0 334 frame->setLayout(layout);
Chris@0 335
gyorgyf@21 336 m_analyser = new Analyser();
Chris@128 337 connect(m_analyser, SIGNAL(layersChanged()),
Chris@128 338 this, SLOT(updateLayerStatuses()));
Chris@187 339 connect(m_analyser, SIGNAL(layersChanged()),
Chris@187 340 this, SLOT(updateMenuStates()));
gyorgyf@21 341
Chris@0 342 setupMenus();
Chris@0 343 setupToolbars();
Chris@0 344 setupHelpMenu();
Chris@0 345
Chris@0 346 statusBar();
Chris@0 347
Chris@95 348 newSession();
Chris@6 349
Chris@95 350 settings.beginGroup("MainWindow");
Chris@95 351 settings.setValue("zoom-default", 512);
Chris@95 352 settings.endGroup();
Chris@95 353 zoomDefault();
Chris@95 354
Chris@95 355 NetworkPermissionTester tester;
Chris@95 356 bool networkPermission = tester.havePermission();
Chris@95 357 if (networkPermission) {
Chris@95 358 m_versionTester = new VersionTester
Chris@95 359 ("sonicvisualiser.org", "latest-tony-version.txt", TONY_VERSION);
Chris@95 360 connect(m_versionTester, SIGNAL(newerVersionAvailable(QString)),
Chris@95 361 this, SLOT(newerVersionAvailable(QString)));
Chris@95 362 } else {
Chris@95 363 m_versionTester = 0;
Chris@95 364 }
Chris@0 365 }
Chris@0 366
Chris@0 367 MainWindow::~MainWindow()
Chris@0 368 {
Chris@6 369 delete m_analyser;
Chris@0 370 delete m_keyReference;
Chris@0 371 Profiles::getInstance()->dump();
Chris@0 372 }
Chris@0 373
Chris@0 374 void
Chris@0 375 MainWindow::setupMenus()
Chris@0 376 {
Chris@0 377 if (!m_mainMenusCreated) {
Chris@0 378 m_rightButtonMenu = new QMenu();
Chris@0 379 }
Chris@0 380
Chris@0 381 if (!m_mainMenusCreated) {
Chris@0 382 CommandHistory::getInstance()->registerMenu(m_rightButtonMenu);
Chris@0 383 m_rightButtonMenu->addSeparator();
Chris@0 384 }
Chris@0 385
Chris@0 386 setupFileMenu();
Chris@0 387 setupEditMenu();
Chris@0 388 setupViewMenu();
Chris@0 389
Chris@0 390 m_mainMenusCreated = true;
Chris@0 391 }
Chris@0 392
Chris@0 393 void
Chris@0 394 MainWindow::setupFileMenu()
Chris@0 395 {
Chris@0 396 if (m_mainMenusCreated) return;
Chris@0 397
Chris@0 398 QMenu *menu = menuBar()->addMenu(tr("&File"));
Chris@0 399 menu->setTearOffEnabled(true);
Chris@0 400 QToolBar *toolbar = addToolBar(tr("File Toolbar"));
Chris@0 401
Chris@0 402 m_keyReference->setCategory(tr("File and Session Management"));
Chris@0 403
Chris@0 404 IconLoader il;
Chris@1 405 QIcon icon;
Chris@1 406 QAction *action;
Chris@0 407
Chris@0 408 icon = il.load("fileopen");
Chris@0 409 icon.addPixmap(il.loadPixmap("fileopen-22"));
Chris@1 410 action = new QAction(icon, tr("&Open..."), this);
Chris@0 411 action->setShortcut(tr("Ctrl+O"));
Chris@1 412 action->setStatusTip(tr("Open a file"));
Chris@0 413 connect(action, SIGNAL(triggered()), this, SLOT(openFile()));
Chris@0 414 m_keyReference->registerShortcut(action);
Chris@0 415 menu->addAction(action);
Chris@0 416 toolbar->addAction(action);
Chris@0 417
Chris@1 418 action = new QAction(tr("Open Lo&cation..."), this);
Chris@0 419 action->setShortcut(tr("Ctrl+Shift+O"));
Chris@1 420 action->setStatusTip(tr("Open a file from a remote URL"));
Chris@0 421 connect(action, SIGNAL(triggered()), this, SLOT(openLocation()));
Chris@0 422 m_keyReference->registerShortcut(action);
Chris@0 423 menu->addAction(action);
Chris@0 424
Chris@1 425 m_recentFilesMenu = menu->addMenu(tr("Open &Recent"));
Chris@0 426 m_recentFilesMenu->setTearOffEnabled(true);
Chris@0 427 setupRecentFilesMenu();
Chris@0 428 connect(&m_recentFiles, SIGNAL(recentChanged()),
Chris@0 429 this, SLOT(setupRecentFilesMenu()));
Chris@0 430
Chris@0 431 menu->addSeparator();
Chris@174 432 action = new QAction(tr("Import Pitch Track Data..."), this);
Chris@174 433 action->setStatusTip(tr("Import pitch-track data from a file"));
Chris@174 434 connect(action, SIGNAL(triggered()), this, SLOT(importPitchLayer()));
Chris@174 435 connect(this, SIGNAL(canImportLayer(bool)), action, SLOT(setEnabled(bool)));
Chris@174 436 menu->addAction(action);
Chris@174 437
Chris@85 438 action = new QAction(tr("Export Pitch Track Data..."), this);
Chris@85 439 action->setStatusTip(tr("Export pitch-track data to a file"));
Chris@85 440 connect(action, SIGNAL(triggered()), this, SLOT(exportPitchLayer()));
Chris@85 441 connect(this, SIGNAL(canExportLayer(bool)), action, SLOT(setEnabled(bool)));
Chris@85 442 menu->addAction(action);
Chris@85 443
Chris@85 444 action = new QAction(tr("Export Note Data..."), this);
Chris@85 445 action->setStatusTip(tr("Export note data to a file"));
Chris@85 446 connect(action, SIGNAL(triggered()), this, SLOT(exportNoteLayer()));
matthiasm@26 447 connect(this, SIGNAL(canExportLayer(bool)), action, SLOT(setEnabled(bool)));
matthiasm@26 448 menu->addAction(action);
matthiasm@26 449
matthiasm@26 450 menu->addSeparator();
Chris@0 451 action = new QAction(il.load("exit"), tr("&Quit"), this);
Chris@0 452 action->setShortcut(tr("Ctrl+Q"));
Chris@0 453 action->setStatusTip(tr("Exit %1").arg(QApplication::applicationName()));
Chris@0 454 connect(action, SIGNAL(triggered()), this, SLOT(close()));
Chris@0 455 m_keyReference->registerShortcut(action);
Chris@0 456 menu->addAction(action);
Chris@0 457 }
Chris@0 458
Chris@0 459 void
Chris@0 460 MainWindow::setupEditMenu()
Chris@0 461 {
Chris@0 462 if (m_mainMenusCreated) return;
Chris@0 463
Chris@0 464 QMenu *menu = menuBar()->addMenu(tr("&Edit"));
Chris@0 465 menu->setTearOffEnabled(true);
Chris@0 466 CommandHistory::getInstance()->registerMenu(menu);
Chris@126 467 menu->addSeparator();
Chris@126 468
Chris@126 469 QToolBar *toolbar = addToolBar(tr("Tools Toolbar"));
Chris@126 470
Chris@126 471 CommandHistory::getInstance()->registerToolbar(toolbar);
Chris@126 472
Chris@126 473 m_keyReference->setCategory(tr("Tool Selection"));
Chris@126 474
Chris@126 475 QActionGroup *group = new QActionGroup(this);
Chris@126 476
Chris@126 477 IconLoader il;
Chris@126 478
Chris@126 479 QAction *action = toolbar->addAction(il.load("navigate"),
Chris@126 480 tr("Navigate"));
Chris@126 481 action->setCheckable(true);
Chris@126 482 action->setChecked(true);
Chris@126 483 action->setShortcut(tr("1"));
Chris@126 484 action->setStatusTip(tr("Navigate"));
Chris@126 485 connect(action, SIGNAL(triggered()), this, SLOT(toolNavigateSelected()));
Chris@126 486 connect(this, SIGNAL(replacedDocument()), action, SLOT(trigger()));
Chris@126 487 group->addAction(action);
Chris@126 488 menu->addAction(action);
Chris@126 489 m_keyReference->registerShortcut(action);
Chris@126 490
Chris@126 491 action = toolbar->addAction(il.load("move"),
Chris@126 492 tr("Edit"));
Chris@126 493 action->setCheckable(true);
Chris@126 494 action->setShortcut(tr("2"));
Chris@126 495 action->setStatusTip(tr("Edit with Note Intelligence"));
Chris@126 496 connect(action, SIGNAL(triggered()), this, SLOT(toolEditSelected()));
Chris@126 497 connect(this, SIGNAL(canEditLayer(bool)), action, SLOT(setEnabled(bool)));
Chris@126 498 group->addAction(action);
Chris@126 499 menu->addAction(action);
Chris@126 500 m_keyReference->registerShortcut(action);
Chris@126 501
Chris@126 502 /* Remove for now...
Chris@126 503
Chris@126 504 action = toolbar->addAction(il.load("notes"),
Chris@126 505 tr("Free Edit"));
Chris@126 506 action->setCheckable(true);
Chris@126 507 action->setShortcut(tr("3"));
Chris@126 508 action->setStatusTip(tr("Free Edit"));
Chris@126 509 connect(action, SIGNAL(triggered()), this, SLOT(toolFreeEditSelected()));
Chris@126 510 connect(this, SIGNAL(canEditLayer(bool)), action, SLOT(setEnabled(bool)));
Chris@126 511 group->addAction(action);
Chris@126 512 m_keyReference->registerShortcut(action);
Chris@126 513 */
Chris@142 514
Chris@142 515 menu->addSeparator();
Chris@142 516
Chris@143 517 m_keyReference->setCategory(tr("Selection"));
Chris@143 518
Chris@143 519 action = new QAction(tr("Select &All"), this);
Chris@143 520 action->setShortcut(tr("Ctrl+A"));
Chris@143 521 action->setStatusTip(tr("Select the whole duration of the current session"));
Chris@143 522 connect(action, SIGNAL(triggered()), this, SLOT(selectAll()));
Chris@143 523 connect(this, SIGNAL(canSelect(bool)), action, SLOT(setEnabled(bool)));
Chris@143 524 m_keyReference->registerShortcut(action);
Chris@143 525 menu->addAction(action);
Chris@143 526 m_rightButtonMenu->addAction(action);
Chris@143 527
Chris@143 528 action = new QAction(tr("C&lear Selection"), this);
Chris@143 529 action->setShortcut(tr("Esc"));
Chris@143 530 action->setStatusTip(tr("Clear the selection"));
Chris@194 531 connect(action, SIGNAL(triggered()), this, SLOT(abandonSelection()));
Chris@143 532 connect(this, SIGNAL(canClearSelection(bool)), action, SLOT(setEnabled(bool)));
Chris@143 533 m_keyReference->registerShortcut(action);
Chris@143 534 menu->addAction(action);
Chris@143 535 m_rightButtonMenu->addAction(action);
Chris@143 536
Chris@143 537 menu->addSeparator();
Chris@189 538 m_rightButtonMenu->addSeparator();
Chris@143 539
Chris@189 540 m_keyReference->setCategory(tr("Pitch Track"));
Chris@189 541
Chris@187 542 m_showCandidatesAction = new QAction(tr("Show Pitch Candidates"), this);
Chris@187 543 m_showCandidatesAction->setShortcut(tr("Ctrl+Return"));
Chris@189 544 m_showCandidatesAction->setStatusTip(tr("Toggle the display of alternative pitch candidates for the selected region"));
Chris@189 545 m_keyReference->registerShortcut(m_showCandidatesAction);
Chris@187 546 connect(m_showCandidatesAction, SIGNAL(triggered()), this, SLOT(togglePitchCandidates()));
Chris@187 547 connect(this, SIGNAL(canClearSelection(bool)), m_showCandidatesAction, SLOT(setEnabled(bool)));
Chris@187 548 menu->addAction(m_showCandidatesAction);
Chris@189 549 m_rightButtonMenu->addAction(m_showCandidatesAction);
Chris@187 550
Chris@187 551 action = new QAction(tr("Pick Higher Pitch Candidate"), this);
Chris@187 552 action->setShortcut(tr("Ctrl+Up"));
Chris@189 553 action->setStatusTip(tr("Switch to the next higher pitch candidate in the selected region"));
Chris@189 554 m_keyReference->registerShortcut(action);
Chris@187 555 connect(action, SIGNAL(triggered()), this, SLOT(switchPitchUp()));
Chris@198 556 connect(this, SIGNAL(canChangeToHigherCandidate(bool)), action, SLOT(setEnabled(bool)));
Chris@168 557 menu->addAction(action);
Chris@189 558 m_rightButtonMenu->addAction(action);
Chris@187 559
Chris@187 560 action = new QAction(tr("Pick Lower Pitch Candidate"), this);
Chris@187 561 action->setShortcut(tr("Ctrl+Down"));
Chris@189 562 action->setStatusTip(tr("Switch to the next lower pitch candidate in the selected region"));
Chris@189 563 m_keyReference->registerShortcut(action);
Chris@187 564 connect(action, SIGNAL(triggered()), this, SLOT(switchPitchDown()));
Chris@198 565 connect(this, SIGNAL(canChangeToLowerCandidate(bool)), action, SLOT(setEnabled(bool)));
Chris@187 566 menu->addAction(action);
Chris@189 567 m_rightButtonMenu->addAction(action);
Chris@187 568
Chris@187 569 menu->addSeparator();
Chris@189 570 m_rightButtonMenu->addSeparator();
Chris@187 571
Chris@142 572 action = new QAction(tr("Octave Shift Up"), this);
Chris@142 573 action->setShortcut(tr("PgUp"));
Chris@189 574 action->setStatusTip(tr("Move all pitches up an octave in the selected region"));
Chris@189 575 m_keyReference->registerShortcut(action);
Chris@142 576 connect(action, SIGNAL(triggered()), this, SLOT(octaveShiftUp()));
Chris@142 577 connect(this, SIGNAL(canClearSelection(bool)), action, SLOT(setEnabled(bool)));
Chris@142 578 menu->addAction(action);
Chris@189 579 m_rightButtonMenu->addAction(action);
Chris@142 580
Chris@142 581 action = new QAction(tr("Octave Shift Down"), this);
Chris@142 582 action->setShortcut(tr("PgDown"));
Chris@189 583 action->setStatusTip(tr("Move all pitches down an octave in the selected region"));
Chris@189 584 m_keyReference->registerShortcut(action);
Chris@142 585 connect(action, SIGNAL(triggered()), this, SLOT(octaveShiftDown()));
Chris@142 586 connect(this, SIGNAL(canClearSelection(bool)), action, SLOT(setEnabled(bool)));
Chris@142 587 menu->addAction(action);
Chris@189 588 m_rightButtonMenu->addAction(action);
Chris@187 589
Chris@187 590 menu->addSeparator();
Chris@189 591 m_rightButtonMenu->addSeparator();
Chris@167 592
Chris@187 593 action = new QAction(tr("Remove Pitches"), this);
Chris@187 594 action->setShortcut(tr("Ctrl+Backspace"));
Chris@189 595 action->setStatusTip(tr("Remove all pitch estimates within the selected region (converting it to unvoiced)"));
Chris@189 596 m_keyReference->registerShortcut(action);
Chris@187 597 connect(action, SIGNAL(triggered()), this, SLOT(clearPitches()));
Chris@167 598 connect(this, SIGNAL(canClearSelection(bool)), action, SLOT(setEnabled(bool)));
Chris@167 599 menu->addAction(action);
Chris@189 600 m_rightButtonMenu->addAction(action);
Chris@0 601 }
Chris@0 602
Chris@0 603 void
Chris@0 604 MainWindow::setupViewMenu()
Chris@0 605 {
Chris@0 606 if (m_mainMenusCreated) return;
Chris@0 607
Chris@0 608 IconLoader il;
Chris@0 609
Chris@0 610 QAction *action = 0;
Chris@0 611
Chris@0 612 m_keyReference->setCategory(tr("Panning and Navigation"));
Chris@0 613
Chris@0 614 QMenu *menu = menuBar()->addMenu(tr("&View"));
Chris@0 615 menu->setTearOffEnabled(true);
Chris@0 616 action = new QAction(tr("Scroll &Left"), this);
Chris@0 617 action->setShortcut(tr("Left"));
Chris@0 618 action->setStatusTip(tr("Scroll the current pane to the left"));
Chris@0 619 connect(action, SIGNAL(triggered()), this, SLOT(scrollLeft()));
Chris@0 620 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool)));
Chris@0 621 m_keyReference->registerShortcut(action);
Chris@0 622 menu->addAction(action);
gyorgyf@27 623
Chris@0 624 action = new QAction(tr("Scroll &Right"), this);
Chris@0 625 action->setShortcut(tr("Right"));
Chris@0 626 action->setStatusTip(tr("Scroll the current pane to the right"));
Chris@0 627 connect(action, SIGNAL(triggered()), this, SLOT(scrollRight()));
Chris@0 628 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool)));
Chris@0 629 m_keyReference->registerShortcut(action);
Chris@0 630 menu->addAction(action);
gyorgyf@27 631
Chris@0 632 action = new QAction(tr("&Jump Left"), this);
Chris@0 633 action->setShortcut(tr("Ctrl+Left"));
Chris@0 634 action->setStatusTip(tr("Scroll the current pane a big step to the left"));
Chris@0 635 connect(action, SIGNAL(triggered()), this, SLOT(jumpLeft()));
Chris@0 636 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool)));
Chris@0 637 m_keyReference->registerShortcut(action);
Chris@0 638 menu->addAction(action);
gyorgyf@27 639
Chris@0 640 action = new QAction(tr("J&ump Right"), this);
Chris@0 641 action->setShortcut(tr("Ctrl+Right"));
Chris@0 642 action->setStatusTip(tr("Scroll the current pane a big step to the right"));
Chris@0 643 connect(action, SIGNAL(triggered()), this, SLOT(jumpRight()));
Chris@0 644 connect(this, SIGNAL(canScroll(bool)), action, SLOT(setEnabled(bool)));
Chris@0 645 m_keyReference->registerShortcut(action);
Chris@0 646 menu->addAction(action);
Chris@0 647
Chris@0 648 menu->addSeparator();
Chris@0 649
Chris@0 650 m_keyReference->setCategory(tr("Zoom"));
Chris@0 651
Chris@0 652 action = new QAction(il.load("zoom-in"),
Chris@0 653 tr("Zoom &In"), this);
Chris@0 654 action->setShortcut(tr("Up"));
Chris@0 655 action->setStatusTip(tr("Increase the zoom level"));
Chris@0 656 connect(action, SIGNAL(triggered()), this, SLOT(zoomIn()));
Chris@0 657 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool)));
Chris@0 658 m_keyReference->registerShortcut(action);
Chris@0 659 menu->addAction(action);
gyorgyf@27 660
Chris@0 661 action = new QAction(il.load("zoom-out"),
Chris@0 662 tr("Zoom &Out"), this);
Chris@0 663 action->setShortcut(tr("Down"));
Chris@0 664 action->setStatusTip(tr("Decrease the zoom level"));
Chris@0 665 connect(action, SIGNAL(triggered()), this, SLOT(zoomOut()));
Chris@0 666 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool)));
Chris@0 667 m_keyReference->registerShortcut(action);
Chris@0 668 menu->addAction(action);
gyorgyf@27 669
Chris@0 670 action = new QAction(tr("Restore &Default Zoom"), this);
Chris@0 671 action->setStatusTip(tr("Restore the zoom level to the default"));
Chris@0 672 connect(action, SIGNAL(triggered()), this, SLOT(zoomDefault()));
Chris@0 673 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool)));
Chris@0 674 menu->addAction(action);
Chris@0 675
Chris@0 676 action = new QAction(il.load("zoom-fit"),
Chris@0 677 tr("Zoom to &Fit"), this);
Chris@0 678 action->setShortcut(tr("F"));
Chris@0 679 action->setStatusTip(tr("Zoom to show the whole file"));
Chris@0 680 connect(action, SIGNAL(triggered()), this, SLOT(zoomToFit()));
Chris@0 681 connect(this, SIGNAL(canZoom(bool)), action, SLOT(setEnabled(bool)));
Chris@0 682 m_keyReference->registerShortcut(action);
Chris@0 683 menu->addAction(action);
Chris@0 684 }
Chris@0 685
Chris@0 686 void
Chris@0 687 MainWindow::setupHelpMenu()
Chris@0 688 {
Chris@0 689 QMenu *menu = menuBar()->addMenu(tr("&Help"));
Chris@0 690 menu->setTearOffEnabled(true);
Chris@0 691
Chris@0 692 m_keyReference->setCategory(tr("Help"));
Chris@0 693
Chris@0 694 IconLoader il;
Chris@0 695
Chris@1 696 QString name = QApplication::applicationName();
Chris@1 697
Chris@0 698 QAction *action = new QAction(il.load("help"),
Chris@0 699 tr("&Help Reference"), this);
Chris@0 700 action->setShortcut(tr("F1"));
Chris@1 701 action->setStatusTip(tr("Open the %1 reference manual").arg(name));
Chris@0 702 connect(action, SIGNAL(triggered()), this, SLOT(help()));
Chris@0 703 m_keyReference->registerShortcut(action);
Chris@0 704 menu->addAction(action);
Chris@0 705
Chris@0 706 action = new QAction(tr("&Key and Mouse Reference"), this);
Chris@0 707 action->setShortcut(tr("F2"));
Chris@1 708 action->setStatusTip(tr("Open a window showing the keystrokes you can use in %1").arg(name));
Chris@0 709 connect(action, SIGNAL(triggered()), this, SLOT(keyReference()));
Chris@0 710 m_keyReference->registerShortcut(action);
Chris@0 711 menu->addAction(action);
Chris@0 712
Chris@1 713 action = new QAction(tr("%1 on the &Web").arg(name), this);
Chris@1 714 action->setStatusTip(tr("Open the %1 website").arg(name));
Chris@0 715 connect(action, SIGNAL(triggered()), this, SLOT(website()));
Chris@0 716 menu->addAction(action);
Chris@0 717
Chris@1 718 action = new QAction(tr("&About %1").arg(name), this);
Chris@1 719 action->setStatusTip(tr("Show information about %1").arg(name));
Chris@0 720 connect(action, SIGNAL(triggered()), this, SLOT(about()));
Chris@0 721 menu->addAction(action);
Chris@0 722 }
Chris@0 723
Chris@0 724 void
Chris@0 725 MainWindow::setupRecentFilesMenu()
Chris@0 726 {
Chris@0 727 m_recentFilesMenu->clear();
Chris@0 728 vector<QString> files = m_recentFiles.getRecent();
Chris@0 729 for (size_t i = 0; i < files.size(); ++i) {
Chris@50 730 QAction *action = new QAction(files[i], this);
Chris@50 731 connect(action, SIGNAL(triggered()), this, SLOT(openRecentFile()));
Chris@0 732 if (i == 0) {
Chris@0 733 action->setShortcut(tr("Ctrl+R"));
Chris@0 734 m_keyReference->registerShortcut
Chris@0 735 (tr("Re-open"),
Chris@50 736 action->shortcut().toString(),
Chris@0 737 tr("Re-open the current or most recently opened file"));
Chris@0 738 }
Chris@50 739 m_recentFilesMenu->addAction(action);
Chris@0 740 }
Chris@0 741 }
Chris@0 742
Chris@0 743 void
Chris@0 744 MainWindow::setupToolbars()
Chris@0 745 {
Chris@0 746 m_keyReference->setCategory(tr("Playback and Transport Controls"));
Chris@0 747
Chris@0 748 IconLoader il;
Chris@0 749
Chris@0 750 QMenu *menu = m_playbackMenu = menuBar()->addMenu(tr("Play&back"));
Chris@0 751 menu->setTearOffEnabled(true);
Chris@0 752 m_rightButtonMenu->addSeparator();
Chris@0 753 m_rightButtonPlaybackMenu = m_rightButtonMenu->addMenu(tr("Playback"));
Chris@0 754
Chris@0 755 QToolBar *toolbar = addToolBar(tr("Playback Toolbar"));
Chris@0 756
Chris@0 757 QAction *rwdStartAction = toolbar->addAction(il.load("rewind-start"),
Chris@0 758 tr("Rewind to Start"));
Chris@0 759 rwdStartAction->setShortcut(tr("Home"));
Chris@0 760 rwdStartAction->setStatusTip(tr("Rewind to the start"));
Chris@0 761 connect(rwdStartAction, SIGNAL(triggered()), this, SLOT(rewindStart()));
Chris@0 762 connect(this, SIGNAL(canPlay(bool)), rwdStartAction, SLOT(setEnabled(bool)));
Chris@0 763
Chris@0 764 QAction *m_rwdAction = toolbar->addAction(il.load("rewind"),
Chris@0 765 tr("Rewind"));
Chris@0 766 m_rwdAction->setStatusTip(tr("Rewind to the previous time instant or time ruler notch"));
Chris@0 767 connect(m_rwdAction, SIGNAL(triggered()), this, SLOT(rewind()));
Chris@0 768 connect(this, SIGNAL(canRewind(bool)), m_rwdAction, SLOT(setEnabled(bool)));
Chris@0 769
Chris@0 770 QAction *playAction = toolbar->addAction(il.load("playpause"),
Chris@0 771 tr("Play / Pause"));
Chris@0 772 playAction->setCheckable(true);
Chris@0 773 playAction->setShortcut(tr("Space"));
Chris@0 774 playAction->setStatusTip(tr("Start or stop playback from the current position"));
Chris@0 775 connect(playAction, SIGNAL(triggered()), this, SLOT(play()));
Chris@0 776 connect(m_playSource, SIGNAL(playStatusChanged(bool)),
gyorgyf@27 777 playAction, SLOT(setChecked(bool)));
Chris@0 778 connect(this, SIGNAL(canPlay(bool)), playAction, SLOT(setEnabled(bool)));
Chris@0 779
Chris@0 780 m_ffwdAction = toolbar->addAction(il.load("ffwd"),
Chris@0 781 tr("Fast Forward"));
Chris@0 782 m_ffwdAction->setStatusTip(tr("Fast-forward to the next time instant or time ruler notch"));
Chris@0 783 connect(m_ffwdAction, SIGNAL(triggered()), this, SLOT(ffwd()));
Chris@0 784 connect(this, SIGNAL(canFfwd(bool)), m_ffwdAction, SLOT(setEnabled(bool)));
Chris@0 785
Chris@0 786 QAction *ffwdEndAction = toolbar->addAction(il.load("ffwd-end"),
Chris@0 787 tr("Fast Forward to End"));
Chris@0 788 ffwdEndAction->setShortcut(tr("End"));
Chris@0 789 ffwdEndAction->setStatusTip(tr("Fast-forward to the end"));
Chris@0 790 connect(ffwdEndAction, SIGNAL(triggered()), this, SLOT(ffwdEnd()));
Chris@0 791 connect(this, SIGNAL(canPlay(bool)), ffwdEndAction, SLOT(setEnabled(bool)));
Chris@6 792
Chris@0 793 toolbar = addToolBar(tr("Play Mode Toolbar"));
Chris@0 794
Chris@0 795 QAction *psAction = toolbar->addAction(il.load("playselection"),
Chris@0 796 tr("Constrain Playback to Selection"));
Chris@0 797 psAction->setCheckable(true);
Chris@0 798 psAction->setChecked(m_viewManager->getPlaySelectionMode());
Chris@0 799 psAction->setShortcut(tr("s"));
Chris@0 800 psAction->setStatusTip(tr("Constrain playback to the selected regions"));
Chris@0 801 connect(m_viewManager, SIGNAL(playSelectionModeChanged(bool)),
Chris@0 802 psAction, SLOT(setChecked(bool)));
Chris@0 803 connect(psAction, SIGNAL(triggered()), this, SLOT(playSelectionToggled()));
Chris@0 804 connect(this, SIGNAL(canPlaySelection(bool)), psAction, SLOT(setEnabled(bool)));
Chris@0 805
Chris@0 806 QAction *plAction = toolbar->addAction(il.load("playloop"),
Chris@0 807 tr("Loop Playback"));
Chris@0 808 plAction->setCheckable(true);
Chris@0 809 plAction->setChecked(m_viewManager->getPlayLoopMode());
Chris@0 810 plAction->setShortcut(tr("l"));
Chris@0 811 plAction->setStatusTip(tr("Loop playback"));
Chris@0 812 connect(m_viewManager, SIGNAL(playLoopModeChanged(bool)),
Chris@0 813 plAction, SLOT(setChecked(bool)));
Chris@0 814 connect(plAction, SIGNAL(triggered()), this, SLOT(playLoopToggled()));
Chris@0 815 connect(this, SIGNAL(canPlay(bool)), plAction, SLOT(setEnabled(bool)));
Chris@0 816
Chris@0 817 m_keyReference->registerShortcut(psAction);
Chris@0 818 m_keyReference->registerShortcut(plAction);
Chris@0 819 m_keyReference->registerShortcut(playAction);
Chris@0 820 m_keyReference->registerShortcut(m_rwdAction);
Chris@0 821 m_keyReference->registerShortcut(m_ffwdAction);
Chris@0 822 m_keyReference->registerShortcut(rwdStartAction);
Chris@0 823 m_keyReference->registerShortcut(ffwdEndAction);
Chris@0 824
Chris@6 825 menu->addAction(playAction);
Chris@0 826 menu->addAction(psAction);
Chris@0 827 menu->addAction(plAction);
Chris@0 828 menu->addSeparator();
Chris@0 829 menu->addAction(m_rwdAction);
Chris@0 830 menu->addAction(m_ffwdAction);
Chris@0 831 menu->addSeparator();
Chris@0 832 menu->addAction(rwdStartAction);
Chris@0 833 menu->addAction(ffwdEndAction);
Chris@0 834 menu->addSeparator();
Chris@0 835
Chris@0 836 m_rightButtonPlaybackMenu->addAction(playAction);
Chris@0 837 m_rightButtonPlaybackMenu->addAction(psAction);
Chris@0 838 m_rightButtonPlaybackMenu->addAction(plAction);
Chris@0 839 m_rightButtonPlaybackMenu->addSeparator();
Chris@0 840 m_rightButtonPlaybackMenu->addAction(m_rwdAction);
Chris@0 841 m_rightButtonPlaybackMenu->addAction(m_ffwdAction);
Chris@0 842 m_rightButtonPlaybackMenu->addSeparator();
Chris@0 843 m_rightButtonPlaybackMenu->addAction(rwdStartAction);
Chris@0 844 m_rightButtonPlaybackMenu->addAction(ffwdEndAction);
Chris@0 845 m_rightButtonPlaybackMenu->addSeparator();
Chris@0 846
Chris@0 847 QAction *fastAction = menu->addAction(tr("Speed Up"));
Chris@0 848 fastAction->setShortcut(tr("Ctrl+PgUp"));
Chris@0 849 fastAction->setStatusTip(tr("Time-stretch playback to speed it up without changing pitch"));
Chris@0 850 connect(fastAction, SIGNAL(triggered()), this, SLOT(speedUpPlayback()));
Chris@0 851 connect(this, SIGNAL(canSpeedUpPlayback(bool)), fastAction, SLOT(setEnabled(bool)));
Chris@0 852
Chris@0 853 QAction *slowAction = menu->addAction(tr("Slow Down"));
Chris@0 854 slowAction->setShortcut(tr("Ctrl+PgDown"));
Chris@0 855 slowAction->setStatusTip(tr("Time-stretch playback to slow it down without changing pitch"));
Chris@0 856 connect(slowAction, SIGNAL(triggered()), this, SLOT(slowDownPlayback()));
Chris@0 857 connect(this, SIGNAL(canSlowDownPlayback(bool)), slowAction, SLOT(setEnabled(bool)));
Chris@0 858
Chris@0 859 QAction *normalAction = menu->addAction(tr("Restore Normal Speed"));
Chris@0 860 normalAction->setShortcut(tr("Ctrl+Home"));
Chris@0 861 normalAction->setStatusTip(tr("Restore non-time-stretched playback"));
Chris@0 862 connect(normalAction, SIGNAL(triggered()), this, SLOT(restoreNormalPlayback()));
Chris@0 863 connect(this, SIGNAL(canChangePlaybackSpeed(bool)), normalAction, SLOT(setEnabled(bool)));
Chris@0 864
Chris@0 865 m_keyReference->registerShortcut(fastAction);
Chris@0 866 m_keyReference->registerShortcut(slowAction);
Chris@0 867 m_keyReference->registerShortcut(normalAction);
Chris@0 868
Chris@0 869 m_rightButtonPlaybackMenu->addAction(fastAction);
Chris@0 870 m_rightButtonPlaybackMenu->addAction(slowAction);
Chris@0 871 m_rightButtonPlaybackMenu->addAction(normalAction);
Chris@6 872
Chris@195 873 toolbar = new QToolBar(tr("Playback Controls"));
Chris@195 874 addToolBar(Qt::BottomToolBarArea, toolbar);
Chris@195 875
Chris@6 876 toolbar->addWidget(m_playSpeed);
Chris@6 877 toolbar->addWidget(m_fader);
Chris@0 878
Chris@128 879 toolbar = addToolBar(tr("Show and Play"));
Chris@144 880
justin@156 881 /* ORIGINAL DESIGN
Chris@144 882 QLabel *eye = new QLabel;
Chris@144 883 eye->setFixedWidth(40);
Chris@144 884 eye->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
Chris@144 885 eye->setPixmap(il.loadPixmap("eye"));
Chris@144 886 toolbar->addWidget(eye);
Chris@144 887
Chris@144 888 m_showAudio = toolbar->addAction(il.load("waveform"), tr("Show Audio"));
Chris@144 889 m_showAudio->setCheckable(true);
Chris@144 890 connect(m_showAudio, SIGNAL(triggered()), this, SLOT(showAudioToggled()));
Chris@144 891 connect(this, SIGNAL(canPlay(bool)), m_showAudio, SLOT(setEnabled(bool)));
Chris@144 892
Chris@145 893 m_showSpect = toolbar->addAction(il.load("spectrogram"), tr("Show Spectrogram"));
Chris@145 894 m_showSpect->setCheckable(true);
Chris@145 895 connect(m_showSpect, SIGNAL(triggered()), this, SLOT(showSpectToggled()));
Chris@145 896 connect(this, SIGNAL(canPlay(bool)), m_showSpect, SLOT(setEnabled(bool)));
Chris@145 897
Chris@144 898 m_showPitch = toolbar->addAction(il.load("values"), tr("Show Pitch Track"));
Chris@144 899 m_showPitch->setCheckable(true);
Chris@144 900 connect(m_showPitch, SIGNAL(triggered()), this, SLOT(showPitchToggled()));
Chris@144 901 connect(this, SIGNAL(canPlay(bool)), m_showPitch, SLOT(setEnabled(bool)));
Chris@144 902
Chris@144 903 m_showNotes = toolbar->addAction(il.load("notes"), tr("Show Notes"));
Chris@144 904 m_showNotes->setCheckable(true);
Chris@144 905 connect(m_showNotes, SIGNAL(triggered()), this, SLOT(showNotesToggled()));
Chris@144 906 connect(this, SIGNAL(canPlay(bool)), m_showNotes, SLOT(setEnabled(bool)));
Chris@144 907
Chris@144 908 QLabel *speaker = new QLabel;
Chris@144 909 speaker->setFixedWidth(40);
Chris@144 910 speaker->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
Chris@144 911 speaker->setPixmap(il.loadPixmap("speaker"));
Chris@144 912 toolbar->addWidget(speaker);
Chris@128 913
Chris@144 914 m_playAudio = toolbar->addAction(il.load("waveform"), tr("Play Audio"));
Chris@144 915 m_playAudio->setCheckable(true);
Chris@144 916 connect(m_playAudio, SIGNAL(triggered()), this, SLOT(playAudioToggled()));
Chris@144 917 connect(this, SIGNAL(canPlay(bool)), m_playAudio, SLOT(setEnabled(bool)));
Chris@128 918
Chris@144 919 m_playPitch = toolbar->addAction(il.load("values"), tr("Play Pitch Track"));
Chris@144 920 m_playPitch->setCheckable(true);
Chris@144 921 connect(m_playPitch, SIGNAL(triggered()), this, SLOT(playPitchToggled()));
Chris@144 922 connect(this, SIGNAL(canPlay(bool)), m_playPitch, SLOT(setEnabled(bool)));
Chris@128 923
Chris@144 924 m_playNotes = toolbar->addAction(il.load("notes"), tr("Play Notes"));
Chris@144 925 m_playNotes->setCheckable(true);
Chris@144 926 connect(m_playNotes, SIGNAL(triggered()), this, SLOT(playNotesToggled()));
Chris@144 927 connect(this, SIGNAL(canPlay(bool)), m_playNotes, SLOT(setEnabled(bool)));
justin@156 928 */
justin@156 929
justin@156 930 // Audio
justin@156 931 QLabel *icon_audio = new QLabel;
justin@156 932 icon_audio->setFixedWidth(40);
justin@156 933 icon_audio->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
justin@156 934 icon_audio->setPixmap(il.loadPixmap("waveform"));
justin@156 935 toolbar->addWidget(icon_audio);
justin@156 936
justin@156 937 m_showAudio = toolbar->addAction(il.load("eye"), tr("Show Audio"));
justin@156 938 m_showAudio->setCheckable(true);
justin@156 939 connect(m_showAudio, SIGNAL(triggered()), this, SLOT(showAudioToggled()));
justin@156 940 connect(this, SIGNAL(canPlay(bool)), m_showAudio, SLOT(setEnabled(bool)));
justin@156 941
justin@156 942 m_playAudio = toolbar->addAction(il.load("speaker"), tr("Play Audio"));
justin@156 943 m_playAudio->setCheckable(true);
justin@156 944 connect(m_playAudio, SIGNAL(triggered()), this, SLOT(playAudioToggled()));
justin@156 945 connect(this, SIGNAL(canPlay(bool)), m_playAudio, SLOT(setEnabled(bool)));
justin@156 946
justin@159 947 toolbar->addWidget(m_gainAudio);
justin@160 948 toolbar->addWidget(m_panAudio);
justin@159 949
justin@156 950 // Pitch (f0)
justin@156 951 QLabel *icon_pitch = new QLabel;
justin@156 952 icon_pitch->setFixedWidth(40);
justin@156 953 icon_pitch->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
justin@156 954 icon_pitch->setPixmap(il.loadPixmap("values"));
justin@156 955 toolbar->addWidget(icon_pitch);
justin@156 956
justin@156 957 m_showPitch = toolbar->addAction(il.load("eye"), tr("Show Pitch Track"));
justin@156 958 m_showPitch->setCheckable(true);
justin@156 959 connect(m_showPitch, SIGNAL(triggered()), this, SLOT(showPitchToggled()));
justin@156 960 connect(this, SIGNAL(canPlay(bool)), m_showPitch, SLOT(setEnabled(bool)));
justin@156 961
justin@156 962 m_playPitch = toolbar->addAction(il.load("speaker"), tr("Play Pitch Track"));
justin@156 963 m_playPitch->setCheckable(true);
justin@156 964 connect(m_playPitch, SIGNAL(triggered()), this, SLOT(playPitchToggled()));
justin@186 965 connect(this, SIGNAL(canPlay(bool)), m_playPitch, SLOT(setEnabled(bool))); // JTEST: this resets the enabled state of m_playPitch.
justin@156 966
Chris@158 967 toolbar->addWidget(m_gainPitch);
justin@160 968 toolbar->addWidget(m_panPitch);
justin@156 969
justin@156 970 // Notes
justin@156 971 QLabel *icon_notes = new QLabel;
justin@156 972 icon_notes->setFixedWidth(40);
justin@156 973 icon_notes->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
justin@156 974 icon_notes->setPixmap(il.loadPixmap("notes"));
justin@156 975 toolbar->addWidget(icon_notes);
justin@156 976
justin@156 977 m_showNotes = toolbar->addAction(il.load("eye"), tr("Show Notes"));
justin@156 978 m_showNotes->setCheckable(true);
justin@156 979 connect(m_showNotes, SIGNAL(triggered()), this, SLOT(showNotesToggled()));
justin@156 980 connect(this, SIGNAL(canPlay(bool)), m_showNotes, SLOT(setEnabled(bool)));
justin@156 981
justin@156 982 m_playNotes = toolbar->addAction(il.load("speaker"), tr("Play Notes"));
justin@156 983 m_playNotes->setCheckable(true);
justin@156 984 connect(m_playNotes, SIGNAL(triggered()), this, SLOT(playNotesToggled()));
justin@156 985 connect(this, SIGNAL(canPlay(bool)), m_playNotes, SLOT(setEnabled(bool)));
justin@156 986
justin@159 987 toolbar->addWidget(m_gainNotes);
justin@160 988 toolbar->addWidget(m_panNotes);
justin@159 989
justin@156 990 // Spectrogram
justin@156 991 QLabel *icon_spectrogram = new QLabel;
justin@156 992 icon_spectrogram->setFixedWidth(40);
justin@156 993 icon_spectrogram->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
justin@156 994 icon_spectrogram->setPixmap(il.loadPixmap("spectrogram"));
justin@156 995 toolbar->addWidget(icon_spectrogram);
justin@156 996
justin@156 997 m_showSpect = toolbar->addAction(il.load("eye"), tr("Show Spectrogram"));
justin@156 998 m_showSpect->setCheckable(true);
justin@156 999 connect(m_showSpect, SIGNAL(triggered()), this, SLOT(showSpectToggled()));
justin@156 1000 connect(this, SIGNAL(canPlay(bool)), m_showSpect, SLOT(setEnabled(bool)));
Chris@128 1001
Chris@0 1002 Pane::registerShortcuts(*m_keyReference);
Chris@0 1003 }
Chris@0 1004
Chris@0 1005 void
Chris@70 1006 MainWindow::toolNavigateSelected()
Chris@70 1007 {
Chris@70 1008 m_viewManager->setToolMode(ViewManager::NavigateMode);
Chris@70 1009 m_intelligentActionOn = true;
Chris@70 1010 }
Chris@70 1011
Chris@70 1012 void
Chris@70 1013 MainWindow::toolEditSelected()
Chris@70 1014 {
Chris@77 1015 m_viewManager->setToolMode(ViewManager::NoteEditMode);
Chris@70 1016 m_intelligentActionOn = true;
Chris@70 1017 m_analyser->setIntelligentActions(m_intelligentActionOn);
Chris@70 1018 }
Chris@70 1019
Chris@70 1020 void
Chris@70 1021 MainWindow::toolFreeEditSelected()
Chris@70 1022 {
Chris@77 1023 m_viewManager->setToolMode(ViewManager::NoteEditMode);
Chris@70 1024 m_intelligentActionOn = false;
Chris@70 1025 m_analyser->setIntelligentActions(m_intelligentActionOn);
Chris@70 1026 }
Chris@70 1027
gyorgyf@21 1028 void
Chris@0 1029 MainWindow::updateMenuStates()
Chris@0 1030 {
Chris@0 1031 MainWindowBase::updateMenuStates();
Chris@0 1032
Chris@0 1033 Pane *currentPane = 0;
Chris@0 1034 Layer *currentLayer = 0;
Chris@0 1035
Chris@0 1036 if (m_paneStack) currentPane = m_paneStack->getCurrentPane();
Chris@0 1037 if (currentPane) currentLayer = currentPane->getSelectedLayer();
Chris@0 1038
Chris@0 1039 bool haveCurrentPane =
Chris@0 1040 (currentPane != 0);
Chris@0 1041 bool haveCurrentLayer =
Chris@0 1042 (haveCurrentPane &&
Chris@0 1043 (currentLayer != 0));
Chris@0 1044 bool haveSelection =
Chris@187 1045 (m_viewManager &&
Chris@187 1046 !m_viewManager->getSelections().empty());
Chris@0 1047 bool haveCurrentEditableLayer =
Chris@187 1048 (haveCurrentLayer &&
Chris@187 1049 currentLayer->isLayerEditable());
Chris@0 1050 bool haveCurrentTimeInstantsLayer =
Chris@187 1051 (haveCurrentLayer &&
Chris@187 1052 qobject_cast<TimeInstantLayer *>(currentLayer));
Chris@0 1053 bool haveCurrentTimeValueLayer =
Chris@187 1054 (haveCurrentLayer &&
Chris@187 1055 qobject_cast<TimeValueLayer *>(currentLayer));
Chris@187 1056 bool pitchCandidatesVisible =
Chris@187 1057 m_analyser->arePitchCandidatesShown();
Chris@198 1058 bool haveHigher =
Chris@198 1059 m_analyser->haveHigherPitchCandidate();
Chris@198 1060 bool haveLower =
Chris@198 1061 m_analyser->haveLowerPitchCandidate();
Chris@0 1062
Chris@0 1063 emit canChangePlaybackSpeed(true);
Chris@0 1064 int v = m_playSpeed->value();
Chris@0 1065 emit canSpeedUpPlayback(v < m_playSpeed->maximum());
Chris@0 1066 emit canSlowDownPlayback(v > m_playSpeed->minimum());
Chris@0 1067
Chris@187 1068 emit canChangePitchCandidate(pitchCandidatesVisible && haveSelection);
Chris@198 1069 emit canChangeToHigherCandidate(pitchCandidatesVisible && haveSelection && haveHigher);
Chris@198 1070 emit canChangeToLowerCandidate(pitchCandidatesVisible && haveSelection && haveLower);
Chris@187 1071
Chris@187 1072 if (pitchCandidatesVisible) {
Chris@187 1073 m_showCandidatesAction->setText(tr("Hide Pitch Candidates"));
Chris@187 1074 m_showCandidatesAction->setStatusTip(tr("Remove the display of alternate pitch candidates for the selected region"));
Chris@187 1075 } else {
Chris@187 1076 m_showCandidatesAction->setText(tr("Show Pitch Candidates"));
Chris@187 1077 m_showCandidatesAction->setStatusTip(tr("Show alternate pitch candidates for the selected region"));
Chris@187 1078 }
Chris@187 1079
Chris@0 1080 if (m_ffwdAction && m_rwdAction) {
Chris@0 1081 if (haveCurrentTimeInstantsLayer) {
Chris@0 1082 m_ffwdAction->setText(tr("Fast Forward to Next Instant"));
Chris@0 1083 m_ffwdAction->setStatusTip(tr("Fast forward to the next time instant in the current layer"));
Chris@0 1084 m_rwdAction->setText(tr("Rewind to Previous Instant"));
Chris@0 1085 m_rwdAction->setStatusTip(tr("Rewind to the previous time instant in the current layer"));
Chris@0 1086 } else if (haveCurrentTimeValueLayer) {
Chris@0 1087 m_ffwdAction->setText(tr("Fast Forward to Next Point"));
Chris@0 1088 m_ffwdAction->setStatusTip(tr("Fast forward to the next point in the current layer"));
Chris@0 1089 m_rwdAction->setText(tr("Rewind to Previous Point"));
Chris@0 1090 m_rwdAction->setStatusTip(tr("Rewind to the previous point in the current layer"));
Chris@0 1091 } else {
Chris@0 1092 m_ffwdAction->setText(tr("Fast Forward"));
Chris@0 1093 m_ffwdAction->setStatusTip(tr("Fast forward"));
Chris@0 1094 m_rwdAction->setText(tr("Rewind"));
Chris@0 1095 m_rwdAction->setStatusTip(tr("Rewind"));
Chris@0 1096 }
Chris@0 1097 }
Chris@0 1098 }
Chris@0 1099
Chris@0 1100 void
Chris@144 1101 MainWindow::showAudioToggled()
Chris@128 1102 {
Chris@144 1103 m_analyser->toggleVisible(Analyser::Audio);
Chris@128 1104 }
Chris@128 1105
Chris@128 1106 void
Chris@144 1107 MainWindow::showPitchToggled()
Chris@128 1108 {
Chris@144 1109 m_analyser->toggleVisible(Analyser::PitchTrack);
justin@185 1110
justin@186 1111 // JTEST
justin@185 1112 if (!m_analyser->isVisible(Analyser::PitchTrack))
justin@185 1113 {
justin@185 1114 m_analyser->setAudible(Analyser::PitchTrack,false);
justin@185 1115 m_playPitch->setChecked(false);
justin@185 1116 m_playPitch->setEnabled(false);
justin@185 1117 }
justin@185 1118 else
justin@185 1119 {
justin@185 1120 m_playPitch->setEnabled(true);
justin@185 1121 }
Chris@128 1122 }
Chris@128 1123
Chris@128 1124 void
Chris@145 1125 MainWindow::showSpectToggled()
Chris@145 1126 {
Chris@145 1127 m_analyser->toggleVisible(Analyser::Spectrogram);
Chris@145 1128 }
Chris@145 1129
Chris@145 1130 void
Chris@144 1131 MainWindow::showNotesToggled()
Chris@128 1132 {
Chris@144 1133 m_analyser->toggleVisible(Analyser::Notes);
Chris@144 1134 }
Chris@144 1135
Chris@144 1136 void
Chris@144 1137 MainWindow::playAudioToggled()
Chris@144 1138 {
Chris@144 1139 m_analyser->toggleAudible(Analyser::Audio);
Chris@144 1140 }
Chris@144 1141
Chris@144 1142 void
Chris@144 1143 MainWindow::playPitchToggled()
Chris@144 1144 {
Chris@144 1145 m_analyser->toggleAudible(Analyser::PitchTrack);
Chris@144 1146 }
Chris@144 1147
Chris@144 1148 void
Chris@144 1149 MainWindow::playNotesToggled()
Chris@144 1150 {
Chris@144 1151 m_analyser->toggleAudible(Analyser::Notes);
Chris@144 1152 }
Chris@144 1153
Chris@144 1154 void
Chris@144 1155 MainWindow::updateLayerStatuses()
Chris@144 1156 {
Chris@144 1157 m_showAudio->setChecked(m_analyser->isVisible(Analyser::Audio));
Chris@145 1158 m_showSpect->setChecked(m_analyser->isVisible(Analyser::Spectrogram));
Chris@144 1159 m_showPitch->setChecked(m_analyser->isVisible(Analyser::PitchTrack));
Chris@144 1160 m_showNotes->setChecked(m_analyser->isVisible(Analyser::Notes));
Chris@144 1161 m_playAudio->setChecked(m_analyser->isAudible(Analyser::Audio));
Chris@144 1162 m_playPitch->setChecked(m_analyser->isAudible(Analyser::PitchTrack));
Chris@144 1163 m_playNotes->setChecked(m_analyser->isAudible(Analyser::Notes));
Chris@128 1164 }
Chris@128 1165
Chris@128 1166 void
Chris@0 1167 MainWindow::updateDescriptionLabel()
Chris@0 1168 {
Chris@6 1169 // Nothing, we don't have one
Chris@0 1170 }
Chris@0 1171
Chris@0 1172 void
Chris@0 1173 MainWindow::documentModified()
Chris@0 1174 {
Chris@0 1175 MainWindowBase::documentModified();
Chris@0 1176 }
Chris@0 1177
Chris@0 1178 void
Chris@0 1179 MainWindow::documentRestored()
Chris@0 1180 {
Chris@0 1181 MainWindowBase::documentRestored();
Chris@0 1182 }
Chris@0 1183
Chris@0 1184 void
Chris@0 1185 MainWindow::newSession()
Chris@0 1186 {
Chris@0 1187 if (!checkSaveModified()) return;
Chris@0 1188
Chris@0 1189 closeSession();
Chris@0 1190 createDocument();
Chris@0 1191 m_document->setAutoAlignment(true);
Chris@0 1192
Chris@0 1193 Pane *pane = m_paneStack->addPane();
Chris@0 1194
Chris@0 1195 connect(pane, SIGNAL(contextHelpChanged(const QString &)),
Chris@0 1196 this, SLOT(contextHelpChanged(const QString &)));
Chris@0 1197
Chris@6 1198 // Layer *waveform = m_document->createMainModelLayer(LayerFactory::Waveform);
Chris@6 1199 // m_document->addLayerToView(pane, waveform);
Chris@0 1200
Chris@0 1201 m_overview->registerView(pane);
Chris@0 1202
Chris@0 1203 CommandHistory::getInstance()->clear();
Chris@0 1204 CommandHistory::getInstance()->documentSaved();
Chris@0 1205 documentRestored();
Chris@0 1206 updateMenuStates();
Chris@0 1207 }
Chris@0 1208
Chris@0 1209 void
Chris@0 1210 MainWindow::closeSession()
Chris@0 1211 {
Chris@0 1212 if (!checkSaveModified()) return;
Chris@0 1213
Chris@0 1214 while (m_paneStack->getPaneCount() > 0) {
Chris@0 1215
Chris@167 1216 Pane *pane = m_paneStack->getPane(m_paneStack->getPaneCount() - 1);
Chris@0 1217
Chris@167 1218 while (pane->getLayerCount() > 0) {
Chris@167 1219 m_document->removeLayerFromView
Chris@167 1220 (pane, pane->getLayer(pane->getLayerCount() - 1));
Chris@167 1221 }
Chris@167 1222
Chris@167 1223 m_overview->unregisterView(pane);
Chris@167 1224 m_paneStack->deletePane(pane);
Chris@0 1225 }
Chris@0 1226
Chris@0 1227 while (m_paneStack->getHiddenPaneCount() > 0) {
Chris@0 1228
Chris@167 1229 Pane *pane = m_paneStack->getHiddenPane
Chris@167 1230 (m_paneStack->getHiddenPaneCount() - 1);
Chris@167 1231
Chris@167 1232 while (pane->getLayerCount() > 0) {
Chris@167 1233 m_document->removeLayerFromView
Chris@167 1234 (pane, pane->getLayer(pane->getLayerCount() - 1));
Chris@167 1235 }
Chris@167 1236
Chris@167 1237 m_overview->unregisterView(pane);
Chris@167 1238 m_paneStack->deletePane(pane);
Chris@0 1239 }
Chris@0 1240
Chris@0 1241 delete m_document;
Chris@0 1242 m_document = 0;
Chris@0 1243 m_viewManager->clearSelections();
Chris@0 1244 m_timeRulerLayer = 0; // document owned this
Chris@0 1245
Chris@0 1246 m_sessionFile = "";
Chris@0 1247
Chris@0 1248 CommandHistory::getInstance()->clear();
Chris@0 1249 CommandHistory::getInstance()->documentSaved();
Chris@0 1250 documentRestored();
Chris@0 1251 }
Chris@0 1252
Chris@0 1253 void
Chris@0 1254 MainWindow::openFile()
Chris@0 1255 {
Chris@0 1256 QString orig = m_audioFile;
Chris@0 1257 if (orig == "") orig = ".";
Chris@0 1258 else orig = QFileInfo(orig).absoluteDir().canonicalPath();
Chris@0 1259
Chris@0 1260 QString path = getOpenFileName(FileFinder::AnyFile);
Chris@0 1261
Chris@0 1262 if (path.isEmpty()) return;
Chris@0 1263
Chris@1 1264 FileOpenStatus status = open(path, ReplaceSession);
Chris@0 1265
Chris@0 1266 if (status == FileOpenFailed) {
Chris@0 1267 QMessageBox::critical(this, tr("Failed to open file"),
Chris@0 1268 tr("<b>File open failed</b><p>File \"%1\" could not be opened").arg(path));
Chris@0 1269 } else if (status == FileOpenWrongMode) {
Chris@0 1270 QMessageBox::critical(this, tr("Failed to open file"),
Chris@0 1271 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
Chris@0 1272 }
Chris@0 1273 }
Chris@0 1274
Chris@0 1275 void
Chris@0 1276 MainWindow::openLocation()
Chris@0 1277 {
Chris@0 1278 QSettings settings;
Chris@0 1279 settings.beginGroup("MainWindow");
Chris@0 1280 QString lastLocation = settings.value("lastremote", "").toString();
Chris@0 1281
Chris@0 1282 bool ok = false;
Chris@0 1283 QString text = QInputDialog::getText
Chris@0 1284 (this, tr("Open Location"),
Chris@0 1285 tr("Please enter the URL of the location to open:"),
Chris@0 1286 QLineEdit::Normal, lastLocation, &ok);
Chris@0 1287
Chris@0 1288 if (!ok) return;
Chris@0 1289
Chris@0 1290 settings.setValue("lastremote", text);
Chris@0 1291
Chris@0 1292 if (text.isEmpty()) return;
Chris@0 1293
Chris@1 1294 FileOpenStatus status = open(text, ReplaceSession);
Chris@0 1295
Chris@0 1296 if (status == FileOpenFailed) {
Chris@0 1297 QMessageBox::critical(this, tr("Failed to open location"),
Chris@0 1298 tr("<b>Open failed</b><p>URL \"%1\" could not be opened").arg(text));
Chris@0 1299 } else if (status == FileOpenWrongMode) {
Chris@0 1300 QMessageBox::critical(this, tr("Failed to open location"),
Chris@0 1301 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
Chris@0 1302 }
Chris@0 1303 }
Chris@0 1304
Chris@0 1305 void
Chris@0 1306 MainWindow::openRecentFile()
Chris@0 1307 {
Chris@0 1308 QObject *obj = sender();
Chris@3 1309 QAction *action = qobject_cast<QAction *>(obj);
Chris@0 1310
Chris@0 1311 if (!action) {
Chris@188 1312 cerr << "WARNING: MainWindow::openRecentFile: sender is not an action"
Chris@188 1313 << endl;
Chris@188 1314 return;
Chris@0 1315 }
Chris@0 1316
Chris@0 1317 QString path = action->text();
Chris@0 1318 if (path == "") return;
Chris@0 1319
Chris@1 1320 FileOpenStatus status = open(path, ReplaceSession);
Chris@0 1321
Chris@0 1322 if (status == FileOpenFailed) {
Chris@0 1323 QMessageBox::critical(this, tr("Failed to open location"),
Chris@0 1324 tr("<b>Open failed</b><p>File or URL \"%1\" could not be opened").arg(path));
Chris@0 1325 } else if (status == FileOpenWrongMode) {
Chris@0 1326 QMessageBox::critical(this, tr("Failed to open location"),
Chris@0 1327 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
Chris@0 1328 }
Chris@0 1329 }
Chris@0 1330
Chris@0 1331 void
Chris@0 1332 MainWindow::paneAdded(Pane *pane)
Chris@0 1333 {
Chris@6 1334 pane->setPlaybackFollow(PlaybackScrollPage);
Chris@0 1335 m_paneStack->sizePanesEqually();
Chris@0 1336 if (m_overview) m_overview->registerView(pane);
Chris@0 1337 }
Chris@0 1338
Chris@0 1339 void
Chris@0 1340 MainWindow::paneHidden(Pane *pane)
Chris@0 1341 {
Chris@0 1342 if (m_overview) m_overview->unregisterView(pane);
Chris@0 1343 }
Chris@0 1344
Chris@0 1345 void
Chris@0 1346 MainWindow::paneAboutToBeDeleted(Pane *pane)
Chris@0 1347 {
Chris@0 1348 if (m_overview) m_overview->unregisterView(pane);
Chris@0 1349 }
Chris@0 1350
Chris@0 1351 void
Chris@0 1352 MainWindow::paneDropAccepted(Pane *pane, QStringList uriList)
Chris@0 1353 {
Chris@4 1354 if (pane) m_paneStack->setCurrentPane(pane);
Chris@0 1355
Chris@0 1356 for (QStringList::iterator i = uriList.begin(); i != uriList.end(); ++i) {
Chris@0 1357
Chris@1 1358 FileOpenStatus status = open(*i, ReplaceSession);
Chris@0 1359
Chris@0 1360 if (status == FileOpenFailed) {
Chris@0 1361 QMessageBox::critical(this, tr("Failed to open dropped URL"),
Chris@0 1362 tr("<b>Open failed</b><p>Dropped URL \"%1\" could not be opened").arg(*i));
Chris@0 1363 } else if (status == FileOpenWrongMode) {
Chris@0 1364 QMessageBox::critical(this, tr("Failed to open dropped URL"),
Chris@0 1365 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
Chris@0 1366 }
Chris@0 1367 }
Chris@0 1368 }
Chris@0 1369
Chris@0 1370 void
Chris@0 1371 MainWindow::paneDropAccepted(Pane *pane, QString text)
Chris@0 1372 {
Chris@0 1373 if (pane) m_paneStack->setCurrentPane(pane);
Chris@0 1374
Chris@0 1375 QUrl testUrl(text);
Chris@0 1376 if (testUrl.scheme() == "file" ||
Chris@0 1377 testUrl.scheme() == "http" ||
Chris@0 1378 testUrl.scheme() == "ftp") {
Chris@0 1379 QStringList list;
Chris@0 1380 list.push_back(text);
Chris@0 1381 paneDropAccepted(pane, list);
Chris@0 1382 return;
Chris@0 1383 }
Chris@0 1384
Chris@0 1385 //!!! open as text -- but by importing as if a CSV, or just adding
Chris@0 1386 //to a text layer?
Chris@0 1387 }
Chris@0 1388
Chris@0 1389 void
Chris@0 1390 MainWindow::closeEvent(QCloseEvent *e)
Chris@0 1391 {
Chris@70 1392 // cerr << "MainWindow::closeEvent" << endl;
Chris@0 1393
Chris@0 1394 if (m_openingAudioFile) {
Chris@70 1395 // cerr << "Busy - ignoring close event" << endl;
gyorgyf@27 1396 e->ignore();
gyorgyf@27 1397 return;
Chris@0 1398 }
Chris@0 1399
Chris@0 1400 if (!m_abandoning && !checkSaveModified()) {
Chris@70 1401 // cerr << "Ignoring close event" << endl;
gyorgyf@27 1402 e->ignore();
gyorgyf@27 1403 return;
Chris@0 1404 }
Chris@0 1405
Chris@0 1406 QSettings settings;
Chris@0 1407 settings.beginGroup("MainWindow");
Chris@0 1408 settings.setValue("size", size());
Chris@0 1409 settings.setValue("position", pos());
Chris@0 1410 settings.endGroup();
Chris@0 1411
Chris@0 1412 delete m_keyReference;
Chris@0 1413 m_keyReference = 0;
Chris@0 1414
Chris@0 1415 closeSession();
Chris@0 1416
Chris@0 1417 e->accept();
Chris@0 1418 return;
Chris@0 1419 }
Chris@0 1420
Chris@0 1421 bool
Chris@0 1422 MainWindow::commitData(bool mayAskUser)
Chris@0 1423 {
Chris@0 1424 if (mayAskUser) {
Chris@0 1425 bool rv = checkSaveModified();
Chris@0 1426 return rv;
Chris@0 1427 } else {
Chris@0 1428 if (!m_documentModified) return true;
Chris@0 1429
Chris@0 1430 // If we can't check with the user first, then we can't save
Chris@0 1431 // to the original session file (even if we have it) -- have
Chris@0 1432 // to use a temporary file
Chris@0 1433
Chris@0 1434 QString svDirBase = ".sv1";
Chris@0 1435 QString svDir = QDir::home().filePath(svDirBase);
Chris@0 1436
Chris@0 1437 if (!QFileInfo(svDir).exists()) {
Chris@0 1438 if (!QDir::home().mkdir(svDirBase)) return false;
Chris@0 1439 } else {
Chris@0 1440 if (!QFileInfo(svDir).isDir()) return false;
Chris@0 1441 }
Chris@0 1442
Chris@0 1443 // This name doesn't have to be unguessable
Chris@0 1444 #ifndef _WIN32
Chris@0 1445 QString fname = QString("tmp-%1-%2.sv")
Chris@0 1446 .arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"))
Chris@0 1447 .arg(QProcess().pid());
Chris@0 1448 #else
Chris@0 1449 QString fname = QString("tmp-%1.sv")
Chris@0 1450 .arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"));
Chris@0 1451 #endif
Chris@0 1452 QString fpath = QDir(svDir).filePath(fname);
Chris@0 1453 if (saveSessionFile(fpath)) {
Chris@0 1454 m_recentFiles.addFile(fpath);
Chris@0 1455 return true;
Chris@0 1456 } else {
Chris@0 1457 return false;
Chris@0 1458 }
Chris@0 1459 }
Chris@0 1460 }
Chris@0 1461
Chris@0 1462 bool
Chris@0 1463 MainWindow::checkSaveModified()
Chris@0 1464 {
Chris@0 1465 // Called before some destructive operation (e.g. new session,
Chris@0 1466 // exit program). Return true if we can safely proceed, false to
Chris@0 1467 // cancel.
Chris@0 1468
Chris@0 1469 if (!m_documentModified) return true;
Chris@0 1470
Chris@0 1471 int button =
gyorgyf@27 1472 QMessageBox::warning(this,
gyorgyf@27 1473 tr("Session modified"),
gyorgyf@27 1474 tr("The current session has been modified.\nDo you want to save it?"),
gyorgyf@27 1475 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
Chris@0 1476 QMessageBox::Yes);
Chris@0 1477
Chris@0 1478 if (button == QMessageBox::Yes) {
gyorgyf@27 1479 saveSession();
gyorgyf@27 1480 if (m_documentModified) { // save failed -- don't proceed!
gyorgyf@27 1481 return false;
gyorgyf@27 1482 } else {
Chris@0 1483 return true; // saved, so it's safe to continue now
Chris@0 1484 }
Chris@0 1485 } else if (button == QMessageBox::No) {
gyorgyf@27 1486 m_documentModified = false; // so we know to abandon it
gyorgyf@27 1487 return true;
Chris@0 1488 }
Chris@0 1489
Chris@0 1490 // else cancel
Chris@0 1491 return false;
Chris@0 1492 }
Chris@0 1493
Chris@0 1494 void
Chris@0 1495 MainWindow::saveSession()
Chris@0 1496 {
Chris@0 1497 if (m_sessionFile != "") {
gyorgyf@27 1498 if (!saveSessionFile(m_sessionFile)) {
gyorgyf@27 1499 QMessageBox::critical(this, tr("Failed to save file"),
gyorgyf@27 1500 tr("Session file \"%1\" could not be saved.").arg(m_sessionFile));
Chris@0 1501 } else {
gyorgyf@27 1502 CommandHistory::getInstance()->documentSaved();
gyorgyf@27 1503 documentRestored();
gyorgyf@27 1504 }
gyorgyf@27 1505 } else {
gyorgyf@27 1506 saveSessionAs();
Chris@0 1507 }
Chris@0 1508 }
Chris@0 1509
Chris@0 1510 void
Chris@0 1511 MainWindow::saveSessionAs()
Chris@0 1512 {
Chris@0 1513 QString orig = m_audioFile;
Chris@0 1514 if (orig == "") orig = ".";
Chris@0 1515 else orig = QFileInfo(orig).absoluteDir().canonicalPath();
Chris@0 1516
Chris@0 1517 QString path = getSaveFileName(FileFinder::SessionFile);
Chris@0 1518
Chris@0 1519 if (path == "") return;
Chris@0 1520
Chris@0 1521 if (!saveSessionFile(path)) {
Chris@85 1522 QMessageBox::critical(this, tr("Failed to save file"),
Chris@85 1523 tr("Session file \"%1\" could not be saved.").arg(path));
Chris@0 1524 } else {
Chris@85 1525 setWindowTitle(tr("%1: %2")
Chris@0 1526 .arg(QApplication::applicationName())
Chris@85 1527 .arg(QFileInfo(path).fileName()));
Chris@85 1528 m_sessionFile = path;
Chris@85 1529 CommandHistory::getInstance()->documentSaved();
Chris@85 1530 documentRestored();
Chris@0 1531 m_recentFiles.addFile(path);
Chris@0 1532 }
Chris@0 1533 }
Chris@0 1534
Chris@85 1535 QString
Chris@85 1536 MainWindow::exportToSVL(QString path, Layer *layer)
Chris@85 1537 {
Chris@85 1538 Model *model = layer->getModel();
Chris@85 1539
Chris@85 1540 QFile file(path);
Chris@85 1541 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
Chris@85 1542 return tr("Failed to open file %1 for writing").arg(path);
Chris@85 1543 } else {
Chris@85 1544 QTextStream out(&file);
Chris@85 1545 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
Chris@85 1546 << "<!DOCTYPE sonic-visualiser>\n"
Chris@85 1547 << "<sv>\n"
Chris@85 1548 << " <data>\n";
Chris@85 1549
Chris@85 1550 model->toXml(out, " ");
Chris@85 1551
Chris@85 1552 out << " </data>\n"
Chris@85 1553 << " <display>\n";
Chris@85 1554
Chris@85 1555 layer->toXml(out, " ");
Chris@85 1556
Chris@85 1557 out << " </display>\n"
Chris@85 1558 << "</sv>\n";
Chris@85 1559
Chris@85 1560 return "";
Chris@85 1561 }
Chris@85 1562 }
Chris@85 1563
Chris@0 1564 void
Chris@174 1565 MainWindow::importPitchLayer()
Chris@174 1566 {
Chris@174 1567 QString path = getOpenFileName(FileFinder::LayerFileNoMidiNonSV);
Chris@174 1568 if (path == "") return;
Chris@174 1569
Chris@174 1570 FileOpenStatus status = importPitchLayer(path);
Chris@174 1571
Chris@174 1572 if (status == FileOpenFailed) {
Chris@174 1573 emit hideSplash();
Chris@174 1574 QMessageBox::critical(this, tr("Failed to open file"),
Chris@174 1575 tr("<b>File open failed</b><p>Layer file %1 could not be opened.").arg(path));
Chris@174 1576 return;
Chris@174 1577 } else if (status == FileOpenWrongMode) {
Chris@174 1578 emit hideSplash();
Chris@174 1579 QMessageBox::critical(this, tr("Failed to open file"),
Chris@174 1580 tr("<b>Audio required</b><p>Unable to load layer data from \"%1\" without an audio file.<br>Please load at least one audio file before importing annotations.").arg(path));
Chris@174 1581 }
Chris@174 1582 }
Chris@174 1583
Chris@174 1584 MainWindow::FileOpenStatus
Chris@174 1585 MainWindow::importPitchLayer(FileSource source)
Chris@174 1586 {
Chris@174 1587 if (!source.isAvailable()) return FileOpenFailed;
Chris@174 1588 source.waitForData();
Chris@174 1589
Chris@174 1590 QString path = source.getLocalFilename();
Chris@174 1591
Chris@174 1592 RDFImporter::RDFDocumentType rdfType =
Chris@174 1593 RDFImporter::identifyDocumentType(QUrl::fromLocalFile(path).toString());
Chris@174 1594
Chris@174 1595 if (rdfType != RDFImporter::NotRDF) {
Chris@174 1596
Chris@174 1597 //!!!
Chris@174 1598 return FileOpenFailed;
Chris@174 1599
Chris@174 1600 } else if (source.getExtension().toLower() == "svl" ||
Chris@174 1601 (source.getExtension().toLower() == "xml" &&
Chris@174 1602 (SVFileReader::identifyXmlFile(source.getLocalFilename())
Chris@174 1603 == SVFileReader::SVLayerFile))) {
Chris@174 1604
Chris@174 1605 //!!!
Chris@174 1606 return FileOpenFailed;
Chris@174 1607
Chris@174 1608 } else {
Chris@174 1609
Chris@174 1610 try {
Chris@174 1611
Chris@174 1612 CSVFormat format(path);
Chris@174 1613 format.setSampleRate(getMainModel()->getSampleRate());
Chris@174 1614
Chris@174 1615 if (format.getModelType() != CSVFormat::TwoDimensionalModel) {
Chris@174 1616 //!!! error report
Chris@174 1617 return FileOpenFailed;
Chris@174 1618 }
Chris@174 1619
Chris@174 1620 Model *model = DataFileReaderFactory::loadCSV
Chris@174 1621 (path, format, getMainModel()->getSampleRate());
Chris@174 1622
Chris@174 1623 if (model) {
Chris@174 1624
Chris@174 1625 SVDEBUG << "MainWindow::importPitchLayer: Have model" << endl;
Chris@174 1626
Chris@174 1627 CommandHistory::getInstance()->startCompoundOperation
Chris@174 1628 (tr("Import Pitch Track"), true);
Chris@174 1629
Chris@174 1630 Layer *newLayer = m_document->createImportedLayer(model);
Chris@174 1631
Chris@174 1632 m_analyser->takePitchTrackFrom(newLayer);
Chris@174 1633
Chris@174 1634 m_document->deleteLayer(newLayer);
Chris@174 1635
Chris@174 1636 CommandHistory::getInstance()->endCompoundOperation();
Chris@174 1637
Chris@174 1638 //!!! swap all data in to existing layer instead of this
Chris@174 1639
Chris@174 1640 if (!source.isRemote()) {
Chris@174 1641 registerLastOpenedFilePath
Chris@174 1642 (FileFinder::LayerFile,
Chris@174 1643 path); // for file dialog
Chris@174 1644 }
Chris@174 1645
Chris@174 1646 return FileOpenSucceeded;
Chris@174 1647 }
Chris@174 1648 } catch (DataFileReaderFactory::Exception e) {
Chris@174 1649 if (e == DataFileReaderFactory::ImportCancelled) {
Chris@174 1650 return FileOpenCancelled;
Chris@174 1651 }
Chris@174 1652 }
Chris@174 1653 }
Chris@174 1654
Chris@174 1655 return FileOpenFailed;
Chris@174 1656 }
Chris@174 1657
Chris@174 1658 void
Chris@85 1659 MainWindow::exportPitchLayer()
matthiasm@26 1660 {
Chris@174 1661 Layer *layer = m_analyser->getLayer(Analyser::PitchTrack);
matthiasm@26 1662 if (!layer) return;
matthiasm@26 1663
Chris@85 1664 SparseTimeValueModel *model =
Chris@85 1665 qobject_cast<SparseTimeValueModel *>(layer->getModel());
matthiasm@26 1666 if (!model) return;
matthiasm@26 1667
Chris@96 1668 FileFinder::FileType type = FileFinder::LayerFileNoMidiNonSV;
matthiasm@26 1669
matthiasm@26 1670 QString path = getSaveFileName(type);
matthiasm@26 1671
matthiasm@26 1672 if (path == "") return;
matthiasm@26 1673
matthiasm@26 1674 if (QFileInfo(path).suffix() == "") path += ".svl";
matthiasm@26 1675
matthiasm@26 1676 QString suffix = QFileInfo(path).suffix().toLower();
matthiasm@26 1677
matthiasm@26 1678 QString error;
matthiasm@26 1679
matthiasm@26 1680 if (suffix == "xml" || suffix == "svl") {
matthiasm@26 1681
Chris@85 1682 error = exportToSVL(path, layer);
matthiasm@26 1683
matthiasm@26 1684 } else if (suffix == "ttl" || suffix == "n3") {
matthiasm@26 1685
Chris@85 1686 RDFExporter exporter(path, model);
Chris@85 1687 exporter.write();
Chris@85 1688 if (!exporter.isOK()) {
Chris@85 1689 error = exporter.getError();
Chris@85 1690 }
Chris@85 1691
Chris@85 1692 } else {
Chris@85 1693
Chris@85 1694 CSVFileWriter writer(path, model,
Chris@85 1695 ((suffix == "csv") ? "," : "\t"));
Chris@85 1696 writer.write();
Chris@85 1697
Chris@85 1698 if (!writer.isOK()) {
Chris@85 1699 error = writer.getError();
Chris@85 1700 }
Chris@85 1701 }
Chris@85 1702
Chris@85 1703 if (error != "") {
Chris@85 1704 QMessageBox::critical(this, tr("Failed to write file"), error);
Chris@85 1705 } else {
Chris@85 1706 emit activity(tr("Export layer to \"%1\"").arg(path));
Chris@85 1707 }
Chris@85 1708 }
Chris@85 1709
Chris@85 1710 void
Chris@85 1711 MainWindow::exportNoteLayer()
Chris@85 1712 {
Chris@174 1713 Layer *layer = m_analyser->getLayer(Analyser::Notes);
Chris@85 1714 if (!layer) return;
Chris@85 1715
Chris@85 1716 FlexiNoteModel *model = qobject_cast<FlexiNoteModel *>(layer->getModel());
Chris@85 1717 if (!model) return;
Chris@85 1718
Chris@96 1719 FileFinder::FileType type = FileFinder::LayerFileNonSV;
Chris@85 1720
Chris@85 1721 QString path = getSaveFileName(type);
Chris@85 1722
Chris@85 1723 if (path == "") return;
Chris@85 1724
Chris@85 1725 if (QFileInfo(path).suffix() == "") path += ".svl";
Chris@85 1726
Chris@85 1727 QString suffix = QFileInfo(path).suffix().toLower();
Chris@85 1728
Chris@85 1729 QString error;
Chris@85 1730
Chris@85 1731 if (suffix == "xml" || suffix == "svl") {
Chris@85 1732
Chris@85 1733 error = exportToSVL(path, layer);
Chris@85 1734
Chris@85 1735 } else if (suffix == "mid" || suffix == "midi") {
Chris@85 1736
Chris@85 1737 MIDIFileWriter writer(path, model, model->getSampleRate());
Chris@85 1738 writer.write();
Chris@85 1739 if (!writer.isOK()) {
Chris@85 1740 error = writer.getError();
Chris@85 1741 }
Chris@85 1742
Chris@85 1743 } else if (suffix == "ttl" || suffix == "n3") {
Chris@85 1744
Chris@85 1745 RDFExporter exporter(path, model);
Chris@85 1746 exporter.write();
Chris@85 1747 if (!exporter.isOK()) {
Chris@85 1748 error = exporter.getError();
matthiasm@26 1749 }
matthiasm@26 1750
matthiasm@26 1751 } else {
matthiasm@26 1752
matthiasm@26 1753 CSVFileWriter writer(path, model,
matthiasm@26 1754 ((suffix == "csv") ? "," : "\t"));
matthiasm@26 1755 writer.write();
matthiasm@26 1756
matthiasm@26 1757 if (!writer.isOK()) {
matthiasm@26 1758 error = writer.getError();
matthiasm@26 1759 }
matthiasm@26 1760 }
matthiasm@26 1761
matthiasm@26 1762 if (error != "") {
matthiasm@26 1763 QMessageBox::critical(this, tr("Failed to write file"), error);
matthiasm@26 1764 } else {
matthiasm@26 1765 emit activity(tr("Export layer to \"%1\"").arg(path));
matthiasm@26 1766 }
matthiasm@26 1767 }
matthiasm@26 1768
Chris@139 1769 void
Chris@139 1770 MainWindow::doubleClickSelectInvoked(size_t frame)
Chris@139 1771 {
Chris@139 1772 size_t f0, f1;
Chris@139 1773 m_analyser->getEnclosingSelectionScope(frame, f0, f1);
Chris@139 1774
Chris@139 1775 cerr << "MainWindow::doubleClickSelectInvoked(" << frame << "): [" << f0 << "," << f1 << "]" << endl;
Chris@139 1776
Chris@164 1777 Selection sel(f0, f1);
Chris@164 1778 m_viewManager->setSelection(sel);
Chris@164 1779 }
Chris@164 1780
Chris@164 1781 void
Chris@194 1782 MainWindow::abandonSelection()
Chris@167 1783 {
Chris@194 1784 // Named abandonSelection rather than clearSelection to indicate
Chris@194 1785 // that this is an active operation -- it restores the original
Chris@194 1786 // content of the pitch track in the selected region rather than
Chris@194 1787 // simply un-selecting.
Chris@194 1788
Chris@194 1789 cerr << "MainWindow::abandonSelection()" << endl;
Chris@167 1790
Chris@168 1791 CommandHistory::getInstance()->startCompoundOperation(tr("Clear Selection"), true);
Chris@168 1792
Chris@194 1793 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@194 1794 if (!selections.empty()) {
Chris@194 1795 Selection sel = *selections.begin();
Chris@194 1796 m_analyser->clearReAnalysis(sel);
Chris@194 1797 }
Chris@194 1798
Chris@167 1799 MainWindowBase::clearSelection();
Chris@168 1800
Chris@168 1801 CommandHistory::getInstance()->endCompoundOperation();
Chris@167 1802 }
Chris@167 1803
Chris@167 1804 void
Chris@192 1805 MainWindow::selectionChangedByUser()
Chris@164 1806 {
Chris@164 1807 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@164 1808
Chris@192 1809 cerr << "MainWindow::selectionChangedByUser" << endl;
Chris@192 1810
Chris@192 1811 m_analyser->showPitchCandidates(m_pendingConstraint.isConstrained());
Chris@190 1812
Chris@164 1813 if (!selections.empty()) {
Chris@164 1814 Selection sel = *selections.begin();
Chris@192 1815 cerr << "MainWindow::selectionChangedByUser: have selection" << endl;
Chris@192 1816 QString error = m_analyser->reAnalyseSelection
Chris@192 1817 (sel, m_pendingConstraint);
Chris@164 1818 if (error != "") {
Chris@164 1819 QMessageBox::critical
Chris@164 1820 (this, tr("Failed to analyse selection"),
Chris@164 1821 tr("<b>Analysis failed</b><p>%2</p>").arg(error));
Chris@164 1822 }
Chris@164 1823 }
Chris@192 1824
Chris@192 1825 m_pendingConstraint = Analyser::FrequencyRange();
Chris@192 1826 }
Chris@192 1827
Chris@192 1828 void
Chris@192 1829 MainWindow::regionOutlined(QRect r)
Chris@192 1830 {
Chris@192 1831 cerr << "MainWindow::regionOutlined(" << r.x() << "," << r.y() << "," << r.width() << "," << r.height() << ")" << endl;
Chris@192 1832
Chris@192 1833 Pane *pane = qobject_cast<Pane *>(sender());
Chris@192 1834 if (!pane) {
Chris@192 1835 cerr << "MainWindow::regionOutlined: not sent by pane, ignoring" << endl;
Chris@192 1836 return;
Chris@192 1837 }
Chris@192 1838
Chris@192 1839 if (!m_analyser) {
Chris@192 1840 cerr << "MainWindow::regionOutlined: no analyser, ignoring" << endl;
Chris@192 1841 return;
Chris@192 1842 }
Chris@192 1843
Chris@192 1844 SpectrogramLayer *spectrogram = qobject_cast<SpectrogramLayer *>
Chris@192 1845 (m_analyser->getLayer(Analyser::Spectrogram));
Chris@192 1846 if (!spectrogram) {
Chris@192 1847 cerr << "MainWindow::regionOutlined: no spectrogram layer, ignoring" << endl;
Chris@192 1848 return;
Chris@192 1849 }
Chris@192 1850
Chris@192 1851 int f0 = pane->getFrameForX(r.x());
Chris@192 1852 int f1 = pane->getFrameForX(r.x() + r.width());
Chris@192 1853
Chris@192 1854 float v0 = spectrogram->getFrequencyForY(pane, r.y() + r.height());
Chris@192 1855 float v1 = spectrogram->getFrequencyForY(pane, r.y());
Chris@192 1856
Chris@192 1857 cerr << "MainWindow::regionOutlined: frame " << f0 << " -> " << f1
Chris@192 1858 << ", frequency " << v0 << " -> " << v1 << endl;
Chris@192 1859
Chris@192 1860 m_pendingConstraint = Analyser::FrequencyRange(v0, v1);
Chris@192 1861
Chris@192 1862 Selection sel(f0, f1);
Chris@192 1863 m_viewManager->setSelection(sel);
Chris@0 1864 }
Chris@0 1865
Chris@0 1866 void
Chris@168 1867 MainWindow::clearPitches()
Chris@168 1868 {
Chris@168 1869 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@168 1870
Chris@168 1871 CommandHistory::getInstance()->startCompoundOperation(tr("Clear Pitches"), true);
Chris@168 1872
Chris@168 1873 for (MultiSelection::SelectionList::iterator k = selections.begin();
Chris@168 1874 k != selections.end(); ++k) {
Chris@184 1875 m_analyser->deletePitches(*k);
Chris@168 1876 }
Chris@168 1877
Chris@168 1878 CommandHistory::getInstance()->endCompoundOperation();
Chris@168 1879 }
Chris@168 1880
Chris@168 1881 void
Chris@142 1882 MainWindow::octaveShiftUp()
Chris@142 1883 {
Chris@142 1884 octaveShift(true);
Chris@142 1885 }
Chris@142 1886
Chris@142 1887 void
Chris@142 1888 MainWindow::octaveShiftDown()
Chris@142 1889 {
Chris@142 1890 octaveShift(false);
Chris@142 1891 }
Chris@142 1892
Chris@142 1893 void
Chris@142 1894 MainWindow::octaveShift(bool up)
Chris@142 1895 {
Chris@142 1896 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@142 1897
Chris@142 1898 CommandHistory::getInstance()->startCompoundOperation(tr("Octave Shift"), true);
Chris@142 1899
Chris@168 1900 for (MultiSelection::SelectionList::iterator k = selections.begin();
Chris@168 1901 k != selections.end(); ++k) {
Chris@142 1902
Chris@168 1903 m_analyser->shiftOctave(*k, up);
Chris@142 1904 }
Chris@142 1905
Chris@142 1906 CommandHistory::getInstance()->endCompoundOperation();
Chris@142 1907 }
Chris@142 1908
Chris@142 1909 void
Chris@184 1910 MainWindow::togglePitchCandidates()
Chris@184 1911 {
Chris@184 1912 m_analyser->showPitchCandidates(!m_analyser->arePitchCandidatesShown());
Chris@187 1913 updateMenuStates();
Chris@184 1914 }
Chris@184 1915
Chris@184 1916 void
Chris@184 1917 MainWindow::switchPitchUp()
Chris@167 1918 {
Chris@168 1919 CommandHistory::getInstance()->startCompoundOperation
Chris@168 1920 (tr("Switch Pitch Candidate"), true);
Chris@168 1921
Chris@167 1922 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@167 1923
Chris@167 1924 for (MultiSelection::SelectionList::iterator k = selections.begin();
Chris@167 1925 k != selections.end(); ++k) {
Chris@167 1926 m_analyser->switchPitchCandidate(*k, true);
Chris@167 1927 }
Chris@167 1928
Chris@168 1929 CommandHistory::getInstance()->endCompoundOperation();
Chris@167 1930 }
Chris@167 1931
Chris@167 1932 void
Chris@184 1933 MainWindow::switchPitchDown()
Chris@184 1934 {
Chris@184 1935 CommandHistory::getInstance()->startCompoundOperation
Chris@184 1936 (tr("Switch Pitch Candidate"), true);
Chris@184 1937
Chris@184 1938 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@184 1939
Chris@184 1940 for (MultiSelection::SelectionList::iterator k = selections.begin();
Chris@184 1941 k != selections.end(); ++k) {
Chris@184 1942 m_analyser->switchPitchCandidate(*k, false);
Chris@184 1943 }
Chris@184 1944
Chris@184 1945 CommandHistory::getInstance()->endCompoundOperation();
Chris@184 1946 }
Chris@184 1947
Chris@184 1948 void
Chris@0 1949 MainWindow::playSpeedChanged(int position)
Chris@0 1950 {
Chris@0 1951 PlaySpeedRangeMapper mapper(0, 200);
Chris@0 1952
Chris@0 1953 float percent = m_playSpeed->mappedValue();
Chris@0 1954 float factor = mapper.getFactorForValue(percent);
Chris@0 1955
Chris@70 1956 cerr << "speed = " << position << " percent = " << percent << " factor = " << factor << endl;
Chris@0 1957
Chris@0 1958 bool something = (position != 100);
Chris@0 1959
Chris@0 1960 int pc = lrintf(percent);
Chris@0 1961
Chris@0 1962 if (!something) {
Chris@0 1963 contextHelpChanged(tr("Playback speed: Normal"));
Chris@0 1964 } else {
Chris@0 1965 contextHelpChanged(tr("Playback speed: %1%2%")
Chris@0 1966 .arg(position > 100 ? "+" : "")
Chris@0 1967 .arg(pc));
Chris@0 1968 }
Chris@0 1969
Chris@0 1970 m_playSource->setTimeStretch(factor);
Chris@0 1971
Chris@0 1972 updateMenuStates();
Chris@0 1973 }
Chris@0 1974
Chris@0 1975 void
Chris@0 1976 MainWindow::playSharpenToggled()
Chris@0 1977 {
Chris@0 1978 QSettings settings;
Chris@0 1979 settings.beginGroup("MainWindow");
Chris@0 1980 settings.setValue("playsharpen", m_playSharpen->isChecked());
Chris@0 1981 settings.endGroup();
Chris@0 1982
Chris@0 1983 playSpeedChanged(m_playSpeed->value());
justin@157 1984 // TODO: pitch gain?
Chris@0 1985 }
Chris@0 1986
Chris@0 1987 void
Chris@0 1988 MainWindow::playMonoToggled()
Chris@0 1989 {
Chris@0 1990 QSettings settings;
Chris@0 1991 settings.beginGroup("MainWindow");
Chris@0 1992 settings.setValue("playmono", m_playMono->isChecked());
Chris@0 1993 settings.endGroup();
Chris@0 1994
Chris@0 1995 playSpeedChanged(m_playSpeed->value());
justin@157 1996 // TODO: pitch gain?
Chris@0 1997 }
Chris@0 1998
Chris@0 1999 void
Chris@0 2000 MainWindow::speedUpPlayback()
Chris@0 2001 {
Chris@0 2002 int value = m_playSpeed->value();
Chris@0 2003 value = value + m_playSpeed->pageStep();
Chris@0 2004 if (value > m_playSpeed->maximum()) value = m_playSpeed->maximum();
Chris@0 2005 m_playSpeed->setValue(value);
Chris@0 2006 }
Chris@0 2007
Chris@0 2008 void
Chris@0 2009 MainWindow::slowDownPlayback()
Chris@0 2010 {
Chris@0 2011 int value = m_playSpeed->value();
Chris@0 2012 value = value - m_playSpeed->pageStep();
Chris@0 2013 if (value < m_playSpeed->minimum()) value = m_playSpeed->minimum();
Chris@0 2014 m_playSpeed->setValue(value);
Chris@0 2015 }
Chris@0 2016
Chris@0 2017 void
Chris@0 2018 MainWindow::restoreNormalPlayback()
Chris@0 2019 {
Chris@0 2020 m_playSpeed->setValue(m_playSpeed->defaultValue());
Chris@0 2021 }
Chris@0 2022
justin@157 2023 void
justin@159 2024 MainWindow::audioGainChanged(int position)
justin@159 2025 {
justin@159 2026 float level = m_gainAudio->mappedValue();
justin@159 2027 float gain = powf(10, level / 20.0);
justin@159 2028
justin@159 2029 cerr << "gain = " << gain << " (" << position << " dB)" << endl;
justin@159 2030
justin@159 2031 contextHelpChanged(tr("Audio Gain: %1 dB").arg(position));
justin@159 2032
justin@159 2033 m_analyser->setGain(Analyser::Audio, gain);
justin@159 2034
justin@159 2035 updateMenuStates();
justin@159 2036 }
justin@159 2037
justin@159 2038 void
justin@159 2039 MainWindow::increaseAudioGain()
justin@159 2040 {
justin@159 2041 int value = m_gainAudio->value();
justin@159 2042 value = value + m_gainAudio->pageStep();
justin@159 2043 if (value > m_gainAudio->maximum()) value = m_gainAudio->maximum();
justin@159 2044 m_gainAudio->setValue(value);
justin@159 2045 }
justin@159 2046
justin@159 2047 void
justin@159 2048 MainWindow::decreaseAudioGain()
justin@159 2049 {
justin@159 2050 int value = m_gainAudio->value();
justin@159 2051 value = value - m_gainAudio->pageStep();
justin@159 2052 if (value < m_gainAudio->minimum()) value = m_gainAudio->minimum();
justin@159 2053 m_gainAudio->setValue(value);
justin@159 2054 }
justin@159 2055
justin@159 2056 void
justin@159 2057 MainWindow::restoreNormalAudioGain()
justin@159 2058 {
justin@159 2059 m_gainAudio->setValue(m_gainAudio->defaultValue());
justin@159 2060 }
justin@159 2061
justin@159 2062 void
justin@157 2063 MainWindow::pitchGainChanged(int position)
justin@157 2064 {
Chris@158 2065 float level = m_gainPitch->mappedValue();
Chris@158 2066 float gain = powf(10, level / 20.0);
justin@157 2067
Chris@158 2068 cerr << "gain = " << gain << " (" << position << " dB)" << endl;
justin@157 2069
Chris@158 2070 contextHelpChanged(tr("Pitch Gain: %1 dB").arg(position));
justin@157 2071
Chris@158 2072 m_analyser->setGain(Analyser::PitchTrack, gain);
justin@157 2073
justin@157 2074 updateMenuStates();
justin@157 2075 }
justin@157 2076
justin@157 2077 void
justin@157 2078 MainWindow::increasePitchGain()
justin@157 2079 {
justin@157 2080 int value = m_gainPitch->value();
justin@157 2081 value = value + m_gainPitch->pageStep();
justin@157 2082 if (value > m_gainPitch->maximum()) value = m_gainPitch->maximum();
justin@157 2083 m_gainPitch->setValue(value);
justin@157 2084 }
justin@157 2085
justin@157 2086 void
justin@157 2087 MainWindow::decreasePitchGain()
justin@157 2088 {
justin@157 2089 int value = m_gainPitch->value();
justin@157 2090 value = value - m_gainPitch->pageStep();
justin@157 2091 if (value < m_gainPitch->minimum()) value = m_gainPitch->minimum();
justin@157 2092 m_gainPitch->setValue(value);
justin@157 2093 }
justin@157 2094
justin@157 2095 void
justin@157 2096 MainWindow::restoreNormalPitchGain()
justin@157 2097 {
justin@157 2098 m_gainPitch->setValue(m_gainPitch->defaultValue());
justin@157 2099 }
justin@157 2100
Chris@0 2101 void
justin@159 2102 MainWindow::notesGainChanged(int position)
justin@159 2103 {
justin@159 2104 float level = m_gainNotes->mappedValue();
justin@159 2105 float gain = powf(10, level / 20.0);
justin@159 2106
justin@159 2107 cerr << "gain = " << gain << " (" << position << " dB)" << endl;
justin@159 2108
justin@159 2109 contextHelpChanged(tr("Notes Gain: %1 dB").arg(position));
justin@159 2110
justin@159 2111 m_analyser->setGain(Analyser::Notes, gain);
justin@159 2112
justin@159 2113 updateMenuStates();
justin@159 2114 }
justin@159 2115
justin@159 2116 void
justin@159 2117 MainWindow::increaseNotesGain()
justin@159 2118 {
justin@159 2119 int value = m_gainNotes->value();
justin@159 2120 value = value + m_gainNotes->pageStep();
justin@159 2121 if (value > m_gainNotes->maximum()) value = m_gainNotes->maximum();
justin@159 2122 m_gainNotes->setValue(value);
justin@159 2123 }
justin@159 2124
justin@159 2125 void
justin@159 2126 MainWindow::decreaseNotesGain()
justin@159 2127 {
justin@159 2128 int value = m_gainNotes->value();
justin@159 2129 value = value - m_gainNotes->pageStep();
justin@159 2130 if (value < m_gainNotes->minimum()) value = m_gainNotes->minimum();
justin@159 2131 m_gainNotes->setValue(value);
justin@159 2132 }
justin@159 2133
justin@159 2134 void
justin@159 2135 MainWindow::restoreNormalNotesGain()
justin@159 2136 {
justin@159 2137 m_gainNotes->setValue(m_gainNotes->defaultValue());
justin@159 2138 }
justin@159 2139
justin@159 2140 void
justin@160 2141 MainWindow::audioPanChanged(int position)
justin@160 2142 {
justin@160 2143 float level = m_panAudio->mappedValue();
justin@160 2144 float pan = level/100.f;
justin@160 2145
justin@160 2146 cerr << "pan = " << pan << " (" << position << ")" << endl;
justin@160 2147
justin@160 2148 contextHelpChanged(tr("Audio Pan: %1").arg(position));
justin@160 2149
justin@160 2150 m_analyser->setPan(Analyser::Audio, pan);
justin@160 2151
justin@160 2152 updateMenuStates();
justin@160 2153 }
justin@160 2154
justin@160 2155 void
justin@160 2156 MainWindow::increaseAudioPan()
justin@160 2157 {
justin@160 2158 int value = m_panAudio->value();
justin@160 2159 value = value + m_panAudio->pageStep();
justin@160 2160 if (value > m_panAudio->maximum()) value = m_panAudio->maximum();
justin@160 2161 m_panAudio->setValue(value);
justin@160 2162 }
justin@160 2163
justin@160 2164 void
justin@160 2165 MainWindow::decreaseAudioPan()
justin@160 2166 {
justin@160 2167 int value = m_panAudio->value();
justin@160 2168 value = value - m_panAudio->pageStep();
justin@160 2169 if (value < m_panAudio->minimum()) value = m_panAudio->minimum();
justin@160 2170 m_panAudio->setValue(value);
justin@160 2171 }
justin@160 2172
justin@160 2173 void
justin@160 2174 MainWindow::restoreNormalAudioPan()
justin@160 2175 {
justin@160 2176 m_panAudio->setValue(m_panAudio->defaultValue());
justin@160 2177 }
justin@160 2178
justin@160 2179 void
justin@160 2180 MainWindow::pitchPanChanged(int position)
justin@160 2181 {
justin@160 2182 float level = m_panPitch->mappedValue();
justin@160 2183 float pan = level/100.f;
justin@160 2184
justin@160 2185 cerr << "pan = " << pan << " (" << position << ")" << endl;
justin@160 2186
justin@160 2187 contextHelpChanged(tr("Pitch Pan: %1").arg(position));
justin@160 2188
justin@160 2189 m_analyser->setPan(Analyser::PitchTrack, pan);
justin@160 2190
justin@160 2191 updateMenuStates();
justin@160 2192 }
justin@160 2193
justin@160 2194 void
justin@160 2195 MainWindow::increasePitchPan()
justin@160 2196 {
justin@160 2197 int value = m_panPitch->value();
justin@160 2198 value = value + m_panPitch->pageStep();
justin@160 2199 if (value > m_panPitch->maximum()) value = m_panPitch->maximum();
justin@160 2200 m_panPitch->setValue(value);
justin@160 2201 }
justin@160 2202
justin@160 2203 void
justin@160 2204 MainWindow::decreasePitchPan()
justin@160 2205 {
justin@160 2206 int value = m_panPitch->value();
justin@160 2207 value = value - m_panPitch->pageStep();
justin@160 2208 if (value < m_panPitch->minimum()) value = m_panPitch->minimum();
justin@160 2209 m_panPitch->setValue(value);
justin@160 2210 }
justin@160 2211
justin@160 2212 void
justin@160 2213 MainWindow::restoreNormalPitchPan()
justin@160 2214 {
justin@160 2215 m_panPitch->setValue(m_panPitch->defaultValue());
justin@160 2216 }
justin@160 2217
justin@160 2218 void
justin@160 2219 MainWindow::notesPanChanged(int position)
justin@160 2220 {
justin@160 2221 float level = m_panNotes->mappedValue();
justin@160 2222 float pan = level/100.f;
justin@160 2223
justin@160 2224 cerr << "pan = " << pan << " (" << position << ")" << endl;
justin@160 2225
justin@160 2226 contextHelpChanged(tr("Notes Pan: %1").arg(position));
justin@160 2227
justin@160 2228 m_analyser->setPan(Analyser::Notes, pan);
justin@160 2229
justin@160 2230 updateMenuStates();
justin@160 2231 }
justin@160 2232
justin@160 2233 void
justin@160 2234 MainWindow::increaseNotesPan()
justin@160 2235 {
justin@160 2236 int value = m_panNotes->value();
justin@160 2237 value = value + m_panNotes->pageStep();
justin@160 2238 if (value > m_panNotes->maximum()) value = m_panNotes->maximum();
justin@160 2239 m_panNotes->setValue(value);
justin@160 2240 }
justin@160 2241
justin@160 2242 void
justin@160 2243 MainWindow::decreaseNotesPan()
justin@160 2244 {
justin@160 2245 int value = m_panNotes->value();
justin@160 2246 value = value - m_panNotes->pageStep();
justin@160 2247 if (value < m_panNotes->minimum()) value = m_panNotes->minimum();
justin@160 2248 m_panNotes->setValue(value);
justin@160 2249 }
justin@160 2250
justin@160 2251 void
justin@160 2252 MainWindow::restoreNormalNotesPan()
justin@160 2253 {
justin@160 2254 m_panNotes->setValue(m_panNotes->defaultValue());
justin@160 2255 }
justin@160 2256
justin@160 2257 void
Chris@0 2258 MainWindow::updateVisibleRangeDisplay(Pane *p) const
Chris@0 2259 {
Chris@0 2260 if (!getMainModel() || !p) {
Chris@0 2261 return;
Chris@0 2262 }
Chris@0 2263
Chris@0 2264 bool haveSelection = false;
Chris@0 2265 size_t startFrame = 0, endFrame = 0;
Chris@0 2266
Chris@0 2267 if (m_viewManager && m_viewManager->haveInProgressSelection()) {
Chris@0 2268
Chris@0 2269 bool exclusive = false;
Chris@0 2270 Selection s = m_viewManager->getInProgressSelection(exclusive);
Chris@0 2271
Chris@0 2272 if (!s.isEmpty()) {
Chris@0 2273 haveSelection = true;
Chris@0 2274 startFrame = s.getStartFrame();
Chris@0 2275 endFrame = s.getEndFrame();
Chris@0 2276 }
Chris@0 2277 }
Chris@0 2278
Chris@0 2279 if (!haveSelection) {
Chris@0 2280 startFrame = p->getFirstVisibleFrame();
Chris@0 2281 endFrame = p->getLastVisibleFrame();
Chris@0 2282 }
Chris@0 2283
Chris@0 2284 RealTime start = RealTime::frame2RealTime
Chris@0 2285 (startFrame, getMainModel()->getSampleRate());
Chris@0 2286
Chris@0 2287 RealTime end = RealTime::frame2RealTime
Chris@0 2288 (endFrame, getMainModel()->getSampleRate());
Chris@0 2289
Chris@0 2290 RealTime duration = end - start;
Chris@0 2291
Chris@0 2292 QString startStr, endStr, durationStr;
Chris@0 2293 startStr = start.toText(true).c_str();
Chris@0 2294 endStr = end.toText(true).c_str();
Chris@0 2295 durationStr = duration.toText(true).c_str();
Chris@0 2296
Chris@0 2297 if (haveSelection) {
Chris@0 2298 m_myStatusMessage = tr("Selection: %1 to %2 (duration %3)")
Chris@0 2299 .arg(startStr).arg(endStr).arg(durationStr);
Chris@0 2300 } else {
Chris@0 2301 m_myStatusMessage = tr("Visible: %1 to %2 (duration %3)")
Chris@0 2302 .arg(startStr).arg(endStr).arg(durationStr);
Chris@0 2303 }
matthiasm@42 2304
matthiasm@42 2305 // scale Y axis
matthiasm@42 2306 FlexiNoteLayer *fnl = dynamic_cast<FlexiNoteLayer *>(p->getLayer(2));
matthiasm@42 2307 if (fnl) {
matthiasm@42 2308 fnl->setVerticalRangeToNoteRange(p);
matthiasm@42 2309 }
matthiasm@42 2310
Chris@0 2311 statusBar()->showMessage(m_myStatusMessage);
Chris@0 2312 }
Chris@0 2313
Chris@0 2314 void
Chris@0 2315 MainWindow::updatePositionStatusDisplays() const
Chris@0 2316 {
Chris@0 2317 if (!statusBar()->isVisible()) return;
Chris@0 2318
Chris@0 2319 }
Chris@0 2320
Chris@0 2321 void
Chris@0 2322 MainWindow::outputLevelsChanged(float left, float right)
Chris@0 2323 {
Chris@0 2324 m_fader->setPeakLeft(left);
Chris@0 2325 m_fader->setPeakRight(right);
Chris@0 2326 }
Chris@0 2327
Chris@0 2328 void
Chris@0 2329 MainWindow::sampleRateMismatch(size_t requested, size_t actual,
Chris@0 2330 bool willResample)
Chris@0 2331 {
Chris@0 2332 updateDescriptionLabel();
Chris@0 2333 }
Chris@0 2334
Chris@0 2335 void
Chris@0 2336 MainWindow::audioOverloadPluginDisabled()
Chris@0 2337 {
Chris@0 2338 QMessageBox::information
Chris@0 2339 (this, tr("Audio processing overload"),
Chris@0 2340 tr("<b>Overloaded</b><p>Audio effects plugin auditioning has been disabled due to a processing overload."));
Chris@0 2341 }
Chris@0 2342
Chris@0 2343 void
Chris@0 2344 MainWindow::audioTimeStretchMultiChannelDisabled()
Chris@0 2345 {
Chris@0 2346 static bool shownOnce = false;
Chris@0 2347 if (shownOnce) return;
Chris@0 2348 QMessageBox::information
Chris@0 2349 (this, tr("Audio processing overload"),
Chris@0 2350 tr("<b>Overloaded</b><p>Audio playback speed processing has been reduced to a single channel, due to a processing overload."));
Chris@0 2351 shownOnce = true;
Chris@0 2352 }
Chris@0 2353
Chris@0 2354 void
Chris@0 2355 MainWindow::layerRemoved(Layer *layer)
Chris@0 2356 {
Chris@0 2357 MainWindowBase::layerRemoved(layer);
Chris@0 2358 }
Chris@0 2359
Chris@0 2360 void
Chris@0 2361 MainWindow::layerInAView(Layer *layer, bool inAView)
Chris@0 2362 {
Chris@0 2363 MainWindowBase::layerInAView(layer, inAView);
Chris@0 2364 }
Chris@0 2365
Chris@0 2366 void
Chris@0 2367 MainWindow::modelAdded(Model *model)
Chris@0 2368 {
Chris@0 2369 MainWindowBase::modelAdded(model);
Chris@3 2370 DenseTimeValueModel *dtvm = qobject_cast<DenseTimeValueModel *>(model);
Chris@0 2371 if (dtvm) {
Chris@70 2372 cerr << "A dense time-value model (such as an audio file) has been loaded" << endl;
Chris@0 2373 }
Chris@0 2374 }
Chris@0 2375
Chris@0 2376 void
Chris@0 2377 MainWindow::modelAboutToBeDeleted(Model *model)
Chris@0 2378 {
Chris@0 2379 MainWindowBase::modelAboutToBeDeleted(model);
Chris@0 2380 }
Chris@0 2381
Chris@0 2382 void
Chris@0 2383 MainWindow::mainModelChanged(WaveFileModel *model)
Chris@0 2384 {
Chris@0 2385 m_panLayer->setModel(model);
Chris@0 2386
Chris@0 2387 MainWindowBase::mainModelChanged(model);
Chris@0 2388
Chris@0 2389 if (m_playTarget) {
Chris@0 2390 connect(m_fader, SIGNAL(valueChanged(float)),
Chris@0 2391 m_playTarget, SLOT(setOutputGain(float)));
Chris@0 2392 }
Chris@72 2393
Chris@72 2394 if (model) {
Chris@72 2395 if (m_paneStack) {
Chris@174 2396
Chris@174 2397 int pc = m_paneStack->getPaneCount();
Chris@174 2398 Pane *pane = 0;
Chris@174 2399
Chris@174 2400 if (pc < 1) {
Chris@72 2401 pane = m_paneStack->addPane();
Chris@131 2402
Chris@131 2403 Pane *selectionStrip = m_paneStack->addPane();
Chris@131 2404 selectionStrip->setFixedHeight(26);
Chris@131 2405 m_document->addLayerToView
Chris@131 2406 (selectionStrip,
Chris@131 2407 m_document->createMainModelLayer(LayerFactory::TimeRuler));
Chris@131 2408 m_paneStack->sizePanesEqually();
Chris@131 2409
Chris@131 2410 m_viewManager->clearToolModeOverrides();
Chris@131 2411 m_viewManager->setToolModeFor(selectionStrip,
Chris@131 2412 ViewManager::SelectMode);
Chris@174 2413 } else {
Chris@174 2414 pane = m_paneStack->getPane(0);
Chris@72 2415 }
Chris@174 2416
Chris@72 2417 if (pane) {
Chris@192 2418
Chris@192 2419 disconnect(pane, SIGNAL(regionOutlined(QRect)),
Chris@192 2420 pane, SLOT(zoomToRegion(QRect)));
Chris@192 2421 connect(pane, SIGNAL(regionOutlined(QRect)),
Chris@192 2422 this, SLOT(regionOutlined(QRect)));
Chris@192 2423
Chris@140 2424 QString error = m_analyser->newFileLoaded
Chris@72 2425 (m_document, getMainModel(), m_paneStack, pane);
Chris@140 2426 if (error != "") {
Chris@140 2427 QMessageBox::warning
Chris@140 2428 (this,
Chris@140 2429 tr("Failed to analyse audio"),
Chris@140 2430 tr("<b>Analysis failed</b><p>%1</p>").arg(error),
Chris@140 2431 QMessageBox::Ok);
Chris@140 2432 }
Chris@72 2433 }
Chris@72 2434 }
Chris@72 2435 }
Chris@0 2436 }
Chris@0 2437
Chris@0 2438 void
Chris@0 2439 MainWindow::modelGenerationFailed(QString transformName, QString message)
Chris@0 2440 {
Chris@0 2441 if (message != "") {
Chris@0 2442
Chris@0 2443 QMessageBox::warning
Chris@0 2444 (this,
Chris@0 2445 tr("Failed to generate layer"),
Chris@0 2446 tr("<b>Layer generation failed</b><p>Failed to generate derived layer.<p>The layer transform \"%1\" failed:<p>%2")
Chris@0 2447 .arg(transformName).arg(message),
Chris@0 2448 QMessageBox::Ok);
Chris@0 2449 } else {
Chris@0 2450 QMessageBox::warning
Chris@0 2451 (this,
Chris@0 2452 tr("Failed to generate layer"),
Chris@0 2453 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.")
Chris@0 2454 .arg(transformName),
Chris@0 2455 QMessageBox::Ok);
Chris@0 2456 }
Chris@0 2457 }
Chris@0 2458
Chris@0 2459 void
Chris@0 2460 MainWindow::modelGenerationWarning(QString transformName, QString message)
Chris@0 2461 {
Chris@0 2462 QMessageBox::warning
Chris@0 2463 (this, tr("Warning"), message, QMessageBox::Ok);
Chris@0 2464 }
Chris@0 2465
Chris@0 2466 void
Chris@0 2467 MainWindow::modelRegenerationFailed(QString layerName,
Chris@0 2468 QString transformName, QString message)
Chris@0 2469 {
Chris@0 2470 if (message != "") {
Chris@0 2471
Chris@0 2472 QMessageBox::warning
Chris@0 2473 (this,
Chris@0 2474 tr("Failed to regenerate layer"),
Chris@0 2475 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")
Chris@0 2476 .arg(layerName).arg(transformName).arg(message),
Chris@0 2477 QMessageBox::Ok);
Chris@0 2478 } else {
Chris@0 2479 QMessageBox::warning
Chris@0 2480 (this,
Chris@0 2481 tr("Failed to regenerate layer"),
Chris@0 2482 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.")
Chris@0 2483 .arg(layerName).arg(transformName),
Chris@0 2484 QMessageBox::Ok);
Chris@0 2485 }
Chris@0 2486 }
Chris@0 2487
Chris@0 2488 void
Chris@0 2489 MainWindow::modelRegenerationWarning(QString layerName,
Chris@0 2490 QString transformName, QString message)
Chris@0 2491 {
Chris@0 2492 QMessageBox::warning
Chris@0 2493 (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);
Chris@0 2494 }
Chris@0 2495
Chris@0 2496 void
Chris@0 2497 MainWindow::alignmentFailed(QString transformName, QString message)
Chris@0 2498 {
Chris@0 2499 QMessageBox::warning
Chris@0 2500 (this,
Chris@0 2501 tr("Failed to calculate alignment"),
Chris@0 2502 tr("<b>Alignment calculation failed</b><p>Failed to calculate an audio alignment using transform \"%1\":<p>%2")
Chris@0 2503 .arg(transformName).arg(message),
Chris@0 2504 QMessageBox::Ok);
Chris@0 2505 }
Chris@0 2506
Chris@0 2507 void
Chris@0 2508 MainWindow::rightButtonMenuRequested(Pane *pane, QPoint position)
Chris@0 2509 {
Chris@70 2510 // cerr << "MainWindow::rightButtonMenuRequested(" << pane << ", " << position.x() << ", " << position.y() << ")" << endl;
Chris@0 2511 m_paneStack->setCurrentPane(pane);
Chris@0 2512 m_rightButtonMenu->popup(position);
Chris@0 2513 }
Chris@0 2514
Chris@0 2515 void
Chris@0 2516 MainWindow::handleOSCMessage(const OSCMessage &message)
Chris@0 2517 {
Chris@70 2518 cerr << "MainWindow::handleOSCMessage: Not implemented" << endl;
Chris@0 2519 }
Chris@0 2520
Chris@0 2521 void
Chris@0 2522 MainWindow::mouseEnteredWidget()
Chris@0 2523 {
Chris@3 2524 QWidget *w = qobject_cast<QWidget *>(sender());
Chris@0 2525 if (!w) return;
Chris@0 2526
Chris@0 2527 if (w == m_fader) {
Chris@0 2528 contextHelpChanged(tr("Adjust the master playback level"));
Chris@0 2529 } else if (w == m_playSpeed) {
Chris@0 2530 contextHelpChanged(tr("Adjust the master playback speed"));
Chris@0 2531 } else if (w == m_playSharpen && w->isEnabled()) {
Chris@0 2532 contextHelpChanged(tr("Toggle transient sharpening for playback time scaling"));
Chris@0 2533 } else if (w == m_playMono && w->isEnabled()) {
Chris@0 2534 contextHelpChanged(tr("Toggle mono mode for playback time scaling"));
Chris@0 2535 }
Chris@0 2536 }
Chris@0 2537
Chris@0 2538 void
Chris@0 2539 MainWindow::mouseLeftWidget()
Chris@0 2540 {
Chris@0 2541 contextHelpChanged("");
Chris@0 2542 }
Chris@0 2543
Chris@0 2544 void
Chris@0 2545 MainWindow::website()
Chris@0 2546 {
Chris@4 2547 //!!! todo: URL!
Chris@4 2548 openHelpUrl(tr("http://code.soundsoftware.ac.uk/projects/tony/"));
Chris@0 2549 }
Chris@0 2550
Chris@0 2551 void
Chris@0 2552 MainWindow::help()
Chris@0 2553 {
Chris@4 2554 //!!! todo: help URL!
Chris@4 2555 openHelpUrl(tr("http://code.soundsoftware.ac.uk/projects/tony/"));
Chris@0 2556 }
Chris@0 2557
Chris@0 2558 void
Chris@0 2559 MainWindow::about()
Chris@0 2560 {
Chris@0 2561 bool debug = false;
Chris@0 2562 QString version = "(unknown version)";
Chris@0 2563
Chris@0 2564 #ifdef BUILD_DEBUG
Chris@0 2565 debug = true;
Chris@0 2566 #endif
Chris@0 2567 version = tr("Release %1").arg(TONY_VERSION);
Chris@0 2568
Chris@0 2569 QString aboutText;
Chris@0 2570
Chris@0 2571 aboutText += tr("<h3>About Tony</h3>");
Chris@0 2572 aboutText += tr("<p>Tony is a program for interactive note and pitch analysis and annotation.</p>");
Chris@0 2573 aboutText += tr("<p>%1 : %2 configuration</p>")
Chris@0 2574 .arg(version)
Chris@0 2575 .arg(debug ? tr("Debug") : tr("Release"));
Chris@0 2576
Chris@0 2577 aboutText +=
Chris@90 2578 "<p>Copyright &copy; 2005&ndash;2013 Chris Cannam, Matthias Mauch, George Fazekas, and Queen Mary University of London.</p>"
Chris@90 2579 "<p>This program is free software; you can redistribute it and/or "
Chris@90 2580 "modify it under the terms of the GNU General Public License as "
Chris@90 2581 "published by the Free Software Foundation; either version 2 of the "
Chris@0 2582 "License, or (at your option) any later version.<br>See the file "
Chris@0 2583 "COPYING included with this distribution for more information.</p>";
Chris@0 2584
Chris@0 2585 QMessageBox::about(this, tr("About %1").arg(QApplication::applicationName()), aboutText);
Chris@0 2586 }
Chris@0 2587
Chris@0 2588 void
Chris@0 2589 MainWindow::keyReference()
Chris@0 2590 {
Chris@0 2591 m_keyReference->show();
Chris@0 2592 }
Chris@0 2593
Chris@0 2594