annotate src/MainWindow.cpp @ 194:34797795a76c

Clearing the selection by hitting Esc now restores the selected region of the pitch track to its contents from before the selection was made (and any alternate candidate chosen). Fixes feature #885
author Chris Cannam
date Wed, 05 Mar 2014 10:38:23 +0000
parents 431a95c9d14d
children 797395e56489
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@187 556 connect(this, SIGNAL(canChangePitchCandidate(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@187 565 connect(this, SIGNAL(canChangePitchCandidate(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@6 873 toolbar = addToolBar(tr("Playback Controls"));
Chris@6 874 toolbar->addWidget(m_playSpeed);
Chris@6 875 toolbar->addWidget(m_fader);
Chris@0 876
Chris@128 877 toolbar = addToolBar(tr("Show and Play"));
Chris@144 878
justin@156 879 /* ORIGINAL DESIGN
Chris@144 880 QLabel *eye = new QLabel;
Chris@144 881 eye->setFixedWidth(40);
Chris@144 882 eye->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
Chris@144 883 eye->setPixmap(il.loadPixmap("eye"));
Chris@144 884 toolbar->addWidget(eye);
Chris@144 885
Chris@144 886 m_showAudio = toolbar->addAction(il.load("waveform"), tr("Show Audio"));
Chris@144 887 m_showAudio->setCheckable(true);
Chris@144 888 connect(m_showAudio, SIGNAL(triggered()), this, SLOT(showAudioToggled()));
Chris@144 889 connect(this, SIGNAL(canPlay(bool)), m_showAudio, SLOT(setEnabled(bool)));
Chris@144 890
Chris@145 891 m_showSpect = toolbar->addAction(il.load("spectrogram"), tr("Show Spectrogram"));
Chris@145 892 m_showSpect->setCheckable(true);
Chris@145 893 connect(m_showSpect, SIGNAL(triggered()), this, SLOT(showSpectToggled()));
Chris@145 894 connect(this, SIGNAL(canPlay(bool)), m_showSpect, SLOT(setEnabled(bool)));
Chris@145 895
Chris@144 896 m_showPitch = toolbar->addAction(il.load("values"), tr("Show Pitch Track"));
Chris@144 897 m_showPitch->setCheckable(true);
Chris@144 898 connect(m_showPitch, SIGNAL(triggered()), this, SLOT(showPitchToggled()));
Chris@144 899 connect(this, SIGNAL(canPlay(bool)), m_showPitch, SLOT(setEnabled(bool)));
Chris@144 900
Chris@144 901 m_showNotes = toolbar->addAction(il.load("notes"), tr("Show Notes"));
Chris@144 902 m_showNotes->setCheckable(true);
Chris@144 903 connect(m_showNotes, SIGNAL(triggered()), this, SLOT(showNotesToggled()));
Chris@144 904 connect(this, SIGNAL(canPlay(bool)), m_showNotes, SLOT(setEnabled(bool)));
Chris@144 905
Chris@144 906 QLabel *speaker = new QLabel;
Chris@144 907 speaker->setFixedWidth(40);
Chris@144 908 speaker->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
Chris@144 909 speaker->setPixmap(il.loadPixmap("speaker"));
Chris@144 910 toolbar->addWidget(speaker);
Chris@128 911
Chris@144 912 m_playAudio = toolbar->addAction(il.load("waveform"), tr("Play Audio"));
Chris@144 913 m_playAudio->setCheckable(true);
Chris@144 914 connect(m_playAudio, SIGNAL(triggered()), this, SLOT(playAudioToggled()));
Chris@144 915 connect(this, SIGNAL(canPlay(bool)), m_playAudio, SLOT(setEnabled(bool)));
Chris@128 916
Chris@144 917 m_playPitch = toolbar->addAction(il.load("values"), tr("Play Pitch Track"));
Chris@144 918 m_playPitch->setCheckable(true);
Chris@144 919 connect(m_playPitch, SIGNAL(triggered()), this, SLOT(playPitchToggled()));
Chris@144 920 connect(this, SIGNAL(canPlay(bool)), m_playPitch, SLOT(setEnabled(bool)));
Chris@128 921
Chris@144 922 m_playNotes = toolbar->addAction(il.load("notes"), tr("Play Notes"));
Chris@144 923 m_playNotes->setCheckable(true);
Chris@144 924 connect(m_playNotes, SIGNAL(triggered()), this, SLOT(playNotesToggled()));
Chris@144 925 connect(this, SIGNAL(canPlay(bool)), m_playNotes, SLOT(setEnabled(bool)));
justin@156 926 */
justin@156 927
justin@156 928 // Audio
justin@156 929 QLabel *icon_audio = new QLabel;
justin@156 930 icon_audio->setFixedWidth(40);
justin@156 931 icon_audio->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
justin@156 932 icon_audio->setPixmap(il.loadPixmap("waveform"));
justin@156 933 toolbar->addWidget(icon_audio);
justin@156 934
justin@156 935 m_showAudio = toolbar->addAction(il.load("eye"), tr("Show Audio"));
justin@156 936 m_showAudio->setCheckable(true);
justin@156 937 connect(m_showAudio, SIGNAL(triggered()), this, SLOT(showAudioToggled()));
justin@156 938 connect(this, SIGNAL(canPlay(bool)), m_showAudio, SLOT(setEnabled(bool)));
justin@156 939
justin@156 940 m_playAudio = toolbar->addAction(il.load("speaker"), tr("Play Audio"));
justin@156 941 m_playAudio->setCheckable(true);
justin@156 942 connect(m_playAudio, SIGNAL(triggered()), this, SLOT(playAudioToggled()));
justin@156 943 connect(this, SIGNAL(canPlay(bool)), m_playAudio, SLOT(setEnabled(bool)));
justin@156 944
justin@159 945 toolbar->addWidget(m_gainAudio);
justin@160 946 toolbar->addWidget(m_panAudio);
justin@159 947
justin@156 948 // Pitch (f0)
justin@156 949 QLabel *icon_pitch = new QLabel;
justin@156 950 icon_pitch->setFixedWidth(40);
justin@156 951 icon_pitch->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
justin@156 952 icon_pitch->setPixmap(il.loadPixmap("values"));
justin@156 953 toolbar->addWidget(icon_pitch);
justin@156 954
justin@156 955 m_showPitch = toolbar->addAction(il.load("eye"), tr("Show Pitch Track"));
justin@156 956 m_showPitch->setCheckable(true);
justin@156 957 connect(m_showPitch, SIGNAL(triggered()), this, SLOT(showPitchToggled()));
justin@156 958 connect(this, SIGNAL(canPlay(bool)), m_showPitch, SLOT(setEnabled(bool)));
justin@156 959
justin@156 960 m_playPitch = toolbar->addAction(il.load("speaker"), tr("Play Pitch Track"));
justin@156 961 m_playPitch->setCheckable(true);
justin@156 962 connect(m_playPitch, SIGNAL(triggered()), this, SLOT(playPitchToggled()));
justin@186 963 connect(this, SIGNAL(canPlay(bool)), m_playPitch, SLOT(setEnabled(bool))); // JTEST: this resets the enabled state of m_playPitch.
justin@156 964
Chris@158 965 toolbar->addWidget(m_gainPitch);
justin@160 966 toolbar->addWidget(m_panPitch);
justin@156 967
justin@156 968 // Notes
justin@156 969 QLabel *icon_notes = new QLabel;
justin@156 970 icon_notes->setFixedWidth(40);
justin@156 971 icon_notes->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
justin@156 972 icon_notes->setPixmap(il.loadPixmap("notes"));
justin@156 973 toolbar->addWidget(icon_notes);
justin@156 974
justin@156 975 m_showNotes = toolbar->addAction(il.load("eye"), tr("Show Notes"));
justin@156 976 m_showNotes->setCheckable(true);
justin@156 977 connect(m_showNotes, SIGNAL(triggered()), this, SLOT(showNotesToggled()));
justin@156 978 connect(this, SIGNAL(canPlay(bool)), m_showNotes, SLOT(setEnabled(bool)));
justin@156 979
justin@156 980 m_playNotes = toolbar->addAction(il.load("speaker"), tr("Play Notes"));
justin@156 981 m_playNotes->setCheckable(true);
justin@156 982 connect(m_playNotes, SIGNAL(triggered()), this, SLOT(playNotesToggled()));
justin@156 983 connect(this, SIGNAL(canPlay(bool)), m_playNotes, SLOT(setEnabled(bool)));
justin@156 984
justin@159 985 toolbar->addWidget(m_gainNotes);
justin@160 986 toolbar->addWidget(m_panNotes);
justin@159 987
justin@156 988 // Spectrogram
justin@156 989 QLabel *icon_spectrogram = new QLabel;
justin@156 990 icon_spectrogram->setFixedWidth(40);
justin@156 991 icon_spectrogram->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
justin@156 992 icon_spectrogram->setPixmap(il.loadPixmap("spectrogram"));
justin@156 993 toolbar->addWidget(icon_spectrogram);
justin@156 994
justin@156 995 m_showSpect = toolbar->addAction(il.load("eye"), tr("Show Spectrogram"));
justin@156 996 m_showSpect->setCheckable(true);
justin@156 997 connect(m_showSpect, SIGNAL(triggered()), this, SLOT(showSpectToggled()));
justin@156 998 connect(this, SIGNAL(canPlay(bool)), m_showSpect, SLOT(setEnabled(bool)));
Chris@128 999
Chris@0 1000 Pane::registerShortcuts(*m_keyReference);
Chris@0 1001 }
Chris@0 1002
Chris@0 1003 void
Chris@70 1004 MainWindow::toolNavigateSelected()
Chris@70 1005 {
Chris@70 1006 m_viewManager->setToolMode(ViewManager::NavigateMode);
Chris@70 1007 m_intelligentActionOn = true;
Chris@70 1008 }
Chris@70 1009
Chris@70 1010 void
Chris@70 1011 MainWindow::toolEditSelected()
Chris@70 1012 {
Chris@77 1013 m_viewManager->setToolMode(ViewManager::NoteEditMode);
Chris@70 1014 m_intelligentActionOn = true;
Chris@70 1015 m_analyser->setIntelligentActions(m_intelligentActionOn);
Chris@70 1016 }
Chris@70 1017
Chris@70 1018 void
Chris@70 1019 MainWindow::toolFreeEditSelected()
Chris@70 1020 {
Chris@77 1021 m_viewManager->setToolMode(ViewManager::NoteEditMode);
Chris@70 1022 m_intelligentActionOn = false;
Chris@70 1023 m_analyser->setIntelligentActions(m_intelligentActionOn);
Chris@70 1024 }
Chris@70 1025
gyorgyf@21 1026 void
Chris@0 1027 MainWindow::updateMenuStates()
Chris@0 1028 {
Chris@0 1029 MainWindowBase::updateMenuStates();
Chris@0 1030
Chris@0 1031 Pane *currentPane = 0;
Chris@0 1032 Layer *currentLayer = 0;
Chris@0 1033
Chris@0 1034 if (m_paneStack) currentPane = m_paneStack->getCurrentPane();
Chris@0 1035 if (currentPane) currentLayer = currentPane->getSelectedLayer();
Chris@0 1036
Chris@0 1037 bool haveCurrentPane =
Chris@0 1038 (currentPane != 0);
Chris@0 1039 bool haveCurrentLayer =
Chris@0 1040 (haveCurrentPane &&
Chris@0 1041 (currentLayer != 0));
Chris@0 1042 bool haveSelection =
Chris@187 1043 (m_viewManager &&
Chris@187 1044 !m_viewManager->getSelections().empty());
Chris@0 1045 bool haveCurrentEditableLayer =
Chris@187 1046 (haveCurrentLayer &&
Chris@187 1047 currentLayer->isLayerEditable());
Chris@0 1048 bool haveCurrentTimeInstantsLayer =
Chris@187 1049 (haveCurrentLayer &&
Chris@187 1050 qobject_cast<TimeInstantLayer *>(currentLayer));
Chris@0 1051 bool haveCurrentTimeValueLayer =
Chris@187 1052 (haveCurrentLayer &&
Chris@187 1053 qobject_cast<TimeValueLayer *>(currentLayer));
Chris@187 1054 bool pitchCandidatesVisible =
Chris@187 1055 m_analyser->arePitchCandidatesShown();
Chris@0 1056
Chris@0 1057 emit canChangePlaybackSpeed(true);
Chris@0 1058 int v = m_playSpeed->value();
Chris@0 1059 emit canSpeedUpPlayback(v < m_playSpeed->maximum());
Chris@0 1060 emit canSlowDownPlayback(v > m_playSpeed->minimum());
Chris@0 1061
Chris@187 1062 emit canChangePitchCandidate(pitchCandidatesVisible && haveSelection);
Chris@187 1063
Chris@187 1064 if (pitchCandidatesVisible) {
Chris@187 1065 m_showCandidatesAction->setText(tr("Hide Pitch Candidates"));
Chris@187 1066 m_showCandidatesAction->setStatusTip(tr("Remove the display of alternate pitch candidates for the selected region"));
Chris@187 1067 } else {
Chris@187 1068 m_showCandidatesAction->setText(tr("Show Pitch Candidates"));
Chris@187 1069 m_showCandidatesAction->setStatusTip(tr("Show alternate pitch candidates for the selected region"));
Chris@187 1070 }
Chris@187 1071
Chris@0 1072 if (m_ffwdAction && m_rwdAction) {
Chris@0 1073 if (haveCurrentTimeInstantsLayer) {
Chris@0 1074 m_ffwdAction->setText(tr("Fast Forward to Next Instant"));
Chris@0 1075 m_ffwdAction->setStatusTip(tr("Fast forward to the next time instant in the current layer"));
Chris@0 1076 m_rwdAction->setText(tr("Rewind to Previous Instant"));
Chris@0 1077 m_rwdAction->setStatusTip(tr("Rewind to the previous time instant in the current layer"));
Chris@0 1078 } else if (haveCurrentTimeValueLayer) {
Chris@0 1079 m_ffwdAction->setText(tr("Fast Forward to Next Point"));
Chris@0 1080 m_ffwdAction->setStatusTip(tr("Fast forward to the next point in the current layer"));
Chris@0 1081 m_rwdAction->setText(tr("Rewind to Previous Point"));
Chris@0 1082 m_rwdAction->setStatusTip(tr("Rewind to the previous point in the current layer"));
Chris@0 1083 } else {
Chris@0 1084 m_ffwdAction->setText(tr("Fast Forward"));
Chris@0 1085 m_ffwdAction->setStatusTip(tr("Fast forward"));
Chris@0 1086 m_rwdAction->setText(tr("Rewind"));
Chris@0 1087 m_rwdAction->setStatusTip(tr("Rewind"));
Chris@0 1088 }
Chris@0 1089 }
Chris@0 1090 }
Chris@0 1091
Chris@0 1092 void
Chris@144 1093 MainWindow::showAudioToggled()
Chris@128 1094 {
Chris@144 1095 m_analyser->toggleVisible(Analyser::Audio);
Chris@128 1096 }
Chris@128 1097
Chris@128 1098 void
Chris@144 1099 MainWindow::showPitchToggled()
Chris@128 1100 {
Chris@144 1101 m_analyser->toggleVisible(Analyser::PitchTrack);
justin@185 1102
justin@186 1103 // JTEST
justin@185 1104 if (!m_analyser->isVisible(Analyser::PitchTrack))
justin@185 1105 {
justin@185 1106 m_analyser->setAudible(Analyser::PitchTrack,false);
justin@185 1107 m_playPitch->setChecked(false);
justin@185 1108 m_playPitch->setEnabled(false);
justin@185 1109 }
justin@185 1110 else
justin@185 1111 {
justin@185 1112 m_playPitch->setEnabled(true);
justin@185 1113 }
Chris@128 1114 }
Chris@128 1115
Chris@128 1116 void
Chris@145 1117 MainWindow::showSpectToggled()
Chris@145 1118 {
Chris@145 1119 m_analyser->toggleVisible(Analyser::Spectrogram);
Chris@145 1120 }
Chris@145 1121
Chris@145 1122 void
Chris@144 1123 MainWindow::showNotesToggled()
Chris@128 1124 {
Chris@144 1125 m_analyser->toggleVisible(Analyser::Notes);
Chris@144 1126 }
Chris@144 1127
Chris@144 1128 void
Chris@144 1129 MainWindow::playAudioToggled()
Chris@144 1130 {
Chris@144 1131 m_analyser->toggleAudible(Analyser::Audio);
Chris@144 1132 }
Chris@144 1133
Chris@144 1134 void
Chris@144 1135 MainWindow::playPitchToggled()
Chris@144 1136 {
Chris@144 1137 m_analyser->toggleAudible(Analyser::PitchTrack);
Chris@144 1138 }
Chris@144 1139
Chris@144 1140 void
Chris@144 1141 MainWindow::playNotesToggled()
Chris@144 1142 {
Chris@144 1143 m_analyser->toggleAudible(Analyser::Notes);
Chris@144 1144 }
Chris@144 1145
Chris@144 1146 void
Chris@144 1147 MainWindow::updateLayerStatuses()
Chris@144 1148 {
Chris@144 1149 m_showAudio->setChecked(m_analyser->isVisible(Analyser::Audio));
Chris@145 1150 m_showSpect->setChecked(m_analyser->isVisible(Analyser::Spectrogram));
Chris@144 1151 m_showPitch->setChecked(m_analyser->isVisible(Analyser::PitchTrack));
Chris@144 1152 m_showNotes->setChecked(m_analyser->isVisible(Analyser::Notes));
Chris@144 1153 m_playAudio->setChecked(m_analyser->isAudible(Analyser::Audio));
Chris@144 1154 m_playPitch->setChecked(m_analyser->isAudible(Analyser::PitchTrack));
Chris@144 1155 m_playNotes->setChecked(m_analyser->isAudible(Analyser::Notes));
Chris@128 1156 }
Chris@128 1157
Chris@128 1158 void
Chris@0 1159 MainWindow::updateDescriptionLabel()
Chris@0 1160 {
Chris@6 1161 // Nothing, we don't have one
Chris@0 1162 }
Chris@0 1163
Chris@0 1164 void
Chris@0 1165 MainWindow::documentModified()
Chris@0 1166 {
Chris@0 1167 MainWindowBase::documentModified();
Chris@0 1168 }
Chris@0 1169
Chris@0 1170 void
Chris@0 1171 MainWindow::documentRestored()
Chris@0 1172 {
Chris@0 1173 MainWindowBase::documentRestored();
Chris@0 1174 }
Chris@0 1175
Chris@0 1176 void
Chris@0 1177 MainWindow::newSession()
Chris@0 1178 {
Chris@0 1179 if (!checkSaveModified()) return;
Chris@0 1180
Chris@0 1181 closeSession();
Chris@0 1182 createDocument();
Chris@0 1183 m_document->setAutoAlignment(true);
Chris@0 1184
Chris@0 1185 Pane *pane = m_paneStack->addPane();
Chris@0 1186
Chris@0 1187 connect(pane, SIGNAL(contextHelpChanged(const QString &)),
Chris@0 1188 this, SLOT(contextHelpChanged(const QString &)));
Chris@0 1189
Chris@6 1190 // Layer *waveform = m_document->createMainModelLayer(LayerFactory::Waveform);
Chris@6 1191 // m_document->addLayerToView(pane, waveform);
Chris@0 1192
Chris@0 1193 m_overview->registerView(pane);
Chris@0 1194
Chris@0 1195 CommandHistory::getInstance()->clear();
Chris@0 1196 CommandHistory::getInstance()->documentSaved();
Chris@0 1197 documentRestored();
Chris@0 1198 updateMenuStates();
Chris@0 1199 }
Chris@0 1200
Chris@0 1201 void
Chris@0 1202 MainWindow::closeSession()
Chris@0 1203 {
Chris@0 1204 if (!checkSaveModified()) return;
Chris@0 1205
Chris@0 1206 while (m_paneStack->getPaneCount() > 0) {
Chris@0 1207
Chris@167 1208 Pane *pane = m_paneStack->getPane(m_paneStack->getPaneCount() - 1);
Chris@0 1209
Chris@167 1210 while (pane->getLayerCount() > 0) {
Chris@167 1211 m_document->removeLayerFromView
Chris@167 1212 (pane, pane->getLayer(pane->getLayerCount() - 1));
Chris@167 1213 }
Chris@167 1214
Chris@167 1215 m_overview->unregisterView(pane);
Chris@167 1216 m_paneStack->deletePane(pane);
Chris@0 1217 }
Chris@0 1218
Chris@0 1219 while (m_paneStack->getHiddenPaneCount() > 0) {
Chris@0 1220
Chris@167 1221 Pane *pane = m_paneStack->getHiddenPane
Chris@167 1222 (m_paneStack->getHiddenPaneCount() - 1);
Chris@167 1223
Chris@167 1224 while (pane->getLayerCount() > 0) {
Chris@167 1225 m_document->removeLayerFromView
Chris@167 1226 (pane, pane->getLayer(pane->getLayerCount() - 1));
Chris@167 1227 }
Chris@167 1228
Chris@167 1229 m_overview->unregisterView(pane);
Chris@167 1230 m_paneStack->deletePane(pane);
Chris@0 1231 }
Chris@0 1232
Chris@0 1233 delete m_document;
Chris@0 1234 m_document = 0;
Chris@0 1235 m_viewManager->clearSelections();
Chris@0 1236 m_timeRulerLayer = 0; // document owned this
Chris@0 1237
Chris@0 1238 m_sessionFile = "";
Chris@0 1239
Chris@0 1240 CommandHistory::getInstance()->clear();
Chris@0 1241 CommandHistory::getInstance()->documentSaved();
Chris@0 1242 documentRestored();
Chris@0 1243 }
Chris@0 1244
Chris@0 1245 void
Chris@0 1246 MainWindow::openFile()
Chris@0 1247 {
Chris@0 1248 QString orig = m_audioFile;
Chris@0 1249 if (orig == "") orig = ".";
Chris@0 1250 else orig = QFileInfo(orig).absoluteDir().canonicalPath();
Chris@0 1251
Chris@0 1252 QString path = getOpenFileName(FileFinder::AnyFile);
Chris@0 1253
Chris@0 1254 if (path.isEmpty()) return;
Chris@0 1255
Chris@1 1256 FileOpenStatus status = open(path, ReplaceSession);
Chris@0 1257
Chris@0 1258 if (status == FileOpenFailed) {
Chris@0 1259 QMessageBox::critical(this, tr("Failed to open file"),
Chris@0 1260 tr("<b>File open failed</b><p>File \"%1\" could not be opened").arg(path));
Chris@0 1261 } else if (status == FileOpenWrongMode) {
Chris@0 1262 QMessageBox::critical(this, tr("Failed to open file"),
Chris@0 1263 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
Chris@0 1264 }
Chris@0 1265 }
Chris@0 1266
Chris@0 1267 void
Chris@0 1268 MainWindow::openLocation()
Chris@0 1269 {
Chris@0 1270 QSettings settings;
Chris@0 1271 settings.beginGroup("MainWindow");
Chris@0 1272 QString lastLocation = settings.value("lastremote", "").toString();
Chris@0 1273
Chris@0 1274 bool ok = false;
Chris@0 1275 QString text = QInputDialog::getText
Chris@0 1276 (this, tr("Open Location"),
Chris@0 1277 tr("Please enter the URL of the location to open:"),
Chris@0 1278 QLineEdit::Normal, lastLocation, &ok);
Chris@0 1279
Chris@0 1280 if (!ok) return;
Chris@0 1281
Chris@0 1282 settings.setValue("lastremote", text);
Chris@0 1283
Chris@0 1284 if (text.isEmpty()) return;
Chris@0 1285
Chris@1 1286 FileOpenStatus status = open(text, ReplaceSession);
Chris@0 1287
Chris@0 1288 if (status == FileOpenFailed) {
Chris@0 1289 QMessageBox::critical(this, tr("Failed to open location"),
Chris@0 1290 tr("<b>Open failed</b><p>URL \"%1\" could not be opened").arg(text));
Chris@0 1291 } else if (status == FileOpenWrongMode) {
Chris@0 1292 QMessageBox::critical(this, tr("Failed to open location"),
Chris@0 1293 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
Chris@0 1294 }
Chris@0 1295 }
Chris@0 1296
Chris@0 1297 void
Chris@0 1298 MainWindow::openRecentFile()
Chris@0 1299 {
Chris@0 1300 QObject *obj = sender();
Chris@3 1301 QAction *action = qobject_cast<QAction *>(obj);
Chris@0 1302
Chris@0 1303 if (!action) {
Chris@188 1304 cerr << "WARNING: MainWindow::openRecentFile: sender is not an action"
Chris@188 1305 << endl;
Chris@188 1306 return;
Chris@0 1307 }
Chris@0 1308
Chris@0 1309 QString path = action->text();
Chris@0 1310 if (path == "") return;
Chris@0 1311
Chris@1 1312 FileOpenStatus status = open(path, ReplaceSession);
Chris@0 1313
Chris@0 1314 if (status == FileOpenFailed) {
Chris@0 1315 QMessageBox::critical(this, tr("Failed to open location"),
Chris@0 1316 tr("<b>Open failed</b><p>File or URL \"%1\" could not be opened").arg(path));
Chris@0 1317 } else if (status == FileOpenWrongMode) {
Chris@0 1318 QMessageBox::critical(this, tr("Failed to open location"),
Chris@0 1319 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
Chris@0 1320 }
Chris@0 1321 }
Chris@0 1322
Chris@0 1323 void
Chris@0 1324 MainWindow::paneAdded(Pane *pane)
Chris@0 1325 {
Chris@6 1326 pane->setPlaybackFollow(PlaybackScrollPage);
Chris@0 1327 m_paneStack->sizePanesEqually();
Chris@0 1328 if (m_overview) m_overview->registerView(pane);
Chris@0 1329 }
Chris@0 1330
Chris@0 1331 void
Chris@0 1332 MainWindow::paneHidden(Pane *pane)
Chris@0 1333 {
Chris@0 1334 if (m_overview) m_overview->unregisterView(pane);
Chris@0 1335 }
Chris@0 1336
Chris@0 1337 void
Chris@0 1338 MainWindow::paneAboutToBeDeleted(Pane *pane)
Chris@0 1339 {
Chris@0 1340 if (m_overview) m_overview->unregisterView(pane);
Chris@0 1341 }
Chris@0 1342
Chris@0 1343 void
Chris@0 1344 MainWindow::paneDropAccepted(Pane *pane, QStringList uriList)
Chris@0 1345 {
Chris@4 1346 if (pane) m_paneStack->setCurrentPane(pane);
Chris@0 1347
Chris@0 1348 for (QStringList::iterator i = uriList.begin(); i != uriList.end(); ++i) {
Chris@0 1349
Chris@1 1350 FileOpenStatus status = open(*i, ReplaceSession);
Chris@0 1351
Chris@0 1352 if (status == FileOpenFailed) {
Chris@0 1353 QMessageBox::critical(this, tr("Failed to open dropped URL"),
Chris@0 1354 tr("<b>Open failed</b><p>Dropped URL \"%1\" could not be opened").arg(*i));
Chris@0 1355 } else if (status == FileOpenWrongMode) {
Chris@0 1356 QMessageBox::critical(this, tr("Failed to open dropped URL"),
Chris@0 1357 tr("<b>Audio required</b><p>Please load at least one audio file before importing annotation data"));
Chris@0 1358 }
Chris@0 1359 }
Chris@0 1360 }
Chris@0 1361
Chris@0 1362 void
Chris@0 1363 MainWindow::paneDropAccepted(Pane *pane, QString text)
Chris@0 1364 {
Chris@0 1365 if (pane) m_paneStack->setCurrentPane(pane);
Chris@0 1366
Chris@0 1367 QUrl testUrl(text);
Chris@0 1368 if (testUrl.scheme() == "file" ||
Chris@0 1369 testUrl.scheme() == "http" ||
Chris@0 1370 testUrl.scheme() == "ftp") {
Chris@0 1371 QStringList list;
Chris@0 1372 list.push_back(text);
Chris@0 1373 paneDropAccepted(pane, list);
Chris@0 1374 return;
Chris@0 1375 }
Chris@0 1376
Chris@0 1377 //!!! open as text -- but by importing as if a CSV, or just adding
Chris@0 1378 //to a text layer?
Chris@0 1379 }
Chris@0 1380
Chris@0 1381 void
Chris@0 1382 MainWindow::closeEvent(QCloseEvent *e)
Chris@0 1383 {
Chris@70 1384 // cerr << "MainWindow::closeEvent" << endl;
Chris@0 1385
Chris@0 1386 if (m_openingAudioFile) {
Chris@70 1387 // cerr << "Busy - ignoring close event" << endl;
gyorgyf@27 1388 e->ignore();
gyorgyf@27 1389 return;
Chris@0 1390 }
Chris@0 1391
Chris@0 1392 if (!m_abandoning && !checkSaveModified()) {
Chris@70 1393 // cerr << "Ignoring close event" << endl;
gyorgyf@27 1394 e->ignore();
gyorgyf@27 1395 return;
Chris@0 1396 }
Chris@0 1397
Chris@0 1398 QSettings settings;
Chris@0 1399 settings.beginGroup("MainWindow");
Chris@0 1400 settings.setValue("size", size());
Chris@0 1401 settings.setValue("position", pos());
Chris@0 1402 settings.endGroup();
Chris@0 1403
Chris@0 1404 delete m_keyReference;
Chris@0 1405 m_keyReference = 0;
Chris@0 1406
Chris@0 1407 closeSession();
Chris@0 1408
Chris@0 1409 e->accept();
Chris@0 1410 return;
Chris@0 1411 }
Chris@0 1412
Chris@0 1413 bool
Chris@0 1414 MainWindow::commitData(bool mayAskUser)
Chris@0 1415 {
Chris@0 1416 if (mayAskUser) {
Chris@0 1417 bool rv = checkSaveModified();
Chris@0 1418 return rv;
Chris@0 1419 } else {
Chris@0 1420 if (!m_documentModified) return true;
Chris@0 1421
Chris@0 1422 // If we can't check with the user first, then we can't save
Chris@0 1423 // to the original session file (even if we have it) -- have
Chris@0 1424 // to use a temporary file
Chris@0 1425
Chris@0 1426 QString svDirBase = ".sv1";
Chris@0 1427 QString svDir = QDir::home().filePath(svDirBase);
Chris@0 1428
Chris@0 1429 if (!QFileInfo(svDir).exists()) {
Chris@0 1430 if (!QDir::home().mkdir(svDirBase)) return false;
Chris@0 1431 } else {
Chris@0 1432 if (!QFileInfo(svDir).isDir()) return false;
Chris@0 1433 }
Chris@0 1434
Chris@0 1435 // This name doesn't have to be unguessable
Chris@0 1436 #ifndef _WIN32
Chris@0 1437 QString fname = QString("tmp-%1-%2.sv")
Chris@0 1438 .arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"))
Chris@0 1439 .arg(QProcess().pid());
Chris@0 1440 #else
Chris@0 1441 QString fname = QString("tmp-%1.sv")
Chris@0 1442 .arg(QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"));
Chris@0 1443 #endif
Chris@0 1444 QString fpath = QDir(svDir).filePath(fname);
Chris@0 1445 if (saveSessionFile(fpath)) {
Chris@0 1446 m_recentFiles.addFile(fpath);
Chris@0 1447 return true;
Chris@0 1448 } else {
Chris@0 1449 return false;
Chris@0 1450 }
Chris@0 1451 }
Chris@0 1452 }
Chris@0 1453
Chris@0 1454 bool
Chris@0 1455 MainWindow::checkSaveModified()
Chris@0 1456 {
Chris@0 1457 // Called before some destructive operation (e.g. new session,
Chris@0 1458 // exit program). Return true if we can safely proceed, false to
Chris@0 1459 // cancel.
Chris@0 1460
Chris@0 1461 if (!m_documentModified) return true;
Chris@0 1462
Chris@0 1463 int button =
gyorgyf@27 1464 QMessageBox::warning(this,
gyorgyf@27 1465 tr("Session modified"),
gyorgyf@27 1466 tr("The current session has been modified.\nDo you want to save it?"),
gyorgyf@27 1467 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
Chris@0 1468 QMessageBox::Yes);
Chris@0 1469
Chris@0 1470 if (button == QMessageBox::Yes) {
gyorgyf@27 1471 saveSession();
gyorgyf@27 1472 if (m_documentModified) { // save failed -- don't proceed!
gyorgyf@27 1473 return false;
gyorgyf@27 1474 } else {
Chris@0 1475 return true; // saved, so it's safe to continue now
Chris@0 1476 }
Chris@0 1477 } else if (button == QMessageBox::No) {
gyorgyf@27 1478 m_documentModified = false; // so we know to abandon it
gyorgyf@27 1479 return true;
Chris@0 1480 }
Chris@0 1481
Chris@0 1482 // else cancel
Chris@0 1483 return false;
Chris@0 1484 }
Chris@0 1485
Chris@0 1486 void
Chris@0 1487 MainWindow::saveSession()
Chris@0 1488 {
Chris@0 1489 if (m_sessionFile != "") {
gyorgyf@27 1490 if (!saveSessionFile(m_sessionFile)) {
gyorgyf@27 1491 QMessageBox::critical(this, tr("Failed to save file"),
gyorgyf@27 1492 tr("Session file \"%1\" could not be saved.").arg(m_sessionFile));
Chris@0 1493 } else {
gyorgyf@27 1494 CommandHistory::getInstance()->documentSaved();
gyorgyf@27 1495 documentRestored();
gyorgyf@27 1496 }
gyorgyf@27 1497 } else {
gyorgyf@27 1498 saveSessionAs();
Chris@0 1499 }
Chris@0 1500 }
Chris@0 1501
Chris@0 1502 void
Chris@0 1503 MainWindow::saveSessionAs()
Chris@0 1504 {
Chris@0 1505 QString orig = m_audioFile;
Chris@0 1506 if (orig == "") orig = ".";
Chris@0 1507 else orig = QFileInfo(orig).absoluteDir().canonicalPath();
Chris@0 1508
Chris@0 1509 QString path = getSaveFileName(FileFinder::SessionFile);
Chris@0 1510
Chris@0 1511 if (path == "") return;
Chris@0 1512
Chris@0 1513 if (!saveSessionFile(path)) {
Chris@85 1514 QMessageBox::critical(this, tr("Failed to save file"),
Chris@85 1515 tr("Session file \"%1\" could not be saved.").arg(path));
Chris@0 1516 } else {
Chris@85 1517 setWindowTitle(tr("%1: %2")
Chris@0 1518 .arg(QApplication::applicationName())
Chris@85 1519 .arg(QFileInfo(path).fileName()));
Chris@85 1520 m_sessionFile = path;
Chris@85 1521 CommandHistory::getInstance()->documentSaved();
Chris@85 1522 documentRestored();
Chris@0 1523 m_recentFiles.addFile(path);
Chris@0 1524 }
Chris@0 1525 }
Chris@0 1526
Chris@85 1527 QString
Chris@85 1528 MainWindow::exportToSVL(QString path, Layer *layer)
Chris@85 1529 {
Chris@85 1530 Model *model = layer->getModel();
Chris@85 1531
Chris@85 1532 QFile file(path);
Chris@85 1533 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
Chris@85 1534 return tr("Failed to open file %1 for writing").arg(path);
Chris@85 1535 } else {
Chris@85 1536 QTextStream out(&file);
Chris@85 1537 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
Chris@85 1538 << "<!DOCTYPE sonic-visualiser>\n"
Chris@85 1539 << "<sv>\n"
Chris@85 1540 << " <data>\n";
Chris@85 1541
Chris@85 1542 model->toXml(out, " ");
Chris@85 1543
Chris@85 1544 out << " </data>\n"
Chris@85 1545 << " <display>\n";
Chris@85 1546
Chris@85 1547 layer->toXml(out, " ");
Chris@85 1548
Chris@85 1549 out << " </display>\n"
Chris@85 1550 << "</sv>\n";
Chris@85 1551
Chris@85 1552 return "";
Chris@85 1553 }
Chris@85 1554 }
Chris@85 1555
Chris@0 1556 void
Chris@174 1557 MainWindow::importPitchLayer()
Chris@174 1558 {
Chris@174 1559 QString path = getOpenFileName(FileFinder::LayerFileNoMidiNonSV);
Chris@174 1560 if (path == "") return;
Chris@174 1561
Chris@174 1562 FileOpenStatus status = importPitchLayer(path);
Chris@174 1563
Chris@174 1564 if (status == FileOpenFailed) {
Chris@174 1565 emit hideSplash();
Chris@174 1566 QMessageBox::critical(this, tr("Failed to open file"),
Chris@174 1567 tr("<b>File open failed</b><p>Layer file %1 could not be opened.").arg(path));
Chris@174 1568 return;
Chris@174 1569 } else if (status == FileOpenWrongMode) {
Chris@174 1570 emit hideSplash();
Chris@174 1571 QMessageBox::critical(this, tr("Failed to open file"),
Chris@174 1572 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 1573 }
Chris@174 1574 }
Chris@174 1575
Chris@174 1576 MainWindow::FileOpenStatus
Chris@174 1577 MainWindow::importPitchLayer(FileSource source)
Chris@174 1578 {
Chris@174 1579 if (!source.isAvailable()) return FileOpenFailed;
Chris@174 1580 source.waitForData();
Chris@174 1581
Chris@174 1582 QString path = source.getLocalFilename();
Chris@174 1583
Chris@174 1584 RDFImporter::RDFDocumentType rdfType =
Chris@174 1585 RDFImporter::identifyDocumentType(QUrl::fromLocalFile(path).toString());
Chris@174 1586
Chris@174 1587 if (rdfType != RDFImporter::NotRDF) {
Chris@174 1588
Chris@174 1589 //!!!
Chris@174 1590 return FileOpenFailed;
Chris@174 1591
Chris@174 1592 } else if (source.getExtension().toLower() == "svl" ||
Chris@174 1593 (source.getExtension().toLower() == "xml" &&
Chris@174 1594 (SVFileReader::identifyXmlFile(source.getLocalFilename())
Chris@174 1595 == SVFileReader::SVLayerFile))) {
Chris@174 1596
Chris@174 1597 //!!!
Chris@174 1598 return FileOpenFailed;
Chris@174 1599
Chris@174 1600 } else {
Chris@174 1601
Chris@174 1602 try {
Chris@174 1603
Chris@174 1604 CSVFormat format(path);
Chris@174 1605 format.setSampleRate(getMainModel()->getSampleRate());
Chris@174 1606
Chris@174 1607 if (format.getModelType() != CSVFormat::TwoDimensionalModel) {
Chris@174 1608 //!!! error report
Chris@174 1609 return FileOpenFailed;
Chris@174 1610 }
Chris@174 1611
Chris@174 1612 Model *model = DataFileReaderFactory::loadCSV
Chris@174 1613 (path, format, getMainModel()->getSampleRate());
Chris@174 1614
Chris@174 1615 if (model) {
Chris@174 1616
Chris@174 1617 SVDEBUG << "MainWindow::importPitchLayer: Have model" << endl;
Chris@174 1618
Chris@174 1619 CommandHistory::getInstance()->startCompoundOperation
Chris@174 1620 (tr("Import Pitch Track"), true);
Chris@174 1621
Chris@174 1622 Layer *newLayer = m_document->createImportedLayer(model);
Chris@174 1623
Chris@174 1624 m_analyser->takePitchTrackFrom(newLayer);
Chris@174 1625
Chris@174 1626 m_document->deleteLayer(newLayer);
Chris@174 1627
Chris@174 1628 CommandHistory::getInstance()->endCompoundOperation();
Chris@174 1629
Chris@174 1630 //!!! swap all data in to existing layer instead of this
Chris@174 1631
Chris@174 1632 if (!source.isRemote()) {
Chris@174 1633 registerLastOpenedFilePath
Chris@174 1634 (FileFinder::LayerFile,
Chris@174 1635 path); // for file dialog
Chris@174 1636 }
Chris@174 1637
Chris@174 1638 return FileOpenSucceeded;
Chris@174 1639 }
Chris@174 1640 } catch (DataFileReaderFactory::Exception e) {
Chris@174 1641 if (e == DataFileReaderFactory::ImportCancelled) {
Chris@174 1642 return FileOpenCancelled;
Chris@174 1643 }
Chris@174 1644 }
Chris@174 1645 }
Chris@174 1646
Chris@174 1647 return FileOpenFailed;
Chris@174 1648 }
Chris@174 1649
Chris@174 1650 void
Chris@85 1651 MainWindow::exportPitchLayer()
matthiasm@26 1652 {
Chris@174 1653 Layer *layer = m_analyser->getLayer(Analyser::PitchTrack);
matthiasm@26 1654 if (!layer) return;
matthiasm@26 1655
Chris@85 1656 SparseTimeValueModel *model =
Chris@85 1657 qobject_cast<SparseTimeValueModel *>(layer->getModel());
matthiasm@26 1658 if (!model) return;
matthiasm@26 1659
Chris@96 1660 FileFinder::FileType type = FileFinder::LayerFileNoMidiNonSV;
matthiasm@26 1661
matthiasm@26 1662 QString path = getSaveFileName(type);
matthiasm@26 1663
matthiasm@26 1664 if (path == "") return;
matthiasm@26 1665
matthiasm@26 1666 if (QFileInfo(path).suffix() == "") path += ".svl";
matthiasm@26 1667
matthiasm@26 1668 QString suffix = QFileInfo(path).suffix().toLower();
matthiasm@26 1669
matthiasm@26 1670 QString error;
matthiasm@26 1671
matthiasm@26 1672 if (suffix == "xml" || suffix == "svl") {
matthiasm@26 1673
Chris@85 1674 error = exportToSVL(path, layer);
matthiasm@26 1675
matthiasm@26 1676 } else if (suffix == "ttl" || suffix == "n3") {
matthiasm@26 1677
Chris@85 1678 RDFExporter exporter(path, model);
Chris@85 1679 exporter.write();
Chris@85 1680 if (!exporter.isOK()) {
Chris@85 1681 error = exporter.getError();
Chris@85 1682 }
Chris@85 1683
Chris@85 1684 } else {
Chris@85 1685
Chris@85 1686 CSVFileWriter writer(path, model,
Chris@85 1687 ((suffix == "csv") ? "," : "\t"));
Chris@85 1688 writer.write();
Chris@85 1689
Chris@85 1690 if (!writer.isOK()) {
Chris@85 1691 error = writer.getError();
Chris@85 1692 }
Chris@85 1693 }
Chris@85 1694
Chris@85 1695 if (error != "") {
Chris@85 1696 QMessageBox::critical(this, tr("Failed to write file"), error);
Chris@85 1697 } else {
Chris@85 1698 emit activity(tr("Export layer to \"%1\"").arg(path));
Chris@85 1699 }
Chris@85 1700 }
Chris@85 1701
Chris@85 1702 void
Chris@85 1703 MainWindow::exportNoteLayer()
Chris@85 1704 {
Chris@174 1705 Layer *layer = m_analyser->getLayer(Analyser::Notes);
Chris@85 1706 if (!layer) return;
Chris@85 1707
Chris@85 1708 FlexiNoteModel *model = qobject_cast<FlexiNoteModel *>(layer->getModel());
Chris@85 1709 if (!model) return;
Chris@85 1710
Chris@96 1711 FileFinder::FileType type = FileFinder::LayerFileNonSV;
Chris@85 1712
Chris@85 1713 QString path = getSaveFileName(type);
Chris@85 1714
Chris@85 1715 if (path == "") return;
Chris@85 1716
Chris@85 1717 if (QFileInfo(path).suffix() == "") path += ".svl";
Chris@85 1718
Chris@85 1719 QString suffix = QFileInfo(path).suffix().toLower();
Chris@85 1720
Chris@85 1721 QString error;
Chris@85 1722
Chris@85 1723 if (suffix == "xml" || suffix == "svl") {
Chris@85 1724
Chris@85 1725 error = exportToSVL(path, layer);
Chris@85 1726
Chris@85 1727 } else if (suffix == "mid" || suffix == "midi") {
Chris@85 1728
Chris@85 1729 MIDIFileWriter writer(path, model, model->getSampleRate());
Chris@85 1730 writer.write();
Chris@85 1731 if (!writer.isOK()) {
Chris@85 1732 error = writer.getError();
Chris@85 1733 }
Chris@85 1734
Chris@85 1735 } else if (suffix == "ttl" || suffix == "n3") {
Chris@85 1736
Chris@85 1737 RDFExporter exporter(path, model);
Chris@85 1738 exporter.write();
Chris@85 1739 if (!exporter.isOK()) {
Chris@85 1740 error = exporter.getError();
matthiasm@26 1741 }
matthiasm@26 1742
matthiasm@26 1743 } else {
matthiasm@26 1744
matthiasm@26 1745 CSVFileWriter writer(path, model,
matthiasm@26 1746 ((suffix == "csv") ? "," : "\t"));
matthiasm@26 1747 writer.write();
matthiasm@26 1748
matthiasm@26 1749 if (!writer.isOK()) {
matthiasm@26 1750 error = writer.getError();
matthiasm@26 1751 }
matthiasm@26 1752 }
matthiasm@26 1753
matthiasm@26 1754 if (error != "") {
matthiasm@26 1755 QMessageBox::critical(this, tr("Failed to write file"), error);
matthiasm@26 1756 } else {
matthiasm@26 1757 emit activity(tr("Export layer to \"%1\"").arg(path));
matthiasm@26 1758 }
matthiasm@26 1759 }
matthiasm@26 1760
Chris@139 1761 void
Chris@139 1762 MainWindow::doubleClickSelectInvoked(size_t frame)
Chris@139 1763 {
Chris@139 1764 size_t f0, f1;
Chris@139 1765 m_analyser->getEnclosingSelectionScope(frame, f0, f1);
Chris@139 1766
Chris@139 1767 cerr << "MainWindow::doubleClickSelectInvoked(" << frame << "): [" << f0 << "," << f1 << "]" << endl;
Chris@139 1768
Chris@164 1769 Selection sel(f0, f1);
Chris@164 1770 m_viewManager->setSelection(sel);
Chris@164 1771 }
Chris@164 1772
Chris@164 1773 void
Chris@194 1774 MainWindow::abandonSelection()
Chris@167 1775 {
Chris@194 1776 // Named abandonSelection rather than clearSelection to indicate
Chris@194 1777 // that this is an active operation -- it restores the original
Chris@194 1778 // content of the pitch track in the selected region rather than
Chris@194 1779 // simply un-selecting.
Chris@194 1780
Chris@194 1781 cerr << "MainWindow::abandonSelection()" << endl;
Chris@167 1782
Chris@168 1783 CommandHistory::getInstance()->startCompoundOperation(tr("Clear Selection"), true);
Chris@168 1784
Chris@194 1785 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@194 1786 if (!selections.empty()) {
Chris@194 1787 Selection sel = *selections.begin();
Chris@194 1788 m_analyser->clearReAnalysis(sel);
Chris@194 1789 }
Chris@194 1790
Chris@167 1791 MainWindowBase::clearSelection();
Chris@168 1792
Chris@168 1793 CommandHistory::getInstance()->endCompoundOperation();
Chris@167 1794 }
Chris@167 1795
Chris@167 1796 void
Chris@192 1797 MainWindow::selectionChangedByUser()
Chris@164 1798 {
Chris@164 1799 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@164 1800
Chris@192 1801 cerr << "MainWindow::selectionChangedByUser" << endl;
Chris@192 1802
Chris@192 1803 m_analyser->showPitchCandidates(m_pendingConstraint.isConstrained());
Chris@190 1804
Chris@164 1805 if (!selections.empty()) {
Chris@164 1806 Selection sel = *selections.begin();
Chris@192 1807 cerr << "MainWindow::selectionChangedByUser: have selection" << endl;
Chris@192 1808 QString error = m_analyser->reAnalyseSelection
Chris@192 1809 (sel, m_pendingConstraint);
Chris@164 1810 if (error != "") {
Chris@164 1811 QMessageBox::critical
Chris@164 1812 (this, tr("Failed to analyse selection"),
Chris@164 1813 tr("<b>Analysis failed</b><p>%2</p>").arg(error));
Chris@164 1814 }
Chris@164 1815 }
Chris@192 1816
Chris@192 1817 m_pendingConstraint = Analyser::FrequencyRange();
Chris@192 1818 }
Chris@192 1819
Chris@192 1820 void
Chris@192 1821 MainWindow::regionOutlined(QRect r)
Chris@192 1822 {
Chris@192 1823 cerr << "MainWindow::regionOutlined(" << r.x() << "," << r.y() << "," << r.width() << "," << r.height() << ")" << endl;
Chris@192 1824
Chris@192 1825 Pane *pane = qobject_cast<Pane *>(sender());
Chris@192 1826 if (!pane) {
Chris@192 1827 cerr << "MainWindow::regionOutlined: not sent by pane, ignoring" << endl;
Chris@192 1828 return;
Chris@192 1829 }
Chris@192 1830
Chris@192 1831 if (!m_analyser) {
Chris@192 1832 cerr << "MainWindow::regionOutlined: no analyser, ignoring" << endl;
Chris@192 1833 return;
Chris@192 1834 }
Chris@192 1835
Chris@192 1836 SpectrogramLayer *spectrogram = qobject_cast<SpectrogramLayer *>
Chris@192 1837 (m_analyser->getLayer(Analyser::Spectrogram));
Chris@192 1838 if (!spectrogram) {
Chris@192 1839 cerr << "MainWindow::regionOutlined: no spectrogram layer, ignoring" << endl;
Chris@192 1840 return;
Chris@192 1841 }
Chris@192 1842
Chris@192 1843 int f0 = pane->getFrameForX(r.x());
Chris@192 1844 int f1 = pane->getFrameForX(r.x() + r.width());
Chris@192 1845
Chris@192 1846 float v0 = spectrogram->getFrequencyForY(pane, r.y() + r.height());
Chris@192 1847 float v1 = spectrogram->getFrequencyForY(pane, r.y());
Chris@192 1848
Chris@192 1849 cerr << "MainWindow::regionOutlined: frame " << f0 << " -> " << f1
Chris@192 1850 << ", frequency " << v0 << " -> " << v1 << endl;
Chris@192 1851
Chris@192 1852 m_pendingConstraint = Analyser::FrequencyRange(v0, v1);
Chris@192 1853
Chris@192 1854 Selection sel(f0, f1);
Chris@192 1855 m_viewManager->setSelection(sel);
Chris@0 1856 }
Chris@0 1857
Chris@0 1858 void
Chris@168 1859 MainWindow::clearPitches()
Chris@168 1860 {
Chris@168 1861 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@168 1862
Chris@168 1863 CommandHistory::getInstance()->startCompoundOperation(tr("Clear Pitches"), true);
Chris@168 1864
Chris@168 1865 for (MultiSelection::SelectionList::iterator k = selections.begin();
Chris@168 1866 k != selections.end(); ++k) {
Chris@184 1867 m_analyser->deletePitches(*k);
Chris@168 1868 }
Chris@168 1869
Chris@168 1870 CommandHistory::getInstance()->endCompoundOperation();
Chris@168 1871 }
Chris@168 1872
Chris@168 1873 void
Chris@142 1874 MainWindow::octaveShiftUp()
Chris@142 1875 {
Chris@142 1876 octaveShift(true);
Chris@142 1877 }
Chris@142 1878
Chris@142 1879 void
Chris@142 1880 MainWindow::octaveShiftDown()
Chris@142 1881 {
Chris@142 1882 octaveShift(false);
Chris@142 1883 }
Chris@142 1884
Chris@142 1885 void
Chris@142 1886 MainWindow::octaveShift(bool up)
Chris@142 1887 {
Chris@142 1888 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@142 1889
Chris@142 1890 CommandHistory::getInstance()->startCompoundOperation(tr("Octave Shift"), true);
Chris@142 1891
Chris@168 1892 for (MultiSelection::SelectionList::iterator k = selections.begin();
Chris@168 1893 k != selections.end(); ++k) {
Chris@142 1894
Chris@168 1895 m_analyser->shiftOctave(*k, up);
Chris@142 1896 }
Chris@142 1897
Chris@142 1898 CommandHistory::getInstance()->endCompoundOperation();
Chris@142 1899 }
Chris@142 1900
Chris@142 1901 void
Chris@184 1902 MainWindow::togglePitchCandidates()
Chris@184 1903 {
Chris@184 1904 m_analyser->showPitchCandidates(!m_analyser->arePitchCandidatesShown());
Chris@187 1905 updateMenuStates();
Chris@184 1906 }
Chris@184 1907
Chris@184 1908 void
Chris@184 1909 MainWindow::switchPitchUp()
Chris@167 1910 {
Chris@168 1911 CommandHistory::getInstance()->startCompoundOperation
Chris@168 1912 (tr("Switch Pitch Candidate"), true);
Chris@168 1913
Chris@167 1914 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@167 1915
Chris@167 1916 for (MultiSelection::SelectionList::iterator k = selections.begin();
Chris@167 1917 k != selections.end(); ++k) {
Chris@167 1918 m_analyser->switchPitchCandidate(*k, true);
Chris@167 1919 }
Chris@167 1920
Chris@168 1921 CommandHistory::getInstance()->endCompoundOperation();
Chris@167 1922 }
Chris@167 1923
Chris@167 1924 void
Chris@184 1925 MainWindow::switchPitchDown()
Chris@184 1926 {
Chris@184 1927 CommandHistory::getInstance()->startCompoundOperation
Chris@184 1928 (tr("Switch Pitch Candidate"), true);
Chris@184 1929
Chris@184 1930 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@184 1931
Chris@184 1932 for (MultiSelection::SelectionList::iterator k = selections.begin();
Chris@184 1933 k != selections.end(); ++k) {
Chris@184 1934 m_analyser->switchPitchCandidate(*k, false);
Chris@184 1935 }
Chris@184 1936
Chris@184 1937 CommandHistory::getInstance()->endCompoundOperation();
Chris@184 1938 }
Chris@184 1939
Chris@184 1940 void
Chris@0 1941 MainWindow::playSpeedChanged(int position)
Chris@0 1942 {
Chris@0 1943 PlaySpeedRangeMapper mapper(0, 200);
Chris@0 1944
Chris@0 1945 float percent = m_playSpeed->mappedValue();
Chris@0 1946 float factor = mapper.getFactorForValue(percent);
Chris@0 1947
Chris@70 1948 cerr << "speed = " << position << " percent = " << percent << " factor = " << factor << endl;
Chris@0 1949
Chris@0 1950 bool something = (position != 100);
Chris@0 1951
Chris@0 1952 int pc = lrintf(percent);
Chris@0 1953
Chris@0 1954 if (!something) {
Chris@0 1955 contextHelpChanged(tr("Playback speed: Normal"));
Chris@0 1956 } else {
Chris@0 1957 contextHelpChanged(tr("Playback speed: %1%2%")
Chris@0 1958 .arg(position > 100 ? "+" : "")
Chris@0 1959 .arg(pc));
Chris@0 1960 }
Chris@0 1961
Chris@0 1962 m_playSource->setTimeStretch(factor);
Chris@0 1963
Chris@0 1964 updateMenuStates();
Chris@0 1965 }
Chris@0 1966
Chris@0 1967 void
Chris@0 1968 MainWindow::playSharpenToggled()
Chris@0 1969 {
Chris@0 1970 QSettings settings;
Chris@0 1971 settings.beginGroup("MainWindow");
Chris@0 1972 settings.setValue("playsharpen", m_playSharpen->isChecked());
Chris@0 1973 settings.endGroup();
Chris@0 1974
Chris@0 1975 playSpeedChanged(m_playSpeed->value());
justin@157 1976 // TODO: pitch gain?
Chris@0 1977 }
Chris@0 1978
Chris@0 1979 void
Chris@0 1980 MainWindow::playMonoToggled()
Chris@0 1981 {
Chris@0 1982 QSettings settings;
Chris@0 1983 settings.beginGroup("MainWindow");
Chris@0 1984 settings.setValue("playmono", m_playMono->isChecked());
Chris@0 1985 settings.endGroup();
Chris@0 1986
Chris@0 1987 playSpeedChanged(m_playSpeed->value());
justin@157 1988 // TODO: pitch gain?
Chris@0 1989 }
Chris@0 1990
Chris@0 1991 void
Chris@0 1992 MainWindow::speedUpPlayback()
Chris@0 1993 {
Chris@0 1994 int value = m_playSpeed->value();
Chris@0 1995 value = value + m_playSpeed->pageStep();
Chris@0 1996 if (value > m_playSpeed->maximum()) value = m_playSpeed->maximum();
Chris@0 1997 m_playSpeed->setValue(value);
Chris@0 1998 }
Chris@0 1999
Chris@0 2000 void
Chris@0 2001 MainWindow::slowDownPlayback()
Chris@0 2002 {
Chris@0 2003 int value = m_playSpeed->value();
Chris@0 2004 value = value - m_playSpeed->pageStep();
Chris@0 2005 if (value < m_playSpeed->minimum()) value = m_playSpeed->minimum();
Chris@0 2006 m_playSpeed->setValue(value);
Chris@0 2007 }
Chris@0 2008
Chris@0 2009 void
Chris@0 2010 MainWindow::restoreNormalPlayback()
Chris@0 2011 {
Chris@0 2012 m_playSpeed->setValue(m_playSpeed->defaultValue());
Chris@0 2013 }
Chris@0 2014
justin@157 2015 void
justin@159 2016 MainWindow::audioGainChanged(int position)
justin@159 2017 {
justin@159 2018 float level = m_gainAudio->mappedValue();
justin@159 2019 float gain = powf(10, level / 20.0);
justin@159 2020
justin@159 2021 cerr << "gain = " << gain << " (" << position << " dB)" << endl;
justin@159 2022
justin@159 2023 contextHelpChanged(tr("Audio Gain: %1 dB").arg(position));
justin@159 2024
justin@159 2025 m_analyser->setGain(Analyser::Audio, gain);
justin@159 2026
justin@159 2027 updateMenuStates();
justin@159 2028 }
justin@159 2029
justin@159 2030 void
justin@159 2031 MainWindow::increaseAudioGain()
justin@159 2032 {
justin@159 2033 int value = m_gainAudio->value();
justin@159 2034 value = value + m_gainAudio->pageStep();
justin@159 2035 if (value > m_gainAudio->maximum()) value = m_gainAudio->maximum();
justin@159 2036 m_gainAudio->setValue(value);
justin@159 2037 }
justin@159 2038
justin@159 2039 void
justin@159 2040 MainWindow::decreaseAudioGain()
justin@159 2041 {
justin@159 2042 int value = m_gainAudio->value();
justin@159 2043 value = value - m_gainAudio->pageStep();
justin@159 2044 if (value < m_gainAudio->minimum()) value = m_gainAudio->minimum();
justin@159 2045 m_gainAudio->setValue(value);
justin@159 2046 }
justin@159 2047
justin@159 2048 void
justin@159 2049 MainWindow::restoreNormalAudioGain()
justin@159 2050 {
justin@159 2051 m_gainAudio->setValue(m_gainAudio->defaultValue());
justin@159 2052 }
justin@159 2053
justin@159 2054 void
justin@157 2055 MainWindow::pitchGainChanged(int position)
justin@157 2056 {
Chris@158 2057 float level = m_gainPitch->mappedValue();
Chris@158 2058 float gain = powf(10, level / 20.0);
justin@157 2059
Chris@158 2060 cerr << "gain = " << gain << " (" << position << " dB)" << endl;
justin@157 2061
Chris@158 2062 contextHelpChanged(tr("Pitch Gain: %1 dB").arg(position));
justin@157 2063
Chris@158 2064 m_analyser->setGain(Analyser::PitchTrack, gain);
justin@157 2065
justin@157 2066 updateMenuStates();
justin@157 2067 }
justin@157 2068
justin@157 2069 void
justin@157 2070 MainWindow::increasePitchGain()
justin@157 2071 {
justin@157 2072 int value = m_gainPitch->value();
justin@157 2073 value = value + m_gainPitch->pageStep();
justin@157 2074 if (value > m_gainPitch->maximum()) value = m_gainPitch->maximum();
justin@157 2075 m_gainPitch->setValue(value);
justin@157 2076 }
justin@157 2077
justin@157 2078 void
justin@157 2079 MainWindow::decreasePitchGain()
justin@157 2080 {
justin@157 2081 int value = m_gainPitch->value();
justin@157 2082 value = value - m_gainPitch->pageStep();
justin@157 2083 if (value < m_gainPitch->minimum()) value = m_gainPitch->minimum();
justin@157 2084 m_gainPitch->setValue(value);
justin@157 2085 }
justin@157 2086
justin@157 2087 void
justin@157 2088 MainWindow::restoreNormalPitchGain()
justin@157 2089 {
justin@157 2090 m_gainPitch->setValue(m_gainPitch->defaultValue());
justin@157 2091 }
justin@157 2092
Chris@0 2093 void
justin@159 2094 MainWindow::notesGainChanged(int position)
justin@159 2095 {
justin@159 2096 float level = m_gainNotes->mappedValue();
justin@159 2097 float gain = powf(10, level / 20.0);
justin@159 2098
justin@159 2099 cerr << "gain = " << gain << " (" << position << " dB)" << endl;
justin@159 2100
justin@159 2101 contextHelpChanged(tr("Notes Gain: %1 dB").arg(position));
justin@159 2102
justin@159 2103 m_analyser->setGain(Analyser::Notes, gain);
justin@159 2104
justin@159 2105 updateMenuStates();
justin@159 2106 }
justin@159 2107
justin@159 2108 void
justin@159 2109 MainWindow::increaseNotesGain()
justin@159 2110 {
justin@159 2111 int value = m_gainNotes->value();
justin@159 2112 value = value + m_gainNotes->pageStep();
justin@159 2113 if (value > m_gainNotes->maximum()) value = m_gainNotes->maximum();
justin@159 2114 m_gainNotes->setValue(value);
justin@159 2115 }
justin@159 2116
justin@159 2117 void
justin@159 2118 MainWindow::decreaseNotesGain()
justin@159 2119 {
justin@159 2120 int value = m_gainNotes->value();
justin@159 2121 value = value - m_gainNotes->pageStep();
justin@159 2122 if (value < m_gainNotes->minimum()) value = m_gainNotes->minimum();
justin@159 2123 m_gainNotes->setValue(value);
justin@159 2124 }
justin@159 2125
justin@159 2126 void
justin@159 2127 MainWindow::restoreNormalNotesGain()
justin@159 2128 {
justin@159 2129 m_gainNotes->setValue(m_gainNotes->defaultValue());
justin@159 2130 }
justin@159 2131
justin@159 2132 void
justin@160 2133 MainWindow::audioPanChanged(int position)
justin@160 2134 {
justin@160 2135 float level = m_panAudio->mappedValue();
justin@160 2136 float pan = level/100.f;
justin@160 2137
justin@160 2138 cerr << "pan = " << pan << " (" << position << ")" << endl;
justin@160 2139
justin@160 2140 contextHelpChanged(tr("Audio Pan: %1").arg(position));
justin@160 2141
justin@160 2142 m_analyser->setPan(Analyser::Audio, pan);
justin@160 2143
justin@160 2144 updateMenuStates();
justin@160 2145 }
justin@160 2146
justin@160 2147 void
justin@160 2148 MainWindow::increaseAudioPan()
justin@160 2149 {
justin@160 2150 int value = m_panAudio->value();
justin@160 2151 value = value + m_panAudio->pageStep();
justin@160 2152 if (value > m_panAudio->maximum()) value = m_panAudio->maximum();
justin@160 2153 m_panAudio->setValue(value);
justin@160 2154 }
justin@160 2155
justin@160 2156 void
justin@160 2157 MainWindow::decreaseAudioPan()
justin@160 2158 {
justin@160 2159 int value = m_panAudio->value();
justin@160 2160 value = value - m_panAudio->pageStep();
justin@160 2161 if (value < m_panAudio->minimum()) value = m_panAudio->minimum();
justin@160 2162 m_panAudio->setValue(value);
justin@160 2163 }
justin@160 2164
justin@160 2165 void
justin@160 2166 MainWindow::restoreNormalAudioPan()
justin@160 2167 {
justin@160 2168 m_panAudio->setValue(m_panAudio->defaultValue());
justin@160 2169 }
justin@160 2170
justin@160 2171 void
justin@160 2172 MainWindow::pitchPanChanged(int position)
justin@160 2173 {
justin@160 2174 float level = m_panPitch->mappedValue();
justin@160 2175 float pan = level/100.f;
justin@160 2176
justin@160 2177 cerr << "pan = " << pan << " (" << position << ")" << endl;
justin@160 2178
justin@160 2179 contextHelpChanged(tr("Pitch Pan: %1").arg(position));
justin@160 2180
justin@160 2181 m_analyser->setPan(Analyser::PitchTrack, pan);
justin@160 2182
justin@160 2183 updateMenuStates();
justin@160 2184 }
justin@160 2185
justin@160 2186 void
justin@160 2187 MainWindow::increasePitchPan()
justin@160 2188 {
justin@160 2189 int value = m_panPitch->value();
justin@160 2190 value = value + m_panPitch->pageStep();
justin@160 2191 if (value > m_panPitch->maximum()) value = m_panPitch->maximum();
justin@160 2192 m_panPitch->setValue(value);
justin@160 2193 }
justin@160 2194
justin@160 2195 void
justin@160 2196 MainWindow::decreasePitchPan()
justin@160 2197 {
justin@160 2198 int value = m_panPitch->value();
justin@160 2199 value = value - m_panPitch->pageStep();
justin@160 2200 if (value < m_panPitch->minimum()) value = m_panPitch->minimum();
justin@160 2201 m_panPitch->setValue(value);
justin@160 2202 }
justin@160 2203
justin@160 2204 void
justin@160 2205 MainWindow::restoreNormalPitchPan()
justin@160 2206 {
justin@160 2207 m_panPitch->setValue(m_panPitch->defaultValue());
justin@160 2208 }
justin@160 2209
justin@160 2210 void
justin@160 2211 MainWindow::notesPanChanged(int position)
justin@160 2212 {
justin@160 2213 float level = m_panNotes->mappedValue();
justin@160 2214 float pan = level/100.f;
justin@160 2215
justin@160 2216 cerr << "pan = " << pan << " (" << position << ")" << endl;
justin@160 2217
justin@160 2218 contextHelpChanged(tr("Notes Pan: %1").arg(position));
justin@160 2219
justin@160 2220 m_analyser->setPan(Analyser::Notes, pan);
justin@160 2221
justin@160 2222 updateMenuStates();
justin@160 2223 }
justin@160 2224
justin@160 2225 void
justin@160 2226 MainWindow::increaseNotesPan()
justin@160 2227 {
justin@160 2228 int value = m_panNotes->value();
justin@160 2229 value = value + m_panNotes->pageStep();
justin@160 2230 if (value > m_panNotes->maximum()) value = m_panNotes->maximum();
justin@160 2231 m_panNotes->setValue(value);
justin@160 2232 }
justin@160 2233
justin@160 2234 void
justin@160 2235 MainWindow::decreaseNotesPan()
justin@160 2236 {
justin@160 2237 int value = m_panNotes->value();
justin@160 2238 value = value - m_panNotes->pageStep();
justin@160 2239 if (value < m_panNotes->minimum()) value = m_panNotes->minimum();
justin@160 2240 m_panNotes->setValue(value);
justin@160 2241 }
justin@160 2242
justin@160 2243 void
justin@160 2244 MainWindow::restoreNormalNotesPan()
justin@160 2245 {
justin@160 2246 m_panNotes->setValue(m_panNotes->defaultValue());
justin@160 2247 }
justin@160 2248
justin@160 2249 void
Chris@0 2250 MainWindow::updateVisibleRangeDisplay(Pane *p) const
Chris@0 2251 {
Chris@0 2252 if (!getMainModel() || !p) {
Chris@0 2253 return;
Chris@0 2254 }
Chris@0 2255
Chris@0 2256 bool haveSelection = false;
Chris@0 2257 size_t startFrame = 0, endFrame = 0;
Chris@0 2258
Chris@0 2259 if (m_viewManager && m_viewManager->haveInProgressSelection()) {
Chris@0 2260
Chris@0 2261 bool exclusive = false;
Chris@0 2262 Selection s = m_viewManager->getInProgressSelection(exclusive);
Chris@0 2263
Chris@0 2264 if (!s.isEmpty()) {
Chris@0 2265 haveSelection = true;
Chris@0 2266 startFrame = s.getStartFrame();
Chris@0 2267 endFrame = s.getEndFrame();
Chris@0 2268 }
Chris@0 2269 }
Chris@0 2270
Chris@0 2271 if (!haveSelection) {
Chris@0 2272 startFrame = p->getFirstVisibleFrame();
Chris@0 2273 endFrame = p->getLastVisibleFrame();
Chris@0 2274 }
Chris@0 2275
Chris@0 2276 RealTime start = RealTime::frame2RealTime
Chris@0 2277 (startFrame, getMainModel()->getSampleRate());
Chris@0 2278
Chris@0 2279 RealTime end = RealTime::frame2RealTime
Chris@0 2280 (endFrame, getMainModel()->getSampleRate());
Chris@0 2281
Chris@0 2282 RealTime duration = end - start;
Chris@0 2283
Chris@0 2284 QString startStr, endStr, durationStr;
Chris@0 2285 startStr = start.toText(true).c_str();
Chris@0 2286 endStr = end.toText(true).c_str();
Chris@0 2287 durationStr = duration.toText(true).c_str();
Chris@0 2288
Chris@0 2289 if (haveSelection) {
Chris@0 2290 m_myStatusMessage = tr("Selection: %1 to %2 (duration %3)")
Chris@0 2291 .arg(startStr).arg(endStr).arg(durationStr);
Chris@0 2292 } else {
Chris@0 2293 m_myStatusMessage = tr("Visible: %1 to %2 (duration %3)")
Chris@0 2294 .arg(startStr).arg(endStr).arg(durationStr);
Chris@0 2295 }
matthiasm@42 2296
matthiasm@42 2297 // scale Y axis
matthiasm@42 2298 FlexiNoteLayer *fnl = dynamic_cast<FlexiNoteLayer *>(p->getLayer(2));
matthiasm@42 2299 if (fnl) {
matthiasm@42 2300 fnl->setVerticalRangeToNoteRange(p);
matthiasm@42 2301 }
matthiasm@42 2302
Chris@0 2303 statusBar()->showMessage(m_myStatusMessage);
Chris@0 2304 }
Chris@0 2305
Chris@0 2306 void
Chris@0 2307 MainWindow::updatePositionStatusDisplays() const
Chris@0 2308 {
Chris@0 2309 if (!statusBar()->isVisible()) return;
Chris@0 2310
Chris@0 2311 }
Chris@0 2312
Chris@0 2313 void
Chris@0 2314 MainWindow::outputLevelsChanged(float left, float right)
Chris@0 2315 {
Chris@0 2316 m_fader->setPeakLeft(left);
Chris@0 2317 m_fader->setPeakRight(right);
Chris@0 2318 }
Chris@0 2319
Chris@0 2320 void
Chris@0 2321 MainWindow::sampleRateMismatch(size_t requested, size_t actual,
Chris@0 2322 bool willResample)
Chris@0 2323 {
Chris@0 2324 updateDescriptionLabel();
Chris@0 2325 }
Chris@0 2326
Chris@0 2327 void
Chris@0 2328 MainWindow::audioOverloadPluginDisabled()
Chris@0 2329 {
Chris@0 2330 QMessageBox::information
Chris@0 2331 (this, tr("Audio processing overload"),
Chris@0 2332 tr("<b>Overloaded</b><p>Audio effects plugin auditioning has been disabled due to a processing overload."));
Chris@0 2333 }
Chris@0 2334
Chris@0 2335 void
Chris@0 2336 MainWindow::audioTimeStretchMultiChannelDisabled()
Chris@0 2337 {
Chris@0 2338 static bool shownOnce = false;
Chris@0 2339 if (shownOnce) return;
Chris@0 2340 QMessageBox::information
Chris@0 2341 (this, tr("Audio processing overload"),
Chris@0 2342 tr("<b>Overloaded</b><p>Audio playback speed processing has been reduced to a single channel, due to a processing overload."));
Chris@0 2343 shownOnce = true;
Chris@0 2344 }
Chris@0 2345
Chris@0 2346 void
Chris@0 2347 MainWindow::layerRemoved(Layer *layer)
Chris@0 2348 {
Chris@0 2349 MainWindowBase::layerRemoved(layer);
Chris@0 2350 }
Chris@0 2351
Chris@0 2352 void
Chris@0 2353 MainWindow::layerInAView(Layer *layer, bool inAView)
Chris@0 2354 {
Chris@0 2355 MainWindowBase::layerInAView(layer, inAView);
Chris@0 2356 }
Chris@0 2357
Chris@0 2358 void
Chris@0 2359 MainWindow::modelAdded(Model *model)
Chris@0 2360 {
Chris@0 2361 MainWindowBase::modelAdded(model);
Chris@3 2362 DenseTimeValueModel *dtvm = qobject_cast<DenseTimeValueModel *>(model);
Chris@0 2363 if (dtvm) {
Chris@70 2364 cerr << "A dense time-value model (such as an audio file) has been loaded" << endl;
Chris@0 2365 }
Chris@0 2366 }
Chris@0 2367
Chris@0 2368 void
Chris@0 2369 MainWindow::modelAboutToBeDeleted(Model *model)
Chris@0 2370 {
Chris@0 2371 MainWindowBase::modelAboutToBeDeleted(model);
Chris@0 2372 }
Chris@0 2373
Chris@0 2374 void
Chris@0 2375 MainWindow::mainModelChanged(WaveFileModel *model)
Chris@0 2376 {
Chris@0 2377 m_panLayer->setModel(model);
Chris@0 2378
Chris@0 2379 MainWindowBase::mainModelChanged(model);
Chris@0 2380
Chris@0 2381 if (m_playTarget) {
Chris@0 2382 connect(m_fader, SIGNAL(valueChanged(float)),
Chris@0 2383 m_playTarget, SLOT(setOutputGain(float)));
Chris@0 2384 }
Chris@72 2385
Chris@72 2386 if (model) {
Chris@72 2387 if (m_paneStack) {
Chris@174 2388
Chris@174 2389 int pc = m_paneStack->getPaneCount();
Chris@174 2390 Pane *pane = 0;
Chris@174 2391
Chris@174 2392 if (pc < 1) {
Chris@72 2393 pane = m_paneStack->addPane();
Chris@131 2394
Chris@131 2395 Pane *selectionStrip = m_paneStack->addPane();
Chris@131 2396 selectionStrip->setFixedHeight(26);
Chris@131 2397 m_document->addLayerToView
Chris@131 2398 (selectionStrip,
Chris@131 2399 m_document->createMainModelLayer(LayerFactory::TimeRuler));
Chris@131 2400 m_paneStack->sizePanesEqually();
Chris@131 2401
Chris@131 2402 m_viewManager->clearToolModeOverrides();
Chris@131 2403 m_viewManager->setToolModeFor(selectionStrip,
Chris@131 2404 ViewManager::SelectMode);
Chris@174 2405 } else {
Chris@174 2406 pane = m_paneStack->getPane(0);
Chris@72 2407 }
Chris@174 2408
Chris@72 2409 if (pane) {
Chris@192 2410
Chris@192 2411 disconnect(pane, SIGNAL(regionOutlined(QRect)),
Chris@192 2412 pane, SLOT(zoomToRegion(QRect)));
Chris@192 2413 connect(pane, SIGNAL(regionOutlined(QRect)),
Chris@192 2414 this, SLOT(regionOutlined(QRect)));
Chris@192 2415
Chris@140 2416 QString error = m_analyser->newFileLoaded
Chris@72 2417 (m_document, getMainModel(), m_paneStack, pane);
Chris@140 2418 if (error != "") {
Chris@140 2419 QMessageBox::warning
Chris@140 2420 (this,
Chris@140 2421 tr("Failed to analyse audio"),
Chris@140 2422 tr("<b>Analysis failed</b><p>%1</p>").arg(error),
Chris@140 2423 QMessageBox::Ok);
Chris@140 2424 }
Chris@72 2425 }
Chris@72 2426 }
Chris@72 2427 }
Chris@0 2428 }
Chris@0 2429
Chris@0 2430 void
Chris@0 2431 MainWindow::modelGenerationFailed(QString transformName, QString message)
Chris@0 2432 {
Chris@0 2433 if (message != "") {
Chris@0 2434
Chris@0 2435 QMessageBox::warning
Chris@0 2436 (this,
Chris@0 2437 tr("Failed to generate layer"),
Chris@0 2438 tr("<b>Layer generation failed</b><p>Failed to generate derived layer.<p>The layer transform \"%1\" failed:<p>%2")
Chris@0 2439 .arg(transformName).arg(message),
Chris@0 2440 QMessageBox::Ok);
Chris@0 2441 } else {
Chris@0 2442 QMessageBox::warning
Chris@0 2443 (this,
Chris@0 2444 tr("Failed to generate layer"),
Chris@0 2445 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 2446 .arg(transformName),
Chris@0 2447 QMessageBox::Ok);
Chris@0 2448 }
Chris@0 2449 }
Chris@0 2450
Chris@0 2451 void
Chris@0 2452 MainWindow::modelGenerationWarning(QString transformName, QString message)
Chris@0 2453 {
Chris@0 2454 QMessageBox::warning
Chris@0 2455 (this, tr("Warning"), message, QMessageBox::Ok);
Chris@0 2456 }
Chris@0 2457
Chris@0 2458 void
Chris@0 2459 MainWindow::modelRegenerationFailed(QString layerName,
Chris@0 2460 QString transformName, QString message)
Chris@0 2461 {
Chris@0 2462 if (message != "") {
Chris@0 2463
Chris@0 2464 QMessageBox::warning
Chris@0 2465 (this,
Chris@0 2466 tr("Failed to regenerate layer"),
Chris@0 2467 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 2468 .arg(layerName).arg(transformName).arg(message),
Chris@0 2469 QMessageBox::Ok);
Chris@0 2470 } else {
Chris@0 2471 QMessageBox::warning
Chris@0 2472 (this,
Chris@0 2473 tr("Failed to regenerate layer"),
Chris@0 2474 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 2475 .arg(layerName).arg(transformName),
Chris@0 2476 QMessageBox::Ok);
Chris@0 2477 }
Chris@0 2478 }
Chris@0 2479
Chris@0 2480 void
Chris@0 2481 MainWindow::modelRegenerationWarning(QString layerName,
Chris@0 2482 QString transformName, QString message)
Chris@0 2483 {
Chris@0 2484 QMessageBox::warning
Chris@0 2485 (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 2486 }
Chris@0 2487
Chris@0 2488 void
Chris@0 2489 MainWindow::alignmentFailed(QString transformName, QString message)
Chris@0 2490 {
Chris@0 2491 QMessageBox::warning
Chris@0 2492 (this,
Chris@0 2493 tr("Failed to calculate alignment"),
Chris@0 2494 tr("<b>Alignment calculation failed</b><p>Failed to calculate an audio alignment using transform \"%1\":<p>%2")
Chris@0 2495 .arg(transformName).arg(message),
Chris@0 2496 QMessageBox::Ok);
Chris@0 2497 }
Chris@0 2498
Chris@0 2499 void
Chris@0 2500 MainWindow::rightButtonMenuRequested(Pane *pane, QPoint position)
Chris@0 2501 {
Chris@70 2502 // cerr << "MainWindow::rightButtonMenuRequested(" << pane << ", " << position.x() << ", " << position.y() << ")" << endl;
Chris@0 2503 m_paneStack->setCurrentPane(pane);
Chris@0 2504 m_rightButtonMenu->popup(position);
Chris@0 2505 }
Chris@0 2506
Chris@0 2507 void
Chris@0 2508 MainWindow::handleOSCMessage(const OSCMessage &message)
Chris@0 2509 {
Chris@70 2510 cerr << "MainWindow::handleOSCMessage: Not implemented" << endl;
Chris@0 2511 }
Chris@0 2512
Chris@0 2513 void
Chris@0 2514 MainWindow::mouseEnteredWidget()
Chris@0 2515 {
Chris@3 2516 QWidget *w = qobject_cast<QWidget *>(sender());
Chris@0 2517 if (!w) return;
Chris@0 2518
Chris@0 2519 if (w == m_fader) {
Chris@0 2520 contextHelpChanged(tr("Adjust the master playback level"));
Chris@0 2521 } else if (w == m_playSpeed) {
Chris@0 2522 contextHelpChanged(tr("Adjust the master playback speed"));
Chris@0 2523 } else if (w == m_playSharpen && w->isEnabled()) {
Chris@0 2524 contextHelpChanged(tr("Toggle transient sharpening for playback time scaling"));
Chris@0 2525 } else if (w == m_playMono && w->isEnabled()) {
Chris@0 2526 contextHelpChanged(tr("Toggle mono mode for playback time scaling"));
Chris@0 2527 }
Chris@0 2528 }
Chris@0 2529
Chris@0 2530 void
Chris@0 2531 MainWindow::mouseLeftWidget()
Chris@0 2532 {
Chris@0 2533 contextHelpChanged("");
Chris@0 2534 }
Chris@0 2535
Chris@0 2536 void
Chris@0 2537 MainWindow::website()
Chris@0 2538 {
Chris@4 2539 //!!! todo: URL!
Chris@4 2540 openHelpUrl(tr("http://code.soundsoftware.ac.uk/projects/tony/"));
Chris@0 2541 }
Chris@0 2542
Chris@0 2543 void
Chris@0 2544 MainWindow::help()
Chris@0 2545 {
Chris@4 2546 //!!! todo: help URL!
Chris@4 2547 openHelpUrl(tr("http://code.soundsoftware.ac.uk/projects/tony/"));
Chris@0 2548 }
Chris@0 2549
Chris@0 2550 void
Chris@0 2551 MainWindow::about()
Chris@0 2552 {
Chris@0 2553 bool debug = false;
Chris@0 2554 QString version = "(unknown version)";
Chris@0 2555
Chris@0 2556 #ifdef BUILD_DEBUG
Chris@0 2557 debug = true;
Chris@0 2558 #endif
Chris@0 2559 version = tr("Release %1").arg(TONY_VERSION);
Chris@0 2560
Chris@0 2561 QString aboutText;
Chris@0 2562
Chris@0 2563 aboutText += tr("<h3>About Tony</h3>");
Chris@0 2564 aboutText += tr("<p>Tony is a program for interactive note and pitch analysis and annotation.</p>");
Chris@0 2565 aboutText += tr("<p>%1 : %2 configuration</p>")
Chris@0 2566 .arg(version)
Chris@0 2567 .arg(debug ? tr("Debug") : tr("Release"));
Chris@0 2568
Chris@0 2569 aboutText +=
Chris@90 2570 "<p>Copyright &copy; 2005&ndash;2013 Chris Cannam, Matthias Mauch, George Fazekas, and Queen Mary University of London.</p>"
Chris@90 2571 "<p>This program is free software; you can redistribute it and/or "
Chris@90 2572 "modify it under the terms of the GNU General Public License as "
Chris@90 2573 "published by the Free Software Foundation; either version 2 of the "
Chris@0 2574 "License, or (at your option) any later version.<br>See the file "
Chris@0 2575 "COPYING included with this distribution for more information.</p>";
Chris@0 2576
Chris@0 2577 QMessageBox::about(this, tr("About %1").arg(QApplication::applicationName()), aboutText);
Chris@0 2578 }
Chris@0 2579
Chris@0 2580 void
Chris@0 2581 MainWindow::keyReference()
Chris@0 2582 {
Chris@0 2583 m_keyReference->show();
Chris@0 2584 }
Chris@0 2585
Chris@0 2586