annotate framework/MainWindowBase.cpp @ 77:0535c49069ba

* Various fixes to object lifetime management, particularly in the spectrum layer and for notification of main model deletion. The main purpose of this is to improve the behaviour of the spectrum, but I think it may also help with #1840922 Various crashes in Layer Summary window.
author Chris Cannam
date Wed, 23 Jan 2008 15:43:27 +0000
parents 2da0999dac1d
children 58bfaaed07ed
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@45 26 #include "view/ViewManager.h"
Chris@45 27
Chris@45 28 #include "layer/WaveformLayer.h"
Chris@45 29 #include "layer/TimeRulerLayer.h"
Chris@45 30 #include "layer/TimeInstantLayer.h"
Chris@45 31 #include "layer/TimeValueLayer.h"
Chris@45 32 #include "layer/Colour3DPlotLayer.h"
Chris@45 33 #include "layer/SliceLayer.h"
Chris@45 34 #include "layer/SliceableLayer.h"
Chris@45 35 #include "layer/ImageLayer.h"
Chris@45 36
Chris@45 37 #include "widgets/ListInputDialog.h"
Chris@45 38
Chris@45 39 #include "audioio/AudioCallbackPlaySource.h"
Chris@45 40 #include "audioio/AudioCallbackPlayTarget.h"
Chris@45 41 #include "audioio/AudioTargetFactory.h"
Chris@45 42 #include "audioio/PlaySpeedRangeMapper.h"
Chris@45 43 #include "data/fileio/DataFileReaderFactory.h"
Chris@45 44 #include "data/fileio/PlaylistFileReader.h"
Chris@45 45 #include "data/fileio/WavFileWriter.h"
Chris@45 46 #include "data/fileio/CSVFileWriter.h"
Chris@45 47 #include "data/fileio/MIDIFileWriter.h"
Chris@45 48 #include "data/fileio/BZipFileDevice.h"
Chris@45 49 #include "data/fileio/FileSource.h"
Chris@45 50
Chris@45 51 #include "data/fft/FFTDataServer.h"
Chris@45 52
Chris@45 53 #include "base/RecentFiles.h"
Chris@45 54
Chris@45 55 #include "base/PlayParameterRepository.h"
Chris@45 56 #include "base/XmlExportable.h"
Chris@45 57 #include "base/CommandHistory.h"
Chris@45 58 #include "base/Profiler.h"
Chris@45 59 #include "base/Preferences.h"
Chris@45 60
Chris@45 61 #include "data/osc/OSCQueue.h"
Chris@45 62
Chris@45 63 #include <QApplication>
Chris@45 64 #include <QMessageBox>
Chris@45 65 #include <QGridLayout>
Chris@45 66 #include <QLabel>
Chris@45 67 #include <QAction>
Chris@45 68 #include <QMenuBar>
Chris@45 69 #include <QToolBar>
Chris@45 70 #include <QInputDialog>
Chris@45 71 #include <QStatusBar>
Chris@45 72 #include <QTreeView>
Chris@45 73 #include <QFile>
Chris@45 74 #include <QFileInfo>
Chris@45 75 #include <QDir>
Chris@45 76 #include <QTextStream>
Chris@45 77 #include <QProcess>
Chris@45 78 #include <QShortcut>
Chris@45 79 #include <QSettings>
Chris@45 80 #include <QDateTime>
Chris@45 81 #include <QProcess>
Chris@45 82 #include <QCheckBox>
Chris@45 83 #include <QRegExp>
Chris@45 84 #include <QScrollArea>
Chris@45 85
Chris@45 86 #include <iostream>
Chris@45 87 #include <cstdio>
Chris@45 88 #include <errno.h>
Chris@45 89
Chris@45 90 using std::cerr;
Chris@45 91 using std::endl;
Chris@45 92
Chris@45 93 using std::vector;
Chris@45 94 using std::map;
Chris@45 95 using std::set;
Chris@45 96
Chris@45 97
Chris@45 98 MainWindowBase::MainWindowBase(bool withAudioOutput, bool withOSCSupport) :
Chris@45 99 m_document(0),
Chris@45 100 m_paneStack(0),
Chris@45 101 m_viewManager(0),
Chris@45 102 m_timeRulerLayer(0),
Chris@45 103 m_audioOutput(withAudioOutput),
Chris@45 104 m_playSource(0),
Chris@45 105 m_playTarget(0),
Chris@45 106 m_oscQueue(withOSCSupport ? new OSCQueue() : 0),
Chris@45 107 m_recentFiles("RecentFiles", 20),
Chris@54 108 m_recentTransforms("RecentTransforms", 20),
Chris@45 109 m_documentModified(false),
Chris@45 110 m_openingAudioFile(false),
Chris@45 111 m_abandoning(false),
Chris@45 112 m_labeller(0)
Chris@45 113 {
Chris@45 114 connect(CommandHistory::getInstance(), SIGNAL(commandExecuted()),
Chris@45 115 this, SLOT(documentModified()));
Chris@45 116 connect(CommandHistory::getInstance(), SIGNAL(documentRestored()),
Chris@45 117 this, SLOT(documentRestored()));
Chris@45 118
Chris@45 119 m_viewManager = new ViewManager();
Chris@45 120 connect(m_viewManager, SIGNAL(selectionChanged()),
Chris@45 121 this, SLOT(updateMenuStates()));
Chris@45 122 connect(m_viewManager, SIGNAL(inProgressSelectionChanged()),
Chris@45 123 this, SLOT(inProgressSelectionChanged()));
Chris@45 124
Chris@45 125 Preferences::BackgroundMode mode =
Chris@45 126 Preferences::getInstance()->getBackgroundMode();
Chris@45 127 m_initialDarkBackground = m_viewManager->getGlobalDarkBackground();
Chris@45 128 if (mode != Preferences::BackgroundFromTheme) {
Chris@45 129 m_viewManager->setGlobalDarkBackground
Chris@45 130 (mode == Preferences::DarkBackground);
Chris@45 131 }
Chris@45 132
Chris@45 133 m_paneStack = new PaneStack(0, m_viewManager);
Chris@45 134 connect(m_paneStack, SIGNAL(currentPaneChanged(Pane *)),
Chris@45 135 this, SLOT(currentPaneChanged(Pane *)));
Chris@45 136 connect(m_paneStack, SIGNAL(currentLayerChanged(Pane *, Layer *)),
Chris@45 137 this, SLOT(currentLayerChanged(Pane *, Layer *)));
Chris@45 138 connect(m_paneStack, SIGNAL(rightButtonMenuRequested(Pane *, QPoint)),
Chris@45 139 this, SLOT(rightButtonMenuRequested(Pane *, QPoint)));
Chris@45 140 connect(m_paneStack, SIGNAL(contextHelpChanged(const QString &)),
Chris@45 141 this, SLOT(contextHelpChanged(const QString &)));
Chris@45 142 connect(m_paneStack, SIGNAL(paneAdded(Pane *)),
Chris@45 143 this, SLOT(paneAdded(Pane *)));
Chris@45 144 connect(m_paneStack, SIGNAL(paneHidden(Pane *)),
Chris@45 145 this, SLOT(paneHidden(Pane *)));
Chris@45 146 connect(m_paneStack, SIGNAL(paneAboutToBeDeleted(Pane *)),
Chris@45 147 this, SLOT(paneAboutToBeDeleted(Pane *)));
Chris@45 148 connect(m_paneStack, SIGNAL(dropAccepted(Pane *, QStringList)),
Chris@45 149 this, SLOT(paneDropAccepted(Pane *, QStringList)));
Chris@45 150 connect(m_paneStack, SIGNAL(dropAccepted(Pane *, QString)),
Chris@45 151 this, SLOT(paneDropAccepted(Pane *, QString)));
Chris@55 152 connect(m_paneStack, SIGNAL(paneDeleteButtonClicked(Pane *)),
Chris@55 153 this, SLOT(paneDeleteButtonClicked(Pane *)));
Chris@45 154
Chris@57 155 m_playSource = new AudioCallbackPlaySource(m_viewManager,
Chris@57 156 QApplication::applicationName());
Chris@45 157
Chris@45 158 connect(m_playSource, SIGNAL(sampleRateMismatch(size_t, size_t, bool)),
Chris@45 159 this, SLOT(sampleRateMismatch(size_t, size_t, bool)));
Chris@45 160 connect(m_playSource, SIGNAL(audioOverloadPluginDisabled()),
Chris@45 161 this, SLOT(audioOverloadPluginDisabled()));
Chris@45 162
Chris@45 163 connect(m_viewManager, SIGNAL(outputLevelsChanged(float, float)),
Chris@45 164 this, SLOT(outputLevelsChanged(float, float)));
Chris@45 165
Chris@45 166 connect(m_viewManager, SIGNAL(playbackFrameChanged(unsigned long)),
Chris@45 167 this, SLOT(playbackFrameChanged(unsigned long)));
Chris@45 168
Chris@45 169 connect(m_viewManager, SIGNAL(globalCentreFrameChanged(unsigned long)),
Chris@45 170 this, SLOT(globalCentreFrameChanged(unsigned long)));
Chris@45 171
Chris@45 172 connect(m_viewManager, SIGNAL(viewCentreFrameChanged(View *, unsigned long)),
Chris@45 173 this, SLOT(viewCentreFrameChanged(View *, unsigned long)));
Chris@45 174
Chris@45 175 connect(m_viewManager, SIGNAL(viewZoomLevelChanged(View *, unsigned long, bool)),
Chris@45 176 this, SLOT(viewZoomLevelChanged(View *, unsigned long, bool)));
Chris@45 177
Chris@45 178 connect(Preferences::getInstance(),
Chris@45 179 SIGNAL(propertyChanged(PropertyContainer::PropertyName)),
Chris@45 180 this,
Chris@45 181 SLOT(preferenceChanged(PropertyContainer::PropertyName)));
Chris@45 182
Chris@45 183 if (m_oscQueue && m_oscQueue->isOK()) {
Chris@45 184 connect(m_oscQueue, SIGNAL(messagesAvailable()), this, SLOT(pollOSC()));
Chris@45 185 QTimer *oscTimer = new QTimer(this);
Chris@45 186 connect(oscTimer, SIGNAL(timeout()), this, SLOT(pollOSC()));
Chris@45 187 oscTimer->start(1000);
Chris@45 188 }
Chris@45 189
Chris@45 190 Labeller::ValueType labellerType = Labeller::ValueFromTwoLevelCounter;
Chris@45 191 QSettings settings;
Chris@45 192 settings.beginGroup("MainWindow");
Chris@45 193 labellerType = (Labeller::ValueType)
Chris@45 194 settings.value("labellertype", (int)labellerType).toInt();
Chris@45 195 int cycle = settings.value("labellercycle", 4).toInt();
Chris@45 196 settings.endGroup();
Chris@45 197
Chris@45 198 m_labeller = new Labeller(labellerType);
Chris@45 199 m_labeller->setCounterCycleSize(cycle);
Chris@45 200 }
Chris@45 201
Chris@45 202 MainWindowBase::~MainWindowBase()
Chris@45 203 {
Chris@70 204 if (m_playTarget) m_playTarget->shutdown();
Chris@70 205 // delete m_playTarget;
Chris@45 206 delete m_playSource;
Chris@45 207 delete m_viewManager;
Chris@45 208 delete m_oscQueue;
Chris@45 209 Profiles::getInstance()->dump();
Chris@45 210 }
Chris@45 211
Chris@45 212 QString
Chris@45 213 MainWindowBase::getOpenFileName(FileFinder::FileType type)
Chris@45 214 {
Chris@45 215 FileFinder *ff = FileFinder::getInstance();
Chris@45 216 switch (type) {
Chris@45 217 case FileFinder::SessionFile:
Chris@45 218 return ff->getOpenFileName(type, m_sessionFile);
Chris@45 219 case FileFinder::AudioFile:
Chris@45 220 return ff->getOpenFileName(type, m_audioFile);
Chris@45 221 case FileFinder::LayerFile:
Chris@45 222 return ff->getOpenFileName(type, m_sessionFile);
Chris@45 223 case FileFinder::LayerFileNoMidi:
Chris@45 224 return ff->getOpenFileName(type, m_sessionFile);
Chris@45 225 case FileFinder::SessionOrAudioFile:
Chris@45 226 return ff->getOpenFileName(type, m_sessionFile);
Chris@45 227 case FileFinder::ImageFile:
Chris@45 228 return ff->getOpenFileName(type, m_sessionFile);
Chris@45 229 case FileFinder::AnyFile:
Chris@45 230 if (getMainModel() != 0 &&
Chris@45 231 m_paneStack != 0 &&
Chris@45 232 m_paneStack->getCurrentPane() != 0) { // can import a layer
Chris@45 233 return ff->getOpenFileName(FileFinder::AnyFile, m_sessionFile);
Chris@45 234 } else {
Chris@45 235 return ff->getOpenFileName(FileFinder::SessionOrAudioFile,
Chris@45 236 m_sessionFile);
Chris@45 237 }
Chris@45 238 }
Chris@45 239 return "";
Chris@45 240 }
Chris@45 241
Chris@45 242 QString
Chris@45 243 MainWindowBase::getSaveFileName(FileFinder::FileType type)
Chris@45 244 {
Chris@45 245 FileFinder *ff = FileFinder::getInstance();
Chris@45 246 switch (type) {
Chris@45 247 case FileFinder::SessionFile:
Chris@45 248 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 249 case FileFinder::AudioFile:
Chris@45 250 return ff->getSaveFileName(type, m_audioFile);
Chris@45 251 case FileFinder::LayerFile:
Chris@45 252 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 253 case FileFinder::LayerFileNoMidi:
Chris@45 254 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 255 case FileFinder::SessionOrAudioFile:
Chris@45 256 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 257 case FileFinder::ImageFile:
Chris@45 258 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 259 case FileFinder::AnyFile:
Chris@45 260 return ff->getSaveFileName(type, m_sessionFile);
Chris@45 261 }
Chris@45 262 return "";
Chris@45 263 }
Chris@45 264
Chris@45 265 void
Chris@45 266 MainWindowBase::registerLastOpenedFilePath(FileFinder::FileType type, QString path)
Chris@45 267 {
Chris@45 268 FileFinder *ff = FileFinder::getInstance();
Chris@45 269 ff->registerLastOpenedFilePath(type, path);
Chris@45 270 }
Chris@45 271
Chris@45 272 void
Chris@45 273 MainWindowBase::updateMenuStates()
Chris@45 274 {
Chris@45 275 Pane *currentPane = 0;
Chris@45 276 Layer *currentLayer = 0;
Chris@45 277
Chris@45 278 if (m_paneStack) currentPane = m_paneStack->getCurrentPane();
Chris@45 279 if (currentPane) currentLayer = currentPane->getSelectedLayer();
Chris@45 280
Chris@73 281 bool havePrevPane = false, haveNextPane = false;
Chris@73 282 bool havePrevLayer = false, haveNextLayer = false;
Chris@73 283
Chris@73 284 if (currentPane) {
Chris@73 285 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@73 286 if (m_paneStack->getPane(i) == currentPane) {
Chris@73 287 if (i > 0) havePrevPane = true;
Chris@73 288 if (i < m_paneStack->getPaneCount()-1) haveNextPane = true;
Chris@73 289 break;
Chris@73 290 }
Chris@73 291 }
Chris@73 292 if (currentLayer) {
Chris@73 293 for (int i = 0; i < currentPane->getLayerCount(); ++i) {
Chris@73 294 if (currentPane->getLayer(i) == currentLayer) {
Chris@73 295 if (i > 0) havePrevLayer = true;
Chris@73 296 if (i < currentPane->getLayerCount()-1) haveNextLayer = true;
Chris@73 297 break;
Chris@73 298 }
Chris@73 299 }
Chris@73 300 }
Chris@73 301 }
Chris@73 302
Chris@45 303 bool haveCurrentPane =
Chris@45 304 (currentPane != 0);
Chris@45 305 bool haveCurrentLayer =
Chris@45 306 (haveCurrentPane &&
Chris@45 307 (currentLayer != 0));
Chris@45 308 bool haveMainModel =
Chris@45 309 (getMainModel() != 0);
Chris@45 310 bool havePlayTarget =
Chris@45 311 (m_playTarget != 0);
Chris@45 312 bool haveSelection =
Chris@45 313 (m_viewManager &&
Chris@45 314 !m_viewManager->getSelections().empty());
Chris@45 315 bool haveCurrentEditableLayer =
Chris@45 316 (haveCurrentLayer &&
Chris@45 317 currentLayer->isLayerEditable());
Chris@45 318 bool haveCurrentTimeInstantsLayer =
Chris@45 319 (haveCurrentLayer &&
Chris@45 320 dynamic_cast<TimeInstantLayer *>(currentLayer));
Chris@45 321 bool haveCurrentColour3DPlot =
Chris@45 322 (haveCurrentLayer &&
Chris@45 323 dynamic_cast<Colour3DPlotLayer *>(currentLayer));
Chris@45 324 bool haveClipboardContents =
Chris@45 325 (m_viewManager &&
Chris@45 326 !m_viewManager->getClipboard().empty());
Chris@45 327
Chris@45 328 emit canAddPane(haveMainModel);
Chris@45 329 emit canDeleteCurrentPane(haveCurrentPane);
Chris@45 330 emit canZoom(haveMainModel && haveCurrentPane);
Chris@45 331 emit canScroll(haveMainModel && haveCurrentPane);
Chris@45 332 emit canAddLayer(haveMainModel && haveCurrentPane);
Chris@45 333 emit canImportMoreAudio(haveMainModel);
Chris@45 334 emit canImportLayer(haveMainModel && haveCurrentPane);
Chris@45 335 emit canExportAudio(haveMainModel);
Chris@45 336 emit canExportLayer(haveMainModel &&
Chris@45 337 (haveCurrentEditableLayer || haveCurrentColour3DPlot));
Chris@45 338 emit canExportImage(haveMainModel && haveCurrentPane);
Chris@45 339 emit canDeleteCurrentLayer(haveCurrentLayer);
Chris@45 340 emit canRenameLayer(haveCurrentLayer);
Chris@45 341 emit canEditLayer(haveCurrentEditableLayer);
Chris@45 342 emit canMeasureLayer(haveCurrentLayer);
Chris@45 343 emit canSelect(haveMainModel && haveCurrentPane);
Chris@45 344 emit canPlay(havePlayTarget);
Chris@45 345 emit canFfwd(true);
Chris@45 346 emit canRewind(true);
Chris@45 347 emit canPaste(haveCurrentEditableLayer && haveClipboardContents);
Chris@45 348 emit canInsertInstant(haveCurrentPane);
Chris@45 349 emit canInsertInstantsAtBoundaries(haveCurrentPane && haveSelection);
Chris@45 350 emit canRenumberInstants(haveCurrentTimeInstantsLayer && haveSelection);
Chris@45 351 emit canPlaySelection(haveMainModel && havePlayTarget && haveSelection);
Chris@45 352 emit canClearSelection(haveSelection);
Chris@45 353 emit canEditSelection(haveSelection && haveCurrentEditableLayer);
Chris@45 354 emit canSave(m_sessionFile != "" && m_documentModified);
Chris@73 355 emit canSelectPreviousPane(havePrevPane);
Chris@73 356 emit canSelectNextPane(haveNextPane);
Chris@73 357 emit canSelectPreviousLayer(havePrevLayer);
Chris@73 358 emit canSelectNextLayer(haveNextLayer);
Chris@45 359 }
Chris@45 360
Chris@45 361 void
Chris@45 362 MainWindowBase::documentModified()
Chris@45 363 {
Chris@45 364 // std::cerr << "MainWindowBase::documentModified" << std::endl;
Chris@45 365
Chris@45 366 if (!m_documentModified) {
Chris@45 367 //!!! this in subclass implementation?
Chris@45 368 setWindowTitle(tr("%1 (modified)").arg(windowTitle()));
Chris@45 369 }
Chris@45 370
Chris@45 371 m_documentModified = true;
Chris@45 372 updateMenuStates();
Chris@45 373 }
Chris@45 374
Chris@45 375 void
Chris@45 376 MainWindowBase::documentRestored()
Chris@45 377 {
Chris@45 378 // std::cerr << "MainWindowBase::documentRestored" << std::endl;
Chris@45 379
Chris@45 380 if (m_documentModified) {
Chris@45 381 //!!! this in subclass implementation?
Chris@45 382 QString wt(windowTitle());
Chris@45 383 wt.replace(tr(" (modified)"), "");
Chris@45 384 setWindowTitle(wt);
Chris@45 385 }
Chris@45 386
Chris@45 387 m_documentModified = false;
Chris@45 388 updateMenuStates();
Chris@45 389 }
Chris@45 390
Chris@45 391 void
Chris@45 392 MainWindowBase::playLoopToggled()
Chris@45 393 {
Chris@45 394 QAction *action = dynamic_cast<QAction *>(sender());
Chris@45 395
Chris@45 396 if (action) {
Chris@45 397 m_viewManager->setPlayLoopMode(action->isChecked());
Chris@45 398 } else {
Chris@45 399 m_viewManager->setPlayLoopMode(!m_viewManager->getPlayLoopMode());
Chris@45 400 }
Chris@45 401 }
Chris@45 402
Chris@45 403 void
Chris@45 404 MainWindowBase::playSelectionToggled()
Chris@45 405 {
Chris@45 406 QAction *action = dynamic_cast<QAction *>(sender());
Chris@45 407
Chris@45 408 if (action) {
Chris@45 409 m_viewManager->setPlaySelectionMode(action->isChecked());
Chris@45 410 } else {
Chris@45 411 m_viewManager->setPlaySelectionMode(!m_viewManager->getPlaySelectionMode());
Chris@45 412 }
Chris@45 413 }
Chris@45 414
Chris@45 415 void
Chris@45 416 MainWindowBase::playSoloToggled()
Chris@45 417 {
Chris@45 418 QAction *action = dynamic_cast<QAction *>(sender());
Chris@45 419
Chris@45 420 if (action) {
Chris@45 421 m_viewManager->setPlaySoloMode(action->isChecked());
Chris@45 422 } else {
Chris@45 423 m_viewManager->setPlaySoloMode(!m_viewManager->getPlaySoloMode());
Chris@45 424 }
Chris@45 425
Chris@45 426 if (m_viewManager->getPlaySoloMode()) {
Chris@45 427 currentPaneChanged(m_paneStack->getCurrentPane());
Chris@45 428 } else {
Chris@45 429 m_viewManager->setPlaybackModel(0);
Chris@45 430 if (m_playSource) {
Chris@45 431 m_playSource->clearSoloModelSet();
Chris@45 432 }
Chris@45 433 }
Chris@45 434 }
Chris@45 435
Chris@45 436 void
Chris@45 437 MainWindowBase::currentPaneChanged(Pane *p)
Chris@45 438 {
Chris@45 439 updateMenuStates();
Chris@45 440 updateVisibleRangeDisplay(p);
Chris@45 441
Chris@45 442 if (!p) return;
Chris@45 443
Chris@45 444 if (!(m_viewManager &&
Chris@45 445 m_playSource &&
Chris@45 446 m_viewManager->getPlaySoloMode())) {
Chris@45 447 if (m_viewManager) m_viewManager->setPlaybackModel(0);
Chris@45 448 return;
Chris@45 449 }
Chris@45 450
Chris@45 451 Model *prevPlaybackModel = m_viewManager->getPlaybackModel();
Chris@60 452 int frame = m_playSource->getCurrentPlayingFrame();
Chris@60 453
Chris@60 454 std::cerr << "playing frame (in ref model) = " << frame << std::endl;
Chris@45 455
Chris@45 456 View::ModelSet soloModels = p->getModels();
Chris@45 457
Chris@57 458 View::ModelSet sources;
Chris@57 459 for (View::ModelSet::iterator mi = soloModels.begin();
Chris@57 460 mi != soloModels.end(); ++mi) {
Chris@57 461 if (*mi && (*mi)->getSourceModel()) {
Chris@57 462 sources.insert((*mi)->getSourceModel());
Chris@57 463 }
Chris@57 464 }
Chris@57 465 for (View::ModelSet::iterator mi = sources.begin();
Chris@57 466 mi != sources.end(); ++mi) {
Chris@57 467 soloModels.insert(*mi);
Chris@57 468 }
Chris@57 469
Chris@60 470 //!!! Need an "atomic" way of telling the play source that the
Chris@60 471 //playback model has changed, and changing it on ViewManager --
Chris@60 472 //the play source should be making the setPlaybackModel call to
Chris@60 473 //ViewManager
Chris@60 474
Chris@45 475 for (View::ModelSet::iterator mi = soloModels.begin();
Chris@45 476 mi != soloModels.end(); ++mi) {
Chris@45 477 if (dynamic_cast<RangeSummarisableTimeValueModel *>(*mi)) {
Chris@45 478 m_viewManager->setPlaybackModel(*mi);
Chris@45 479 }
Chris@45 480 }
Chris@45 481
Chris@45 482 RangeSummarisableTimeValueModel *a =
Chris@45 483 dynamic_cast<RangeSummarisableTimeValueModel *>(prevPlaybackModel);
Chris@45 484 RangeSummarisableTimeValueModel *b =
Chris@45 485 dynamic_cast<RangeSummarisableTimeValueModel *>(m_viewManager->
Chris@45 486 getPlaybackModel());
Chris@45 487
Chris@45 488 m_playSource->setSoloModelSet(soloModels);
Chris@45 489
Chris@45 490 if (a && b && (a != b)) {
Chris@60 491 /*!!!
Chris@60 492 int rframe = a->alignToReference(frame);
Chris@60 493 int bframe = b->alignFromReference(rframe);
Chris@45 494 if (m_playSource->isPlaying()) m_playSource->play(bframe);
Chris@60 495 */
Chris@60 496 if (m_playSource->isPlaying()) m_playSource->play(frame);
Chris@45 497 }
Chris@45 498 }
Chris@45 499
Chris@45 500 void
Chris@45 501 MainWindowBase::currentLayerChanged(Pane *p, Layer *)
Chris@45 502 {
Chris@45 503 updateMenuStates();
Chris@45 504 updateVisibleRangeDisplay(p);
Chris@45 505 }
Chris@45 506
Chris@45 507 void
Chris@45 508 MainWindowBase::selectAll()
Chris@45 509 {
Chris@45 510 if (!getMainModel()) return;
Chris@45 511 m_viewManager->setSelection(Selection(getMainModel()->getStartFrame(),
Chris@45 512 getMainModel()->getEndFrame()));
Chris@45 513 }
Chris@45 514
Chris@45 515 void
Chris@45 516 MainWindowBase::selectToStart()
Chris@45 517 {
Chris@45 518 if (!getMainModel()) return;
Chris@45 519 m_viewManager->setSelection(Selection(getMainModel()->getStartFrame(),
Chris@45 520 m_viewManager->getGlobalCentreFrame()));
Chris@45 521 }
Chris@45 522
Chris@45 523 void
Chris@45 524 MainWindowBase::selectToEnd()
Chris@45 525 {
Chris@45 526 if (!getMainModel()) return;
Chris@45 527 m_viewManager->setSelection(Selection(m_viewManager->getGlobalCentreFrame(),
Chris@45 528 getMainModel()->getEndFrame()));
Chris@45 529 }
Chris@45 530
Chris@45 531 void
Chris@45 532 MainWindowBase::selectVisible()
Chris@45 533 {
Chris@45 534 Model *model = getMainModel();
Chris@45 535 if (!model) return;
Chris@45 536
Chris@45 537 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 538 if (!currentPane) return;
Chris@45 539
Chris@45 540 size_t startFrame, endFrame;
Chris@45 541
Chris@45 542 if (currentPane->getStartFrame() < 0) startFrame = 0;
Chris@45 543 else startFrame = currentPane->getStartFrame();
Chris@45 544
Chris@45 545 if (currentPane->getEndFrame() > model->getEndFrame()) endFrame = model->getEndFrame();
Chris@45 546 else endFrame = currentPane->getEndFrame();
Chris@45 547
Chris@45 548 m_viewManager->setSelection(Selection(startFrame, endFrame));
Chris@45 549 }
Chris@45 550
Chris@45 551 void
Chris@45 552 MainWindowBase::clearSelection()
Chris@45 553 {
Chris@45 554 m_viewManager->clearSelections();
Chris@45 555 }
Chris@45 556
Chris@45 557 void
Chris@45 558 MainWindowBase::cut()
Chris@45 559 {
Chris@45 560 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 561 if (!currentPane) return;
Chris@45 562
Chris@45 563 Layer *layer = currentPane->getSelectedLayer();
Chris@45 564 if (!layer) return;
Chris@45 565
Chris@45 566 Clipboard &clipboard = m_viewManager->getClipboard();
Chris@45 567 clipboard.clear();
Chris@45 568
Chris@45 569 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@45 570
Chris@45 571 CommandHistory::getInstance()->startCompoundOperation(tr("Cut"), true);
Chris@45 572
Chris@45 573 for (MultiSelection::SelectionList::iterator i = selections.begin();
Chris@45 574 i != selections.end(); ++i) {
Chris@45 575 layer->copy(*i, clipboard);
Chris@45 576 layer->deleteSelection(*i);
Chris@45 577 }
Chris@45 578
Chris@45 579 CommandHistory::getInstance()->endCompoundOperation();
Chris@45 580 }
Chris@45 581
Chris@45 582 void
Chris@45 583 MainWindowBase::copy()
Chris@45 584 {
Chris@45 585 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 586 if (!currentPane) return;
Chris@45 587
Chris@45 588 Layer *layer = currentPane->getSelectedLayer();
Chris@45 589 if (!layer) return;
Chris@45 590
Chris@45 591 Clipboard &clipboard = m_viewManager->getClipboard();
Chris@45 592 clipboard.clear();
Chris@45 593
Chris@45 594 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@45 595
Chris@45 596 for (MultiSelection::SelectionList::iterator i = selections.begin();
Chris@45 597 i != selections.end(); ++i) {
Chris@45 598 layer->copy(*i, clipboard);
Chris@45 599 }
Chris@45 600 }
Chris@45 601
Chris@45 602 void
Chris@45 603 MainWindowBase::paste()
Chris@45 604 {
Chris@45 605 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 606 if (!currentPane) return;
Chris@45 607
Chris@45 608 //!!! if we have no current layer, we should create one of the most
Chris@45 609 // appropriate type
Chris@45 610
Chris@45 611 Layer *layer = currentPane->getSelectedLayer();
Chris@45 612 if (!layer) return;
Chris@45 613
Chris@45 614 Clipboard &clipboard = m_viewManager->getClipboard();
Chris@45 615 Clipboard::PointList contents = clipboard.getPoints();
Chris@45 616 /*
Chris@45 617 long minFrame = 0;
Chris@45 618 bool have = false;
Chris@45 619 for (int i = 0; i < contents.size(); ++i) {
Chris@45 620 if (!contents[i].haveFrame()) continue;
Chris@45 621 if (!have || contents[i].getFrame() < minFrame) {
Chris@45 622 minFrame = contents[i].getFrame();
Chris@45 623 have = true;
Chris@45 624 }
Chris@45 625 }
Chris@45 626
Chris@45 627 long frameOffset = long(m_viewManager->getGlobalCentreFrame()) - minFrame;
Chris@45 628
Chris@45 629 layer->paste(clipboard, frameOffset);
Chris@45 630 */
Chris@45 631 layer->paste(clipboard, 0, true);
Chris@45 632 }
Chris@45 633
Chris@45 634 void
Chris@45 635 MainWindowBase::deleteSelected()
Chris@45 636 {
Chris@45 637 if (m_paneStack->getCurrentPane() &&
Chris@45 638 m_paneStack->getCurrentPane()->getSelectedLayer()) {
Chris@45 639
Chris@45 640 Layer *layer = m_paneStack->getCurrentPane()->getSelectedLayer();
Chris@45 641
Chris@45 642 if (m_viewManager &&
Chris@45 643 (m_viewManager->getToolMode() == ViewManager::MeasureMode)) {
Chris@45 644
Chris@45 645 layer->deleteCurrentMeasureRect();
Chris@45 646
Chris@45 647 } else {
Chris@45 648
Chris@45 649 MultiSelection::SelectionList selections =
Chris@45 650 m_viewManager->getSelections();
Chris@45 651
Chris@45 652 for (MultiSelection::SelectionList::iterator i = selections.begin();
Chris@45 653 i != selections.end(); ++i) {
Chris@45 654 layer->deleteSelection(*i);
Chris@45 655 }
Chris@45 656 }
Chris@45 657 }
Chris@45 658 }
Chris@45 659
Chris@45 660 void
Chris@45 661 MainWindowBase::insertInstant()
Chris@45 662 {
Chris@45 663 int frame = m_viewManager->getPlaybackFrame();
Chris@45 664 insertInstantAt(frame);
Chris@45 665 }
Chris@45 666
Chris@45 667 void
Chris@45 668 MainWindowBase::insertInstantsAtBoundaries()
Chris@45 669 {
Chris@45 670 MultiSelection::SelectionList selections = m_viewManager->getSelections();
Chris@45 671 for (MultiSelection::SelectionList::iterator i = selections.begin();
Chris@45 672 i != selections.end(); ++i) {
Chris@45 673 size_t start = i->getStartFrame();
Chris@45 674 size_t end = i->getEndFrame();
Chris@45 675 if (start != end) {
Chris@45 676 insertInstantAt(i->getStartFrame());
Chris@45 677 insertInstantAt(i->getEndFrame());
Chris@45 678 }
Chris@45 679 }
Chris@45 680 }
Chris@45 681
Chris@45 682 void
Chris@45 683 MainWindowBase::insertInstantAt(size_t frame)
Chris@45 684 {
Chris@45 685 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 686 if (!pane) {
Chris@45 687 return;
Chris@45 688 }
Chris@45 689
Chris@74 690 frame = pane->alignFromReference(frame);
Chris@74 691
Chris@45 692 Layer *layer = dynamic_cast<TimeInstantLayer *>
Chris@45 693 (pane->getSelectedLayer());
Chris@45 694
Chris@45 695 if (!layer) {
Chris@45 696 for (int i = pane->getLayerCount(); i > 0; --i) {
Chris@45 697 layer = dynamic_cast<TimeInstantLayer *>(pane->getLayer(i - 1));
Chris@45 698 if (layer) break;
Chris@45 699 }
Chris@45 700
Chris@45 701 if (!layer) {
Chris@45 702 CommandHistory::getInstance()->startCompoundOperation
Chris@45 703 (tr("Add Point"), true);
Chris@45 704 layer = m_document->createEmptyLayer(LayerFactory::TimeInstants);
Chris@45 705 if (layer) {
Chris@45 706 m_document->addLayerToView(pane, layer);
Chris@45 707 m_paneStack->setCurrentLayer(pane, layer);
Chris@45 708 }
Chris@45 709 CommandHistory::getInstance()->endCompoundOperation();
Chris@45 710 }
Chris@45 711 }
Chris@45 712
Chris@45 713 if (layer) {
Chris@45 714
Chris@45 715 Model *model = layer->getModel();
Chris@45 716 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
Chris@45 717 (model);
Chris@45 718
Chris@45 719 if (sodm) {
Chris@45 720 SparseOneDimensionalModel::Point point(frame, "");
Chris@45 721
Chris@45 722 SparseOneDimensionalModel::Point prevPoint(0);
Chris@45 723 bool havePrevPoint = false;
Chris@45 724
Chris@45 725 SparseOneDimensionalModel::EditCommand *command =
Chris@45 726 new SparseOneDimensionalModel::EditCommand(sodm, tr("Add Point"));
Chris@45 727
Chris@74 728 if (m_labeller->requiresPrevPoint()) {
Chris@45 729
Chris@45 730 SparseOneDimensionalModel::PointList prevPoints =
Chris@45 731 sodm->getPreviousPoints(frame);
Chris@45 732
Chris@45 733 if (!prevPoints.empty()) {
Chris@45 734 prevPoint = *prevPoints.begin();
Chris@45 735 havePrevPoint = true;
Chris@45 736 }
Chris@45 737 }
Chris@45 738
Chris@45 739 if (m_labeller) {
Chris@45 740
Chris@45 741 m_labeller->setSampleRate(sodm->getSampleRate());
Chris@45 742
Chris@74 743 if (m_labeller->actingOnPrevPoint()) {
Chris@45 744 command->deletePoint(prevPoint);
Chris@45 745 }
Chris@45 746
Chris@45 747 m_labeller->label<SparseOneDimensionalModel::Point>
Chris@45 748 (point, havePrevPoint ? &prevPoint : 0);
Chris@45 749
Chris@74 750 if (m_labeller->actingOnPrevPoint()) {
Chris@45 751 command->addPoint(prevPoint);
Chris@45 752 }
Chris@45 753 }
Chris@45 754
Chris@45 755 command->addPoint(point);
Chris@45 756
Chris@45 757 command->setName(tr("Add Point at %1 s")
Chris@45 758 .arg(RealTime::frame2RealTime
Chris@45 759 (frame,
Chris@45 760 sodm->getSampleRate())
Chris@45 761 .toText(false).c_str()));
Chris@45 762
Chris@45 763 command->finish();
Chris@45 764 }
Chris@45 765 }
Chris@45 766 }
Chris@45 767
Chris@45 768 void
Chris@45 769 MainWindowBase::renumberInstants()
Chris@45 770 {
Chris@45 771 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 772 if (!pane) return;
Chris@45 773
Chris@45 774 Layer *layer = dynamic_cast<TimeInstantLayer *>(pane->getSelectedLayer());
Chris@45 775 if (!layer) return;
Chris@45 776
Chris@45 777 MultiSelection ms(m_viewManager->getSelection());
Chris@45 778
Chris@45 779 Model *model = layer->getModel();
Chris@45 780 SparseOneDimensionalModel *sodm = dynamic_cast<SparseOneDimensionalModel *>
Chris@45 781 (model);
Chris@45 782 if (!sodm) return;
Chris@45 783
Chris@45 784 if (!m_labeller) return;
Chris@45 785
Chris@45 786 Labeller labeller(*m_labeller);
Chris@45 787 labeller.setSampleRate(sodm->getSampleRate());
Chris@45 788
Chris@45 789 // This uses a command
Chris@45 790
Chris@45 791 labeller.labelAll<SparseOneDimensionalModel::Point>(*sodm, &ms);
Chris@45 792 }
Chris@45 793
Chris@45 794 MainWindowBase::FileOpenStatus
Chris@45 795 MainWindowBase::open(QString fileOrUrl, AudioFileOpenMode mode)
Chris@45 796 {
Chris@76 797 return open(FileSource(fileOrUrl, FileSource::ProgressDialog), mode);
Chris@45 798 }
Chris@45 799
Chris@45 800 MainWindowBase::FileOpenStatus
Chris@45 801 MainWindowBase::open(FileSource source, AudioFileOpenMode mode)
Chris@45 802 {
Chris@45 803 FileOpenStatus status;
Chris@45 804
Chris@45 805 if (!source.isAvailable()) return FileOpenFailed;
Chris@45 806 source.waitForData();
Chris@45 807
Chris@45 808 bool canImportLayer = (getMainModel() != 0 &&
Chris@45 809 m_paneStack != 0 &&
Chris@45 810 m_paneStack->getCurrentPane() != 0);
Chris@45 811
Chris@45 812 if ((status = openAudio(source, mode)) != FileOpenFailed) {
Chris@45 813 return status;
Chris@45 814 } else if ((status = openSession(source)) != FileOpenFailed) {
Chris@45 815 return status;
Chris@45 816 } else if ((status = openPlaylist(source, mode)) != FileOpenFailed) {
Chris@45 817 return status;
Chris@45 818 } else if (!canImportLayer) {
Chris@45 819 return FileOpenWrongMode;
Chris@45 820 } else if ((status = openImage(source)) != FileOpenFailed) {
Chris@45 821 return status;
Chris@45 822 } else if ((status = openLayer(source)) != FileOpenFailed) {
Chris@45 823 return status;
Chris@45 824 } else {
Chris@45 825 return FileOpenFailed;
Chris@45 826 }
Chris@45 827 }
Chris@45 828
Chris@45 829 MainWindowBase::FileOpenStatus
Chris@45 830 MainWindowBase::openAudio(FileSource source, AudioFileOpenMode mode)
Chris@45 831 {
Chris@45 832 std::cerr << "MainWindowBase::openAudio(" << source.getLocation().toStdString() << ")" << std::endl;
Chris@45 833
Chris@45 834 if (!source.isAvailable()) return FileOpenFailed;
Chris@45 835 source.waitForData();
Chris@45 836
Chris@45 837 m_openingAudioFile = true;
Chris@45 838
Chris@45 839 size_t rate = 0;
Chris@45 840
Chris@45 841 if (Preferences::getInstance()->getResampleOnLoad()) {
Chris@45 842 rate = m_playSource->getSourceSampleRate();
Chris@45 843 }
Chris@45 844
Chris@45 845 WaveFileModel *newModel = new WaveFileModel(source, rate);
Chris@45 846
Chris@45 847 if (!newModel->isOK()) {
Chris@45 848 delete newModel;
Chris@45 849 m_openingAudioFile = false;
Chris@45 850 return FileOpenFailed;
Chris@45 851 }
Chris@45 852
Chris@45 853 std::cerr << "mode = " << mode << std::endl;
Chris@45 854
Chris@45 855 if (mode == AskUser) {
Chris@45 856 if (getMainModel()) {
Chris@45 857
Chris@45 858 static bool prevSetAsMain = true;
Chris@45 859 bool setAsMain = true;
Chris@45 860
Chris@45 861 QStringList items;
Chris@45 862 items << tr("Replace the existing main waveform")
Chris@45 863 << tr("Load this file into a new waveform pane");
Chris@45 864
Chris@45 865 bool ok = false;
Chris@45 866 QString item = ListInputDialog::getItem
Chris@45 867 (this, tr("Select target for import"),
Chris@45 868 tr("You already have an audio waveform loaded.\nWhat would you like to do with the new audio file?"),
Chris@45 869 items, prevSetAsMain ? 0 : 1, &ok);
Chris@45 870
Chris@45 871 if (!ok || item.isEmpty()) {
Chris@45 872 delete newModel;
Chris@45 873 m_openingAudioFile = false;
Chris@45 874 return FileOpenCancelled;
Chris@45 875 }
Chris@45 876
Chris@45 877 setAsMain = (item == items[0]);
Chris@45 878 prevSetAsMain = setAsMain;
Chris@45 879
Chris@45 880 if (setAsMain) mode = ReplaceMainModel;
Chris@45 881 else mode = CreateAdditionalModel;
Chris@45 882
Chris@45 883 } else {
Chris@45 884 mode = ReplaceMainModel;
Chris@45 885 }
Chris@45 886 }
Chris@45 887
Chris@45 888 if (mode == ReplaceCurrentPane) {
Chris@45 889
Chris@45 890 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 891 if (pane) {
Chris@45 892 if (getMainModel()) {
Chris@45 893 View::ModelSet models(pane->getModels());
Chris@45 894 if (models.find(getMainModel()) != models.end()) {
Chris@45 895 mode = ReplaceMainModel;
Chris@45 896 }
Chris@45 897 } else {
Chris@45 898 mode = ReplaceMainModel;
Chris@45 899 }
Chris@45 900 } else {
Chris@45 901 mode = CreateAdditionalModel;
Chris@45 902 }
Chris@45 903 }
Chris@45 904
Chris@45 905 if (mode == CreateAdditionalModel && !getMainModel()) {
Chris@45 906 mode = ReplaceMainModel;
Chris@45 907 }
Chris@45 908
Chris@45 909 if (mode == ReplaceMainModel) {
Chris@45 910
Chris@45 911 Model *prevMain = getMainModel();
Chris@45 912 if (prevMain) {
Chris@45 913 m_playSource->removeModel(prevMain);
Chris@45 914 PlayParameterRepository::getInstance()->removeModel(prevMain);
Chris@45 915 }
Chris@45 916 PlayParameterRepository::getInstance()->addModel(newModel);
Chris@45 917
Chris@45 918 m_document->setMainModel(newModel);
Chris@45 919
Chris@45 920 setupMenus();
Chris@45 921
Chris@45 922 if (m_sessionFile == "") {
Chris@45 923 //!!! shouldn't be dealing directly with title from here -- call a method
Chris@57 924 setWindowTitle(tr("%1: %2")
Chris@57 925 .arg(QApplication::applicationName())
Chris@45 926 .arg(source.getLocation()));
Chris@45 927 CommandHistory::getInstance()->clear();
Chris@45 928 CommandHistory::getInstance()->documentSaved();
Chris@45 929 m_documentModified = false;
Chris@45 930 } else {
Chris@57 931 setWindowTitle(tr("%1: %2 [%3]")
Chris@57 932 .arg(QApplication::applicationName())
Chris@45 933 .arg(QFileInfo(m_sessionFile).fileName())
Chris@45 934 .arg(source.getLocation()));
Chris@45 935 if (m_documentModified) {
Chris@45 936 m_documentModified = false;
Chris@45 937 documentModified(); // so as to restore "(modified)" window title
Chris@45 938 }
Chris@45 939 }
Chris@45 940
Chris@45 941 if (!source.isRemote()) m_audioFile = source.getLocalFilename();
Chris@45 942
Chris@45 943 } else if (mode == CreateAdditionalModel) {
Chris@45 944
Chris@45 945 CommandHistory::getInstance()->startCompoundOperation
Chris@45 946 (tr("Import \"%1\"").arg(source.getLocation()), true);
Chris@45 947
Chris@45 948 m_document->addImportedModel(newModel);
Chris@45 949
Chris@45 950 AddPaneCommand *command = new AddPaneCommand(this);
Chris@45 951 CommandHistory::getInstance()->addCommand(command);
Chris@45 952
Chris@45 953 Pane *pane = command->getPane();
Chris@45 954
Chris@47 955 if (m_timeRulerLayer) {
Chris@47 956 m_document->addLayerToView(pane, m_timeRulerLayer);
Chris@47 957 }
Chris@45 958
Chris@45 959 Layer *newLayer = m_document->createImportedLayer(newModel);
Chris@45 960
Chris@45 961 if (newLayer) {
Chris@45 962 m_document->addLayerToView(pane, newLayer);
Chris@45 963 }
Chris@45 964
Chris@45 965 CommandHistory::getInstance()->endCompoundOperation();
Chris@45 966
Chris@45 967 } else if (mode == ReplaceCurrentPane) {
Chris@45 968
Chris@45 969 // We know there is a current pane, otherwise we would have
Chris@45 970 // reset the mode to CreateAdditionalModel above; and we know
Chris@45 971 // the current pane does not contain the main model, otherwise
Chris@45 972 // we would have reset it to ReplaceMainModel. But we don't
Chris@45 973 // know whether the pane contains a waveform model at all.
Chris@45 974
Chris@45 975 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 976 Layer *replace = 0;
Chris@45 977
Chris@45 978 for (int i = 0; i < pane->getLayerCount(); ++i) {
Chris@45 979 Layer *layer = pane->getLayer(i);
Chris@45 980 if (dynamic_cast<WaveformLayer *>(layer)) {
Chris@45 981 replace = layer;
Chris@45 982 break;
Chris@45 983 }
Chris@45 984 }
Chris@45 985
Chris@45 986 CommandHistory::getInstance()->startCompoundOperation
Chris@45 987 (tr("Import \"%1\"").arg(source.getLocation()), true);
Chris@45 988
Chris@45 989 m_document->addImportedModel(newModel);
Chris@45 990
Chris@45 991 if (replace) {
Chris@45 992 m_document->removeLayerFromView(pane, replace);
Chris@45 993 }
Chris@45 994
Chris@45 995 Layer *newLayer = m_document->createImportedLayer(newModel);
Chris@45 996
Chris@45 997 if (newLayer) {
Chris@45 998 m_document->addLayerToView(pane, newLayer);
Chris@45 999 }
Chris@45 1000
Chris@45 1001 CommandHistory::getInstance()->endCompoundOperation();
Chris@45 1002 }
Chris@45 1003
Chris@45 1004 updateMenuStates();
Chris@45 1005 m_recentFiles.addFile(source.getLocation());
Chris@45 1006 if (!source.isRemote()) {
Chris@45 1007 // for file dialog
Chris@45 1008 registerLastOpenedFilePath(FileFinder::AudioFile,
Chris@45 1009 source.getLocalFilename());
Chris@45 1010 }
Chris@45 1011 m_openingAudioFile = false;
Chris@45 1012
Chris@45 1013 currentPaneChanged(m_paneStack->getCurrentPane());
Chris@45 1014
Chris@45 1015 return FileOpenSucceeded;
Chris@45 1016 }
Chris@45 1017
Chris@45 1018 MainWindowBase::FileOpenStatus
Chris@45 1019 MainWindowBase::openPlaylist(FileSource source, AudioFileOpenMode mode)
Chris@45 1020 {
Chris@45 1021 std::set<QString> extensions;
Chris@45 1022 PlaylistFileReader::getSupportedExtensions(extensions);
Chris@45 1023 QString extension = source.getExtension();
Chris@45 1024 if (extensions.find(extension) == extensions.end()) return FileOpenFailed;
Chris@45 1025
Chris@45 1026 if (!source.isAvailable()) return FileOpenFailed;
Chris@45 1027 source.waitForData();
Chris@45 1028
Chris@45 1029 PlaylistFileReader reader(source.getLocalFilename());
Chris@45 1030 if (!reader.isOK()) return FileOpenFailed;
Chris@45 1031
Chris@45 1032 PlaylistFileReader::Playlist playlist = reader.load();
Chris@45 1033
Chris@45 1034 bool someSuccess = false;
Chris@45 1035
Chris@45 1036 for (PlaylistFileReader::Playlist::const_iterator i = playlist.begin();
Chris@45 1037 i != playlist.end(); ++i) {
Chris@45 1038
Chris@76 1039 FileOpenStatus status = openAudio
Chris@76 1040 (FileSource(*i, FileSource::ProgressDialog), mode);
Chris@45 1041
Chris@45 1042 if (status == FileOpenCancelled) {
Chris@45 1043 return FileOpenCancelled;
Chris@45 1044 }
Chris@45 1045
Chris@45 1046 if (status == FileOpenSucceeded) {
Chris@45 1047 someSuccess = true;
Chris@45 1048 mode = CreateAdditionalModel;
Chris@45 1049 }
Chris@45 1050 }
Chris@45 1051
Chris@45 1052 if (someSuccess) return FileOpenSucceeded;
Chris@45 1053 else return FileOpenFailed;
Chris@45 1054 }
Chris@45 1055
Chris@45 1056 MainWindowBase::FileOpenStatus
Chris@45 1057 MainWindowBase::openLayer(FileSource source)
Chris@45 1058 {
Chris@45 1059 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 1060
Chris@45 1061 if (!pane) {
Chris@45 1062 // shouldn't happen, as the menu action should have been disabled
Chris@45 1063 std::cerr << "WARNING: MainWindowBase::openLayer: no current pane" << std::endl;
Chris@45 1064 return FileOpenWrongMode;
Chris@45 1065 }
Chris@45 1066
Chris@45 1067 if (!getMainModel()) {
Chris@45 1068 // shouldn't happen, as the menu action should have been disabled
Chris@45 1069 std::cerr << "WARNING: MainWindowBase::openLayer: No main model -- hence no default sample rate available" << std::endl;
Chris@45 1070 return FileOpenWrongMode;
Chris@45 1071 }
Chris@45 1072
Chris@45 1073 if (!source.isAvailable()) return FileOpenFailed;
Chris@45 1074 source.waitForData();
Chris@45 1075
Chris@45 1076 QString path = source.getLocalFilename();
Chris@45 1077
Chris@45 1078 if (source.getExtension() == "svl" || source.getExtension() == "xml") {
Chris@45 1079
Chris@45 1080 PaneCallback callback(this);
Chris@45 1081 QFile file(path);
Chris@45 1082
Chris@45 1083 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
Chris@45 1084 std::cerr << "ERROR: MainWindowBase::openLayer("
Chris@45 1085 << source.getLocation().toStdString()
Chris@45 1086 << "): Failed to open file for reading" << std::endl;
Chris@45 1087 return FileOpenFailed;
Chris@45 1088 }
Chris@45 1089
Chris@45 1090 SVFileReader reader(m_document, callback, source.getLocation());
Chris@45 1091 reader.setCurrentPane(pane);
Chris@45 1092
Chris@45 1093 QXmlInputSource inputSource(&file);
Chris@45 1094 reader.parse(inputSource);
Chris@45 1095
Chris@45 1096 if (!reader.isOK()) {
Chris@45 1097 std::cerr << "ERROR: MainWindowBase::openLayer("
Chris@45 1098 << source.getLocation().toStdString()
Chris@45 1099 << "): Failed to read XML file: "
Chris@45 1100 << reader.getErrorString().toStdString() << std::endl;
Chris@45 1101 return FileOpenFailed;
Chris@45 1102 }
Chris@45 1103
Chris@45 1104 m_recentFiles.addFile(source.getLocation());
Chris@45 1105
Chris@45 1106 if (!source.isRemote()) {
Chris@45 1107 registerLastOpenedFilePath(FileFinder::LayerFile, path); // for file dialog
Chris@45 1108 }
Chris@45 1109
Chris@75 1110 return FileOpenSucceeded;
Chris@75 1111
Chris@45 1112 } else {
Chris@45 1113
Chris@45 1114 try {
Chris@45 1115
Chris@45 1116 Model *model = DataFileReaderFactory::load
Chris@45 1117 (path, getMainModel()->getSampleRate());
Chris@45 1118
Chris@45 1119 if (model) {
Chris@45 1120
Chris@45 1121 std::cerr << "MainWindowBase::openLayer: Have model" << std::endl;
Chris@45 1122
Chris@45 1123 Layer *newLayer = m_document->createImportedLayer(model);
Chris@45 1124
Chris@45 1125 if (newLayer) {
Chris@45 1126
Chris@45 1127 m_document->addLayerToView(pane, newLayer);
Chris@45 1128 m_recentFiles.addFile(source.getLocation());
Chris@45 1129
Chris@45 1130 if (!source.isRemote()) {
Chris@45 1131 registerLastOpenedFilePath
Chris@45 1132 (FileFinder::LayerFile,
Chris@45 1133 path); // for file dialog
Chris@45 1134 }
Chris@45 1135
Chris@45 1136 return FileOpenSucceeded;
Chris@45 1137 }
Chris@45 1138 }
Chris@45 1139 } catch (DataFileReaderFactory::Exception e) {
Chris@45 1140 if (e == DataFileReaderFactory::ImportCancelled) {
Chris@45 1141 return FileOpenCancelled;
Chris@45 1142 }
Chris@45 1143 }
Chris@45 1144 }
Chris@45 1145
Chris@45 1146 return FileOpenFailed;
Chris@45 1147 }
Chris@45 1148
Chris@45 1149 MainWindowBase::FileOpenStatus
Chris@45 1150 MainWindowBase::openImage(FileSource source)
Chris@45 1151 {
Chris@45 1152 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 1153
Chris@45 1154 if (!pane) {
Chris@45 1155 // shouldn't happen, as the menu action should have been disabled
Chris@45 1156 std::cerr << "WARNING: MainWindowBase::openImage: no current pane" << std::endl;
Chris@45 1157 return FileOpenWrongMode;
Chris@45 1158 }
Chris@45 1159
Chris@45 1160 if (!m_document->getMainModel()) {
Chris@45 1161 return FileOpenWrongMode;
Chris@45 1162 }
Chris@45 1163
Chris@45 1164 bool newLayer = false;
Chris@45 1165
Chris@45 1166 ImageLayer *il = dynamic_cast<ImageLayer *>(pane->getSelectedLayer());
Chris@45 1167 if (!il) {
Chris@45 1168 for (int i = pane->getLayerCount()-1; i >= 0; --i) {
Chris@45 1169 il = dynamic_cast<ImageLayer *>(pane->getLayer(i));
Chris@45 1170 if (il) break;
Chris@45 1171 }
Chris@45 1172 }
Chris@45 1173 if (!il) {
Chris@45 1174 il = dynamic_cast<ImageLayer *>
Chris@45 1175 (m_document->createEmptyLayer(LayerFactory::Image));
Chris@45 1176 if (!il) return FileOpenFailed;
Chris@45 1177 newLayer = true;
Chris@45 1178 }
Chris@45 1179
Chris@45 1180 // We don't put the image file in Recent Files
Chris@45 1181
Chris@45 1182 std::cerr << "openImage: trying location \"" << source.getLocation().toStdString() << "\" in image layer" << std::endl;
Chris@45 1183
Chris@45 1184 if (!il->addImage(m_viewManager->getGlobalCentreFrame(), source.getLocation())) {
Chris@45 1185 if (newLayer) {
Chris@52 1186 m_document->deleteLayer(il); // also releases its model
Chris@45 1187 }
Chris@45 1188 return FileOpenFailed;
Chris@45 1189 } else {
Chris@45 1190 if (newLayer) {
Chris@45 1191 m_document->addLayerToView(pane, il);
Chris@45 1192 }
Chris@45 1193 m_paneStack->setCurrentLayer(pane, il);
Chris@45 1194 }
Chris@45 1195
Chris@45 1196 return FileOpenSucceeded;
Chris@45 1197 }
Chris@45 1198
Chris@45 1199 MainWindowBase::FileOpenStatus
Chris@45 1200 MainWindowBase::openSessionFile(QString fileOrUrl)
Chris@45 1201 {
Chris@76 1202 return openSession(FileSource(fileOrUrl, FileSource::ProgressDialog));
Chris@45 1203 }
Chris@45 1204
Chris@45 1205 MainWindowBase::FileOpenStatus
Chris@45 1206 MainWindowBase::openSession(FileSource source)
Chris@45 1207 {
Chris@45 1208 if (!source.isAvailable()) return FileOpenFailed;
Chris@45 1209 if (source.getExtension() != "sv") return FileOpenFailed;
Chris@45 1210 source.waitForData();
Chris@45 1211
Chris@45 1212 BZipFileDevice bzFile(source.getLocalFilename());
Chris@45 1213 if (!bzFile.open(QIODevice::ReadOnly)) return FileOpenFailed;
Chris@45 1214
Chris@45 1215 if (!checkSaveModified()) return FileOpenCancelled;
Chris@45 1216
Chris@45 1217 QString error;
Chris@45 1218 closeSession();
Chris@45 1219 createDocument();
Chris@45 1220
Chris@45 1221 PaneCallback callback(this);
Chris@45 1222 m_viewManager->clearSelections();
Chris@45 1223
Chris@45 1224 SVFileReader reader(m_document, callback, source.getLocation());
Chris@45 1225 QXmlInputSource inputSource(&bzFile);
Chris@45 1226 reader.parse(inputSource);
Chris@45 1227
Chris@45 1228 if (!reader.isOK()) {
Chris@45 1229 error = tr("SV XML file read error:\n%1").arg(reader.getErrorString());
Chris@45 1230 }
Chris@45 1231
Chris@45 1232 bzFile.close();
Chris@45 1233
Chris@45 1234 bool ok = (error == "");
Chris@45 1235
Chris@45 1236 if (ok) {
Chris@45 1237
Chris@57 1238 setWindowTitle(tr("%1: %2")
Chris@57 1239 .arg(QApplication::applicationName())
Chris@45 1240 .arg(source.getLocation()));
Chris@45 1241
Chris@45 1242 if (!source.isRemote()) m_sessionFile = source.getLocalFilename();
Chris@45 1243
Chris@45 1244 setupMenus();
Chris@45 1245
Chris@45 1246 CommandHistory::getInstance()->clear();
Chris@45 1247 CommandHistory::getInstance()->documentSaved();
Chris@45 1248 m_documentModified = false;
Chris@45 1249 updateMenuStates();
Chris@45 1250
Chris@45 1251 m_recentFiles.addFile(source.getLocation());
Chris@45 1252
Chris@45 1253 if (!source.isRemote()) {
Chris@45 1254 // for file dialog
Chris@45 1255 registerLastOpenedFilePath(FileFinder::SessionFile,
Chris@45 1256 source.getLocalFilename());
Chris@45 1257 }
Chris@45 1258
Chris@45 1259 } else {
Chris@57 1260 setWindowTitle(QApplication::applicationName());
Chris@45 1261 }
Chris@45 1262
Chris@45 1263 return ok ? FileOpenSucceeded : FileOpenFailed;
Chris@45 1264 }
Chris@45 1265
Chris@45 1266 void
Chris@45 1267 MainWindowBase::createPlayTarget()
Chris@45 1268 {
Chris@45 1269 if (m_playTarget) return;
Chris@45 1270
Chris@45 1271 m_playTarget = AudioTargetFactory::createCallbackTarget(m_playSource);
Chris@45 1272 if (!m_playTarget) {
Chris@45 1273 QMessageBox::warning
Chris@45 1274 (this, tr("Couldn't open audio device"),
Chris@45 1275 tr("<b>No audio available</b><p>Could not open an audio device for playback.<p>Audio playback will not be available during this session."),
Chris@45 1276 QMessageBox::Ok);
Chris@45 1277 }
Chris@45 1278 }
Chris@45 1279
Chris@45 1280 WaveFileModel *
Chris@45 1281 MainWindowBase::getMainModel()
Chris@45 1282 {
Chris@45 1283 if (!m_document) return 0;
Chris@45 1284 return m_document->getMainModel();
Chris@45 1285 }
Chris@45 1286
Chris@45 1287 const WaveFileModel *
Chris@45 1288 MainWindowBase::getMainModel() const
Chris@45 1289 {
Chris@45 1290 if (!m_document) return 0;
Chris@45 1291 return m_document->getMainModel();
Chris@45 1292 }
Chris@45 1293
Chris@45 1294 void
Chris@45 1295 MainWindowBase::createDocument()
Chris@45 1296 {
Chris@45 1297 m_document = new Document;
Chris@45 1298
Chris@45 1299 connect(m_document, SIGNAL(layerAdded(Layer *)),
Chris@45 1300 this, SLOT(layerAdded(Layer *)));
Chris@45 1301 connect(m_document, SIGNAL(layerRemoved(Layer *)),
Chris@45 1302 this, SLOT(layerRemoved(Layer *)));
Chris@45 1303 connect(m_document, SIGNAL(layerAboutToBeDeleted(Layer *)),
Chris@45 1304 this, SLOT(layerAboutToBeDeleted(Layer *)));
Chris@45 1305 connect(m_document, SIGNAL(layerInAView(Layer *, bool)),
Chris@45 1306 this, SLOT(layerInAView(Layer *, bool)));
Chris@45 1307
Chris@45 1308 connect(m_document, SIGNAL(modelAdded(Model *)),
Chris@45 1309 this, SLOT(modelAdded(Model *)));
Chris@45 1310 connect(m_document, SIGNAL(mainModelChanged(WaveFileModel *)),
Chris@45 1311 this, SLOT(mainModelChanged(WaveFileModel *)));
Chris@45 1312 connect(m_document, SIGNAL(modelAboutToBeDeleted(Model *)),
Chris@45 1313 this, SLOT(modelAboutToBeDeleted(Model *)));
Chris@45 1314
Chris@45 1315 connect(m_document, SIGNAL(modelGenerationFailed(QString)),
Chris@45 1316 this, SLOT(modelGenerationFailed(QString)));
Chris@45 1317 connect(m_document, SIGNAL(modelRegenerationFailed(QString, QString)),
Chris@45 1318 this, SLOT(modelRegenerationFailed(QString, QString)));
Chris@45 1319 }
Chris@45 1320
Chris@45 1321 bool
Chris@45 1322 MainWindowBase::saveSessionFile(QString path)
Chris@45 1323 {
Chris@45 1324 BZipFileDevice bzFile(path);
Chris@45 1325 if (!bzFile.open(QIODevice::WriteOnly)) {
Chris@45 1326 std::cerr << "Failed to open session file \"" << path.toStdString()
Chris@45 1327 << "\" for writing: "
Chris@45 1328 << bzFile.errorString().toStdString() << std::endl;
Chris@45 1329 return false;
Chris@45 1330 }
Chris@45 1331
Chris@45 1332 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
Chris@45 1333
Chris@45 1334 QTextStream out(&bzFile);
Chris@45 1335 toXml(out);
Chris@45 1336 out.flush();
Chris@45 1337
Chris@45 1338 QApplication::restoreOverrideCursor();
Chris@45 1339
Chris@45 1340 if (!bzFile.isOK()) {
Chris@45 1341 QMessageBox::critical(this, tr("Failed to write file"),
Chris@45 1342 tr("<b>Save failed</b><p>Failed to write to file \"%1\": %2")
Chris@45 1343 .arg(path).arg(bzFile.errorString()));
Chris@45 1344 bzFile.close();
Chris@45 1345 return false;
Chris@45 1346 }
Chris@45 1347
Chris@45 1348 bzFile.close();
Chris@45 1349 return true;
Chris@45 1350 }
Chris@45 1351
Chris@45 1352 void
Chris@45 1353 MainWindowBase::toXml(QTextStream &out)
Chris@45 1354 {
Chris@45 1355 QString indent(" ");
Chris@45 1356
Chris@45 1357 out << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
Chris@45 1358 out << "<!DOCTYPE sonic-visualiser>\n";
Chris@45 1359 out << "<sv>\n";
Chris@45 1360
Chris@45 1361 m_document->toXml(out, "", "");
Chris@45 1362
Chris@45 1363 out << "<display>\n";
Chris@45 1364
Chris@45 1365 out << QString(" <window width=\"%1\" height=\"%2\"/>\n")
Chris@45 1366 .arg(width()).arg(height());
Chris@45 1367
Chris@45 1368 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@45 1369
Chris@45 1370 Pane *pane = m_paneStack->getPane(i);
Chris@45 1371
Chris@45 1372 if (pane) {
Chris@45 1373 pane->toXml(out, indent);
Chris@45 1374 }
Chris@45 1375 }
Chris@45 1376
Chris@45 1377 out << "</display>\n";
Chris@45 1378
Chris@45 1379 m_viewManager->getSelection().toXml(out);
Chris@45 1380
Chris@45 1381 out << "</sv>\n";
Chris@45 1382 }
Chris@45 1383
Chris@45 1384 Pane *
Chris@45 1385 MainWindowBase::addPaneToStack()
Chris@45 1386 {
Chris@45 1387 AddPaneCommand *command = new AddPaneCommand(this);
Chris@45 1388 CommandHistory::getInstance()->addCommand(command);
Chris@57 1389 Pane *pane = command->getPane();
Chris@57 1390 return pane;
Chris@45 1391 }
Chris@45 1392
Chris@45 1393 void
Chris@45 1394 MainWindowBase::zoomIn()
Chris@45 1395 {
Chris@45 1396 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 1397 if (currentPane) currentPane->zoom(true);
Chris@45 1398 }
Chris@45 1399
Chris@45 1400 void
Chris@45 1401 MainWindowBase::zoomOut()
Chris@45 1402 {
Chris@45 1403 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 1404 if (currentPane) currentPane->zoom(false);
Chris@45 1405 }
Chris@45 1406
Chris@45 1407 void
Chris@45 1408 MainWindowBase::zoomToFit()
Chris@45 1409 {
Chris@45 1410 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 1411 if (!currentPane) return;
Chris@45 1412
Chris@45 1413 Model *model = getMainModel();
Chris@45 1414 if (!model) return;
Chris@45 1415
Chris@45 1416 size_t start = model->getStartFrame();
Chris@45 1417 size_t end = model->getEndFrame();
Chris@60 1418 if (m_playSource) end = std::max(end, m_playSource->getPlayEndFrame());
Chris@45 1419 size_t pixels = currentPane->width();
Chris@45 1420
Chris@45 1421 size_t sw = currentPane->getVerticalScaleWidth();
Chris@45 1422 if (pixels > sw * 2) pixels -= sw * 2;
Chris@45 1423 else pixels = 1;
Chris@45 1424 if (pixels > 4) pixels -= 4;
Chris@45 1425
Chris@45 1426 size_t zoomLevel = (end - start) / pixels;
Chris@45 1427
Chris@45 1428 currentPane->setZoomLevel(zoomLevel);
Chris@45 1429 currentPane->setCentreFrame((start + end) / 2);
Chris@45 1430 }
Chris@45 1431
Chris@45 1432 void
Chris@45 1433 MainWindowBase::zoomDefault()
Chris@45 1434 {
Chris@45 1435 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 1436 if (currentPane) currentPane->setZoomLevel(1024);
Chris@45 1437 }
Chris@45 1438
Chris@45 1439 void
Chris@45 1440 MainWindowBase::scrollLeft()
Chris@45 1441 {
Chris@45 1442 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 1443 if (currentPane) currentPane->scroll(false, false);
Chris@45 1444 }
Chris@45 1445
Chris@45 1446 void
Chris@45 1447 MainWindowBase::jumpLeft()
Chris@45 1448 {
Chris@45 1449 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 1450 if (currentPane) currentPane->scroll(false, true);
Chris@45 1451 }
Chris@45 1452
Chris@45 1453 void
Chris@45 1454 MainWindowBase::scrollRight()
Chris@45 1455 {
Chris@45 1456 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 1457 if (currentPane) currentPane->scroll(true, false);
Chris@45 1458 }
Chris@45 1459
Chris@45 1460 void
Chris@45 1461 MainWindowBase::jumpRight()
Chris@45 1462 {
Chris@45 1463 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@45 1464 if (currentPane) currentPane->scroll(true, true);
Chris@45 1465 }
Chris@45 1466
Chris@45 1467 void
Chris@45 1468 MainWindowBase::showNoOverlays()
Chris@45 1469 {
Chris@45 1470 m_viewManager->setOverlayMode(ViewManager::NoOverlays);
Chris@45 1471 }
Chris@45 1472
Chris@45 1473 void
Chris@45 1474 MainWindowBase::showMinimalOverlays()
Chris@45 1475 {
Chris@45 1476 m_viewManager->setOverlayMode(ViewManager::MinimalOverlays);
Chris@45 1477 }
Chris@45 1478
Chris@45 1479 void
Chris@45 1480 MainWindowBase::showStandardOverlays()
Chris@45 1481 {
Chris@45 1482 m_viewManager->setOverlayMode(ViewManager::StandardOverlays);
Chris@45 1483 }
Chris@45 1484
Chris@45 1485 void
Chris@45 1486 MainWindowBase::showAllOverlays()
Chris@45 1487 {
Chris@45 1488 m_viewManager->setOverlayMode(ViewManager::AllOverlays);
Chris@45 1489 }
Chris@45 1490
Chris@45 1491 void
Chris@45 1492 MainWindowBase::toggleZoomWheels()
Chris@45 1493 {
Chris@45 1494 if (m_viewManager->getZoomWheelsEnabled()) {
Chris@45 1495 m_viewManager->setZoomWheelsEnabled(false);
Chris@45 1496 } else {
Chris@45 1497 m_viewManager->setZoomWheelsEnabled(true);
Chris@45 1498 }
Chris@45 1499 }
Chris@45 1500
Chris@45 1501 void
Chris@45 1502 MainWindowBase::togglePropertyBoxes()
Chris@45 1503 {
Chris@45 1504 if (m_paneStack->getLayoutStyle() == PaneStack::NoPropertyStacks) {
Chris@45 1505 if (Preferences::getInstance()->getPropertyBoxLayout() ==
Chris@45 1506 Preferences::VerticallyStacked) {
Chris@45 1507 m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout);
Chris@45 1508 } else {
Chris@45 1509 m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout);
Chris@45 1510 }
Chris@45 1511 } else {
Chris@45 1512 m_paneStack->setLayoutStyle(PaneStack::NoPropertyStacks);
Chris@45 1513 }
Chris@45 1514 }
Chris@45 1515
Chris@45 1516 void
Chris@45 1517 MainWindowBase::toggleStatusBar()
Chris@45 1518 {
Chris@45 1519 QSettings settings;
Chris@45 1520 settings.beginGroup("MainWindow");
Chris@45 1521 bool sb = settings.value("showstatusbar", true).toBool();
Chris@45 1522
Chris@45 1523 if (sb) {
Chris@45 1524 statusBar()->hide();
Chris@45 1525 } else {
Chris@45 1526 statusBar()->show();
Chris@45 1527 }
Chris@45 1528
Chris@45 1529 settings.setValue("showstatusbar", !sb);
Chris@45 1530
Chris@45 1531 settings.endGroup();
Chris@45 1532 }
Chris@45 1533
Chris@45 1534 void
Chris@45 1535 MainWindowBase::preferenceChanged(PropertyContainer::PropertyName name)
Chris@45 1536 {
Chris@45 1537 if (name == "Property Box Layout") {
Chris@45 1538 if (m_paneStack->getLayoutStyle() != PaneStack::NoPropertyStacks) {
Chris@45 1539 if (Preferences::getInstance()->getPropertyBoxLayout() ==
Chris@45 1540 Preferences::VerticallyStacked) {
Chris@45 1541 m_paneStack->setLayoutStyle(PaneStack::PropertyStackPerPaneLayout);
Chris@45 1542 } else {
Chris@45 1543 m_paneStack->setLayoutStyle(PaneStack::SinglePropertyStackLayout);
Chris@45 1544 }
Chris@45 1545 }
Chris@45 1546 } else if (name == "Background Mode" && m_viewManager) {
Chris@45 1547 Preferences::BackgroundMode mode =
Chris@45 1548 Preferences::getInstance()->getBackgroundMode();
Chris@45 1549 if (mode == Preferences::BackgroundFromTheme) {
Chris@45 1550 m_viewManager->setGlobalDarkBackground(m_initialDarkBackground);
Chris@45 1551 } else if (mode == Preferences::DarkBackground) {
Chris@45 1552 m_viewManager->setGlobalDarkBackground(true);
Chris@45 1553 } else {
Chris@45 1554 m_viewManager->setGlobalDarkBackground(false);
Chris@45 1555 }
Chris@45 1556 }
Chris@45 1557 }
Chris@45 1558
Chris@45 1559 void
Chris@45 1560 MainWindowBase::play()
Chris@45 1561 {
Chris@45 1562 if (m_playSource->isPlaying()) {
Chris@45 1563 stop();
Chris@45 1564 } else {
Chris@45 1565 playbackFrameChanged(m_viewManager->getPlaybackFrame());
Chris@45 1566 m_playSource->play(m_viewManager->getPlaybackFrame());
Chris@45 1567 }
Chris@45 1568 }
Chris@45 1569
Chris@45 1570 void
Chris@45 1571 MainWindowBase::ffwd()
Chris@45 1572 {
Chris@45 1573 if (!getMainModel()) return;
Chris@45 1574
Chris@45 1575 int frame = m_viewManager->getPlaybackFrame();
Chris@45 1576 ++frame;
Chris@45 1577
Chris@45 1578 Layer *layer = getSnapLayer();
Chris@45 1579 size_t sr = getMainModel()->getSampleRate();
Chris@45 1580
Chris@45 1581 if (!layer) {
Chris@45 1582
Chris@45 1583 frame = RealTime::realTime2Frame
Chris@45 1584 (RealTime::frame2RealTime(frame, sr) + RealTime(2, 0), sr);
Chris@45 1585 if (frame > int(getMainModel()->getEndFrame())) {
Chris@45 1586 frame = getMainModel()->getEndFrame();
Chris@45 1587 }
Chris@45 1588
Chris@45 1589 } else {
Chris@45 1590
Chris@45 1591 size_t resolution = 0;
Chris@45 1592 if (!layer->snapToFeatureFrame(m_paneStack->getCurrentPane(),
Chris@45 1593 frame, resolution, Layer::SnapRight)) {
Chris@45 1594 frame = getMainModel()->getEndFrame();
Chris@45 1595 }
Chris@45 1596 }
Chris@45 1597
Chris@45 1598 if (frame < 0) frame = 0;
Chris@45 1599
Chris@45 1600 if (m_viewManager->getPlaySelectionMode()) {
Chris@45 1601 frame = m_viewManager->constrainFrameToSelection(size_t(frame));
Chris@45 1602 }
Chris@45 1603
Chris@45 1604 m_viewManager->setPlaybackFrame(frame);
Chris@45 1605 }
Chris@45 1606
Chris@45 1607 void
Chris@45 1608 MainWindowBase::ffwdEnd()
Chris@45 1609 {
Chris@45 1610 if (!getMainModel()) return;
Chris@45 1611
Chris@45 1612 size_t frame = getMainModel()->getEndFrame();
Chris@45 1613
Chris@45 1614 if (m_viewManager->getPlaySelectionMode()) {
Chris@45 1615 frame = m_viewManager->constrainFrameToSelection(frame);
Chris@45 1616 }
Chris@45 1617
Chris@45 1618 m_viewManager->setPlaybackFrame(frame);
Chris@45 1619 }
Chris@45 1620
Chris@45 1621 void
Chris@45 1622 MainWindowBase::rewind()
Chris@45 1623 {
Chris@45 1624 if (!getMainModel()) return;
Chris@45 1625
Chris@45 1626 int frame = m_viewManager->getPlaybackFrame();
Chris@45 1627 if (frame > 0) --frame;
Chris@45 1628
Chris@45 1629 Layer *layer = getSnapLayer();
Chris@45 1630 size_t sr = getMainModel()->getSampleRate();
Chris@45 1631
Chris@45 1632 // when rewinding during playback, we want to allow a period
Chris@45 1633 // following a rewind target point at which the rewind will go to
Chris@45 1634 // the prior point instead of the immediately neighbouring one
Chris@45 1635 if (m_playSource && m_playSource->isPlaying()) {
Chris@45 1636 RealTime ct = RealTime::frame2RealTime(frame, sr);
Chris@45 1637 ct = ct - RealTime::fromSeconds(0.25);
Chris@45 1638 if (ct < RealTime::zeroTime) ct = RealTime::zeroTime;
Chris@45 1639 // std::cerr << "rewind: frame " << frame << " -> ";
Chris@45 1640 frame = RealTime::realTime2Frame(ct, sr);
Chris@45 1641 // std::cerr << frame << std::endl;
Chris@45 1642 }
Chris@45 1643
Chris@45 1644 if (!layer) {
Chris@45 1645
Chris@45 1646 frame = RealTime::realTime2Frame
Chris@45 1647 (RealTime::frame2RealTime(frame, sr) - RealTime(2, 0), sr);
Chris@45 1648 if (frame < int(getMainModel()->getStartFrame())) {
Chris@45 1649 frame = getMainModel()->getStartFrame();
Chris@45 1650 }
Chris@45 1651
Chris@45 1652 } else {
Chris@45 1653
Chris@45 1654 size_t resolution = 0;
Chris@45 1655 if (!layer->snapToFeatureFrame(m_paneStack->getCurrentPane(),
Chris@45 1656 frame, resolution, Layer::SnapLeft)) {
Chris@45 1657 frame = getMainModel()->getStartFrame();
Chris@45 1658 }
Chris@45 1659 }
Chris@45 1660
Chris@45 1661 if (frame < 0) frame = 0;
Chris@45 1662
Chris@45 1663 if (m_viewManager->getPlaySelectionMode()) {
Chris@45 1664 frame = m_viewManager->constrainFrameToSelection(size_t(frame));
Chris@45 1665 }
Chris@45 1666
Chris@45 1667 m_viewManager->setPlaybackFrame(frame);
Chris@45 1668 }
Chris@45 1669
Chris@45 1670 void
Chris@45 1671 MainWindowBase::rewindStart()
Chris@45 1672 {
Chris@45 1673 if (!getMainModel()) return;
Chris@45 1674
Chris@45 1675 size_t frame = getMainModel()->getStartFrame();
Chris@45 1676
Chris@45 1677 if (m_viewManager->getPlaySelectionMode()) {
Chris@45 1678 frame = m_viewManager->constrainFrameToSelection(frame);
Chris@45 1679 }
Chris@45 1680
Chris@45 1681 m_viewManager->setPlaybackFrame(frame);
Chris@45 1682 }
Chris@45 1683
Chris@45 1684 Layer *
Chris@45 1685 MainWindowBase::getSnapLayer() const
Chris@45 1686 {
Chris@45 1687 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 1688 if (!pane) return 0;
Chris@45 1689
Chris@45 1690 Layer *layer = pane->getSelectedLayer();
Chris@45 1691
Chris@45 1692 if (!dynamic_cast<TimeInstantLayer *>(layer) &&
Chris@45 1693 !dynamic_cast<TimeValueLayer *>(layer) &&
Chris@45 1694 !dynamic_cast<TimeRulerLayer *>(layer)) {
Chris@45 1695
Chris@45 1696 layer = 0;
Chris@45 1697
Chris@45 1698 for (int i = pane->getLayerCount(); i > 0; --i) {
Chris@45 1699 Layer *l = pane->getLayer(i-1);
Chris@45 1700 if (dynamic_cast<TimeRulerLayer *>(l)) {
Chris@45 1701 layer = l;
Chris@45 1702 break;
Chris@45 1703 }
Chris@45 1704 }
Chris@45 1705 }
Chris@45 1706
Chris@45 1707 return layer;
Chris@45 1708 }
Chris@45 1709
Chris@45 1710 void
Chris@45 1711 MainWindowBase::stop()
Chris@45 1712 {
Chris@45 1713 m_playSource->stop();
Chris@45 1714
Chris@45 1715 if (m_paneStack && m_paneStack->getCurrentPane()) {
Chris@45 1716 updateVisibleRangeDisplay(m_paneStack->getCurrentPane());
Chris@45 1717 } else {
Chris@45 1718 m_myStatusMessage = "";
Chris@45 1719 statusBar()->showMessage("");
Chris@45 1720 }
Chris@45 1721 }
Chris@45 1722
Chris@45 1723 MainWindowBase::AddPaneCommand::AddPaneCommand(MainWindowBase *mw) :
Chris@45 1724 m_mw(mw),
Chris@45 1725 m_pane(0),
Chris@45 1726 m_prevCurrentPane(0),
Chris@45 1727 m_added(false)
Chris@45 1728 {
Chris@45 1729 }
Chris@45 1730
Chris@45 1731 MainWindowBase::AddPaneCommand::~AddPaneCommand()
Chris@45 1732 {
Chris@45 1733 if (m_pane && !m_added) {
Chris@45 1734 m_mw->m_paneStack->deletePane(m_pane);
Chris@45 1735 }
Chris@45 1736 }
Chris@45 1737
Chris@45 1738 QString
Chris@45 1739 MainWindowBase::AddPaneCommand::getName() const
Chris@45 1740 {
Chris@45 1741 return tr("Add Pane");
Chris@45 1742 }
Chris@45 1743
Chris@45 1744 void
Chris@45 1745 MainWindowBase::AddPaneCommand::execute()
Chris@45 1746 {
Chris@45 1747 if (!m_pane) {
Chris@45 1748 m_prevCurrentPane = m_mw->m_paneStack->getCurrentPane();
Chris@45 1749 m_pane = m_mw->m_paneStack->addPane();
Chris@45 1750
Chris@45 1751 connect(m_pane, SIGNAL(contextHelpChanged(const QString &)),
Chris@45 1752 m_mw, SLOT(contextHelpChanged(const QString &)));
Chris@45 1753 } else {
Chris@45 1754 m_mw->m_paneStack->showPane(m_pane);
Chris@45 1755 }
Chris@45 1756
Chris@45 1757 m_mw->m_paneStack->setCurrentPane(m_pane);
Chris@45 1758 m_added = true;
Chris@45 1759 }
Chris@45 1760
Chris@45 1761 void
Chris@45 1762 MainWindowBase::AddPaneCommand::unexecute()
Chris@45 1763 {
Chris@45 1764 m_mw->m_paneStack->hidePane(m_pane);
Chris@45 1765 m_mw->m_paneStack->setCurrentPane(m_prevCurrentPane);
Chris@45 1766 m_added = false;
Chris@45 1767 }
Chris@45 1768
Chris@45 1769 MainWindowBase::RemovePaneCommand::RemovePaneCommand(MainWindowBase *mw, Pane *pane) :
Chris@45 1770 m_mw(mw),
Chris@45 1771 m_pane(pane),
Chris@45 1772 m_added(true)
Chris@45 1773 {
Chris@45 1774 }
Chris@45 1775
Chris@45 1776 MainWindowBase::RemovePaneCommand::~RemovePaneCommand()
Chris@45 1777 {
Chris@45 1778 if (m_pane && !m_added) {
Chris@45 1779 m_mw->m_paneStack->deletePane(m_pane);
Chris@45 1780 }
Chris@45 1781 }
Chris@45 1782
Chris@45 1783 QString
Chris@45 1784 MainWindowBase::RemovePaneCommand::getName() const
Chris@45 1785 {
Chris@45 1786 return tr("Remove Pane");
Chris@45 1787 }
Chris@45 1788
Chris@45 1789 void
Chris@45 1790 MainWindowBase::RemovePaneCommand::execute()
Chris@45 1791 {
Chris@45 1792 m_prevCurrentPane = m_mw->m_paneStack->getCurrentPane();
Chris@45 1793 m_mw->m_paneStack->hidePane(m_pane);
Chris@45 1794 m_added = false;
Chris@45 1795 }
Chris@45 1796
Chris@45 1797 void
Chris@45 1798 MainWindowBase::RemovePaneCommand::unexecute()
Chris@45 1799 {
Chris@45 1800 m_mw->m_paneStack->showPane(m_pane);
Chris@45 1801 m_mw->m_paneStack->setCurrentPane(m_prevCurrentPane);
Chris@45 1802 m_added = true;
Chris@45 1803 }
Chris@45 1804
Chris@45 1805 void
Chris@45 1806 MainWindowBase::deleteCurrentPane()
Chris@45 1807 {
Chris@45 1808 CommandHistory::getInstance()->startCompoundOperation
Chris@45 1809 (tr("Delete Pane"), true);
Chris@45 1810
Chris@45 1811 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 1812 if (pane) {
Chris@45 1813 while (pane->getLayerCount() > 0) {
Chris@45 1814 Layer *layer = pane->getLayer(0);
Chris@45 1815 if (layer) {
Chris@45 1816 m_document->removeLayerFromView(pane, layer);
Chris@45 1817 } else {
Chris@45 1818 break;
Chris@45 1819 }
Chris@45 1820 }
Chris@45 1821
Chris@45 1822 RemovePaneCommand *command = new RemovePaneCommand(this, pane);
Chris@45 1823 CommandHistory::getInstance()->addCommand(command);
Chris@45 1824 }
Chris@45 1825
Chris@45 1826 CommandHistory::getInstance()->endCompoundOperation();
Chris@45 1827
Chris@45 1828 updateMenuStates();
Chris@45 1829 }
Chris@45 1830
Chris@45 1831 void
Chris@45 1832 MainWindowBase::deleteCurrentLayer()
Chris@45 1833 {
Chris@45 1834 Pane *pane = m_paneStack->getCurrentPane();
Chris@45 1835 if (pane) {
Chris@45 1836 Layer *layer = pane->getSelectedLayer();
Chris@45 1837 if (layer) {
Chris@45 1838 m_document->removeLayerFromView(pane, layer);
Chris@45 1839 }
Chris@45 1840 }
Chris@45 1841 updateMenuStates();
Chris@45 1842 }
Chris@45 1843
Chris@45 1844 void
Chris@73 1845 MainWindowBase::previousPane()
Chris@73 1846 {
Chris@73 1847 if (!m_paneStack) return;
Chris@73 1848
Chris@73 1849 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@73 1850 if (!currentPane) return;
Chris@73 1851
Chris@73 1852 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@73 1853 if (m_paneStack->getPane(i) == currentPane) {
Chris@73 1854 if (i == 0) return;
Chris@73 1855 m_paneStack->setCurrentPane(m_paneStack->getPane(i-1));
Chris@73 1856 updateMenuStates();
Chris@73 1857 return;
Chris@73 1858 }
Chris@73 1859 }
Chris@73 1860 }
Chris@73 1861
Chris@73 1862 void
Chris@73 1863 MainWindowBase::nextPane()
Chris@73 1864 {
Chris@73 1865 if (!m_paneStack) return;
Chris@73 1866
Chris@73 1867 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@73 1868 if (!currentPane) return;
Chris@73 1869
Chris@73 1870 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@73 1871 if (m_paneStack->getPane(i) == currentPane) {
Chris@73 1872 if (i == m_paneStack->getPaneCount()-1) return;
Chris@73 1873 m_paneStack->setCurrentPane(m_paneStack->getPane(i+1));
Chris@73 1874 updateMenuStates();
Chris@73 1875 return;
Chris@73 1876 }
Chris@73 1877 }
Chris@73 1878 }
Chris@73 1879
Chris@73 1880 void
Chris@73 1881 MainWindowBase::previousLayer()
Chris@73 1882 {
Chris@73 1883 //!!! Not right -- pane lists layers in stacking order
Chris@73 1884
Chris@73 1885 if (!m_paneStack) return;
Chris@73 1886
Chris@73 1887 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@73 1888 if (!currentPane) return;
Chris@73 1889
Chris@73 1890 Layer *currentLayer = currentPane->getSelectedLayer();
Chris@73 1891 if (!currentLayer) return;
Chris@73 1892
Chris@73 1893 for (int i = 0; i < currentPane->getLayerCount(); ++i) {
Chris@73 1894 if (currentPane->getLayer(i) == currentLayer) {
Chris@73 1895 if (i == 0) return;
Chris@73 1896 m_paneStack->setCurrentLayer(currentPane,
Chris@73 1897 currentPane->getLayer(i-1));
Chris@73 1898 updateMenuStates();
Chris@73 1899 return;
Chris@73 1900 }
Chris@73 1901 }
Chris@73 1902 }
Chris@73 1903
Chris@73 1904 void
Chris@73 1905 MainWindowBase::nextLayer()
Chris@73 1906 {
Chris@73 1907 //!!! Not right -- pane lists layers in stacking order
Chris@73 1908
Chris@73 1909 if (!m_paneStack) return;
Chris@73 1910
Chris@73 1911 Pane *currentPane = m_paneStack->getCurrentPane();
Chris@73 1912 if (!currentPane) return;
Chris@73 1913
Chris@73 1914 Layer *currentLayer = currentPane->getSelectedLayer();
Chris@73 1915 if (!currentLayer) return;
Chris@73 1916
Chris@73 1917 for (int i = 0; i < currentPane->getLayerCount(); ++i) {
Chris@73 1918 if (currentPane->getLayer(i) == currentLayer) {
Chris@73 1919 if (i == currentPane->getLayerCount()-1) return;
Chris@73 1920 m_paneStack->setCurrentLayer(currentPane,
Chris@73 1921 currentPane->getLayer(i+1));
Chris@73 1922 updateMenuStates();
Chris@73 1923 return;
Chris@73 1924 }
Chris@73 1925 }
Chris@73 1926 }
Chris@73 1927
Chris@73 1928 void
Chris@45 1929 MainWindowBase::playbackFrameChanged(unsigned long frame)
Chris@45 1930 {
Chris@45 1931 if (!(m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
Chris@45 1932
Chris@45 1933 RealTime now = RealTime::frame2RealTime
Chris@45 1934 (frame, getMainModel()->getSampleRate());
Chris@45 1935
Chris@45 1936 if (now.sec == m_lastPlayStatusSec) return;
Chris@45 1937
Chris@45 1938 RealTime then = RealTime::frame2RealTime
Chris@45 1939 (m_playSource->getPlayEndFrame(), getMainModel()->getSampleRate());
Chris@45 1940
Chris@45 1941 QString nowStr;
Chris@45 1942 QString thenStr;
Chris@45 1943 QString remainingStr;
Chris@45 1944
Chris@45 1945 if (then.sec > 10) {
Chris@45 1946 nowStr = now.toSecText().c_str();
Chris@45 1947 thenStr = then.toSecText().c_str();
Chris@45 1948 remainingStr = (then - now).toSecText().c_str();
Chris@45 1949 m_lastPlayStatusSec = now.sec;
Chris@45 1950 } else {
Chris@45 1951 nowStr = now.toText(true).c_str();
Chris@45 1952 thenStr = then.toText(true).c_str();
Chris@45 1953 remainingStr = (then - now).toText(true).c_str();
Chris@45 1954 }
Chris@45 1955
Chris@45 1956 m_myStatusMessage = tr("Playing: %1 of %2 (%3 remaining)")
Chris@45 1957 .arg(nowStr).arg(thenStr).arg(remainingStr);
Chris@45 1958
Chris@45 1959 statusBar()->showMessage(m_myStatusMessage);
Chris@45 1960 }
Chris@45 1961
Chris@45 1962 void
Chris@45 1963 MainWindowBase::globalCentreFrameChanged(unsigned long )
Chris@45 1964 {
Chris@45 1965 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
Chris@45 1966 Pane *p = 0;
Chris@45 1967 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return;
Chris@45 1968 if (!p->getFollowGlobalPan()) return;
Chris@45 1969 updateVisibleRangeDisplay(p);
Chris@45 1970 }
Chris@45 1971
Chris@45 1972 void
Chris@45 1973 MainWindowBase::viewCentreFrameChanged(View *v, unsigned long )
Chris@45 1974 {
Chris@45 1975 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
Chris@45 1976 Pane *p = 0;
Chris@45 1977 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return;
Chris@45 1978 if (v == p) updateVisibleRangeDisplay(p);
Chris@45 1979 }
Chris@45 1980
Chris@45 1981 void
Chris@45 1982 MainWindowBase::viewZoomLevelChanged(View *v, unsigned long , bool )
Chris@45 1983 {
Chris@45 1984 if ((m_playSource && m_playSource->isPlaying()) || !getMainModel()) return;
Chris@45 1985 Pane *p = 0;
Chris@45 1986 if (!m_paneStack || !(p = m_paneStack->getCurrentPane())) return;
Chris@45 1987 if (v == p) updateVisibleRangeDisplay(p);
Chris@45 1988 }
Chris@45 1989
Chris@45 1990 void
Chris@45 1991 MainWindowBase::layerAdded(Layer *)
Chris@45 1992 {
Chris@45 1993 // std::cerr << "MainWindowBase::layerAdded(" << layer << ")" << std::endl;
Chris@45 1994 updateMenuStates();
Chris@45 1995 }
Chris@45 1996
Chris@45 1997 void
Chris@45 1998 MainWindowBase::layerRemoved(Layer *)
Chris@45 1999 {
Chris@45 2000 // std::cerr << "MainWindowBase::layerRemoved(" << layer << ")" << std::endl;
Chris@45 2001 updateMenuStates();
Chris@45 2002 }
Chris@45 2003
Chris@45 2004 void
Chris@45 2005 MainWindowBase::layerAboutToBeDeleted(Layer *layer)
Chris@45 2006 {
Chris@45 2007 // std::cerr << "MainWindowBase::layerAboutToBeDeleted(" << layer << ")" << std::endl;
Chris@47 2008 if (m_timeRulerLayer && (layer == m_timeRulerLayer)) {
Chris@45 2009 // std::cerr << "(this is the time ruler layer)" << std::endl;
Chris@45 2010 m_timeRulerLayer = 0;
Chris@45 2011 }
Chris@45 2012 }
Chris@45 2013
Chris@45 2014 void
Chris@45 2015 MainWindowBase::layerInAView(Layer *layer, bool inAView)
Chris@45 2016 {
Chris@45 2017 // std::cerr << "MainWindowBase::layerInAView(" << layer << "," << inAView << ")" << std::endl;
Chris@45 2018
Chris@45 2019 // Check whether we need to add or remove model from play source
Chris@45 2020 Model *model = layer->getModel();
Chris@45 2021 if (model) {
Chris@45 2022 if (inAView) {
Chris@45 2023 m_playSource->addModel(model);
Chris@45 2024 } else {
Chris@45 2025 bool found = false;
Chris@45 2026 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@45 2027 Pane *pane = m_paneStack->getPane(i);
Chris@45 2028 if (!pane) continue;
Chris@45 2029 for (int j = 0; j < pane->getLayerCount(); ++j) {
Chris@45 2030 Layer *pl = pane->getLayer(j);
Chris@45 2031 if (pl && pl->getModel() == model) {
Chris@45 2032 found = true;
Chris@45 2033 break;
Chris@45 2034 }
Chris@45 2035 }
Chris@45 2036 if (found) break;
Chris@45 2037 }
Chris@45 2038 if (!found) m_playSource->removeModel(model);
Chris@45 2039 }
Chris@45 2040 }
Chris@45 2041
Chris@45 2042 updateMenuStates();
Chris@45 2043 }
Chris@45 2044
Chris@45 2045 void
Chris@45 2046 MainWindowBase::modelAdded(Model *model)
Chris@45 2047 {
Chris@45 2048 // std::cerr << "MainWindowBase::modelAdded(" << model << ")" << std::endl;
Chris@45 2049 m_playSource->addModel(model);
Chris@45 2050 }
Chris@45 2051
Chris@45 2052 void
Chris@45 2053 MainWindowBase::mainModelChanged(WaveFileModel *model)
Chris@45 2054 {
Chris@45 2055 // std::cerr << "MainWindowBase::mainModelChanged(" << model << ")" << std::endl;
Chris@45 2056 updateDescriptionLabel();
Chris@45 2057 if (model) m_viewManager->setMainModelSampleRate(model->getSampleRate());
Chris@45 2058 if (model && !m_playTarget && m_audioOutput) createPlayTarget();
Chris@45 2059 }
Chris@45 2060
Chris@45 2061 void
Chris@45 2062 MainWindowBase::modelAboutToBeDeleted(Model *model)
Chris@45 2063 {
Chris@45 2064 // std::cerr << "MainWindowBase::modelAboutToBeDeleted(" << model << ")" << std::endl;
Chris@45 2065 if (model == m_viewManager->getPlaybackModel()) {
Chris@45 2066 m_viewManager->setPlaybackModel(0);
Chris@45 2067 }
Chris@45 2068 m_playSource->removeModel(model);
Chris@45 2069 FFTDataServer::modelAboutToBeDeleted(model);
Chris@45 2070 }
Chris@45 2071
Chris@45 2072 void
Chris@55 2073 MainWindowBase::paneDeleteButtonClicked(Pane *pane)
Chris@55 2074 {
Chris@55 2075 bool found = false;
Chris@55 2076 for (int i = 0; i < m_paneStack->getPaneCount(); ++i) {
Chris@55 2077 if (m_paneStack->getPane(i) == pane) {
Chris@55 2078 found = true;
Chris@55 2079 break;
Chris@55 2080 }
Chris@55 2081 }
Chris@55 2082 if (!found) {
Chris@55 2083 std::cerr << "MainWindowBase::paneDeleteButtonClicked: Unknown pane "
Chris@55 2084 << pane << std::endl;
Chris@55 2085 return;
Chris@55 2086 }
Chris@55 2087
Chris@55 2088 CommandHistory::getInstance()->startCompoundOperation
Chris@55 2089 (tr("Delete Pane"), true);
Chris@55 2090
Chris@55 2091 while (pane->getLayerCount() > 0) {
Chris@55 2092 Layer *layer = pane->getLayer(0);
Chris@55 2093 if (layer) {
Chris@55 2094 m_document->removeLayerFromView(pane, layer);
Chris@55 2095 } else {
Chris@55 2096 break;
Chris@55 2097 }
Chris@55 2098 }
Chris@55 2099
Chris@55 2100 RemovePaneCommand *command = new RemovePaneCommand(this, pane);
Chris@55 2101 CommandHistory::getInstance()->addCommand(command);
Chris@55 2102
Chris@55 2103 CommandHistory::getInstance()->endCompoundOperation();
Chris@55 2104
Chris@55 2105 updateMenuStates();
Chris@55 2106 }
Chris@55 2107
Chris@55 2108 void
Chris@45 2109 MainWindowBase::pollOSC()
Chris@45 2110 {
Chris@45 2111 if (!m_oscQueue || m_oscQueue->isEmpty()) return;
Chris@45 2112 std::cerr << "MainWindowBase::pollOSC: have " << m_oscQueue->getMessagesAvailable() << " messages" << std::endl;
Chris@45 2113
Chris@45 2114 if (m_openingAudioFile) return;
Chris@45 2115
Chris@45 2116 OSCMessage message = m_oscQueue->readMessage();
Chris@45 2117
Chris@45 2118 if (message.getTarget() != 0) {
Chris@45 2119 return; //!!! for now -- this class is target 0, others not handled yet
Chris@45 2120 }
Chris@45 2121
Chris@45 2122 handleOSCMessage(message);
Chris@45 2123 }
Chris@45 2124
Chris@45 2125 void
Chris@45 2126 MainWindowBase::inProgressSelectionChanged()
Chris@45 2127 {
Chris@45 2128 Pane *currentPane = 0;
Chris@45 2129 if (m_paneStack) currentPane = m_paneStack->getCurrentPane();
Chris@45 2130 if (currentPane) updateVisibleRangeDisplay(currentPane);
Chris@45 2131 }
Chris@45 2132
Chris@45 2133 void
Chris@45 2134 MainWindowBase::contextHelpChanged(const QString &s)
Chris@45 2135 {
Chris@45 2136 if (s == "" && m_myStatusMessage != "") {
Chris@45 2137 statusBar()->showMessage(m_myStatusMessage);
Chris@45 2138 return;
Chris@45 2139 }
Chris@45 2140 statusBar()->showMessage(s);
Chris@45 2141 }
Chris@45 2142
Chris@45 2143 void
Chris@45 2144 MainWindowBase::openHelpUrl(QString url)
Chris@45 2145 {
Chris@45 2146 // This method mostly lifted from Qt Assistant source code
Chris@45 2147
Chris@45 2148 QProcess *process = new QProcess(this);
Chris@45 2149 connect(process, SIGNAL(finished(int)), process, SLOT(deleteLater()));
Chris@45 2150
Chris@45 2151 QStringList args;
Chris@45 2152
Chris@45 2153 #ifdef Q_OS_MAC
Chris@45 2154 args.append(url);
Chris@45 2155 process->start("open", args);
Chris@45 2156 #else
Chris@45 2157 #ifdef Q_OS_WIN32
Chris@45 2158
Chris@45 2159 QString pf(getenv("ProgramFiles"));
Chris@45 2160 QString command = pf + QString("\\Internet Explorer\\IEXPLORE.EXE");
Chris@45 2161
Chris@45 2162 args.append(url);
Chris@45 2163 process->start(command, args);
Chris@45 2164
Chris@45 2165 #else
Chris@45 2166 #ifdef Q_WS_X11
Chris@45 2167 if (!qgetenv("KDE_FULL_SESSION").isEmpty()) {
Chris@45 2168 args.append("exec");
Chris@45 2169 args.append(url);
Chris@45 2170 process->start("kfmclient", args);
Chris@45 2171 } else if (!qgetenv("BROWSER").isEmpty()) {
Chris@45 2172 args.append(url);
Chris@45 2173 process->start(qgetenv("BROWSER"), args);
Chris@45 2174 } else {
Chris@45 2175 args.append(url);
Chris@45 2176 process->start("firefox", args);
Chris@45 2177 }
Chris@45 2178 #endif
Chris@45 2179 #endif
Chris@45 2180 #endif
Chris@45 2181 }
Chris@45 2182