annotate framework/MainWindowBase.cpp @ 285:32d8084f8543

Merge from branch "qt5". This revision actually builds with Qt4 (late releases) or Qt5, though it will warn on configure with Qt4.
author Chris Cannam
date Tue, 14 May 2013 12:37:31 +0100
parents 7ee215c095dd
children 98993f4904df 2925a4bbca5e
rev   line source
Chris@45 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@45 2
Chris@45 3 /*
Chris@45 4 Sonic Visualiser
Chris@45 5 An audio file viewer and annotation editor.
Chris@45 6 Centre for Digital Music, Queen Mary, University of London.
Chris@45 7 This file copyright 2006-2007 Chris Cannam and QMUL.
Chris@45 8
Chris@45 9 This program is free software; you can redistribute it and/or
Chris@45 10 modify it under the terms of the GNU General Public License as
Chris@45 11 published by the Free Software Foundation; either version 2 of the
Chris@45 12 License, or (at your option) any later version. See the file
Chris@45 13 COPYING included with this distribution for more information.
Chris@45 14 */
Chris@45 15
Chris@45 16 #include "MainWindowBase.h"
Chris@46 17 #include "Document.h"
Chris@45 18
Chris@45 19
Chris@45 20 #include "view/Pane.h"
Chris@45 21 #include "view/PaneStack.h"
Chris@45 22 #include "data/model/WaveFileModel.h"
Chris@45 23 #include "data/model/SparseOneDimensionalModel.h"
Chris@45 24 #include "data/model/NoteModel.h"
Chris@45 25 #include "data/model/Labeller.h"
Chris@124 26 #include "data/model/TabularModel.h"
Chris@45 27 #include "view/ViewManager.h"
Chris@45 28
Chris@45 29 #include "layer/WaveformLayer.h"
Chris@45 30 #include "layer/TimeRulerLayer.h"
Chris@45 31 #include "layer/TimeInstantLayer.h"
Chris@45 32 #include "layer/TimeValueLayer.h"
Chris@45 33 #include "layer/Colour3DPlotLayer.h"
Chris@45 34 #include "layer/SliceLayer.h"
Chris@45 35 #include "layer/SliceableLayer.h"
Chris@45 36 #include "layer/ImageLayer.h"
Chris@184 37 #include "layer/NoteLayer.h"
Chris@184 38 #include "layer/RegionLayer.h"
Chris@45 39
Chris@45 40 #include "widgets/ListInputDialog.h"
Chris@105 41 #include "widgets/CommandHistory.h"
Chris@109 42 #include "widgets/ProgressDialog.h"
Chris@109 43 #include "widgets/MIDIFileImportDialog.h"
Chris@109 44 #include "widgets/CSVFormatDialog.h"
Chris@123 45 #include "widgets/ModelDataTableDialog.h"
Chris@45 46
Chris@45 47 #include "audioio/AudioCallbackPlaySource.h"
Chris@45 48 #include "audioio/AudioCallbackPlayTarget.h"
Chris@45 49 #include "audioio/AudioTargetFactory.h"
Chris@45 50 #include "audioio/PlaySpeedRangeMapper.h"
Chris@45 51 #include "data/fileio/DataFileReaderFactory.h"
Chris@45 52 #include "data/fileio/PlaylistFileReader.h"
Chris@45 53 #include "data/fileio/WavFileWriter.h"
Chris@45 54 #include "data/fileio/CSVFileWriter.h"
Chris@45 55 #include "data/fileio/MIDIFileWriter.h"
Chris@45 56 #include "data/fileio/BZipFileDevice.h"
Chris@45 57 #include "data/fileio/FileSource.h"
Chris@152 58 #include "data/fileio/AudioFileReaderFactory.h"
Chris@134 59 #include "rdf/RDFImporter.h"
Chris@45 60
Chris@45 61 #include "data/fft/FFTDataServer.h"
Chris@45 62
Chris@45 63 #include "base/RecentFiles.h"
Chris@45 64
Chris@45 65 #include "base/PlayParameterRepository.h"
Chris@45 66 #include "base/XmlExportable.h"
Chris@45 67 #include "base/Profiler.h"
Chris@45 68 #include "base/Preferences.h"
Chris@217 69 #include "base/TempWriteFile.h"
Chris@217 70 #include "base/Exceptions.h"
Chris@223 71 #include "base/ResourceFinder.h"
Chris@45 72
Chris@45 73 #include "data/osc/OSCQueue.h"
Chris@157 74 #include "data/midi/MIDIInput.h"
Chris@45 75
Chris@45 76 #include <QApplication>
Chris@45 77 #include <QMessageBox>
Chris@45 78 #include <QGridLayout>
Chris@45 79 #include <QLabel>
Chris@45 80 #include <QAction>
Chris@45 81 #include <QMenuBar>
Chris@45 82 #include <QToolBar>
Chris@45 83 #include <QInputDialog>
Chris@45 84 #include <QStatusBar>
Chris@45 85 #include <QTreeView>
Chris@45 86 #include <QFile>
Chris@45 87 #include <QFileInfo>
Chris@45 88 #include <QDir>
Chris@45 89 #include <QTextStream>
Chris@45 90 #include <QProcess>
Chris@45 91 #include <QShortcut>
Chris@45 92 #include <QSettings>
Chris@45 93 #include <QDateTime>
Chris@45 94 #include <QProcess>
Chris@45 95 #include <QCheckBox>
Chris@45 96 #include <QRegExp>
Chris@45 97 #include <QScrollArea>
Chris@168 98 #include <QDesktopWidget>
Chris@45 99
Chris@45 100 #include <iostream>
Chris@45 101 #include <cstdio>
Chris@45 102 #include <errno.h>
Chris@45 103
Chris@45 104 using std::cerr;
Chris@45 105 using std::endl;
Chris@45 106
Chris@45 107 using std::vector;
Chris@45 108 using std::map;
Chris@45 109 using std::set;
Chris@45 110
Chris@255 111 #ifdef Q_WS_X11
Chris@255 112 #define Window X11Window
Chris@255 113 #include <X11/Xlib.h>
Chris@255 114 #include <X11/Xutil.h>
Chris@255 115 #include <X11/Xatom.h>
Chris@255 116 #include <X11/SM/SMlib.h>
Chris@255 117
Chris@255 118 static int handle_x11_error(Display *dpy, XErrorEvent *err)
Chris@255 119 {
Chris@255 120 char errstr[256];
Chris@255 121 XGetErrorText(dpy, err->error_code, errstr, 256);
Chris@255 122 if (err->error_code != BadWindow) {
Chris@255 123 std::cerr << "Sonic Visualiser: X Error: "
Chris@255 124 << errstr << " " << int(err->error_code)
Chris@255 125 << "\nin major opcode: "
Chris@255 126 << int(err->request_code) << std::endl;
Chris@255 127 }
Chris@255 128 return 0;
Chris@255 129 }
Chris@255 130 #undef Window
Chris@255 131 #endif
Chris@45 132
Chris@161 133 MainWindowBase::MainWindowBase(bool withAudioOutput,
Chris@161 134 bool withOSCSupport,
Chris@161 135 bool withMIDIInput) :
Chris@45 136 m_document(0),
Chris@45 137 m_paneStack(0),
Chris@45 138 m_viewManager(0),
Chris@45 139 m_timeRulerLayer(0),
Chris@45 140 m_audioOutput(withAudioOutput),
Chris@45 141 m_playSource(0),
Chris@45 142 m_playTarget(0),
Chris@113 143 m_oscQueue(0),
Chris@113 144 m_oscQueueStarter(0),
Chris@157 145 m_midiInput(0),
Chris@45 146 m_recentFiles("RecentFiles", 20),
Chris@54 147 m_recentTransforms("RecentTransforms", 20),
Chris@45 148 m_documentModified(false),
Chris@45 149 m_openingAudioFile(false),
Chris@45 150 m_abandoning(false),
Chris@121 151 m_labeller(0),
Chris@121 152 m_lastPlayStatusSec(0)
Chris@45 153 {
Chris@113 154 Profiler profiler("MainWindowBase::MainWindowBase");
Chris@113 155
Chris@255 156 #ifdef Q_WS_X11
Chris@255 157 XSetErrorHandler(handle_x11_error);
Chris@255 158 #endif
Chris@255 159
Chris@45 160 connect(CommandHistory::getInstance(), SIGNAL(commandExecuted()),
Chris@45 161 this, SLOT(documentModified()));
Chris@45 162 connect(CommandHistory::getInstance(), SIGNAL(documentRestored()),
Chris@45 163 this, SLOT(documentRestored()));
Chris@45 164
Chris@45 165 m_viewManager = new ViewManager();
Chris@45 166 connect(m_viewManager, SIGNAL(selectionChanged()),
Chris@45 167 this, SLOT(updateMenuStates()));
Chris@45 168 connect(m_viewManager, SIGNAL(inProgressSelectionChanged()),
Chris@45 169 this, SLOT(inProgressSelectionChanged()));
Chris@45 170
Chris@105 171 // set a sensible default font size for views -- cannot do this
Chris@105 172 // in Preferences, which is in base and not supposed to use QtGui
Chris@105 173 int viewFontSize = QApplication::font().pointSize() * 0.9;
Chris@105 174 QSettings settings;
Chris@105 175 settings.beginGroup("Preferences");
Chris@105 176 viewFontSize = settings.value("view-font-size", viewFontSize).toInt();
Chris@105 177 settings.setValue("view-font-size", viewFontSize);
Chris@105 178 settings.endGroup();
Chris@105 179
Chris@45 180 Preferences::BackgroundMode mode =
Chris@45 181 Preferences::getInstance()->getBackgroundMode();
Chris@45 182 m_initialDarkBackground = m_viewManager->getGlobalDarkBackground();
Chris@45 183 if (mode != Preferences::BackgroundFromTheme) {
Chris@45 184 m_viewManager->setGlobalDarkBackground
Chris@45 185 (mode == Preferences::DarkBackground);
Chris@45 186 }
Chris@45 187
Chris@45 188 m_paneStack = new PaneStack(0, m_viewManager);
Chris@45 189 connect(m_paneStack, SIGNAL(currentPaneChanged(Pane *)),
Chris@45 190 this, SLOT(currentPaneChanged(Pane *)));
Chris@45 191 connect(m_paneStack, SIGNAL(currentLayerChanged(Pane *, Layer *)),
Chris@45 192 this, SLOT(currentLayerChanged(Pane *, Layer *)));
Chris@45 193 connect(m_paneStack, SIGNAL(rightButtonMenuRequested(Pane *, QPoint)),
Chris@45 194 this, SLOT(rightButtonMenuRequested(Pane *, QPoint)));
Chris@45 195 connect(m_paneStack, SIGNAL(contextHelpChanged(const QString &)),
Chris@45 196 this, SLOT(contextHelpChanged(const QString &)));
Chris@45 197 connect(m_paneStack, SIGNAL(paneAdded(Pane *)),
Chris@45 198 this, SLOT(paneAdded(Pane *)));
Chris@45 199 connect(m_paneStack, SIGNAL(paneHidden(Pane *)),
Chris@45 200 this, SLOT(paneHidden(Pane *)));
Chris@45 201 connect(m_paneStack, SIGNAL(paneAboutToBeDeleted(Pane *)),
Chris@45 202 this, SLOT(paneAboutToBeDeleted(Pane *)));
Chris@45 203 connect(m_paneStack, SIGNAL(dropAccepted(Pane *, QStringList)),
Chris@45 204 this, SLOT(paneDropAccepted(Pane *, QStringList)));
Chris@45 205 connect(m_paneStack, SIGNAL(dropAccepted(Pane *, QString)),
Chris@45 206 this, SLOT(paneDropAccepted(Pane *, QString)));
Chris@55 207 connect(m_paneStack, SIGNAL(paneDeleteButtonClicked(Pane *)),
Chris@55 208 this, SLOT(paneDeleteButtonClicked(Pane *)));
Chris@45 209
Chris@57 210 m_playSource = new AudioCallbackPlaySource(m_viewManager,
Chris@57 211 QApplication::applicationName());
Chris@45 212
Chris@45 213 connect(m_playSource, SIGNAL(sampleRateMismatch(size_t, size_t, bool)),
Chris@45 214 this, SLOT(sampleRateMismatch(size_t, size_t, bool)));
Chris@45 215 connect(m_playSource, SIGNAL(audioOverloadPluginDisabled()),
Chris@45 216 this, SLOT(audioOverloadPluginDisabled()));
Chris@130 217 connect(m_playSource, SIGNAL(audioTimeStretchMultiChannelDisabled()),
Chris@130 218 this, SLOT(audioTimeStretchMultiChannelDisabled()));
Chris@45 219
Chris@45 220 connect(m_viewManager, SIGNAL(outputLevelsChanged(float, float)),
Chris@45 221 this, SLOT(outputLevelsChanged(float, float)));
Chris@45 222
Chris@45 223 connect(m_viewManager, SIGNAL(playbackFrameChanged(unsigned long)),
Chris@45 224 this, SLOT(playbackFrameChanged(unsigned long)));
Chris@45 225
Chris@45 226 connect(m_viewManager, SIGNAL(globalCentreFrameChanged(unsigned long)),
Chris@45 227 this, SLOT(globalCentreFrameChanged(unsigned long)));
Chris@45 228
Chris@45 229 connect(m_viewManager, SIGNAL(viewCentreFrameChanged(View *, unsigned long)),
Chris@45 230 this, SLOT(viewCentreFrameChanged(View *, unsigned long)));
Chris@45 231
Chris@45 232 connect(m_viewManager, SIGNAL(viewZoomLevelChanged(View *, unsigned long, bool)),
Chris@45 233 this, SLOT(viewZoomLevelChanged(View *, unsigned long, bool)));
Chris@45 234
Chris@45 235 connect(Preferences::getInstance(),
Chris@45 236 SIGNAL(propertyChanged(PropertyContainer::PropertyName)),
Chris@45 237 this,
Chris@45 238 SLOT(preferenceChanged(PropertyContainer::PropertyName)));
Chris@45 239
Chris@45 240 Labeller::ValueType labellerType = Labeller::ValueFromTwoLevelCounter;
Chris@45 241 settings.beginGroup("MainWindow");
Chris@230 242
Chris@45 243 labellerType = (Labeller::ValueType)
Chris@45 244 settings.value("labellertype", (int)labellerType).toInt();
Chris@45 245 int cycle = settings.value("labellercycle", 4).toInt();
Chris@230 246
Chris@45 247 settings.endGroup();
Chris@45 248
Chris@45 249 m_labeller = new Labeller(labellerType);
Chris@45 250 m_labeller->setCounterCycleSize(cycle);
Chris@113 251
Chris@161 252 if (withMIDIInput) {
Chris@161 253 m_midiInput = new MIDIInput(QApplication::applicationName(), this);
Chris@161 254 }
Chris@157 255
Chris@113 256 if (withOSCSupport) {
Chris@113 257 m_oscQueueStarter = new OSCQueueStarter(this);
Chris@113 258 connect(m_oscQueueStarter, SIGNAL(finished()), this, SLOT(oscReady()));
Chris@113 259 m_oscQueueStarter->start();
Chris@113 260 }
Chris@45 261 }
Chris@45 262
Chris@45 263 MainWindowBase::~MainWindowBase()
Chris@45 264 {
Chris@233 265 SVDEBUG << "MainWindowBase::~MainWindowBase" << endl;
Chris@70 266 if (m_playTarget) m_playTarget->shutdown();
Chris@70 267 // delete m_playTarget;
Chris@45 268 delete m_playSource;
Chris@45 269 delete m_viewManager;
Chris@45 270 delete m_oscQueue;
Chris@157 271 delete m_midiInput;
Chris@45 272 Profiles::getInstance()->dump();
Chris@45 273 }
Chris@45 274
Chris@113 275 void
Chris@168 276 MainWindowBase::resizeConstrained(QSize size)
Chris@168 277 {
Chris@168 278 QDesktopWidget *desktop = QApplication::desktop();
Chris@168 279 QRect available = desktop->availableGeometry();
Chris@168 280 QSize actual(std::min(size.width(), available.width()),
Chris@168 281 std::min(size.height(), available.height()));
Chris@168 282 resize(actual);
Chris@168 283 }
Chris@168 284
Chris@168 285 void
Chris@113 286 MainWindowBase::oscReady()
Chris@113 287 {
Chris@113 288 if (m_oscQueue && m_oscQueue->isOK()) {
Chris@113 289 connect(m_oscQueue, SIGNAL(messagesAvailable()), this, SLOT(pollOSC()));
Chris@113 290 QTimer *oscTimer = new QTimer(this);
Chris@113 291 connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC()));
Chris@113 292 oscTimer->start(1000);
Chris@113 293 std::cerr << "Finished setting up OSC interface" << std::endl;
Chris@113 294 }
Chris@113 295 }
Chris@113 296
Chris@45 297 QString
Chris@45 298 MainWindowBase::getOpenFileName(FileFinder::FileType type)
Chris@45 299 {
Chris@45 300 FileFinder *ff = FileFinder::getInstance();
Chris@45 301 switch (type) {
Chris@45 302 case FileFinder::SessionFile:
Chris@45 303 return ff->getOpenFileName(type, m_sessionFile);
Chris@45 304 case FileFinder::AudioFile:
Chris@45 305 return ff->getOpenFileName(type, m_audioFile);
Chris@45 306 case FileFinder::LayerFile:
Chris@45 307 return ff->getOpenFileName(type, m_sessionFile);
Chris@45 308 case FileFinder::LayerFileNoMidi:
Chris@45 309 return ff->getOpenFileName(type, m_sessionFile);
Chris@45 310 case FileFinder::SessionOrAudioFile:
Chris@45 311 return ff->getOpenFileName(type, m_sessionFile);
Chris@45 312 case FileFinder::ImageFile:
Chris@45 313 return ff->getOpenFileName(type, m_sessionFile);
Chris@45 314 case FileFinder::AnyFile:
Chris@45 315 if (getMainModel() != 0 &&
Chris@45 316 m_paneStack != 0 &&
Chris@45 317 m_paneStack->getCurrentPane() != 0) { // can import a layer
Chris@45 318 return ff->getOpenFileName(FileFinder::AnyFile, m_sessionFile);
Chris@45 319 } else {
Chris@45 320 return ff->getOpenFileName(FileFinder::SessionOrAudioFile,
Chris@45 321 m_sessionFile);
Chris@45 322 }
Chris@45 323 }
Chris@45 324 return "";
Chris@45 325 }
Chris@45 326
Chris@45 327 QString
Chris@45 328 MainWindowBase::getSaveFileName(FileFinder::FileType type)
Chris@45 329 {
Chris@45 330 FileFinder *ff = FileFinder::getInstance();
Chris@45 331 switch (type) {
Chris@45 332 case FileFinder::SessionFile:
Chris@45 333 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 334 case FileFinder::AudioFile:
Chris@45 335 return ff->getSaveFileName(type, m_audioFile);
Chris@45 336 case FileFinder::LayerFile:
Chris@45 337 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 338 case FileFinder::LayerFileNoMidi:
Chris@45 339 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 340 case FileFinder::SessionOrAudioFile:
Chris@45 341 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 342 case FileFinder::ImageFile:
Chris@45 343 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 344 case FileFinder::AnyFile:
Chris@45 345 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 346 }
Chris@45 347 return "";
Chris@45 348 }
Chris@45 349
Chris@45 350 void
Chris@45 351 MainWindowBase::registerLastOpenedFilePath(FileFinder::FileType type, QString path)
Chris@45 352 {
Chris@45 353 FileFinder *ff = FileFinder::getInstance();
Chris@45 354 ff->registerLastOpenedFilePath(type, path);
Chris@45 355 }
Chris@45 356
Chris@222 357 QString
Chris@222 358 MainWindowBase::getDefaultSessionTemplate() const
Chris@222 359 {
Chris@231 360 QSettings settings;
Chris@231 361 settings.beginGroup("MainWindow");
Chris@231 362 QString templateName = settings.value("sessiontemplate", "").toString();
Chris@231 363 if (templateName == "") templateName = "default";
Chris@231 364 return templateName;
Chris@222 365 }
Chris@222 366
Chris@222 367 void
Chris@251 368 MainWindowBase::setDefaultSessionTemplate(QString n)
Chris@251 369 {
Chris@251 370 QSettings settings;
Chris@251 371 settings.beginGroup("MainWindow");
Chris@251 372 settings.setValue("sessiontemplate", n);
Chris@251 373 }
Chris@251 374
Chris@251 375 void
Chris@45 376 MainWindowBase::updateMenuStates()
Chris@45 377 {
Chris@45 378 Pane *currentPane = 0;
Chris@45 379 Layer *currentLayer = 0;
Chris@45 380
Chris@45 381 if (m_paneStack) currentPane = m_paneStack->getCurrentPane();
Chris@45 382 if (currentPane) currentLayer = currentPane->getSelectedLayer();
Chris@45 383
Chris@73 384 bool havePrevPane = false, haveNextPane = false;
Chris@73 385 bool havePrevLayer = false, haveNextLayer = false;
Chris@73 386
Chris@73 387 if (currentPane) {
Chris@73 388 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@73 389 if (m_paneStack->getPane(i) == currentPane) {
Chris@73 390 if (i > 0) havePrevPane = true;
Chris@73 391 if (i < m_paneStack->getPaneCount()-1) haveNextPane = true;
Chris@73 392 break;
Chris@73 393 }
Chris@73 394 }
Chris@73 395 if (currentLayer) {
Chris@73 396 for (int i = 0; i < currentPane->getLayerCount(); ++i) {
Chris@73 397 if (currentPane->getLayer(i) == currentLayer) {
Chris@73 398 if (i > 0) havePrevLayer = true;
Chris@73 399 if (i < currentPane->getLayerCount()-1) haveNextLayer = true;
Chris@73 400 break;
Chris@73 401 }
Chris@73 402 }
Chris@73 403 }
Chris@73 404 }
Chris@73 405
Chris@45 406 bool haveCurrentPane =
Chris@45 407 (currentPane != 0);
Chris@45 408 bool haveCurrentLayer =
Chris@45 409 (haveCurrentPane &&
Chris@45 410 (currentLayer != 0));
Chris@45 411 bool haveMainModel =
Chris@45 412 (getMainModel() != 0);
Chris@45 413 bool havePlayTarget =
Chris@45 414 (m_playTarget != 0);
Chris@45 415 bool haveSelection =
Chris@45 416 (m_viewManager &&
Chris@45 417 !m_viewManager->getSelections().empty());
Chris@45 418 bool haveCurrentEditableLayer =
Chris@45 419 (haveCurrentLayer &&
Chris@45 420 currentLayer->isLayerEditable());
Chris@45 421 bool haveCurrentTimeInstantsLayer =
Chris@45 422 (haveCurrentLayer &&
Chris@45 423 dynamic_cast<TimeInstantLayer *>(currentLayer));
Chris@184 424 bool haveCurrentDurationLayer =
Chris@184 425 (haveCurrentLayer &&
Chris@184 426 (dynamic_cast<NoteLayer *>(currentLayer) ||
Chris@184 427 dynamic_cast<RegionLayer *>(currentLayer)));
Chris@45 428 bool haveCurrentColour3DPlot =
Chris@45 429 (haveCurrentLayer &&
Chris@45 430 dynamic_cast<Colour3DPlotLayer *>(currentLayer));
Chris@45 431 bool haveClipboardContents =
Chris@45 432 (m_viewManager &&
Chris@45 433 !m_viewManager->getClipboard().empty());
Chris@146 434 bool haveTabularLayer =
Chris@146 435 (haveCurrentLayer &&
Chris@146 436 dynamic_cast<TabularModel *>(currentLayer->getModel()));
Chris@45 437
Chris@45 438 emit canAddPane(haveMainModel);
Chris@45 439 emit canDeleteCurrentPane(haveCurrentPane);
Chris@45 440 emit canZoom(haveMainModel && haveCurrentPane);
Chris@45 441 emit canScroll(haveMainModel && haveCurrentPane);
Chris@45 442 emit canAddLayer(haveMainModel && haveCurrentPane);
Chris@45 443 emit canImportMoreAudio(haveMainModel);
Chris@259 444 emit canReplaceMainAudio(haveMainModel);
Chris@45 445 emit canImportLayer(haveMainModel && haveCurrentPane);
Chris@45 446 emit canExportAudio(haveMainModel);
Chris@45 447 emit canExportLayer(haveMainModel &&
Chris@45 448 (haveCurrentEditableLayer || haveCurrentColour3DPlot));
Chris@45 449 emit canExportImage(haveMainModel && haveCurrentPane);
Chris@45 450 emit canDeleteCurrentLayer(haveCurrentLayer);
Chris@45 451 emit canRenameLayer(haveCurrentLayer);
Chris@45 452 emit canEditLayer(haveCurrentEditableLayer);
Chris@146 453 emit canEditLayerTabular(haveCurrentEditableLayer || haveTabularLayer);
Chris@45 454 emit canMeasureLayer(haveCurrentLayer);
Chris@45 455 emit canSelect(haveMainModel && haveCurrentPane);
Chris@188 456 emit canPlay(haveMainModel && havePlayTarget);
Chris@45 457 emit canFfwd(true);
Chris@45 458 emit canRewind(true);
Chris@87 459 emit canPaste(haveClipboardContents);
Chris@45 460 emit canInsertInstant(haveCurrentPane);
Chris@45 461 emit canInsertInstantsAtBoundaries(haveCurrentPane && haveSelection);
Chris@184 462 emit canInsertItemAtSelection(haveCurrentPane && haveSelection && haveCurrentDurationLayer);
Chris@45 463 emit canRenumberInstants(haveCurrentTimeInstantsLayer && haveSelection);
Chris@45 464 emit canPlaySelection(haveMainModel && havePlayTarget && haveSelection);
Chris@45 465 emit canClearSelection(haveSelection);
Chris@45 466 emit canEditSelection(haveSelection && haveCurrentEditableLayer);
Chris@45 467 emit canSave(m_sessionFile != "" && m_documentModified);
Chris@73 468 emit canSelectPreviousPane(havePrevPane);
Chris@73 469 emit canSelectNextPane(haveNextPane);
Chris@73 470 emit canSelectPreviousLayer(havePrevLayer);
Chris@73 471 emit canSelectNextLayer(haveNextLayer);
Chris@45 472 }
Chris@45 473
Chris@45 474 void
Chris@45 475 MainWindowBase::documentModified()
Chris@45 476 {
Chris@233 477 // SVDEBUG << "MainWindowBase::documentModified" << endl;
Chris@45 478
Chris@45 479 if (!m_documentModified) {
Chris@45 480 //!!! this in subclass implementation?
Chris@45 481 setWindowTitle(tr("%1 (modified)").arg(windowTitle()));
Chris@45 482 }
Chris@45 483
Chris@45 484 m_documentModified = true;
Chris@45 485 updateMenuStates();
Chris@45 486 }
Chris@45 487
Chris@45 488 void
Chris@45 489 MainWindowBase::documentRestored()
Chris@45 490 {
Chris@233 491 // SVDEBUG << "MainWindowBase::documentRestored" << endl;
Chris@45 492
Chris@45 493 if (m_documentModified) {
Chris@45 494 //!!! this in subclass implementation?
Chris@45 495 QString wt(windowTitle());
Chris@45 496 wt.replace(tr(" (modified)"), "");
Chris@45 497 setWindowTitle(wt);
Chris@45 498 }
Chris@45 499
Chris@45 500 m_documentModified = false;
Chris@45 501 updateMenuStates();
Chris@45 502 }
Chris@45 503
Chris@45 504 void
Chris@45 505 MainWindowBase::playLoopToggled()
Chris@45 506 {
Chris@45 507 QAction *action = dynamic_cast<QAction *>(sender());
Chris@45 508
Chris@45 509 if (action) {
Chris@45 510 m_viewManager->setPlayLoopMode(action->isChecked());
Chris@45 511 } else {
Chris@45 512 m_viewManager->setPlayLoopMode(!m_viewManager->getPlayLoopMode());
Chris@45 513 }
Chris@45 514 }
Chris@45 515
Chris@45 516 void
Chris@45 517 MainWindowBase::playSelectionToggled()
Chris@45 518 {
Chris@45 519 QAction *action = dynamic_cast<QAction *>(sender());
Chris@45 520
Chris@45 521 if (action) {
Chris@45 522 m_viewManager->setPlaySelectionMode(action->isChecked());
Chris@45 523 } else {
Chris@45 524 m_viewManager->setPlaySelectionMode(!m_viewManager->getPlaySelectionMode());
Chris@45 525 }
Chris@45 526 }
Chris@45 527
Chris@45 528 void
Chris@45 529 MainWindowBase::playSoloToggled()
Chris@45 530 {
Chris@45 531 QAction *action = dynamic_cast<QAction *>(sender());
Chris@45 532
Chris@45 533 if (action) {
Chris@45 534 m_viewManager->setPlaySoloMode(action->isChecked());
Chris@45 535 } else {
Chris@45 536 m_viewManager->setPlaySoloMode(!m_viewManager->getPlaySoloMode());
Chris@45 537 }
Chris@45 538
Chris@45 539 if (m_viewManager->getPlaySoloMode()) {
Chris@45 540 currentPaneChanged(m_paneStack->getCurrentPane());
Chris@45 541 } else {
Chris@45 542 m_viewManager->setPlaybackModel(0);
Chris@45 543 if (m_playSource) {
Chris@45 544 m_playSource->clearSoloModelSet();
Chris@45 545 }
Chris@45 546 }
Chris@45 547 }
Chris@45 548
Chris@45 549 void
Chris@45 550 MainWindowBase::currentPaneChanged(Pane *p)
Chris@45 551 {
Chris@45 552 updateMenuStates();
Chris@45 553 updateVisibleRangeDisplay(p);
Chris@45 554
Chris@45 555 if (!p) return;
Chris@45 556
Chris@45 557 if (!(m_viewManager &&
Chris@45 558 m_playSource &&
Chris@45 559 m_viewManager->getPlaySoloMode())) {
Chris@45 560 if (m_viewManager) m_viewManager->setPlaybackModel(0);
Chris@45 561 return;
Chris@45 562 }
Chris@45 563
Chris@45 564 Model *prevPlaybackModel = m_viewManager->getPlaybackModel();
Chris@60 565
Chris@93 566 // What we want here is not the currently playing frame (unless we
Chris@93 567 // are about to clear out the audio playback buffers -- which may
Chris@93 568 // or may not be possible, depending on the audio driver). What
Chris@93 569 // we want is the frame that was last committed to the soundcard
Chris@93 570 // buffers, as the audio driver will continue playing up to that
Chris@93 571 // frame before switching to whichever one we decide we want to
Chris@93 572 // switch to, regardless of our efforts.
Chris@93 573
Chris@93 574 int frame = m_playSource->getCurrentBufferedFrame();
Chris@93 575
Chris@93 576 // std::cerr << "currentPaneChanged: current frame (in ref model) = " << frame << std::endl;
Chris@45 577
Chris@45 578 View::ModelSet soloModels = p->getModels();
Chris@45 579
Chris@57 580 View::ModelSet sources;
Chris@57 581 for (View::ModelSet::iterator mi = soloModels.begin();
Chris@57 582 mi != soloModels.end(); ++mi) {
Chris@190 583 // If a model in this pane is derived from something else,
Chris@190 584 // then we want to play that model as well -- if the model
Chris@190 585 // that's derived from it is not something that is itself
Chris@190 586 // individually playable (e.g. a waveform)
Chris@190 587 if (*mi &&
Chris@190 588 !dynamic_cast<RangeSummarisableTimeValueModel *>(*mi) &&
Chris@190 589 (*mi)->getSourceModel()) {
Chris@57 590 sources.insert((*mi)->getSourceModel());
Chris@57 591 }
Chris@57 592 }
Chris@57 593 for (View::ModelSet::iterator mi = sources.begin();
Chris@57 594 mi != sources.end(); ++mi) {
Chris@57 595 soloModels.insert(*mi);
Chris@57 596 }
Chris@57 597
Chris@60 598 //!!! Need an "atomic" way of telling the play source that the
Chris@60 599 //playback model has changed, and changing it on ViewManager --
Chris@60 600 //the play source should be making the setPlaybackModel call to
Chris@60 601 //ViewManager
Chris@60 602
Chris@45 603 for (View::ModelSet::iterator mi = soloModels.begin();
Chris@45 604 mi != soloModels.end(); ++mi) {
Chris@45 605 if (dynamic_cast<RangeSummarisableTimeValueModel *>(*mi)) {
Chris@45 606 m_viewManager->setPlaybackModel(*mi);
Chris@45 607 }
Chris@45 608 }
Chris@45 609
Chris@45 610 RangeSummarisableTimeValueModel *a =
Chris@45 611 dynamic_cast<RangeSummarisableTimeValueModel *>(prevPlaybackModel);
Chris@45 612 RangeSummarisableTimeValueModel *b =
Chris@45 613 dynamic_cast<RangeSummarisableTimeValueModel *>(m_viewManager->
Chris@45 614 getPlaybackModel());
Chris@45 615
Chris@45 616 m_playSource->setSoloModelSet(soloModels);
Chris@45 617
Chris@45 618 if (a && b && (a != b)) {
Chris@60 619 if (m_playSource->isPlaying()) m_playSource->play(frame);
Chris@45 620 }
Chris@45 621 }
Chris@45 622
Chris@45 623 void
Chris@45 624 MainWindowBase::currentLayerChanged(Pane *p, Layer *)
Chris@45 625 {
Chris@45 626 updateMenuStates();
Chris@45 627 updateVisibleRangeDisplay(p);
Chris@45 628 }
Chris@45 629
Chris@45 630 void
Chris@45 631 MainWindowBase::selectAll()
Chris@45 632 {
Chris@45 633 if (!getMainModel()) return;
Chris@45 634 m_viewManager->setSelection(Selection(getMainModel()->getStartFrame(),
Chris@45 635 getMainModel()->getEndFrame()));
Chris@45 636 }
Chris@45 637
Chris@45 638 void
Chris@45 639 MainWindowBase::selectToStart()
Chris@45 640 {
Chris@45 641 if (!getMainModel()) return;
Chris@45 642 m_viewManager->setSelection(Selection(getMainModel()->getStartFrame(),
Chris@45 643 m_viewManager->getGlobalCentreFrame()));
Chris@45 644 }
Chris@45 645
Chris@45 646 void
Chris@45 647 MainWindowBase::selectToEnd()
Chris@45 648 {
Chris@45 649 if (!getMainModel()) return;
Chris@45 650 m_viewManager->setSelection(Selection(m_viewManager->getGlobalCentreFrame(),
Chris@45 651 getMainModel()->getEndFrame()));
Chris@45 652 }
Chris@45 653
Chris@45 654 void
Chris@45 655 MainWindowBase::selectVisible()
Chris@45 656 {
Chris@45 657 Model *model = getMainModel();
Chris@45 658 if (!model) return;
Chris@45 659
Chris@45 660 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 661 if (!currentPane) return;
Chris@45 662
Chris@45 663 size_t startFrame, endFrame;
Chris@45 664
Chris@45 665 if (currentPane->getStartFrame() < 0) startFrame = 0;
Chris@45 666 else startFrame = currentPane->getStartFrame();
Chris@45 667
Chris@45 668 if (currentPane->getEndFrame() > model->getEndFrame()) endFrame = model->getEndFrame();
Chris@45 669 else endFrame = currentPane->getEndFrame();
Chris@45 670
Chris@45 671 m_viewManager->setSelection(Selection(startFrame, endFrame));
Chris@45 672 }
Chris@45 673
Chris@45 674 void
Chris@45 675 MainWindowBase::clearSelection()
Chris@45 676 {
Chris@45 677 m_viewManager->clearSelections();
Chris@45 678 }
Chris@45 679
Chris@45 680 void
Chris@45 681 MainWindowBase::cut()
Chris@45 682 {
Chris@45 683 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 684 if (!currentPane) return;
Chris@45 685
Chris@45 686 Layer *layer = currentPane->getSelectedLayer();
Chris@45 687 if (!layer) return;
Chris@45 688
Chris@45 689 Clipboard &clipboard = m_viewManager->getClipboard();
Chris@45 690 clipboard.clear();
Chris@45 691
Chris@45 692 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@45 693
Chris@45 694 CommandHistory::getInstance()->startCompoundOperation(tr("Cut"), true);
Chris@45 695
Chris@45 696 for (MultiSelection::SelectionList::iterator i = selections.begin();
Chris@45 697 i != selections.end(); ++i) {
Chris@86 698 layer->copy(currentPane, *i, clipboard);
Chris@45 699 layer->deleteSelection(*i);
Chris@45 700 }
Chris@45 701
Chris@45 702 CommandHistory::getInstance()->endCompoundOperation();
Chris@45 703 }
Chris@45 704
Chris@45 705 void
Chris@45 706 MainWindowBase::copy()
Chris@45 707 {
Chris@45 708 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 709 if (!currentPane) return;
Chris@45 710
Chris@45 711 Layer *layer = currentPane->getSelectedLayer();
Chris@45 712 if (!layer) return;
Chris@45 713
Chris@45 714 Clipboard &clipboard = m_viewManager->getClipboard();
Chris@45 715 clipboard.clear();
Chris@45 716
Chris@45 717 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@45 718
Chris@45 719 for (MultiSelection::SelectionList::iterator i = selections.begin();
Chris@45 720 i != selections.end(); ++i) {
Chris@86 721 layer->copy(currentPane, *i, clipboard);
Chris@45 722 }
Chris@45 723 }
Chris@45 724
Chris@45 725 void
Chris@45 726 MainWindowBase::paste()
Chris@45 727 {
Chris@215 728 pasteRelative(0);
Chris@215 729 }
Chris@215 730
Chris@215 731 void
Chris@215 732 MainWindowBase::pasteAtPlaybackPosition()
Chris@215 733 {
Chris@215 734 unsigned long pos = getFrame();
Chris@215 735 Clipboard &clipboard = m_viewManager->getClipboard();
Chris@215 736 if (!clipboard.empty()) {
Chris@215 737 long firstEventFrame = clipboard.getPoints()[0].getFrame();
Chris@215 738 long offset = 0;
Chris@215 739 if (firstEventFrame < 0) {
Chris@221 740 offset = (long)pos - firstEventFrame;
Chris@215 741 } else if (firstEventFrame < pos) {
Chris@221 742 offset = pos - (unsigned long)firstEventFrame;
Chris@215 743 } else {
Chris@221 744 offset = -((unsigned long)firstEventFrame - pos);
Chris@215 745 }
Chris@215 746 pasteRelative(offset);
Chris@215 747 }
Chris@215 748 }
Chris@215 749
Chris@215 750 void
Chris@215 751 MainWindowBase::pasteRelative(int offset)
Chris@215 752 {
Chris@45 753 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 754 if (!currentPane) return;
Chris@45 755
Chris@45 756 Layer *layer = currentPane->getSelectedLayer();
Chris@45 757
Chris@45 758 Clipboard &clipboard = m_viewManager->getClipboard();
Chris@87 759
Chris@98 760 bool inCompound = false;
Chris@87 761
Chris@87 762 if (!layer || !layer->isLayerEditable()) {
Chris@87 763
Chris@87 764 CommandHistory::getInstance()->startCompoundOperation
Chris@87 765 (tr("Paste"), true);
Chris@87 766
Chris@87 767 // no suitable current layer: create one of the most
Chris@87 768 // appropriate sort
Chris@87 769 LayerFactory::LayerType type =
Chris@87 770 LayerFactory::getInstance()->getLayerTypeForClipboardContents(clipboard);
Chris@87 771 layer = m_document->createEmptyLayer(type);
Chris@87 772
Chris@87 773 if (!layer) {
Chris@87 774 CommandHistory::getInstance()->endCompoundOperation();
Chris@87 775 return;
Chris@45 776 }
Chris@87 777
Chris@87 778 m_document->addLayerToView(currentPane, layer);
Chris@87 779 m_paneStack->setCurrentLayer(currentPane, layer);
Chris@87 780
Chris@87 781 inCompound = true;
Chris@45 782 }
Chris@45 783
Chris@215 784 layer->paste(currentPane, clipboard, offset, true);
Chris@45 785
Chris@87 786 if (inCompound) CommandHistory::getInstance()->endCompoundOperation();
Chris@45 787 }
Chris@45 788
Chris@45 789 void
Chris@45 790 MainWindowBase::deleteSelected()
Chris@45 791 {
Chris@45 792 if (m_paneStack->getCurrentPane() &&
Chris@45 793 m_paneStack->getCurrentPane()->getSelectedLayer()) {
Chris@45 794
Chris@45 795 Layer *layer = m_paneStack->getCurrentPane()->getSelectedLayer();
Chris@45 796
Chris@45 797 if (m_viewManager &&
Chris@45 798 (m_viewManager->getToolMode() == ViewManager::MeasureMode)) {
Chris@45 799
Chris@45 800 layer->deleteCurrentMeasureRect();
Chris@45 801
Chris@45 802 } else {
Chris@45 803
Chris@45 804 MultiSelection::SelectionList selections =
Chris@45 805 m_viewManager->getSelections();
Chris@45 806
Chris@45 807 for (MultiSelection::SelectionList::iterator i = selections.begin();
Chris@45 808 i != selections.end(); ++i) {
Chris@45 809 layer->deleteSelection(*i);
Chris@45 810 }
Chris@45 811 }
Chris@45 812 }
Chris@45 813 }
Chris@45 814
Chris@161 815 // FrameTimer method
Chris@161 816
Chris@161 817 unsigned long
Chris@161 818 MainWindowBase::getFrame() const
Chris@161 819 {
Chris@161 820 if (m_playSource && m_playSource->isPlaying()) {
Chris@161 821 return m_playSource->getCurrentPlayingFrame();
Chris@161 822 } else {
Chris@161 823 return m_viewManager->getPlaybackFrame();
Chris@161 824 }
Chris@161 825 }
Chris@161 826
Chris@45 827 void
Chris@45 828 MainWindowBase::insertInstant()
Chris@45 829 {
Chris@161 830 insertInstantAt(getFrame());
Chris@45 831 }
Chris@45 832
Chris@45 833 void
Chris@45 834 MainWindowBase::insertInstantsAtBoundaries()
Chris@45 835 {
Chris@45 836 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@45 837 for (MultiSelection::SelectionList::iterator i = selections.begin();
Chris@45 838 i != selections.end(); ++i) {
Chris@45 839 size_t start = i->getStartFrame();
Chris@45 840 size_t end = i->getEndFrame();
Chris@45 841 if (start != end) {
Chris@184 842 insertInstantAt(start);
Chris@184 843 insertInstantAt(end);
Chris@45 844 }
Chris@45 845 }
Chris@45 846 }
Chris@45 847
Chris@45 848 void
Chris@45 849 MainWindowBase::insertInstantAt(size_t frame)
Chris@45 850 {
Chris@45 851 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 852 if (!pane) {
Chris@45 853 return;
Chris@45 854 }
Chris@45 855
Chris@74 856 frame = pane->alignFromReference(frame);
Chris@74 857
Chris@45 858 Layer *layer = dynamic_cast<TimeInstantLayer *>
Chris@45 859 (pane->getSelectedLayer());
Chris@45 860
Chris@45 861 if (!layer) {
Chris@45 862 for (int i = pane->getLayerCount(); i > 0; --i) {
Chris@45 863 layer = dynamic_cast<TimeInstantLayer *>(pane->getLayer(i - 1));
Chris@45 864 if (layer) break;
Chris@45 865 }
Chris@45 866
Chris@45 867 if (!layer) {
Chris@45 868 CommandHistory::getInstance()->startCompoundOperation
Chris@45 869 (tr("Add Point"), true);
Chris@45 870 layer = m_document->createEmptyLayer(LayerFactory::TimeInstants);
Chris@45 871 if (layer) {
Chris@45 872 m_document->addLayerToView(pane, layer);
Chris@45 873 m_paneStack->setCurrentLayer(pane, layer);
Chris@45 874 }
Chris@45 875 CommandHistory::getInstance()->endCompoundOperation();
Chris@45 876 }
Chris@45 877 }
Chris@45 878
Chris@45 879 if (layer) {
Chris@45 880
Chris@45 881 Model *model = layer->getModel();
Chris@45 882 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
Chris@45 883 (model);
Chris@45 884
Chris@45 885 if (sodm) {
Chris@45 886 SparseOneDimensionalModel::Point point(frame, "");
Chris@45 887
Chris@45 888 SparseOneDimensionalModel::Point prevPoint(0);
Chris@45 889 bool havePrevPoint = false;
Chris@45 890
Chris@45 891 SparseOneDimensionalModel::EditCommand *command =
Chris@45 892 new SparseOneDimensionalModel::EditCommand(sodm, tr("Add Point"));
Chris@45 893
Chris@74 894 if (m_labeller->requiresPrevPoint()) {
Chris@45 895
Chris@45 896 SparseOneDimensionalModel::PointList prevPoints =
Chris@45 897 sodm->getPreviousPoints(frame);
Chris@45 898
Chris@45 899 if (!prevPoints.empty()) {
Chris@45 900 prevPoint = *prevPoints.begin();
Chris@45 901 havePrevPoint = true;
Chris@45 902 }
Chris@45 903 }
Chris@45 904
Chris@45 905 if (m_labeller) {
Chris@45 906
Chris@45 907 m_labeller->setSampleRate(sodm->getSampleRate());
Chris@45 908
Chris@74 909 if (m_labeller->actingOnPrevPoint()) {
Chris@45 910 command->deletePoint(prevPoint);
Chris@45 911 }
Chris@45 912
Chris@45 913 m_labeller->label<SparseOneDimensionalModel::Point>
Chris@45 914 (point, havePrevPoint ? &prevPoint : 0);
Chris@45 915
Chris@74 916 if (m_labeller->actingOnPrevPoint()) {
Chris@45 917 command->addPoint(prevPoint);
Chris@45 918 }
Chris@45 919 }
Chris@45 920
Chris@45 921 command->addPoint(point);
Chris@45 922
Chris@45 923 command->setName(tr("Add Point at %1 s")
Chris@45 924 .arg(RealTime::frame2RealTime
Chris@45 925 (frame,
Chris@45 926 sodm->getSampleRate())
Chris@45 927 .toText(false).c_str()));
Chris@45 928
Chris@108 929 Command *c = command->finish();
Chris@108 930 if (c) CommandHistory::getInstance()->addCommand(c, false);
Chris@45 931 }
Chris@45 932 }
Chris@45 933 }
Chris@45 934
Chris@45 935 void
Chris@184 936 MainWindowBase::insertItemAtSelection()
Chris@184 937 {
Chris@184 938 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@184 939 for (MultiSelection::SelectionList::iterator i = selections.begin();
Chris@184 940 i != selections.end(); ++i) {
Chris@184 941 size_t start = i->getStartFrame();
Chris@184 942 size_t end = i->getEndFrame();
Chris@184 943 if (start < end) {
Chris@184 944 insertItemAt(start, end - start);
Chris@184 945 }
Chris@184 946 }
Chris@184 947 }
Chris@184 948
Chris@184 949 void
Chris@184 950 MainWindowBase::insertItemAt(size_t frame, size_t duration)
Chris@184 951 {
Chris@184 952 Pane *pane = m_paneStack->getCurrentPane();
Chris@184 953 if (!pane) {
Chris@184 954 return;
Chris@184 955 }
Chris@184 956
Chris@184 957 // ugh!
Chris@184 958
Chris@184 959 size_t alignedStart = pane->alignFromReference(frame);
Chris@184 960 size_t alignedEnd = pane->alignFromReference(frame + duration);
Chris@184 961 if (alignedStart >= alignedEnd) return;
Chris@184 962 size_t alignedDuration = alignedEnd - alignedStart;
Chris@184 963
Chris@184 964 Command *c = 0;
Chris@184 965
Chris@184 966 QString name = tr("Add Item at %1 s")
Chris@184 967 .arg(RealTime::frame2RealTime
Chris@184 968 (alignedStart,
Chris@184 969 getMainModel()->getSampleRate())
Chris@184 970 .toText(false).c_str());
Chris@184 971
Chris@184 972 Layer *layer = pane->getSelectedLayer();
Chris@184 973 if (!layer) return;
Chris@184 974
Chris@184 975 RegionModel *rm = dynamic_cast<RegionModel *>(layer->getModel());
Chris@184 976 if (rm) {
Chris@184 977 RegionModel::Point point(alignedStart,
Chris@185 978 rm->getValueMaximum() + 1,
Chris@184 979 alignedDuration,
Chris@184 980 "");
Chris@184 981 RegionModel::EditCommand *command =
Chris@184 982 new RegionModel::EditCommand(rm, tr("Add Point"));
Chris@184 983 command->addPoint(point);
Chris@184 984 command->setName(name);
Chris@184 985 c = command->finish();
Chris@184 986 }
Chris@184 987
Chris@184 988 if (c) {
Chris@184 989 CommandHistory::getInstance()->addCommand(c, false);
Chris@184 990 return;
Chris@184 991 }
Chris@184 992
Chris@184 993 NoteModel *nm = dynamic_cast<NoteModel *>(layer->getModel());
Chris@184 994 if (nm) {
Chris@184 995 NoteModel::Point point(alignedStart,
Chris@184 996 rm->getValueMinimum(),
Chris@184 997 alignedDuration,
Chris@184 998 1.f,
Chris@184 999 "");
Chris@184 1000 NoteModel::EditCommand *command =
Chris@184 1001 new NoteModel::EditCommand(nm, tr("Add Point"));
Chris@184 1002 command->addPoint(point);
Chris@184 1003 command->setName(name);
Chris@184 1004 c = command->finish();
Chris@184 1005 }
Chris@184 1006
Chris@184 1007 if (c) {
Chris@184 1008 CommandHistory::getInstance()->addCommand(c, false);
Chris@184 1009 return;
Chris@184 1010 }
Chris@184 1011 }
Chris@184 1012
Chris@184 1013 void
Chris@45 1014 MainWindowBase::renumberInstants()
Chris@45 1015 {
Chris@45 1016 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 1017 if (!pane) return;
Chris@45 1018
Chris@45 1019 Layer *layer = dynamic_cast<TimeInstantLayer *>(pane->getSelectedLayer());
Chris@45 1020 if (!layer) return;
Chris@45 1021
Chris@45 1022 MultiSelection ms(m_viewManager->getSelection());
Chris@45 1023
Chris@45 1024 Model *model = layer->getModel();
Chris@45 1025 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
Chris@45 1026 (model);
Chris@45 1027 if (!sodm) return;
Chris@45 1028
Chris@45 1029 if (!m_labeller) return;
Chris@45 1030
Chris@45 1031 Labeller labeller(*m_labeller);
Chris@45 1032 labeller.setSampleRate(sodm->getSampleRate());
Chris@45 1033
Chris@45 1034 // This uses a command
Chris@45 1035
Chris@45 1036 labeller.labelAll<SparseOneDimensionalModel::Point>(*sodm, &ms);
Chris@45 1037 }
Chris@45 1038
Chris@45 1039 MainWindowBase::FileOpenStatus
Chris@45 1040 MainWindowBase::open(QString fileOrUrl, AudioFileOpenMode mode)
Chris@45 1041 {
Chris@134 1042 ProgressDialog dialog(tr("Opening file or URL..."), true, 2000, this);
Chris@134 1043 connect(&dialog, SIGNAL(showing()), this, SIGNAL(hideSplash()));
Chris@109 1044 return open(FileSource(fileOrUrl, &dialog), mode);
Chris@45 1045 }
Chris@45 1046
Chris@45 1047 MainWindowBase::FileOpenStatus
Chris@45 1048 MainWindowBase::open(FileSource source, AudioFileOpenMode mode)
Chris@45 1049 {
Chris@45 1050 FileOpenStatus status;
Chris@45 1051
Chris@45 1052 if (!source.isAvailable()) return FileOpenFailed;
Chris@45 1053 source.waitForData();
Chris@45 1054
Chris@45 1055 bool canImportLayer = (getMainModel() != 0 &&
Chris@45 1056 m_paneStack != 0 &&
Chris@45 1057 m_paneStack->getCurrentPane() != 0);
Chris@45 1058
Chris@152 1059 bool rdf = (source.getExtension().toLower() == "rdf" ||
Chris@152 1060 source.getExtension().toLower() == "n3" ||
Chris@152 1061 source.getExtension().toLower() == "ttl");
Chris@152 1062
Chris@152 1063 bool audio = AudioFileReaderFactory::getKnownExtensions().contains
Chris@152 1064 (source.getExtension().toLower());
Chris@145 1065
Chris@145 1066 bool rdfSession = false;
Chris@145 1067 if (rdf) {
Chris@145 1068 RDFImporter::RDFDocumentType rdfType =
Chris@145 1069 RDFImporter::identifyDocumentType
Chris@145 1070 (QUrl::fromLocalFile(source.getLocalFilename()).toString());
Chris@148 1071 // std::cerr << "RDF type: " << (int)rdfType << std::endl;
Chris@145 1072 if (rdfType == RDFImporter::AudioRefAndAnnotations ||
Chris@145 1073 rdfType == RDFImporter::AudioRef) {
Chris@145 1074 rdfSession = true;
Chris@145 1075 } else if (rdfType == RDFImporter::NotRDF) {
Chris@145 1076 rdf = false;
Chris@145 1077 }
Chris@145 1078 }
Chris@145 1079
Chris@145 1080 if (rdf) {
Chris@145 1081 if (rdfSession) {
Chris@147 1082 bool cancel = false;
Chris@147 1083 if (!canImportLayer || shouldCreateNewSessionForRDFAudio(&cancel)) {
Chris@145 1084 return openSession(source);
Chris@147 1085 } else if (cancel) {
Chris@147 1086 return FileOpenCancelled;
Chris@145 1087 } else {
Chris@145 1088 return openLayer(source);
Chris@145 1089 }
Chris@145 1090 } else {
Chris@145 1091 if ((status = openSession(source)) != FileOpenFailed) {
Chris@145 1092 return status;
Chris@145 1093 } else if (!canImportLayer) {
Chris@145 1094 return FileOpenWrongMode;
Chris@145 1095 } else if ((status = openLayer(source)) != FileOpenFailed) {
Chris@145 1096 return status;
Chris@145 1097 } else {
Chris@145 1098 return FileOpenFailed;
Chris@145 1099 }
Chris@145 1100 }
Chris@145 1101 }
Chris@145 1102
Chris@152 1103 if (audio && (status = openAudio(source, mode)) != FileOpenFailed) {
Chris@45 1104 return status;
Chris@45 1105 } else if ((status = openSession(source)) != FileOpenFailed) {
Chris@45 1106 return status;
Chris@45 1107 } else if ((status = openPlaylist(source, mode)) != FileOpenFailed) {
Chris@45 1108 return status;
Chris@45 1109 } else if (!canImportLayer) {
Chris@45 1110 return FileOpenWrongMode;
Chris@45 1111 } else if ((status = openImage(source)) != FileOpenFailed) {
Chris@45 1112 return status;
Chris@45 1113 } else if ((status = openLayer(source)) != FileOpenFailed) {
Chris@45 1114 return status;
Chris@45 1115 } else {
Chris@45 1116 return FileOpenFailed;
Chris@45 1117 }
Chris@45 1118 }
Chris@45 1119
Chris@45 1120 MainWindowBase::FileOpenStatus
Chris@227 1121 MainWindowBase::openAudio(FileSource source, AudioFileOpenMode mode,
Chris@227 1122 QString templateName)
Chris@45 1123 {
Chris@233 1124 // SVDEBUG << "MainWindowBase::openAudio(" << source.getLocation() << ")" << endl;
Chris@45 1125
Chris@222 1126 if (templateName == "") {
Chris@231 1127 templateName = getDefaultSessionTemplate();
Chris@222 1128 }
Chris@220 1129
Chris@223 1130 std::cerr << "template is: \"" << templateName.toStdString() << "\"" << std::endl;
Chris@223 1131
Chris@45 1132 if (!source.isAvailable()) return FileOpenFailed;
Chris@45 1133 source.waitForData();
Chris@45 1134
Chris@45 1135 m_openingAudioFile = true;
Chris@45 1136
Chris@45 1137 size_t rate = 0;
Chris@45 1138
Chris@45 1139 if (Preferences::getInstance()->getResampleOnLoad()) {
Chris@45 1140 rate = m_playSource->getSourceSampleRate();
Chris@45 1141 }
Chris@45 1142
Chris@45 1143 WaveFileModel *newModel = new WaveFileModel(source, rate);
Chris@45 1144
Chris@45 1145 if (!newModel->isOK()) {
Chris@45 1146 delete newModel;
Chris@45 1147 m_openingAudioFile = false;
Chris@45 1148 return FileOpenFailed;
Chris@45 1149 }
Chris@45 1150
Chris@132 1151 // std::cerr << "mode = " << mode << std::endl;
Chris@45 1152
Chris@45 1153 if (mode == AskUser) {
Chris@45 1154 if (getMainModel()) {
Chris@45 1155
Chris@147 1156 QSettings settings;
Chris@147 1157 settings.beginGroup("MainWindow");
Chris@221 1158 int lastMode = settings.value("lastaudioopenmode", 0).toBool();
Chris@147 1159 settings.endGroup();
Chris@221 1160 int imode = 0;
Chris@45 1161
Chris@45 1162 QStringList items;
Chris@221 1163 items << tr("Close the current session and start a new one")
Chris@221 1164 << tr("Replace the main audio file in this session")
Chris@221 1165 << tr("Add the audio file to this session");
Chris@45 1166
Chris@45 1167 bool ok = false;
Chris@45 1168 QString item = ListInputDialog::getItem
Chris@45 1169 (this, tr("Select target for import"),
Chris@221 1170 tr("<b>Select a target for import</b><p>You already have an audio file loaded.<br>What would you like to do with the new audio file?"),
Chris@221 1171 items, lastMode, &ok);
Chris@45 1172
Chris@45 1173 if (!ok || item.isEmpty()) {
Chris@45 1174 delete newModel;
Chris@45 1175 m_openingAudioFile = false;
Chris@45 1176 return FileOpenCancelled;
Chris@45 1177 }
Chris@45 1178
Chris@221 1179 for (int i = 0; i < items.size(); ++i) {
Chris@221 1180 if (item == items[i]) imode = i;
Chris@221 1181 }
Chris@221 1182
Chris@147 1183 settings.beginGroup("MainWindow");
Chris@221 1184 settings.setValue("lastaudioopenmode", imode);
Chris@147 1185 settings.endGroup();
Chris@45 1186
Chris@221 1187 mode = (AudioFileOpenMode)imode;
Chris@45 1188
Chris@45 1189 } else {
Chris@221 1190 // no main model: make a new session
Chris@221 1191 mode = ReplaceSession;
Chris@45 1192 }
Chris@45 1193 }
Chris@45 1194
Chris@45 1195 if (mode == ReplaceCurrentPane) {
Chris@45 1196
Chris@45 1197 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 1198 if (pane) {
Chris@45 1199 if (getMainModel()) {
Chris@45 1200 View::ModelSet models(pane->getModels());
Chris@45 1201 if (models.find(getMainModel()) != models.end()) {
Chris@221 1202 // Current pane contains main model: replace that
Chris@45 1203 mode = ReplaceMainModel;
Chris@45 1204 }
Chris@221 1205 // Otherwise the current pane has a non-default model,
Chris@221 1206 // which we will deal with later
Chris@45 1207 } else {
Chris@221 1208 // We have no main model, so start a new session with
Chris@221 1209 // optional template
Chris@221 1210 mode = ReplaceSession;
Chris@45 1211 }
Chris@45 1212 } else {
Chris@221 1213 // We seem to have no current pane! Oh well
Chris@45 1214 mode = CreateAdditionalModel;
Chris@45 1215 }
Chris@45 1216 }
Chris@45 1217
Chris@45 1218 if (mode == CreateAdditionalModel && !getMainModel()) {
Chris@221 1219 mode = ReplaceSession;
Chris@221 1220 }
Chris@221 1221
Chris@221 1222 bool loadedTemplate = false;
Chris@221 1223
Chris@221 1224 if (mode == ReplaceSession) {
Chris@258 1225
Chris@258 1226 if (!checkSaveModified()) return FileOpenCancelled;
Chris@258 1227
Chris@237 1228 std::cerr << "SV looking for template " << templateName << std::endl;
Chris@230 1229 if (templateName != "") {
Chris@230 1230 FileOpenStatus tplStatus = openSessionTemplate(templateName);
Chris@258 1231 if (tplStatus == FileOpenCancelled) {
Chris@258 1232 std::cerr << "Template load cancelled" << std::endl;
Chris@258 1233 return FileOpenCancelled;
Chris@258 1234 }
Chris@230 1235 if (tplStatus != FileOpenFailed) {
Chris@230 1236 std::cerr << "Template load succeeded" << std::endl;
Chris@230 1237 loadedTemplate = true;
Chris@221 1238 }
Chris@221 1239 }
Chris@221 1240
Chris@221 1241 if (!loadedTemplate) {
Chris@221 1242 closeSession();
Chris@221 1243 createDocument();
Chris@221 1244 }
Chris@221 1245
Chris@45 1246 mode = ReplaceMainModel;
Chris@45 1247 }
Chris@45 1248
Chris@164 1249 emit activity(tr("Import audio file \"%1\"").arg(source.getLocation()));
Chris@164 1250
Chris@45 1251 if (mode == ReplaceMainModel) {
Chris@45 1252
Chris@45 1253 Model *prevMain = getMainModel();
Chris@45 1254 if (prevMain) {
Chris@45 1255 m_playSource->removeModel(prevMain);
Chris@108 1256 PlayParameterRepository::getInstance()->removePlayable(prevMain);
Chris@45 1257 }
Chris@108 1258 PlayParameterRepository::getInstance()->addPlayable(newModel);
Chris@45 1259
Chris@248 1260 SVDEBUG << "SV about to call setMainModel(" << newModel << "): prevMain is " << prevMain << endl;
Chris@248 1261
Chris@45 1262 m_document->setMainModel(newModel);
Chris@45 1263
Chris@45 1264 setupMenus();
Chris@45 1265
dan@210 1266 if (loadedTemplate || (m_sessionFile == "")) {
Chris@45 1267 //!!! shouldn't be dealing directly with title from here -- call a method
Chris@57 1268 setWindowTitle(tr("%1: %2")
Chris@57 1269 .arg(QApplication::applicationName())
Chris@45 1270 .arg(source.getLocation()));
Chris@45 1271 CommandHistory::getInstance()->clear();
Chris@45 1272 CommandHistory::getInstance()->documentSaved();
Chris@45 1273 m_documentModified = false;
Chris@45 1274 } else {
Chris@57 1275 setWindowTitle(tr("%1: %2 [%3]")
Chris@57 1276 .arg(QApplication::applicationName())
Chris@45 1277 .arg(QFileInfo(m_sessionFile).fileName())
Chris@45 1278 .arg(source.getLocation()));
Chris@45 1279 if (m_documentModified) {
Chris@45 1280 m_documentModified = false;
Chris@45 1281 documentModified(); // so as to restore "(modified)" window title
Chris@45 1282 }
Chris@45 1283 }
Chris@45 1284
Chris@45 1285 if (!source.isRemote()) m_audioFile = source.getLocalFilename();
Chris@45 1286
Chris@45 1287 } else if (mode == CreateAdditionalModel) {
Chris@45 1288
Chris@45 1289 CommandHistory::getInstance()->startCompoundOperation
Chris@219 1290 (tr("Import \"%1\"").arg(source.getBasename()), true);
Chris@45 1291
Chris@45 1292 m_document->addImportedModel(newModel);
Chris@45 1293
Chris@45 1294 AddPaneCommand *command = new AddPaneCommand(this);
Chris@45 1295 CommandHistory::getInstance()->addCommand(command);
Chris@45 1296
Chris@45 1297 Pane *pane = command->getPane();
Chris@45 1298
Chris@47 1299 if (m_timeRulerLayer) {
Chris@47 1300 m_document->addLayerToView(pane, m_timeRulerLayer);
Chris@47 1301 }
Chris@45 1302
Chris@45 1303 Layer *newLayer = m_document->createImportedLayer(newModel);
Chris@45 1304
Chris@45 1305 if (newLayer) {
Chris@45 1306 m_document->addLayerToView(pane, newLayer);
Chris@45 1307 }
Chris@45 1308
Chris@45 1309 CommandHistory::getInstance()->endCompoundOperation();
Chris@45 1310
Chris@45 1311 } else if (mode == ReplaceCurrentPane) {
Chris@45 1312
Chris@45 1313 // We know there is a current pane, otherwise we would have
Chris@45 1314 // reset the mode to CreateAdditionalModel above; and we know
Chris@45 1315 // the current pane does not contain the main model, otherwise
Chris@45 1316 // we would have reset it to ReplaceMainModel. But we don't
Chris@45 1317 // know whether the pane contains a waveform model at all.
Chris@45 1318
Chris@45 1319 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 1320 Layer *replace = 0;
Chris@45 1321
Chris@45 1322 for (int i = 0; i < pane->getLayerCount(); ++i) {
Chris@45 1323 Layer *layer = pane->getLayer(i);
Chris@45 1324 if (dynamic_cast<WaveformLayer *>(layer)) {
Chris@45 1325 replace = layer;
Chris@45 1326 break;
Chris@45 1327 }
Chris@45 1328 }
Chris@45 1329
Chris@45 1330 CommandHistory::getInstance()->startCompoundOperation
Chris@219 1331 (tr("Import \"%1\"").arg(source.getBasename()), true);
Chris@45 1332
Chris@45 1333 m_document->addImportedModel(newModel);
Chris@45 1334
Chris@45 1335 if (replace) {
Chris@45 1336 m_document->removeLayerFromView(pane, replace);
Chris@45 1337 }
Chris@45 1338
Chris@45 1339 Layer *newLayer = m_document->createImportedLayer(newModel);
Chris@45 1340
Chris@45 1341 if (newLayer) {
Chris@45 1342 m_document->addLayerToView(pane, newLayer);
Chris@45 1343 }
Chris@45 1344
Chris@45 1345 CommandHistory::getInstance()->endCompoundOperation();
Chris@45 1346 }
Chris@45 1347
Chris@45 1348 updateMenuStates();
Chris@45 1349 m_recentFiles.addFile(source.getLocation());
Chris@45 1350 if (!source.isRemote()) {
Chris@45 1351 // for file dialog
Chris@45 1352 registerLastOpenedFilePath(FileFinder::AudioFile,
Chris@45 1353 source.getLocalFilename());
Chris@45 1354 }
Chris@45 1355 m_openingAudioFile = false;
Chris@45 1356
Chris@45 1357 currentPaneChanged(m_paneStack->getCurrentPane());
Chris@45 1358
Chris@45 1359 return FileOpenSucceeded;
Chris@45 1360 }
Chris@45 1361
Chris@45 1362 MainWindowBase::FileOpenStatus
Chris@45 1363 MainWindowBase::openPlaylist(FileSource source, AudioFileOpenMode mode)
Chris@45 1364 {
Chris@233 1365 SVDEBUG << "MainWindowBase::openPlaylist(" << source.getLocation() << ")" << endl;
Chris@135 1366
Chris@45 1367 std::set<QString> extensions;
Chris@45 1368 PlaylistFileReader::getSupportedExtensions(extensions);
Chris@152 1369 QString extension = source.getExtension().toLower();
Chris@45 1370 if (extensions.find(extension) == extensions.end()) return FileOpenFailed;
Chris@45 1371
Chris@45 1372 if (!source.isAvailable()) return FileOpenFailed;
Chris@45 1373 source.waitForData();
Chris@45 1374
Chris@45 1375 PlaylistFileReader reader(source.getLocalFilename());
Chris@45 1376 if (!reader.isOK()) return FileOpenFailed;
Chris@45 1377
Chris@45 1378 PlaylistFileReader::Playlist playlist = reader.load();
Chris@45 1379
Chris@45 1380 bool someSuccess = false;
Chris@45 1381
Chris@45 1382 for (PlaylistFileReader::Playlist::const_iterator i = playlist.begin();
Chris@45 1383 i != playlist.end(); ++i) {
Chris@45 1384
Chris@134 1385 ProgressDialog dialog(tr("Opening playlist..."), true, 2000, this);
Chris@134 1386 connect(&dialog, SIGNAL(showing()), this, SIGNAL(hideSplash()));
Chris@109 1387 FileOpenStatus status = openAudio(FileSource(*i, &dialog), mode);
Chris@45 1388
Chris@45 1389 if (status == FileOpenCancelled) {
Chris@45 1390 return FileOpenCancelled;
Chris@45 1391 }
Chris@45 1392
Chris@45 1393 if (status == FileOpenSucceeded) {
Chris@45 1394 someSuccess = true;
Chris@45 1395 mode = CreateAdditionalModel;
Chris@45 1396 }
Chris@45 1397 }
Chris@45 1398
Chris@45 1399 if (someSuccess) return FileOpenSucceeded;
Chris@45 1400 else return FileOpenFailed;
Chris@45 1401 }
Chris@45 1402
Chris@45 1403 MainWindowBase::FileOpenStatus
Chris@45 1404 MainWindowBase::openLayer(FileSource source)
Chris@45 1405 {
Chris@233 1406 SVDEBUG << "MainWindowBase::openLayer(" << source.getLocation() << ")" << endl;
Chris@135 1407
Chris@45 1408 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 1409
Chris@45 1410 if (!pane) {
Chris@45 1411 // shouldn't happen, as the menu action should have been disabled
Chris@45 1412 std::cerr << "WARNING: MainWindowBase::openLayer: no current pane" << std::endl;
Chris@45 1413 return FileOpenWrongMode;
Chris@45 1414 }
Chris@45 1415
Chris@45 1416 if (!getMainModel()) {
Chris@45 1417 // shouldn't happen, as the menu action should have been disabled
Chris@45 1418 std::cerr << "WARNING: MainWindowBase::openLayer: No main model -- hence no default sample rate available" << std::endl;
Chris@45 1419 return FileOpenWrongMode;
Chris@45 1420 }
Chris@45 1421
Chris@45 1422 if (!source.isAvailable()) return FileOpenFailed;
Chris@45 1423 source.waitForData();
Chris@45 1424
Chris@45 1425 QString path = source.getLocalFilename();
Chris@45 1426
Chris@145 1427 RDFImporter::RDFDocumentType rdfType =
Chris@145 1428 RDFImporter::identifyDocumentType(QUrl::fromLocalFile(path).toString());
Chris@145 1429
Chris@148 1430 // std::cerr << "RDF type: (in layer) " << (int) rdfType << std::endl;
Chris@148 1431
Chris@145 1432 if (rdfType != RDFImporter::NotRDF) {
Chris@145 1433
Chris@145 1434 return openLayersFromRDF(source);
Chris@134 1435
Chris@152 1436 } else if (source.getExtension().toLower() == "svl" ||
Chris@152 1437 (source.getExtension().toLower() == "xml" &&
Chris@140 1438 (SVFileReader::identifyXmlFile(source.getLocalFilename())
Chris@140 1439 == SVFileReader::SVLayerFile))) {
Chris@45 1440
Chris@45 1441 PaneCallback callback(this);
Chris@45 1442 QFile file(path);
Chris@45 1443
Chris@45 1444 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
Chris@45 1445 std::cerr << "ERROR: MainWindowBase::openLayer("
Chris@45 1446 << source.getLocation().toStdString()
Chris@45 1447 << "): Failed to open file for reading" << std::endl;
Chris@45 1448 return FileOpenFailed;
Chris@45 1449 }
Chris@45 1450
Chris@45 1451 SVFileReader reader(m_document, callback, source.getLocation());
Chris@79 1452 connect
Chris@79 1453 (&reader, SIGNAL(modelRegenerationFailed(QString, QString, QString)),
Chris@79 1454 this, SLOT(modelRegenerationFailed(QString, QString, QString)));
Chris@79 1455 connect
Chris@79 1456 (&reader, SIGNAL(modelRegenerationWarning(QString, QString, QString)),
Chris@79 1457 this, SLOT(modelRegenerationWarning(QString, QString, QString)));
Chris@45 1458 reader.setCurrentPane(pane);
Chris@45 1459
Chris@45 1460 QXmlInputSource inputSource(&file);
Chris@45 1461 reader.parse(inputSource);
Chris@45 1462
Chris@45 1463 if (!reader.isOK()) {
Chris@45 1464 std::cerr << "ERROR: MainWindowBase::openLayer("
Chris@45 1465 << source.getLocation().toStdString()
Chris@45 1466 << "): Failed to read XML file: "
Chris@228 1467 << reader.getErrorString() << std::endl;
Chris@45 1468 return FileOpenFailed;
Chris@45 1469 }
Chris@45 1470
Chris@164 1471 emit activity(tr("Import layer XML file \"%1\"").arg(source.getLocation()));
Chris@164 1472
Chris@45 1473 m_recentFiles.addFile(source.getLocation());
Chris@45 1474
Chris@45 1475 if (!source.isRemote()) {
Chris@45 1476 registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog
Chris@45 1477 }
Chris@45 1478
Chris@75 1479 return FileOpenSucceeded;
Chris@75 1480
Chris@45 1481 } else {
Chris@45 1482
Chris@45 1483 try {
Chris@45 1484
Chris@109 1485 MIDIFileImportDialog midiDlg(this);
Chris@109 1486
Chris@109 1487 Model *model = DataFileReaderFactory::loadNonCSV
Chris@109 1488 (path, &midiDlg, getMainModel()->getSampleRate());
Chris@45 1489
Chris@109 1490 if (!model) {
Chris@196 1491 CSVFormat format(path);
Chris@196 1492 format.setSampleRate(getMainModel()->getSampleRate());
Chris@196 1493 CSVFormatDialog *dialog = new CSVFormatDialog(this, format);
Chris@109 1494 if (dialog->exec() == QDialog::Accepted) {
Chris@109 1495 model = DataFileReaderFactory::loadCSV
Chris@109 1496 (path, dialog->getFormat(),
Chris@109 1497 getMainModel()->getSampleRate());
Chris@109 1498 }
Chris@109 1499 }
Chris@109 1500
Chris@45 1501 if (model) {
Chris@45 1502
Chris@233 1503 SVDEBUG << "MainWindowBase::openLayer: Have model" << endl;
Chris@45 1504
Chris@164 1505 emit activity(tr("Import MIDI file \"%1\"").arg(source.getLocation()));
Chris@164 1506
Chris@45 1507 Layer *newLayer = m_document->createImportedLayer(model);
Chris@45 1508
Chris@45 1509 if (newLayer) {
Chris@45 1510
Chris@45 1511 m_document->addLayerToView(pane, newLayer);
Chris@88 1512 m_paneStack->setCurrentLayer(pane, newLayer);
Chris@88 1513
Chris@45 1514 m_recentFiles.addFile(source.getLocation());
Chris@45 1515
Chris@45 1516 if (!source.isRemote()) {
Chris@45 1517 registerLastOpenedFilePath
Chris@45 1518 (FileFinder::LayerFile,
Chris@45 1519 path); // for file dialog
Chris@45 1520 }
Chris@88 1521
Chris@45 1522 return FileOpenSucceeded;
Chris@45 1523 }
Chris@45 1524 }
Chris@45 1525 } catch (DataFileReaderFactory::Exception e) {
Chris@45 1526 if (e == DataFileReaderFactory::ImportCancelled) {
Chris@45 1527 return FileOpenCancelled;
Chris@45 1528 }
Chris@45 1529 }
Chris@45 1530 }
Chris@45 1531
Chris@45 1532 return FileOpenFailed;
Chris@45 1533 }
Chris@45 1534
Chris@45 1535 MainWindowBase::FileOpenStatus
Chris@45 1536 MainWindowBase::openImage(FileSource source)
Chris@45 1537 {
Chris@233 1538 SVDEBUG << "MainWindowBase::openImage(" << source.getLocation() << ")" << endl;
Chris@135 1539
Chris@45 1540 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 1541
Chris@45 1542 if (!pane) {
Chris@45 1543 // shouldn't happen, as the menu action should have been disabled
Chris@45 1544 std::cerr << "WARNING: MainWindowBase::openImage: no current pane" << std::endl;
Chris@45 1545 return FileOpenWrongMode;
Chris@45 1546 }
Chris@45 1547
Chris@45 1548 if (!m_document->getMainModel()) {
Chris@45 1549 return FileOpenWrongMode;
Chris@45 1550 }
Chris@45 1551
Chris@45 1552 bool newLayer = false;
Chris@45 1553
Chris@45 1554 ImageLayer *il = dynamic_cast<ImageLayer *>(pane->getSelectedLayer());
Chris@45 1555 if (!il) {
Chris@45 1556 for (int i = pane->getLayerCount()-1; i >= 0; --i) {
Chris@45 1557 il = dynamic_cast<ImageLayer *>(pane->getLayer(i));
Chris@45 1558 if (il) break;
Chris@45 1559 }
Chris@45 1560 }
Chris@45 1561 if (!il) {
Chris@45 1562 il = dynamic_cast<ImageLayer *>
Chris@45 1563 (m_document->createEmptyLayer(LayerFactory::Image));
Chris@45 1564 if (!il) return FileOpenFailed;
Chris@45 1565 newLayer = true;
Chris@45 1566 }
Chris@45 1567
Chris@45 1568 // We don't put the image file in Recent Files
Chris@45 1569
Chris@228 1570 std::cerr << "openImage: trying location \"" << source.getLocation() << "\" in image layer" << std::endl;
Chris@45 1571
Chris@45 1572 if (!il->addImage(m_viewManager->getGlobalCentreFrame(), source.getLocation())) {
Chris@45 1573 if (newLayer) {
Chris@52 1574 m_document->deleteLayer(il); // also releases its model
Chris@45 1575 }
Chris@45 1576 return FileOpenFailed;
Chris@45 1577 } else {
Chris@45 1578 if (newLayer) {
Chris@45 1579 m_document->addLayerToView(pane, il);
Chris@45 1580 }
Chris@45 1581 m_paneStack->setCurrentLayer(pane, il);
Chris@45 1582 }
Chris@45 1583
Chris@45 1584 return FileOpenSucceeded;
Chris@45 1585 }
Chris@45 1586
Chris@45 1587 MainWindowBase::FileOpenStatus
Chris@45 1588 MainWindowBase::openSessionFile(QString fileOrUrl)
Chris@45 1589 {
Chris@134 1590 ProgressDialog dialog(tr("Opening session..."), true, 2000, this);
Chris@134 1591 connect(&dialog, SIGNAL(showing()), this, SIGNAL(hideSplash()));
Chris@109 1592 return openSession(FileSource(fileOrUrl, &dialog));
Chris@45 1593 }
Chris@45 1594
Chris@45 1595 MainWindowBase::FileOpenStatus
Chris@45 1596 MainWindowBase::openSession(FileSource source)
Chris@45 1597 {
Chris@233 1598 SVDEBUG << "MainWindowBase::openSession(" << source.getLocation() << ")" << endl;
Chris@135 1599
Chris@45 1600 if (!source.isAvailable()) return FileOpenFailed;
Chris@145 1601 source.waitForData();
Chris@141 1602
Chris@227 1603 if (source.getExtension().toLower() != "sv") {
Chris@145 1604
Chris@145 1605 RDFImporter::RDFDocumentType rdfType =
Chris@145 1606 RDFImporter::identifyDocumentType
Chris@145 1607 (QUrl::fromLocalFile(source.getLocalFilename()).toString());
Chris@145 1608
Chris@148 1609 // std::cerr << "RDF type: " << (int)rdfType << std::endl;
Chris@148 1610
Chris@145 1611 if (rdfType == RDFImporter::AudioRefAndAnnotations ||
Chris@145 1612 rdfType == RDFImporter::AudioRef) {
Chris@145 1613 return openSessionFromRDF(source);
Chris@145 1614 } else if (rdfType != RDFImporter::NotRDF) {
Chris@145 1615 return FileOpenFailed;
Chris@145 1616 }
Chris@145 1617
Chris@152 1618 if (source.getExtension().toLower() == "xml") {
Chris@140 1619 if (SVFileReader::identifyXmlFile(source.getLocalFilename()) ==
Chris@140 1620 SVFileReader::SVSessionFile) {
Chris@140 1621 std::cerr << "This XML file looks like a session file, attempting to open it as a session" << std::endl;
Chris@140 1622 } else {
Chris@140 1623 return FileOpenFailed;
Chris@140 1624 }
Chris@140 1625 } else {
Chris@140 1626 return FileOpenFailed;
Chris@140 1627 }
Chris@140 1628 }
Chris@45 1629
Chris@140 1630 QXmlInputSource *inputSource = 0;
Chris@140 1631 BZipFileDevice *bzFile = 0;
Chris@140 1632 QFile *rawFile = 0;
Chris@140 1633
Chris@152 1634 if (source.getExtension().toLower() == "sv") {
Chris@140 1635 bzFile = new BZipFileDevice(source.getLocalFilename());
Chris@140 1636 if (!bzFile->open(QIODevice::ReadOnly)) {
Chris@140 1637 delete bzFile;
Chris@140 1638 return FileOpenFailed;
Chris@140 1639 }
Chris@140 1640 inputSource = new QXmlInputSource(bzFile);
Chris@140 1641 } else {
Chris@140 1642 rawFile = new QFile(source.getLocalFilename());
Chris@140 1643 inputSource = new QXmlInputSource(rawFile);
Chris@140 1644 }
Chris@140 1645
Chris@140 1646 if (!checkSaveModified()) {
Chris@140 1647 if (bzFile) bzFile->close();
Chris@140 1648 delete inputSource;
Chris@140 1649 delete bzFile;
Chris@140 1650 delete rawFile;
Chris@140 1651 return FileOpenCancelled;
Chris@140 1652 }
Chris@45 1653
Chris@45 1654 QString error;
Chris@45 1655 closeSession();
Chris@45 1656 createDocument();
Chris@45 1657
Chris@45 1658 PaneCallback callback(this);
Chris@45 1659 m_viewManager->clearSelections();
Chris@45 1660
Chris@45 1661 SVFileReader reader(m_document, callback, source.getLocation());
Chris@79 1662 connect
Chris@79 1663 (&reader, SIGNAL(modelRegenerationFailed(QString, QString, QString)),
Chris@79 1664 this, SLOT(modelRegenerationFailed(QString, QString, QString)));
Chris@79 1665 connect
Chris@79 1666 (&reader, SIGNAL(modelRegenerationWarning(QString, QString, QString)),
Chris@79 1667 this, SLOT(modelRegenerationWarning(QString, QString, QString)));
Chris@140 1668
Chris@140 1669 reader.parse(*inputSource);
Chris@45 1670
Chris@45 1671 if (!reader.isOK()) {
Chris@45 1672 error = tr("SV XML file read error:\n%1").arg(reader.getErrorString());
Chris@45 1673 }
Chris@45 1674
Chris@140 1675 if (bzFile) bzFile->close();
Chris@140 1676
Chris@140 1677 delete inputSource;
Chris@140 1678 delete bzFile;
Chris@140 1679 delete rawFile;
Chris@45 1680
Chris@45 1681 bool ok = (error == "");
Chris@45 1682
Chris@45 1683 if (ok) {
Chris@45 1684
Chris@164 1685 emit activity(tr("Import session file \"%1\"").arg(source.getLocation()));
Chris@164 1686
Chris@57 1687 setWindowTitle(tr("%1: %2")
Chris@57 1688 .arg(QApplication::applicationName())
Chris@45 1689 .arg(source.getLocation()));
Chris@45 1690
Chris@45 1691 if (!source.isRemote()) m_sessionFile = source.getLocalFilename();
Chris@45 1692
Chris@45 1693 setupMenus();
Chris@45 1694
Chris@45 1695 CommandHistory::getInstance()->clear();
Chris@45 1696 CommandHistory::getInstance()->documentSaved();
Chris@45 1697 m_documentModified = false;
Chris@45 1698 updateMenuStates();
Chris@45 1699
Chris@227 1700 m_recentFiles.addFile(source.getLocation());
Chris@45 1701
Chris@45 1702 if (!source.isRemote()) {
Chris@45 1703 // for file dialog
Chris@45 1704 registerLastOpenedFilePath(FileFinder::SessionFile,
Chris@227 1705 source.getLocalFilename());
Chris@45 1706 }
Chris@45 1707
Chris@45 1708 } else {
Chris@57 1709 setWindowTitle(QApplication::applicationName());
Chris@45 1710 }
Chris@45 1711
Chris@45 1712 return ok ? FileOpenSucceeded : FileOpenFailed;
Chris@45 1713 }
Chris@45 1714
Chris@141 1715 MainWindowBase::FileOpenStatus
Chris@230 1716 MainWindowBase::openSessionTemplate(QString templateName)
Chris@230 1717 {
Chris@230 1718 // Template in the user's template directory takes
Chris@230 1719 // priority over a bundled one; we don't unbundle, but
Chris@230 1720 // open directly from the bundled file (where applicable)
Chris@230 1721 ResourceFinder rf;
Chris@230 1722 QString tfile = rf.getResourcePath("templates", templateName + ".svt");
Chris@230 1723 if (tfile != "") {
Chris@230 1724 std::cerr << "SV loading template file " << tfile.toStdString() << std::endl;
Chris@230 1725 return openSessionTemplate(FileSource("file:" + tfile));
Chris@230 1726 } else {
Chris@230 1727 return FileOpenFailed;
Chris@230 1728 }
Chris@230 1729 }
Chris@230 1730
Chris@230 1731 MainWindowBase::FileOpenStatus
Chris@227 1732 MainWindowBase::openSessionTemplate(FileSource source)
Chris@227 1733 {
Chris@227 1734 std::cerr << "MainWindowBase::openSessionTemplate(" << source.getLocation().toStdString() << ")" << std::endl;
Chris@227 1735
Chris@227 1736 if (!source.isAvailable()) return FileOpenFailed;
Chris@227 1737 source.waitForData();
Chris@227 1738
Chris@227 1739 QXmlInputSource *inputSource = 0;
Chris@227 1740 QFile *file = 0;
Chris@227 1741 bool isTemplate = false;
Chris@227 1742
Chris@227 1743 file = new QFile(source.getLocalFilename());
Chris@227 1744 inputSource = new QXmlInputSource(file);
Chris@227 1745
Chris@227 1746 if (!checkSaveModified()) {
Chris@227 1747 delete inputSource;
Chris@227 1748 delete file;
Chris@227 1749 return FileOpenCancelled;
Chris@227 1750 }
Chris@227 1751
Chris@227 1752 QString error;
Chris@227 1753 closeSession();
Chris@227 1754 createDocument();
Chris@227 1755
Chris@227 1756 PaneCallback callback(this);
Chris@227 1757 m_viewManager->clearSelections();
Chris@227 1758
Chris@227 1759 SVFileReader reader(m_document, callback, source.getLocation());
Chris@227 1760 connect
Chris@227 1761 (&reader, SIGNAL(modelRegenerationFailed(QString, QString, QString)),
Chris@227 1762 this, SLOT(modelRegenerationFailed(QString, QString, QString)));
Chris@227 1763 connect
Chris@227 1764 (&reader, SIGNAL(modelRegenerationWarning(QString, QString, QString)),
Chris@227 1765 this, SLOT(modelRegenerationWarning(QString, QString, QString)));
Chris@227 1766
Chris@227 1767 reader.parse(*inputSource);
Chris@227 1768
Chris@227 1769 if (!reader.isOK()) {
Chris@227 1770 error = tr("SV XML file read error:\n%1").arg(reader.getErrorString());
Chris@227 1771 }
Chris@227 1772
Chris@227 1773 delete inputSource;
Chris@227 1774 delete file;
Chris@227 1775
Chris@227 1776 bool ok = (error == "");
Chris@227 1777
Chris@227 1778 setWindowTitle(QApplication::applicationName());
Chris@227 1779
Chris@227 1780 if (ok) {
Chris@227 1781
Chris@227 1782 emit activity(tr("Open session template \"%1\"").arg(source.getLocation()));
Chris@227 1783
Chris@227 1784 setupMenus();
Chris@227 1785
Chris@227 1786 CommandHistory::getInstance()->clear();
Chris@227 1787 CommandHistory::getInstance()->documentSaved();
Chris@227 1788 m_documentModified = false;
Chris@227 1789 updateMenuStates();
Chris@227 1790 }
Chris@227 1791
Chris@227 1792 return ok ? FileOpenSucceeded : FileOpenFailed;
Chris@227 1793 }
Chris@227 1794
Chris@227 1795 MainWindowBase::FileOpenStatus
Chris@141 1796 MainWindowBase::openSessionFromRDF(FileSource source)
Chris@141 1797 {
Chris@233 1798 SVDEBUG << "MainWindowBase::openSessionFromRDF(" << source.getLocation() << ")" << endl;
Chris@141 1799
Chris@141 1800 if (!source.isAvailable()) return FileOpenFailed;
Chris@141 1801 source.waitForData();
Chris@141 1802
Chris@145 1803 if (!checkSaveModified()) {
Chris@145 1804 return FileOpenCancelled;
Chris@141 1805 }
Chris@143 1806
Chris@145 1807 closeSession();
Chris@145 1808 createDocument();
Chris@145 1809
Chris@145 1810 FileOpenStatus status = openLayersFromRDF(source);
Chris@141 1811
Chris@141 1812 setupMenus();
Chris@141 1813
Chris@141 1814 setWindowTitle(tr("%1: %2")
Chris@141 1815 .arg(QApplication::applicationName())
Chris@141 1816 .arg(source.getLocation()));
Chris@141 1817 CommandHistory::getInstance()->clear();
Chris@141 1818 CommandHistory::getInstance()->documentSaved();
Chris@141 1819 m_documentModified = false;
Chris@145 1820
Chris@145 1821 return status;
Chris@145 1822 }
Chris@145 1823
Chris@145 1824 MainWindowBase::FileOpenStatus
Chris@145 1825 MainWindowBase::openLayersFromRDF(FileSource source)
Chris@145 1826 {
Chris@145 1827 size_t rate = 0;
Chris@145 1828
Chris@233 1829 SVDEBUG << "MainWindowBase::openLayersFromRDF" << endl;
Chris@186 1830
Chris@145 1831 ProgressDialog dialog(tr("Importing from RDF..."), true, 2000, this);
Chris@145 1832 connect(&dialog, SIGNAL(showing()), this, SIGNAL(hideSplash()));
Chris@145 1833
Chris@145 1834 if (getMainModel()) {
Chris@145 1835 rate = getMainModel()->getSampleRate();
Chris@145 1836 } else if (Preferences::getInstance()->getResampleOnLoad()) {
Chris@145 1837 rate = m_playSource->getSourceSampleRate();
Chris@145 1838 }
Chris@145 1839
Chris@145 1840 RDFImporter importer
Chris@145 1841 (QUrl::fromLocalFile(source.getLocalFilename()).toString(), rate);
Chris@145 1842
Chris@145 1843 if (!importer.isOK()) {
Chris@147 1844 if (importer.getErrorString() != "") {
Chris@147 1845 QMessageBox::critical
Chris@147 1846 (this, tr("Failed to import RDF"),
Chris@147 1847 tr("<b>Failed to import RDF</b><p>Importing data from RDF document at \"%1\" failed: %2</p>")
Chris@147 1848 .arg(source.getLocation()).arg(importer.getErrorString()));
Chris@147 1849 }
Chris@145 1850 return FileOpenFailed;
Chris@145 1851 }
Chris@145 1852
Chris@145 1853 std::vector<Model *> models = importer.getDataModels(&dialog);
Chris@145 1854
Chris@145 1855 dialog.setMessage(tr("Importing from RDF..."));
Chris@145 1856
Chris@145 1857 if (models.empty()) {
Chris@186 1858 QMessageBox::critical
Chris@186 1859 (this, tr("Failed to import RDF"),
Chris@186 1860 tr("<b>Failed to import RDF</b><p>No suitable data models found for import from RDF document at \"%1\"</p>").arg(source.getLocation()));
Chris@145 1861 return FileOpenFailed;
Chris@145 1862 }
Chris@145 1863
Chris@164 1864 emit activity(tr("Import RDF document \"%1\"").arg(source.getLocation()));
Chris@164 1865
Chris@145 1866 std::set<Model *> added;
Chris@145 1867
Chris@221 1868 for (int i = 0; i < (int)models.size(); ++i) {
Chris@145 1869
Chris@145 1870 Model *m = models[i];
Chris@145 1871 WaveFileModel *w = dynamic_cast<WaveFileModel *>(m);
Chris@145 1872
Chris@145 1873 if (w) {
Chris@145 1874
Chris@145 1875 Pane *pane = addPaneToStack();
Chris@145 1876 Layer *layer = 0;
Chris@145 1877
Chris@145 1878 if (m_timeRulerLayer) {
Chris@145 1879 m_document->addLayerToView(pane, m_timeRulerLayer);
Chris@145 1880 }
Chris@145 1881
Chris@145 1882 if (!getMainModel()) {
Chris@145 1883 m_document->setMainModel(w);
Chris@145 1884 layer = m_document->createMainModelLayer(LayerFactory::Waveform);
Chris@145 1885 } else {
Chris@145 1886 layer = m_document->createImportedLayer(w);
Chris@145 1887 }
Chris@145 1888
Chris@145 1889 m_document->addLayerToView(pane, layer);
Chris@145 1890
Chris@145 1891 added.insert(w);
Chris@145 1892
Chris@221 1893 for (int j = 0; j < (int)models.size(); ++j) {
Chris@145 1894
Chris@145 1895 Model *dm = models[j];
Chris@145 1896
Chris@145 1897 if (dm == m) continue;
Chris@145 1898 if (dm->getSourceModel() != m) continue;
Chris@145 1899
Chris@145 1900 layer = m_document->createImportedLayer(dm);
Chris@145 1901
Chris@145 1902 if (layer->isLayerOpaque() ||
Chris@145 1903 dynamic_cast<Colour3DPlotLayer *>(layer)) {
Chris@145 1904
Chris@156 1905 // these always go in a new pane, with nothing
Chris@156 1906 // else going in the same pane
Chris@156 1907
Chris@145 1908 Pane *singleLayerPane = addPaneToStack();
Chris@145 1909 if (m_timeRulerLayer) {
Chris@145 1910 m_document->addLayerToView(singleLayerPane, m_timeRulerLayer);
Chris@145 1911 }
Chris@145 1912 m_document->addLayerToView(singleLayerPane, layer);
Chris@145 1913
Chris@156 1914 } else if (layer->getLayerColourSignificance() ==
Chris@156 1915 Layer::ColourHasMeaningfulValue) {
Chris@156 1916
Chris@156 1917 // these can go in a pane with something else, but
Chris@156 1918 // only if none of the something elses also have
Chris@156 1919 // this quality
Chris@156 1920
Chris@156 1921 bool needNewPane = false;
Chris@156 1922 for (int i = 0; i < pane->getLayerCount(); ++i) {
Chris@156 1923 Layer *otherLayer = pane->getLayer(i);
Chris@156 1924 if (otherLayer &&
Chris@156 1925 (otherLayer->getLayerColourSignificance() ==
Chris@156 1926 Layer::ColourHasMeaningfulValue)) {
Chris@156 1927 needNewPane = true;
Chris@156 1928 break;
Chris@156 1929 }
Chris@156 1930 }
Chris@156 1931 if (needNewPane) {
Chris@156 1932 pane = addPaneToStack();
Chris@156 1933 }
Chris@156 1934
Chris@156 1935 m_document->addLayerToView(pane, layer);
Chris@156 1936
Chris@145 1937 } else {
Chris@145 1938
Chris@145 1939 if (pane->getLayerCount() > 4) {
Chris@145 1940 pane = addPaneToStack();
Chris@145 1941 }
Chris@145 1942
Chris@145 1943 m_document->addLayerToView(pane, layer);
Chris@145 1944 }
Chris@145 1945
Chris@145 1946 added.insert(dm);
Chris@145 1947 }
Chris@145 1948 }
Chris@145 1949 }
Chris@145 1950
Chris@221 1951 for (int i = 0; i < (int)models.size(); ++i) {
Chris@145 1952
Chris@145 1953 Model *m = models[i];
Chris@145 1954
Chris@145 1955 if (added.find(m) == added.end()) {
Chris@145 1956
Chris@145 1957 Layer *layer = m_document->createImportedLayer(m);
Chris@145 1958 if (!layer) return FileOpenFailed;
Chris@145 1959
Chris@145 1960 Pane *singleLayerPane = addPaneToStack();
Chris@145 1961 if (m_timeRulerLayer) {
Chris@145 1962 m_document->addLayerToView(singleLayerPane, m_timeRulerLayer);
Chris@145 1963 }
Chris@145 1964 m_document->addLayerToView(singleLayerPane, layer);
Chris@145 1965 }
Chris@145 1966 }
Chris@145 1967
Chris@145 1968 m_recentFiles.addFile(source.getLocation());
Chris@145 1969 return FileOpenSucceeded;
Chris@141 1970 }
Chris@141 1971
Chris@45 1972 void
Chris@45 1973 MainWindowBase::createPlayTarget()
Chris@45 1974 {
Chris@45 1975 if (m_playTarget) return;
Chris@45 1976
Chris@126 1977 QSettings settings;
Chris@126 1978 settings.beginGroup("Preferences");
Chris@126 1979 QString targetName = settings.value("audio-target", "").toString();
Chris@126 1980 settings.endGroup();
Chris@126 1981
Chris@126 1982 AudioTargetFactory *factory = AudioTargetFactory::getInstance();
Chris@126 1983
Chris@126 1984 factory->setDefaultCallbackTarget(targetName);
Chris@126 1985 m_playTarget = factory->createCallbackTarget(m_playSource);
Chris@126 1986
Chris@45 1987 if (!m_playTarget) {
Chris@104 1988 emit hideSplash();
Chris@126 1989
Chris@126 1990 if (factory->isAutoCallbackTarget(targetName)) {
Chris@128 1991 QMessageBox::warning
Chris@45 1992 (this, tr("Couldn't open audio device"),
Chris@126 1993 tr("<b>No audio available</b><p>Could not open an audio device for playback.<p>Automatic audio device detection failed. Audio playback will not be available during this session.</p>"),
Chris@45 1994 QMessageBox::Ok);
Chris@126 1995 } else {
Chris@126 1996 QMessageBox::warning
Chris@126 1997 (this, tr("Couldn't open audio device"),
Chris@126 1998 tr("<b>No audio available</b><p>Failed to open your preferred audio device (\"%1\").<p>Audio playback will not be available during this session.</p>")
Chris@126 1999 .arg(factory->getCallbackTargetDescription(targetName)),
Chris@126 2000 QMessageBox::Ok);
Chris@126 2001 }
Chris@45 2002 }
Chris@45 2003 }
Chris@45 2004
Chris@45 2005 WaveFileModel *
Chris@45 2006 MainWindowBase::getMainModel()
Chris@45 2007 {
Chris@45 2008 if (!m_document) return 0;
Chris@45 2009 return m_document->getMainModel();
Chris@45 2010 }
Chris@45 2011
Chris@45 2012 const WaveFileModel *
Chris@45 2013 MainWindowBase::getMainModel() const
Chris@45 2014 {
Chris@45 2015 if (!m_document) return 0;
Chris@45 2016 return m_document->getMainModel();
Chris@45 2017 }
Chris@45 2018
Chris@45 2019 void
Chris@45 2020 MainWindowBase::createDocument()
Chris@45 2021 {
Chris@45 2022 m_document = new Document;
Chris@45 2023
Chris@45 2024 connect(m_document, SIGNAL(layerAdded(Layer *)),
Chris@45 2025 this, SLOT(layerAdded(Layer *)));
Chris@45 2026 connect(m_document, SIGNAL(layerRemoved(Layer *)),
Chris@45 2027 this, SLOT(layerRemoved(Layer *)));
Chris@45 2028 connect(m_document, SIGNAL(layerAboutToBeDeleted(Layer *)),
Chris@45 2029 this, SLOT(layerAboutToBeDeleted(Layer *)));
Chris@45 2030 connect(m_document, SIGNAL(layerInAView(Layer *, bool)),
Chris@45 2031 this, SLOT(layerInAView(Layer *, bool)));
Chris@45 2032
Chris@45 2033 connect(m_document, SIGNAL(modelAdded(Model *)),
Chris@45 2034 this, SLOT(modelAdded(Model *)));
Chris@45 2035 connect(m_document, SIGNAL(mainModelChanged(WaveFileModel *)),
Chris@45 2036 this, SLOT(mainModelChanged(WaveFileModel *)));
Chris@45 2037 connect(m_document, SIGNAL(modelAboutToBeDeleted(Model *)),
Chris@45 2038 this, SLOT(modelAboutToBeDeleted(Model *)));
Chris@45 2039
Chris@78 2040 connect(m_document, SIGNAL(modelGenerationFailed(QString, QString)),
Chris@78 2041 this, SLOT(modelGenerationFailed(QString, QString)));
Chris@78 2042 connect(m_document, SIGNAL(modelRegenerationWarning(QString, QString, QString)),
Chris@78 2043 this, SLOT(modelRegenerationWarning(QString, QString, QString)));
Chris@78 2044 connect(m_document, SIGNAL(modelGenerationFailed(QString, QString)),
Chris@78 2045 this, SLOT(modelGenerationFailed(QString, QString)));
Chris@78 2046 connect(m_document, SIGNAL(modelRegenerationWarning(QString, QString, QString)),
Chris@78 2047 this, SLOT(modelRegenerationWarning(QString, QString, QString)));
Chris@78 2048 connect(m_document, SIGNAL(alignmentFailed(QString, QString)),
Chris@78 2049 this, SLOT(alignmentFailed(QString, QString)));
Chris@160 2050
Chris@160 2051 emit replacedDocument();
Chris@45 2052 }
Chris@45 2053
Chris@45 2054 bool
Chris@45 2055 MainWindowBase::saveSessionFile(QString path)
Chris@45 2056 {
Chris@217 2057 try {
Chris@217 2058
Chris@217 2059 TempWriteFile temp(path);
Chris@217 2060
Chris@217 2061 BZipFileDevice bzFile(temp.getTemporaryFilename());
Chris@217 2062 if (!bzFile.open(QIODevice::WriteOnly)) {
Chris@217 2063 std::cerr << "Failed to open session file \""
Chris@217 2064 << temp.getTemporaryFilename().toStdString()
Chris@217 2065 << "\" for writing: "
Chris@228 2066 << bzFile.errorString() << std::endl;
Chris@217 2067 return false;
Chris@217 2068 }
Chris@217 2069
Chris@217 2070 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
Chris@217 2071
Chris@217 2072 QTextStream out(&bzFile);
Chris@226 2073 toXml(out, false);
Chris@217 2074 out.flush();
Chris@217 2075
Chris@217 2076 QApplication::restoreOverrideCursor();
Chris@217 2077
Chris@217 2078 if (!bzFile.isOK()) {
Chris@217 2079 QMessageBox::critical(this, tr("Failed to write file"),
Chris@217 2080 tr("<b>Save failed</b><p>Failed to write to file \"%1\": %2")
Chris@217 2081 .arg(path).arg(bzFile.errorString()));
Chris@217 2082 bzFile.close();
Chris@217 2083 return false;
Chris@217 2084 }
Chris@217 2085
Chris@217 2086 bzFile.close();
Chris@217 2087 temp.moveToTarget();
Chris@217 2088 return true;
Chris@217 2089
Chris@217 2090 } catch (FileOperationFailed &f) {
Chris@217 2091
Chris@217 2092 QMessageBox::critical(this, tr("Failed to write file"),
Chris@217 2093 tr("<b>Save failed</b><p>Failed to write to file \"%1\": %2")
Chris@217 2094 .arg(path).arg(f.what()));
Chris@45 2095 return false;
Chris@45 2096 }
Chris@45 2097 }
Chris@45 2098
Chris@224 2099 bool
Chris@224 2100 MainWindowBase::saveSessionTemplate(QString path)
Chris@224 2101 {
Chris@224 2102 try {
Chris@224 2103
Chris@224 2104 TempWriteFile temp(path);
Chris@224 2105
Chris@224 2106 QFile file(temp.getTemporaryFilename());
Chris@224 2107 if (!file.open(QIODevice::WriteOnly)) {
Chris@224 2108 std::cerr << "Failed to open session template file \""
Chris@224 2109 << temp.getTemporaryFilename().toStdString()
Chris@224 2110 << "\" for writing: "
Chris@224 2111 << file.errorString().toStdString() << std::endl;
Chris@224 2112 return false;
Chris@224 2113 }
Chris@224 2114
Chris@224 2115 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
Chris@224 2116
Chris@224 2117 QTextStream out(&file);
Chris@226 2118 toXml(out, true);
Chris@224 2119 out.flush();
Chris@224 2120
Chris@224 2121 QApplication::restoreOverrideCursor();
Chris@224 2122
Chris@224 2123 file.close();
Chris@224 2124 temp.moveToTarget();
Chris@224 2125 return true;
Chris@224 2126
Chris@224 2127 } catch (FileOperationFailed &f) {
Chris@224 2128
Chris@224 2129 QMessageBox::critical(this, tr("Failed to write file"),
Chris@224 2130 tr("<b>Save failed</b><p>Failed to write to file \"%1\": %2")
Chris@224 2131 .arg(path).arg(f.what()));
Chris@224 2132 return false;
Chris@224 2133 }
Chris@224 2134 }
Chris@224 2135
Chris@45 2136 void
Chris@226 2137 MainWindowBase::toXml(QTextStream &out, bool asTemplate)
Chris@45 2138 {
Chris@45 2139 QString indent(" ");
Chris@45 2140
Chris@45 2141 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
Chris@45 2142 out << "<!DOCTYPE sonic-visualiser>\n";
Chris@45 2143 out << "<sv>\n";
Chris@45 2144
Chris@226 2145 if (asTemplate) {
Chris@226 2146 m_document->toXmlAsTemplate(out, "", "");
Chris@226 2147 } else {
Chris@226 2148 m_document->toXml(out, "", "");
Chris@226 2149 }
Chris@45 2150
Chris@45 2151 out << "<display>\n";
Chris@45 2152
Chris@45 2153 out << QString(" <window width=\"%1\" height=\"%2\"/>\n")
Chris@45 2154 .arg(width()).arg(height());
Chris@45 2155
Chris@45 2156 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@45 2157
Chris@45 2158 Pane *pane = m_paneStack->getPane(i);
Chris@45 2159
Chris@45 2160 if (pane) {
Chris@45 2161 pane->toXml(out, indent);
Chris@45 2162 }
Chris@45 2163 }
Chris@45 2164
Chris@45 2165 out << "</display>\n";
Chris@45 2166
Chris@45 2167 m_viewManager->getSelection().toXml(out);
Chris@45 2168
Chris@45 2169 out << "</sv>\n";
Chris@45 2170 }
Chris@45 2171
Chris@45 2172 Pane *
Chris@45 2173 MainWindowBase::addPaneToStack()
Chris@45 2174 {
Chris@45 2175 AddPaneCommand *command = new AddPaneCommand(this);
Chris@45 2176 CommandHistory::getInstance()->addCommand(command);
Chris@57 2177 Pane *pane = command->getPane();
Chris@57 2178 return pane;
Chris@45 2179 }
Chris@45 2180
Chris@45 2181 void
Chris@45 2182 MainWindowBase::zoomIn()
Chris@45 2183 {
Chris@45 2184 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 2185 if (currentPane) currentPane->zoom(true);
Chris@45 2186 }
Chris@45 2187
Chris@45 2188 void
Chris@45 2189 MainWindowBase::zoomOut()
Chris@45 2190 {
Chris@45 2191 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 2192 if (currentPane) currentPane->zoom(false);
Chris@45 2193 }
Chris@45 2194
Chris@45 2195 void
Chris@45 2196 MainWindowBase::zoomToFit()
Chris@45 2197 {
Chris@45 2198 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 2199 if (!currentPane) return;
Chris@45 2200
Chris@45 2201 Model *model = getMainModel();
Chris@45 2202 if (!model) return;
Chris@45 2203
Chris@45 2204 size_t start = model->getStartFrame();
Chris@45 2205 size_t end = model->getEndFrame();
Chris@60 2206 if (m_playSource) end = std::max(end, m_playSource->getPlayEndFrame());
Chris@45 2207 size_t pixels = currentPane->width();
Chris@45 2208
Chris@45 2209 size_t sw = currentPane->getVerticalScaleWidth();
Chris@45 2210 if (pixels > sw * 2) pixels -= sw * 2;
Chris@45 2211 else pixels = 1;
Chris@45 2212 if (pixels > 4) pixels -= 4;
Chris@45 2213
Chris@45 2214 size_t zoomLevel = (end - start) / pixels;
Chris@150 2215 if (zoomLevel < 1) zoomLevel = 1;
Chris@45 2216
Chris@45 2217 currentPane->setZoomLevel(zoomLevel);
Chris@45 2218 currentPane->setCentreFrame((start + end) / 2);
Chris@45 2219 }
Chris@45 2220
Chris@45 2221 void
Chris@45 2222 MainWindowBase::zoomDefault()
Chris@45 2223 {
Chris@45 2224 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 2225 if (currentPane) currentPane->setZoomLevel(1024);
Chris@45 2226 }
Chris@45 2227
Chris@45 2228 void
Chris@45 2229 MainWindowBase::scrollLeft()
Chris@45 2230 {
Chris@45 2231 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 2232 if (currentPane) currentPane->scroll(false, false);
Chris@45 2233 }
Chris@45 2234
Chris@45 2235 void
Chris@45 2236 MainWindowBase::jumpLeft()
Chris@45 2237 {
Chris@45 2238 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 2239 if (currentPane) currentPane->scroll(false, true);
Chris@45 2240 }
Chris@45 2241
Chris@45 2242 void
Chris@162 2243 MainWindowBase::peekLeft()
Chris@162 2244 {
Chris@162 2245 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@162 2246 if (currentPane) currentPane->scroll(false, false, false);
Chris@162 2247 }
Chris@162 2248
Chris@162 2249 void
Chris@45 2250 MainWindowBase::scrollRight()
Chris@45 2251 {
Chris@45 2252 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 2253 if (currentPane) currentPane->scroll(true, false);
Chris@45 2254 }
Chris@45 2255
Chris@45 2256 void
Chris@45 2257 MainWindowBase::jumpRight()
Chris@45 2258 {
Chris@45 2259 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 2260 if (currentPane) currentPane->scroll(true, true);
Chris@45 2261 }
Chris@45 2262
Chris@45 2263 void
Chris@162 2264 MainWindowBase::peekRight()
Chris@162 2265 {
Chris@162 2266 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@162 2267 if (currentPane) currentPane->scroll(true, false, false);
Chris@162 2268 }
Chris@162 2269
Chris@162 2270 void
Chris@45 2271 MainWindowBase::showNoOverlays()
Chris@45 2272 {
Chris@45 2273 m_viewManager->setOverlayMode(ViewManager::NoOverlays);
Chris@45 2274 }
Chris@45 2275
Chris@45 2276 void
Chris@45 2277 MainWindowBase::showMinimalOverlays()
Chris@45 2278 {
Chris@45 2279 m_viewManager->setOverlayMode(ViewManager::MinimalOverlays);
Chris@45 2280 }
Chris@45 2281
Chris@45 2282 void
Chris@45 2283 MainWindowBase::showAllOverlays()
Chris@45 2284 {
Chris@45 2285 m_viewManager->setOverlayMode(ViewManager::AllOverlays);
Chris@45 2286 }
Chris@45 2287
Chris@45 2288 void
Chris@211 2289 MainWindowBase::toggleTimeRulers()
Chris@211 2290 {
Chris@211 2291 bool haveRulers = false;
Chris@211 2292 bool someHidden = false;
Chris@211 2293
Chris@211 2294 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@211 2295
Chris@211 2296 Pane *pane = m_paneStack->getPane(i);
Chris@211 2297 if (!pane) continue;
Chris@211 2298
Chris@211 2299 for (int j = 0; j < pane->getLayerCount(); ++j) {
Chris@211 2300
Chris@211 2301 Layer *layer = pane->getLayer(j);
Chris@211 2302 if (!dynamic_cast<TimeRulerLayer *>(layer)) continue;
Chris@211 2303
Chris@211 2304 haveRulers = true;
Chris@211 2305 if (layer->isLayerDormant(pane)) someHidden = true;
Chris@211 2306 }
Chris@211 2307 }
Chris@211 2308
Chris@211 2309 if (haveRulers) {
Chris@211 2310
Chris@211 2311 bool show = someHidden;
Chris@211 2312
Chris@211 2313 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@211 2314
Chris@211 2315 Pane *pane = m_paneStack->getPane(i);
Chris@211 2316 if (!pane) continue;
Chris@211 2317
Chris@211 2318 for (int j = 0; j < pane->getLayerCount(); ++j) {
Chris@211 2319
Chris@211 2320 Layer *layer = pane->getLayer(j);
Chris@211 2321 if (!dynamic_cast<TimeRulerLayer *>(layer)) continue;
Chris@211 2322
Chris@211 2323 layer->showLayer(pane, show);
Chris@211 2324 }
Chris@211 2325 }
Chris@211 2326 }
Chris@211 2327 }
Chris@211 2328
Chris@211 2329 void
Chris@45 2330 MainWindowBase::toggleZoomWheels()
Chris@45 2331 {
Chris@45 2332 if (m_viewManager->getZoomWheelsEnabled()) {
Chris@45 2333 m_viewManager->setZoomWheelsEnabled(false);
Chris@45 2334 } else {
Chris@45 2335 m_viewManager->setZoomWheelsEnabled(true);
Chris@45 2336 }
Chris@45 2337 }
Chris@45 2338
Chris@45 2339 void
Chris@45 2340 MainWindowBase::togglePropertyBoxes()
Chris@45 2341 {
Chris@45 2342 if (m_paneStack->getLayoutStyle() == PaneStack::NoPropertyStacks) {
Chris@45 2343 if (Preferences::getInstance()->getPropertyBoxLayout() ==
Chris@45 2344 Preferences::VerticallyStacked) {
Chris@45 2345 m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout);
Chris@45 2346 } else {
Chris@45 2347 m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout);
Chris@45 2348 }
Chris@45 2349 } else {
Chris@45 2350 m_paneStack->setLayoutStyle(PaneStack::NoPropertyStacks);
Chris@45 2351 }
Chris@45 2352 }
Chris@45 2353
Chris@45 2354 void
Chris@45 2355 MainWindowBase::toggleStatusBar()
Chris@45 2356 {
Chris@45 2357 QSettings settings;
Chris@45 2358 settings.beginGroup("MainWindow");
Chris@45 2359 bool sb = settings.value("showstatusbar", true).toBool();
Chris@45 2360
Chris@45 2361 if (sb) {
Chris@45 2362 statusBar()->hide();
Chris@45 2363 } else {
Chris@45 2364 statusBar()->show();
Chris@45 2365 }
Chris@45 2366
Chris@45 2367 settings.setValue("showstatusbar", !sb);
Chris@45 2368
Chris@45 2369 settings.endGroup();
Chris@45 2370 }
Chris@45 2371
Chris@45 2372 void
Chris@256 2373 MainWindowBase::toggleCentreLine()
Chris@256 2374 {
Chris@256 2375 if (m_viewManager->shouldShowCentreLine()) {
Chris@256 2376 m_viewManager->setShowCentreLine(false);
Chris@256 2377 } else {
Chris@256 2378 m_viewManager->setShowCentreLine(true);
Chris@256 2379 }
Chris@256 2380 }
Chris@256 2381
Chris@256 2382 void
Chris@45 2383 MainWindowBase::preferenceChanged(PropertyContainer::PropertyName name)
Chris@45 2384 {
Chris@45 2385 if (name == "Property Box Layout") {
Chris@45 2386 if (m_paneStack->getLayoutStyle() != PaneStack::NoPropertyStacks) {
Chris@45 2387 if (Preferences::getInstance()->getPropertyBoxLayout() ==
Chris@45 2388 Preferences::VerticallyStacked) {
Chris@45 2389 m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout);
Chris@45 2390 } else {
Chris@45 2391 m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout);
Chris@45 2392 }
Chris@45 2393 }
Chris@45 2394 } else if (name == "Background Mode" && m_viewManager) {
Chris@45 2395 Preferences::BackgroundMode mode =
Chris@45 2396 Preferences::getInstance()->getBackgroundMode();
Chris@45 2397 if (mode == Preferences::BackgroundFromTheme) {
Chris@45 2398 m_viewManager->setGlobalDarkBackground(m_initialDarkBackground);
Chris@45 2399 } else if (mode == Preferences::DarkBackground) {
Chris@45 2400 m_viewManager->setGlobalDarkBackground(true);
Chris@45 2401 } else {
Chris@45 2402 m_viewManager->setGlobalDarkBackground(false);
Chris@45 2403 }
Chris@45 2404 }
Chris@45 2405 }
Chris@45 2406
Chris@45 2407 void
Chris@45 2408 MainWindowBase::play()
Chris@45 2409 {
Chris@45 2410 if (m_playSource->isPlaying()) {
Chris@45 2411 stop();
Chris@45 2412 } else {
Chris@45 2413 playbackFrameChanged(m_viewManager->getPlaybackFrame());
Chris@45 2414 m_playSource->play(m_viewManager->getPlaybackFrame());
Chris@45 2415 }
Chris@45 2416 }
Chris@45 2417
Chris@45 2418 void
Chris@45 2419 MainWindowBase::ffwd()
Chris@45 2420 {
Chris@45 2421 if (!getMainModel()) return;
Chris@45 2422
Chris@45 2423 int frame = m_viewManager->getPlaybackFrame();
Chris@45 2424 ++frame;
Chris@45 2425
Chris@85 2426 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 2427 Layer *layer = getSnapLayer();
Chris@45 2428 size_t sr = getMainModel()->getSampleRate();
Chris@45 2429
Chris@45 2430 if (!layer) {
Chris@45 2431
Chris@45 2432 frame = RealTime::realTime2Frame
Chris@45 2433 (RealTime::frame2RealTime(frame, sr) + RealTime(2, 0), sr);
Chris@45 2434 if (frame > int(getMainModel()->getEndFrame())) {
Chris@45 2435 frame = getMainModel()->getEndFrame();
Chris@45 2436 }
Chris@45 2437
Chris@45 2438 } else {
Chris@45 2439
Chris@45 2440 size_t resolution = 0;
Chris@166 2441 if (pane) frame = pane->alignFromReference(frame);
Chris@85 2442 if (layer->snapToFeatureFrame(m_paneStack->getCurrentPane(),
Chris@85 2443 frame, resolution, Layer::SnapRight)) {
Chris@85 2444 if (pane) frame = pane->alignToReference(frame);
Chris@85 2445 } else {
Chris@45 2446 frame = getMainModel()->getEndFrame();
Chris@45 2447 }
Chris@45 2448 }
Chris@45 2449
Chris@45 2450 if (frame < 0) frame = 0;
Chris@45 2451
Chris@45 2452 if (m_viewManager->getPlaySelectionMode()) {
Chris@45 2453 frame = m_viewManager->constrainFrameToSelection(size_t(frame));
Chris@45 2454 }
Chris@45 2455
Chris@45 2456 m_viewManager->setPlaybackFrame(frame);
Chris@166 2457
Chris@166 2458 if (frame == getMainModel()->getEndFrame() &&
Chris@166 2459 m_playSource &&
Chris@166 2460 m_playSource->isPlaying() &&
Chris@166 2461 !m_viewManager->getPlayLoopMode()) {
Chris@166 2462 stop();
Chris@166 2463 }
Chris@45 2464 }
Chris@45 2465
Chris@45 2466 void
Chris@45 2467 MainWindowBase::ffwdEnd()
Chris@45 2468 {
Chris@45 2469 if (!getMainModel()) return;
Chris@45 2470
Chris@139 2471 if (m_playSource &&
Chris@139 2472 m_playSource->isPlaying() &&
Chris@139 2473 !m_viewManager->getPlayLoopMode()) {
Chris@139 2474 stop();
Chris@139 2475 }
Chris@139 2476
Chris@45 2477 size_t frame = getMainModel()->getEndFrame();
Chris@45 2478
Chris@45 2479 if (m_viewManager->getPlaySelectionMode()) {
Chris@45 2480 frame = m_viewManager->constrainFrameToSelection(frame);
Chris@45 2481 }
Chris@45 2482
Chris@45 2483 m_viewManager->setPlaybackFrame(frame);
Chris@45 2484 }
Chris@45 2485
Chris@45 2486 void
Chris@166 2487 MainWindowBase::ffwdSimilar()
Chris@166 2488 {
Chris@166 2489 if (!getMainModel()) return;
Chris@166 2490
Chris@166 2491 Layer *layer = getSnapLayer();
Chris@166 2492 if (!layer) { ffwd(); return; }
Chris@166 2493
Chris@166 2494 Pane *pane = m_paneStack->getCurrentPane();
Chris@166 2495 size_t sr = getMainModel()->getSampleRate();
Chris@166 2496
Chris@166 2497 int frame = m_viewManager->getPlaybackFrame();
Chris@166 2498
Chris@166 2499 size_t resolution = 0;
Chris@166 2500 if (pane) frame = pane->alignFromReference(frame);
Chris@166 2501 if (layer->snapToSimilarFeature(m_paneStack->getCurrentPane(),
Chris@166 2502 frame, resolution, Layer::SnapRight)) {
Chris@166 2503 if (pane) frame = pane->alignToReference(frame);
Chris@166 2504 } else {
Chris@166 2505 frame = getMainModel()->getEndFrame();
Chris@166 2506 }
Chris@166 2507
Chris@166 2508 if (frame < 0) frame = 0;
Chris@166 2509
Chris@166 2510 if (m_viewManager->getPlaySelectionMode()) {
Chris@166 2511 frame = m_viewManager->constrainFrameToSelection(size_t(frame));
Chris@166 2512 }
Chris@166 2513
Chris@166 2514 m_viewManager->setPlaybackFrame(frame);
Chris@166 2515
Chris@166 2516 if (frame == getMainModel()->getEndFrame() &&
Chris@166 2517 m_playSource &&
Chris@166 2518 m_playSource->isPlaying() &&
Chris@166 2519 !m_viewManager->getPlayLoopMode()) {
Chris@166 2520 stop();
Chris@166 2521 }
Chris@166 2522 }
Chris@166 2523
Chris@166 2524 void
Chris@45 2525 MainWindowBase::rewind()
Chris@45 2526 {
Chris@45 2527 if (!getMainModel()) return;
Chris@45 2528
Chris@45 2529 int frame = m_viewManager->getPlaybackFrame();
Chris@45 2530 if (frame > 0) --frame;
Chris@45 2531
Chris@85 2532 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 2533 Layer *layer = getSnapLayer();
Chris@45 2534 size_t sr = getMainModel()->getSampleRate();
Chris@45 2535
Chris@45 2536 // when rewinding during playback, we want to allow a period
Chris@45 2537 // following a rewind target point at which the rewind will go to
Chris@45 2538 // the prior point instead of the immediately neighbouring one
Chris@45 2539 if (m_playSource && m_playSource->isPlaying()) {
Chris@45 2540 RealTime ct = RealTime::frame2RealTime(frame, sr);
Chris@45 2541 ct = ct - RealTime::fromSeconds(0.25);
Chris@45 2542 if (ct < RealTime::zeroTime) ct = RealTime::zeroTime;
Chris@45 2543 frame = RealTime::realTime2Frame(ct, sr);
Chris@45 2544 }
Chris@45 2545
Chris@45 2546 if (!layer) {
Chris@45 2547
Chris@45 2548 frame = RealTime::realTime2Frame
Chris@45 2549 (RealTime::frame2RealTime(frame, sr) - RealTime(2, 0), sr);
Chris@45 2550 if (frame < int(getMainModel()->getStartFrame())) {
Chris@45 2551 frame = getMainModel()->getStartFrame();
Chris@45 2552 }
Chris@45 2553
Chris@45 2554 } else {
Chris@45 2555
Chris@45 2556 size_t resolution = 0;
Chris@166 2557 if (pane) frame = pane->alignFromReference(frame);
Chris@85 2558 if (layer->snapToFeatureFrame(m_paneStack->getCurrentPane(),
Chris@85 2559 frame, resolution, Layer::SnapLeft)) {
Chris@85 2560 if (pane) frame = pane->alignToReference(frame);
Chris@85 2561 } else {
Chris@45 2562 frame = getMainModel()->getStartFrame();
Chris@45 2563 }
Chris@45 2564 }
Chris@45 2565
Chris@45 2566 if (frame < 0) frame = 0;
Chris@45 2567
Chris@45 2568 if (m_viewManager->getPlaySelectionMode()) {
Chris@45 2569 frame = m_viewManager->constrainFrameToSelection(size_t(frame));
Chris@45 2570 }
Chris@45 2571
Chris@45 2572 m_viewManager->setPlaybackFrame(frame);
Chris@45 2573 }
Chris@45 2574
Chris@45 2575 void
Chris@45 2576 MainWindowBase::rewindStart()
Chris@45 2577 {
Chris@45 2578 if (!getMainModel()) return;
Chris@45 2579
Chris@45 2580 size_t frame = getMainModel()->getStartFrame();
Chris@45 2581
Chris@45 2582 if (m_viewManager->getPlaySelectionMode()) {
Chris@45 2583 frame = m_viewManager->constrainFrameToSelection(frame);
Chris@45 2584 }
Chris@45 2585
Chris@45 2586 m_viewManager->setPlaybackFrame(frame);
Chris@45 2587 }
Chris@45 2588
Chris@166 2589 void
Chris@166 2590 MainWindowBase::rewindSimilar()
Chris@166 2591 {
Chris@166 2592 if (!getMainModel()) return;
Chris@166 2593
Chris@166 2594 Layer *layer = getSnapLayer();
Chris@166 2595 if (!layer) { rewind(); return; }
Chris@166 2596
Chris@166 2597 Pane *pane = m_paneStack->getCurrentPane();
Chris@166 2598 size_t sr = getMainModel()->getSampleRate();
Chris@166 2599
Chris@166 2600 int frame = m_viewManager->getPlaybackFrame();
Chris@166 2601
Chris@166 2602 size_t resolution = 0;
Chris@166 2603 if (pane) frame = pane->alignFromReference(frame);
Chris@166 2604 if (layer->snapToSimilarFeature(m_paneStack->getCurrentPane(),
Chris@166 2605 frame, resolution, Layer::SnapLeft)) {
Chris@166 2606 if (pane) frame = pane->alignToReference(frame);
Chris@166 2607 } else {
Chris@166 2608 frame = getMainModel()->getStartFrame();
Chris@166 2609 }
Chris@166 2610
Chris@166 2611 if (frame < 0) frame = 0;
Chris@166 2612
Chris@166 2613 if (m_viewManager->getPlaySelectionMode()) {
Chris@166 2614 frame = m_viewManager->constrainFrameToSelection(size_t(frame));
Chris@166 2615 }
Chris@166 2616
Chris@166 2617 m_viewManager->setPlaybackFrame(frame);
Chris@166 2618 }
Chris@166 2619
Chris@45 2620 Layer *
Chris@45 2621 MainWindowBase::getSnapLayer() const
Chris@45 2622 {
Chris@45 2623 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 2624 if (!pane) return 0;
Chris@45 2625
Chris@45 2626 Layer *layer = pane->getSelectedLayer();
Chris@45 2627
Chris@45 2628 if (!dynamic_cast<TimeInstantLayer *>(layer) &&
Chris@45 2629 !dynamic_cast<TimeValueLayer *>(layer) &&
Chris@194 2630 !dynamic_cast<RegionLayer *>(layer) &&
Chris@45 2631 !dynamic_cast<TimeRulerLayer *>(layer)) {
Chris@45 2632
Chris@45 2633 layer = 0;
Chris@45 2634
Chris@45 2635 for (int i = pane->getLayerCount(); i > 0; --i) {
Chris@45 2636 Layer *l = pane->getLayer(i-1);
Chris@45 2637 if (dynamic_cast<TimeRulerLayer *>(l)) {
Chris@45 2638 layer = l;
Chris@45 2639 break;
Chris@45 2640 }
Chris@45 2641 }
Chris@45 2642 }
Chris@45 2643
Chris@45 2644 return layer;
Chris@45 2645 }
Chris@45 2646
Chris@45 2647 void
Chris@45 2648 MainWindowBase::stop()
Chris@45 2649 {
Chris@45 2650 m_playSource->stop();
Chris@45 2651
Chris@45 2652 if (m_paneStack && m_paneStack->getCurrentPane()) {
Chris@45 2653 updateVisibleRangeDisplay(m_paneStack->getCurrentPane());
Chris@45 2654 } else {
Chris@45 2655 m_myStatusMessage = "";
Chris@45 2656 statusBar()->showMessage("");
Chris@45 2657 }
Chris@45 2658 }
Chris@45 2659
Chris@45 2660 MainWindowBase::AddPaneCommand::AddPaneCommand(MainWindowBase *mw) :
Chris@45 2661 m_mw(mw),
Chris@45 2662 m_pane(0),
Chris@45 2663 m_prevCurrentPane(0),
Chris@45 2664 m_added(false)
Chris@45 2665 {
Chris@45 2666 }
Chris@45 2667
Chris@45 2668 MainWindowBase::AddPaneCommand::~AddPaneCommand()
Chris@45 2669 {
Chris@45 2670 if (m_pane && !m_added) {
Chris@45 2671 m_mw->m_paneStack->deletePane(m_pane);
Chris@45 2672 }
Chris@45 2673 }
Chris@45 2674
Chris@45 2675 QString
Chris@45 2676 MainWindowBase::AddPaneCommand::getName() const
Chris@45 2677 {
Chris@45 2678 return tr("Add Pane");
Chris@45 2679 }
Chris@45 2680
Chris@45 2681 void
Chris@45 2682 MainWindowBase::AddPaneCommand::execute()
Chris@45 2683 {
Chris@45 2684 if (!m_pane) {
Chris@45 2685 m_prevCurrentPane = m_mw->m_paneStack->getCurrentPane();
Chris@45 2686 m_pane = m_mw->m_paneStack->addPane();
Chris@45 2687
Chris@45 2688 connect(m_pane, SIGNAL(contextHelpChanged(const QString &)),
Chris@45 2689 m_mw, SLOT(contextHelpChanged(const QString &)));
Chris@45 2690 } else {
Chris@45 2691 m_mw->m_paneStack->showPane(m_pane);
Chris@45 2692 }
Chris@45 2693
Chris@45 2694 m_mw->m_paneStack->setCurrentPane(m_pane);
Chris@45 2695 m_added = true;
Chris@45 2696 }
Chris@45 2697
Chris@45 2698 void
Chris@45 2699 MainWindowBase::AddPaneCommand::unexecute()
Chris@45 2700 {
Chris@45 2701 m_mw->m_paneStack->hidePane(m_pane);
Chris@45 2702 m_mw->m_paneStack->setCurrentPane(m_prevCurrentPane);
Chris@45 2703 m_added = false;
Chris@45 2704 }
Chris@45 2705
Chris@45 2706 MainWindowBase::RemovePaneCommand::RemovePaneCommand(MainWindowBase *mw, Pane *pane) :
Chris@45 2707 m_mw(mw),
Chris@45 2708 m_pane(pane),
Chris@45 2709 m_added(true)
Chris@45 2710 {
Chris@45 2711 }
Chris@45 2712
Chris@45 2713 MainWindowBase::RemovePaneCommand::~RemovePaneCommand()
Chris@45 2714 {
Chris@45 2715 if (m_pane && !m_added) {
Chris@45 2716 m_mw->m_paneStack->deletePane(m_pane);
Chris@45 2717 }
Chris@45 2718 }
Chris@45 2719
Chris@45 2720 QString
Chris@45 2721 MainWindowBase::RemovePaneCommand::getName() const
Chris@45 2722 {
Chris@45 2723 return tr("Remove Pane");
Chris@45 2724 }
Chris@45 2725
Chris@45 2726 void
Chris@45 2727 MainWindowBase::RemovePaneCommand::execute()
Chris@45 2728 {
Chris@45 2729 m_prevCurrentPane = m_mw->m_paneStack->getCurrentPane();
Chris@45 2730 m_mw->m_paneStack->hidePane(m_pane);
Chris@45 2731 m_added = false;
Chris@45 2732 }
Chris@45 2733
Chris@45 2734 void
Chris@45 2735 MainWindowBase::RemovePaneCommand::unexecute()
Chris@45 2736 {
Chris@45 2737 m_mw->m_paneStack->showPane(m_pane);
Chris@45 2738 m_mw->m_paneStack->setCurrentPane(m_prevCurrentPane);
Chris@45 2739 m_added = true;
Chris@45 2740 }
Chris@45 2741
Chris@45 2742 void
Chris@45 2743 MainWindowBase::deleteCurrentPane()
Chris@45 2744 {
Chris@45 2745 CommandHistory::getInstance()->startCompoundOperation
Chris@45 2746 (tr("Delete Pane"), true);
Chris@45 2747
Chris@45 2748 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 2749 if (pane) {
Chris@45 2750 while (pane->getLayerCount() > 0) {
Chris@45 2751 Layer *layer = pane->getLayer(0);
Chris@45 2752 if (layer) {
Chris@45 2753 m_document->removeLayerFromView(pane, layer);
Chris@45 2754 } else {
Chris@45 2755 break;
Chris@45 2756 }
Chris@45 2757 }
Chris@45 2758
Chris@45 2759 RemovePaneCommand *command = new RemovePaneCommand(this, pane);
Chris@45 2760 CommandHistory::getInstance()->addCommand(command);
Chris@45 2761 }
Chris@45 2762
Chris@45 2763 CommandHistory::getInstance()->endCompoundOperation();
Chris@45 2764
Chris@45 2765 updateMenuStates();
Chris@45 2766 }
Chris@45 2767
Chris@45 2768 void
Chris@45 2769 MainWindowBase::deleteCurrentLayer()
Chris@45 2770 {
Chris@45 2771 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 2772 if (pane) {
Chris@45 2773 Layer *layer = pane->getSelectedLayer();
Chris@45 2774 if (layer) {
Chris@45 2775 m_document->removeLayerFromView(pane, layer);
Chris@45 2776 }
Chris@45 2777 }
Chris@45 2778 updateMenuStates();
Chris@45 2779 }
Chris@45 2780
Chris@45 2781 void
Chris@123 2782 MainWindowBase::editCurrentLayer()
Chris@123 2783 {
Chris@123 2784 Layer *layer = 0;
Chris@123 2785 Pane *pane = m_paneStack->getCurrentPane();
Chris@123 2786 if (pane) layer = pane->getSelectedLayer();
Chris@123 2787 if (!layer) return;
Chris@123 2788
Chris@123 2789 Model *model = layer->getModel();
Chris@123 2790 if (!model) return;
Chris@123 2791
Chris@124 2792 TabularModel *tabular = dynamic_cast<TabularModel *>(model);
Chris@124 2793 if (!tabular) {
Chris@124 2794 //!!! how to prevent this function from being active if not
Chris@124 2795 //appropriate model type? or will we ultimately support
Chris@124 2796 //tabular display for all editable models?
Chris@233 2797 SVDEBUG << "NOTE: Not a tabular model" << endl;
Chris@124 2798 return;
Chris@124 2799 }
Chris@124 2800
Chris@123 2801 if (m_layerDataDialogMap.find(layer) != m_layerDataDialogMap.end()) {
Chris@126 2802 if (!m_layerDataDialogMap[layer].isNull()) {
Chris@126 2803 m_layerDataDialogMap[layer]->show();
Chris@126 2804 m_layerDataDialogMap[layer]->raise();
Chris@126 2805 return;
Chris@126 2806 }
Chris@123 2807 }
Chris@123 2808
Chris@125 2809 QString title = layer->getLayerPresentationName();
Chris@125 2810
Chris@125 2811 ModelDataTableDialog *dialog = new ModelDataTableDialog(tabular, title, this);
Chris@128 2812 dialog->setAttribute(Qt::WA_DeleteOnClose);
Chris@128 2813
Chris@128 2814 connectLayerEditDialog(dialog);
Chris@123 2815
Chris@128 2816 m_layerDataDialogMap[layer] = dialog;
Chris@128 2817 m_viewDataDialogMap[pane].insert(dialog);
Chris@128 2818
Chris@128 2819 dialog->show();
Chris@128 2820 }
Chris@128 2821
Chris@128 2822 void
Chris@128 2823 MainWindowBase::connectLayerEditDialog(ModelDataTableDialog *dialog)
Chris@128 2824 {
Chris@123 2825 connect(m_viewManager,
Chris@123 2826 SIGNAL(globalCentreFrameChanged(unsigned long)),
Chris@123 2827 dialog,
Chris@127 2828 SLOT(userScrolledToFrame(unsigned long)));
Chris@127 2829
Chris@127 2830 connect(m_viewManager,
Chris@127 2831 SIGNAL(playbackFrameChanged(unsigned long)),
Chris@127 2832 dialog,
Chris@127 2833 SLOT(playbackScrolledToFrame(unsigned long)));
Chris@127 2834
Chris@123 2835 connect(dialog,
Chris@123 2836 SIGNAL(scrollToFrame(unsigned long)),
Chris@123 2837 m_viewManager,
Chris@123 2838 SLOT(setGlobalCentreFrame(unsigned long)));
Chris@129 2839
Chris@129 2840 connect(dialog,
Chris@129 2841 SIGNAL(scrollToFrame(unsigned long)),
Chris@129 2842 m_viewManager,
Chris@129 2843 SLOT(setPlaybackFrame(unsigned long)));
Chris@128 2844 }
Chris@123 2845
Chris@123 2846 void
Chris@73 2847 MainWindowBase::previousPane()
Chris@73 2848 {
Chris@73 2849 if (!m_paneStack) return;
Chris@73 2850
Chris@73 2851 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@73 2852 if (!currentPane) return;
Chris@73 2853
Chris@73 2854 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@73 2855 if (m_paneStack->getPane(i) == currentPane) {
Chris@73 2856 if (i == 0) return;
Chris@73 2857 m_paneStack->setCurrentPane(m_paneStack->getPane(i-1));
Chris@73 2858 updateMenuStates();
Chris@73 2859 return;
Chris@73 2860 }
Chris@73 2861 }
Chris@73 2862 }
Chris@73 2863
Chris@73 2864 void
Chris@73 2865 MainWindowBase::nextPane()
Chris@73 2866 {
Chris@73 2867 if (!m_paneStack) return;
Chris@73 2868
Chris@73 2869 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@73 2870 if (!currentPane) return;
Chris@73 2871
Chris@73 2872 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@73 2873 if (m_paneStack->getPane(i) == currentPane) {
Chris@73 2874 if (i == m_paneStack->getPaneCount()-1) return;
Chris@73 2875 m_paneStack->setCurrentPane(m_paneStack->getPane(i+1));
Chris@73 2876 updateMenuStates();
Chris@73 2877 return;
Chris@73 2878 }
Chris@73 2879 }
Chris@73 2880 }
Chris@73 2881
Chris@73 2882 void
Chris@73 2883 MainWindowBase::previousLayer()
Chris@73 2884 {
Chris@73 2885 //!!! Not right -- pane lists layers in stacking order
Chris@73 2886
Chris@73 2887 if (!m_paneStack) return;
Chris@73 2888
Chris@73 2889 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@73 2890 if (!currentPane) return;
Chris@73 2891
Chris@73 2892 Layer *currentLayer = currentPane->getSelectedLayer();
Chris@73 2893 if (!currentLayer) return;
Chris@73 2894
Chris@73 2895 for (int i = 0; i < currentPane->getLayerCount(); ++i) {
Chris@73 2896 if (currentPane->getLayer(i) == currentLayer) {
Chris@73 2897 if (i == 0) return;
Chris@73 2898 m_paneStack->setCurrentLayer(currentPane,
Chris@73 2899 currentPane->getLayer(i-1));
Chris@73 2900 updateMenuStates();
Chris@73 2901 return;
Chris@73 2902 }
Chris@73 2903 }
Chris@73 2904 }
Chris@73 2905
Chris@73 2906 void
Chris@73 2907 MainWindowBase::nextLayer()
Chris@73 2908 {
Chris@73 2909 //!!! Not right -- pane lists layers in stacking order
Chris@73 2910
Chris@73 2911 if (!m_paneStack) return;
Chris@73 2912
Chris@73 2913 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@73 2914 if (!currentPane) return;
Chris@73 2915
Chris@73 2916 Layer *currentLayer = currentPane->getSelectedLayer();
Chris@73 2917 if (!currentLayer) return;
Chris@73 2918
Chris@73 2919 for (int i = 0; i < currentPane->getLayerCount(); ++i) {
Chris@73 2920 if (currentPane->getLayer(i) == currentLayer) {
Chris@73 2921 if (i == currentPane->getLayerCount()-1) return;
Chris@73 2922 m_paneStack->setCurrentLayer(currentPane,
Chris@73 2923 currentPane->getLayer(i+1));
Chris@73 2924 updateMenuStates();
Chris@73 2925 return;
Chris@73 2926 }
Chris@73 2927 }
Chris@73 2928 }
Chris@73 2929
Chris@73 2930 void
Chris@45 2931 MainWindowBase::playbackFrameChanged(unsigned long frame)
Chris@45 2932 {
Chris@45 2933 if (!(m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
Chris@45 2934
Chris@187 2935 updatePositionStatusDisplays();
Chris@187 2936
Chris@45 2937 RealTime now = RealTime::frame2RealTime
Chris@45 2938 (frame, getMainModel()->getSampleRate());
Chris@45 2939
Chris@45 2940 if (now.sec == m_lastPlayStatusSec) return;
Chris@45 2941
Chris@45 2942 RealTime then = RealTime::frame2RealTime
Chris@45 2943 (m_playSource->getPlayEndFrame(), getMainModel()->getSampleRate());
Chris@45 2944
Chris@45 2945 QString nowStr;
Chris@45 2946 QString thenStr;
Chris@45 2947 QString remainingStr;
Chris@45 2948
Chris@45 2949 if (then.sec > 10) {
Chris@45 2950 nowStr = now.toSecText().c_str();
Chris@45 2951 thenStr = then.toSecText().c_str();
Chris@45 2952 remainingStr = (then - now).toSecText().c_str();
Chris@45 2953 m_lastPlayStatusSec = now.sec;
Chris@45 2954 } else {
Chris@45 2955 nowStr = now.toText(true).c_str();
Chris@45 2956 thenStr = then.toText(true).c_str();
Chris@45 2957 remainingStr = (then - now).toText(true).c_str();
Chris@45 2958 }
Chris@45 2959
Chris@45 2960 m_myStatusMessage = tr("Playing: %1 of %2 (%3 remaining)")
Chris@45 2961 .arg(nowStr).arg(thenStr).arg(remainingStr);
Chris@45 2962
Chris@45 2963 statusBar()->showMessage(m_myStatusMessage);
Chris@45 2964 }
Chris@45 2965
Chris@45 2966 void
Chris@45 2967 MainWindowBase::globalCentreFrameChanged(unsigned long )
Chris@45 2968 {
Chris@45 2969 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
Chris@45 2970 Pane *p = 0;
Chris@45 2971 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return;
Chris@45 2972 if (!p->getFollowGlobalPan()) return;
Chris@45 2973 updateVisibleRangeDisplay(p);
Chris@45 2974 }
Chris@45 2975
Chris@45 2976 void
Chris@123 2977 MainWindowBase::viewCentreFrameChanged(View *v, unsigned long frame)
Chris@45 2978 {
Chris@233 2979 // SVDEBUG << "MainWindowBase::viewCentreFrameChanged(" << v << "," << frame << ")" << endl;
Chris@123 2980
Chris@123 2981 if (m_viewDataDialogMap.find(v) != m_viewDataDialogMap.end()) {
Chris@123 2982 for (DataDialogSet::iterator i = m_viewDataDialogMap[v].begin();
Chris@123 2983 i != m_viewDataDialogMap[v].end(); ++i) {
Chris@127 2984 (*i)->userScrolledToFrame(frame);
Chris@123 2985 }
Chris@123 2986 }
Chris@45 2987 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
Chris@45 2988 Pane *p = 0;
Chris@45 2989 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return;
Chris@45 2990 if (v == p) updateVisibleRangeDisplay(p);
Chris@45 2991 }
Chris@45 2992
Chris@45 2993 void
Chris@45 2994 MainWindowBase::viewZoomLevelChanged(View *v, unsigned long , bool )
Chris@45 2995 {
Chris@45 2996 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
Chris@45 2997 Pane *p = 0;
Chris@45 2998 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return;
Chris@45 2999 if (v == p) updateVisibleRangeDisplay(p);
Chris@45 3000 }
Chris@45 3001
Chris@45 3002 void
Chris@45 3003 MainWindowBase::layerAdded(Layer *)
Chris@45 3004 {
Chris@233 3005 // SVDEBUG << "MainWindowBase::layerAdded(" << layer << ")" << endl;
Chris@45 3006 updateMenuStates();
Chris@45 3007 }
Chris@45 3008
Chris@45 3009 void
Chris@45 3010 MainWindowBase::layerRemoved(Layer *)
Chris@45 3011 {
Chris@233 3012 // SVDEBUG << "MainWindowBase::layerRemoved(" << layer << ")" << endl;
Chris@45 3013 updateMenuStates();
Chris@45 3014 }
Chris@45 3015
Chris@45 3016 void
Chris@45 3017 MainWindowBase::layerAboutToBeDeleted(Layer *layer)
Chris@45 3018 {
Chris@233 3019 // SVDEBUG << "MainWindowBase::layerAboutToBeDeleted(" << layer << ")" << endl;
Chris@123 3020
Chris@128 3021 removeLayerEditDialog(layer);
Chris@123 3022
Chris@47 3023 if (m_timeRulerLayer && (layer == m_timeRulerLayer)) {
Chris@45 3024 // std::cerr << "(this is the time ruler layer)" << std::endl;
Chris@45 3025 m_timeRulerLayer = 0;
Chris@45 3026 }
Chris@45 3027 }
Chris@45 3028
Chris@45 3029 void
Chris@45 3030 MainWindowBase::layerInAView(Layer *layer, bool inAView)
Chris@45 3031 {
Chris@233 3032 // SVDEBUG << "MainWindowBase::layerInAView(" << layer << "," << inAView << ")" << endl;
Chris@128 3033
Chris@128 3034 if (!inAView) removeLayerEditDialog(layer);
Chris@45 3035
Chris@45 3036 // Check whether we need to add or remove model from play source
Chris@45 3037 Model *model = layer->getModel();
Chris@45 3038 if (model) {
Chris@45 3039 if (inAView) {
Chris@45 3040 m_playSource->addModel(model);
Chris@45 3041 } else {
Chris@45 3042 bool found = false;
Chris@45 3043 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@45 3044 Pane *pane = m_paneStack->getPane(i);
Chris@45 3045 if (!pane) continue;
Chris@45 3046 for (int j = 0; j < pane->getLayerCount(); ++j) {
Chris@45 3047 Layer *pl = pane->getLayer(j);
Chris@183 3048 if (pl &&
Chris@183 3049 !dynamic_cast<TimeRulerLayer *>(pl) &&
Chris@183 3050 (pl->getModel() == model)) {
Chris@45 3051 found = true;
Chris@45 3052 break;
Chris@45 3053 }
Chris@45 3054 }
Chris@45 3055 if (found) break;
Chris@45 3056 }
Chris@173 3057 if (!found) {
Chris@173 3058 m_playSource->removeModel(model);
Chris@173 3059 }
Chris@45 3060 }
Chris@45 3061 }
Chris@45 3062
Chris@45 3063 updateMenuStates();
Chris@45 3064 }
Chris@45 3065
Chris@45 3066 void
Chris@128 3067 MainWindowBase::removeLayerEditDialog(Layer *layer)
Chris@128 3068 {
Chris@128 3069 if (m_layerDataDialogMap.find(layer) != m_layerDataDialogMap.end()) {
Chris@128 3070
Chris@128 3071 ModelDataTableDialog *dialog = m_layerDataDialogMap[layer];
Chris@128 3072
Chris@128 3073 for (ViewDataDialogMap::iterator vi = m_viewDataDialogMap.begin();
Chris@128 3074 vi != m_viewDataDialogMap.end(); ++vi) {
Chris@128 3075 vi->second.erase(dialog);
Chris@128 3076 }
Chris@128 3077
Chris@128 3078 m_layerDataDialogMap.erase(layer);
Chris@128 3079 delete dialog;
Chris@128 3080 }
Chris@128 3081 }
Chris@128 3082
Chris@128 3083 void
Chris@45 3084 MainWindowBase::modelAdded(Model *model)
Chris@45 3085 {
Chris@233 3086 // SVDEBUG << "MainWindowBase::modelAdded(" << model << ")" << endl;
Chris@45 3087 m_playSource->addModel(model);
Chris@45 3088 }
Chris@45 3089
Chris@45 3090 void
Chris@45 3091 MainWindowBase::mainModelChanged(WaveFileModel *model)
Chris@45 3092 {
Chris@233 3093 // SVDEBUG << "MainWindowBase::mainModelChanged(" << model << ")" << endl;
Chris@45 3094 updateDescriptionLabel();
Chris@45 3095 if (model) m_viewManager->setMainModelSampleRate(model->getSampleRate());
Chris@45 3096 if (model && !m_playTarget && m_audioOutput) createPlayTarget();
Chris@45 3097 }
Chris@45 3098
Chris@45 3099 void
Chris@45 3100 MainWindowBase::modelAboutToBeDeleted(Model *model)
Chris@45 3101 {
Chris@233 3102 // SVDEBUG << "MainWindowBase::modelAboutToBeDeleted(" << model << ")" << endl;
Chris@45 3103 if (model == m_viewManager->getPlaybackModel()) {
Chris@45 3104 m_viewManager->setPlaybackModel(0);
Chris@45 3105 }
Chris@45 3106 m_playSource->removeModel(model);
Chris@45 3107 FFTDataServer::modelAboutToBeDeleted(model);
Chris@45 3108 }
Chris@45 3109
Chris@45 3110 void
Chris@55 3111 MainWindowBase::paneDeleteButtonClicked(Pane *pane)
Chris@55 3112 {
Chris@55 3113 bool found = false;
Chris@55 3114 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@55 3115 if (m_paneStack->getPane(i) == pane) {
Chris@55 3116 found = true;
Chris@55 3117 break;
Chris@55 3118 }
Chris@55 3119 }
Chris@55 3120 if (!found) {
Chris@233 3121 SVDEBUG << "MainWindowBase::paneDeleteButtonClicked: Unknown pane "
Chris@229 3122 << pane << endl;
Chris@55 3123 return;
Chris@55 3124 }
Chris@55 3125
Chris@55 3126 CommandHistory::getInstance()->startCompoundOperation
Chris@55 3127 (tr("Delete Pane"), true);
Chris@55 3128
Chris@55 3129 while (pane->getLayerCount() > 0) {
Chris@55 3130 Layer *layer = pane->getLayer(0);
Chris@55 3131 if (layer) {
Chris@55 3132 m_document->removeLayerFromView(pane, layer);
Chris@55 3133 } else {
Chris@55 3134 break;
Chris@55 3135 }
Chris@55 3136 }
Chris@55 3137
Chris@55 3138 RemovePaneCommand *command = new RemovePaneCommand(this, pane);
Chris@55 3139 CommandHistory::getInstance()->addCommand(command);
Chris@55 3140
Chris@55 3141 CommandHistory::getInstance()->endCompoundOperation();
Chris@55 3142
Chris@55 3143 updateMenuStates();
Chris@55 3144 }
Chris@55 3145
Chris@55 3146 void
Chris@45 3147 MainWindowBase::pollOSC()
Chris@45 3148 {
Chris@45 3149 if (!m_oscQueue || m_oscQueue->isEmpty()) return;
Chris@233 3150 SVDEBUG << "MainWindowBase::pollOSC: have " << m_oscQueue->getMessagesAvailable() << " messages" << endl;
Chris@45 3151
Chris@45 3152 if (m_openingAudioFile) return;
Chris@45 3153
Chris@45 3154 OSCMessage message = m_oscQueue->readMessage();
Chris@45 3155
Chris@45 3156 if (message.getTarget() != 0) {
Chris@45 3157 return; //!!! for now -- this class is target 0, others not handled yet
Chris@45 3158 }
Chris@45 3159
Chris@45 3160 handleOSCMessage(message);
Chris@45 3161 }
Chris@45 3162
Chris@45 3163 void
Chris@45 3164 MainWindowBase::inProgressSelectionChanged()
Chris@45 3165 {
Chris@45 3166 Pane *currentPane = 0;
Chris@45 3167 if (m_paneStack) currentPane = m_paneStack->getCurrentPane();
Chris@45 3168 if (currentPane) updateVisibleRangeDisplay(currentPane);
Chris@45 3169 }
Chris@45 3170
Chris@45 3171 void
Chris@45 3172 MainWindowBase::contextHelpChanged(const QString &s)
Chris@45 3173 {
Chris@45 3174 if (s == "" && m_myStatusMessage != "") {
Chris@45 3175 statusBar()->showMessage(m_myStatusMessage);
Chris@45 3176 return;
Chris@45 3177 }
Chris@45 3178 statusBar()->showMessage(s);
Chris@45 3179 }
Chris@45 3180
Chris@45 3181 void
Chris@45 3182 MainWindowBase::openHelpUrl(QString url)
Chris@45 3183 {
Chris@45 3184 // This method mostly lifted from Qt Assistant source code
Chris@45 3185
Chris@45 3186 QProcess *process = new QProcess(this);
Chris@45 3187 connect(process, SIGNAL(finished(int)), process, SLOT(deleteLater()));
Chris@45 3188
Chris@45 3189 QStringList args;
Chris@45 3190
Chris@45 3191 #ifdef Q_OS_MAC
Chris@45 3192 args.append(url);
Chris@45 3193 process->start("open", args);
Chris@45 3194 #else
Chris@45 3195 #ifdef Q_OS_WIN32
Chris@45 3196
Chris@45 3197 QString pf(getenv("ProgramFiles"));
Chris@45 3198 QString command = pf + QString("\\Internet Explorer\\IEXPLORE.EXE");
Chris@45 3199
Chris@45 3200 args.append(url);
Chris@45 3201 process->start(command, args);
Chris@45 3202
Chris@45 3203 #else
Chris@45 3204 #ifdef Q_WS_X11
Chris@45 3205 if (!qgetenv("KDE_FULL_SESSION").isEmpty()) {
Chris@45 3206 args.append("exec");
Chris@45 3207 args.append(url);
Chris@45 3208 process->start("kfmclient", args);
Chris@45 3209 } else if (!qgetenv("BROWSER").isEmpty()) {
Chris@45 3210 args.append(url);
Chris@45 3211 process->start(qgetenv("BROWSER"), args);
Chris@45 3212 } else {
Chris@45 3213 args.append(url);
Chris@45 3214 process->start("firefox", args);
Chris@45 3215 }
Chris@45 3216 #endif
Chris@45 3217 #endif
Chris@45 3218 #endif
Chris@45 3219 }
Chris@45 3220
Chris@180 3221