annotate framework/MainWindowBase.cpp @ 304:c837368b1faf

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