annotate framework/MainWindowBase.cpp @ 141:9a8c73ffdce0

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