annotate framework/MainWindowBase.cpp @ 156:89737ffa4580

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