annotate framework/MainWindowBase.cpp @ 60:7b71da2d0631

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