annotate view/View.cpp @ 1245:f0e291fa7b9c

Use Range01 normalisation in Colour 3D Plot. This gives us the same column normalisation behaviour as in 2.5 (better than the Max1 option).
author Chris Cannam
date Tue, 28 Feb 2017 14:06:24 +0000
parents c603aba61702
children a34a2a25907c
rev   line source
Chris@127 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@127 2
Chris@127 3 /*
Chris@127 4 Sonic Visualiser
Chris@127 5 An audio file viewer and annotation editor.
Chris@127 6 Centre for Digital Music, Queen Mary, University of London.
Chris@127 7 This file copyright 2006 Chris Cannam.
Chris@127 8
Chris@127 9 This program is free software; you can redistribute it and/or
Chris@127 10 modify it under the terms of the GNU General Public License as
Chris@127 11 published by the Free Software Foundation; either version 2 of the
Chris@127 12 License, or (at your option) any later version. See the file
Chris@127 13 COPYING included with this distribution for more information.
Chris@127 14 */
Chris@127 15
Chris@128 16 #include "View.h"
Chris@128 17 #include "layer/Layer.h"
Chris@128 18 #include "data/model/Model.h"
Chris@127 19 #include "base/ZoomConstraint.h"
Chris@127 20 #include "base/Profiler.h"
Chris@278 21 #include "base/Pitch.h"
Chris@338 22 #include "base/Preferences.h"
Chris@919 23 #include "ViewProxy.h"
Chris@127 24
Chris@301 25 #include "layer/TimeRulerLayer.h"
Chris@287 26 #include "layer/SingleColourLayer.h"
Chris@1078 27 #include "layer/PaintAssistant.h"
Chris@1078 28
Chris@301 29 #include "data/model/PowerOfSqrtTwoZoomConstraint.h"
Chris@301 30 #include "data/model/RangeSummarisableTimeValueModel.h"
Chris@127 31
Chris@797 32 #include "widgets/IconLoader.h"
Chris@797 33
Chris@127 34 #include <QPainter>
Chris@127 35 #include <QPaintEvent>
Chris@127 36 #include <QRect>
Chris@127 37 #include <QApplication>
Chris@226 38 #include <QProgressDialog>
Chris@316 39 #include <QTextStream>
Chris@338 40 #include <QFont>
Chris@583 41 #include <QMessageBox>
Chris@797 42 #include <QPushButton>
Chris@956 43 #include <QSettings>
Chris@1202 44 #include <QSvgGenerator>
Chris@127 45
Chris@127 46 #include <iostream>
Chris@127 47 #include <cassert>
Chris@520 48 #include <cmath>
Chris@127 49
Chris@1003 50 //#define DEBUG_VIEW 1
Chris@1003 51 //#define DEBUG_VIEW_WIDGET_PAINT 1
Chris@127 52
Chris@127 53 View::View(QWidget *w, bool showProgress) :
Chris@127 54 QFrame(w),
Chris@1044 55 m_id(getNextId()),
Chris@127 56 m_centreFrame(0),
Chris@127 57 m_zoomLevel(1024),
Chris@127 58 m_followPan(true),
Chris@127 59 m_followZoom(true),
Chris@815 60 m_followPlay(PlaybackScrollPageWithCentre),
Chris@789 61 m_followPlayIsDetached(false),
Chris@153 62 m_playPointerFrame(0),
Chris@127 63 m_showProgress(showProgress),
Chris@127 64 m_cache(0),
Chris@952 65 m_buffer(0),
Chris@127 66 m_cacheCentreFrame(0),
Chris@127 67 m_cacheZoomLevel(1024),
Chris@127 68 m_selectionCached(false),
Chris@127 69 m_deleting(false),
Chris@127 70 m_haveSelectedLayer(false),
Chris@127 71 m_manager(0),
Chris@127 72 m_propertyContainer(new ViewPropertyContainer(this))
Chris@127 73 {
Chris@728 74 // cerr << "View::View(" << this << ")" << endl;
Chris@127 75 }
Chris@127 76
Chris@127 77 View::~View()
Chris@127 78 {
Chris@728 79 // cerr << "View::~View(" << this << ")" << endl;
Chris@127 80
Chris@127 81 m_deleting = true;
Chris@127 82 delete m_propertyContainer;
Chris@1215 83 delete m_cache;
Chris@1215 84 delete m_buffer;
Chris@127 85 }
Chris@127 86
Chris@127 87 PropertyContainer::PropertyList
Chris@127 88 View::getProperties() const
Chris@127 89 {
Chris@127 90 PropertyContainer::PropertyList list;
Chris@127 91 list.push_back("Global Scroll");
Chris@127 92 list.push_back("Global Zoom");
Chris@127 93 list.push_back("Follow Playback");
Chris@127 94 return list;
Chris@127 95 }
Chris@127 96
Chris@127 97 QString
Chris@127 98 View::getPropertyLabel(const PropertyName &pn) const
Chris@127 99 {
Chris@127 100 if (pn == "Global Scroll") return tr("Global Scroll");
Chris@127 101 if (pn == "Global Zoom") return tr("Global Zoom");
Chris@127 102 if (pn == "Follow Playback") return tr("Follow Playback");
Chris@127 103 return "";
Chris@127 104 }
Chris@127 105
Chris@127 106 PropertyContainer::PropertyType
Chris@127 107 View::getPropertyType(const PropertyContainer::PropertyName &name) const
Chris@127 108 {
Chris@127 109 if (name == "Global Scroll") return PropertyContainer::ToggleProperty;
Chris@127 110 if (name == "Global Zoom") return PropertyContainer::ToggleProperty;
Chris@127 111 if (name == "Follow Playback") return PropertyContainer::ValueProperty;
Chris@127 112 return PropertyContainer::InvalidProperty;
Chris@127 113 }
Chris@127 114
Chris@127 115 int
Chris@127 116 View::getPropertyRangeAndValue(const PropertyContainer::PropertyName &name,
Chris@216 117 int *min, int *max, int *deflt) const
Chris@127 118 {
Chris@216 119 if (deflt) *deflt = 1;
Chris@127 120 if (name == "Global Scroll") return m_followPan;
Chris@127 121 if (name == "Global Zoom") return m_followZoom;
Chris@127 122 if (name == "Follow Playback") {
Chris@127 123 if (min) *min = 0;
Chris@127 124 if (max) *max = 2;
Chris@815 125 if (deflt) *deflt = int(PlaybackScrollPageWithCentre);
Chris@815 126 switch (m_followPlay) {
Chris@815 127 case PlaybackScrollContinuous: return 0;
Chris@815 128 case PlaybackScrollPageWithCentre: case PlaybackScrollPage: return 1;
Chris@815 129 case PlaybackIgnore: return 2;
Chris@815 130 }
Chris@127 131 }
Chris@127 132 if (min) *min = 0;
Chris@127 133 if (max) *max = 0;
Chris@216 134 if (deflt) *deflt = 0;
Chris@127 135 return 0;
Chris@127 136 }
Chris@127 137
Chris@127 138 QString
Chris@127 139 View::getPropertyValueLabel(const PropertyContainer::PropertyName &name,
Chris@127 140 int value) const
Chris@127 141 {
Chris@127 142 if (name == "Follow Playback") {
Chris@127 143 switch (value) {
Chris@127 144 default:
Chris@127 145 case 0: return tr("Scroll");
Chris@127 146 case 1: return tr("Page");
Chris@127 147 case 2: return tr("Off");
Chris@127 148 }
Chris@127 149 }
Chris@127 150 return tr("<unknown>");
Chris@127 151 }
Chris@127 152
Chris@127 153 void
Chris@127 154 View::setProperty(const PropertyContainer::PropertyName &name, int value)
Chris@127 155 {
Chris@127 156 if (name == "Global Scroll") {
Chris@127 157 setFollowGlobalPan(value != 0);
Chris@127 158 } else if (name == "Global Zoom") {
Chris@127 159 setFollowGlobalZoom(value != 0);
Chris@127 160 } else if (name == "Follow Playback") {
Chris@127 161 switch (value) {
Chris@127 162 default:
Chris@127 163 case 0: setPlaybackFollow(PlaybackScrollContinuous); break;
Chris@815 164 case 1: setPlaybackFollow(PlaybackScrollPageWithCentre); break;
Chris@127 165 case 2: setPlaybackFollow(PlaybackIgnore); break;
Chris@127 166 }
Chris@127 167 }
Chris@127 168 }
Chris@127 169
Chris@806 170 int
Chris@127 171 View::getPropertyContainerCount() const
Chris@127 172 {
Chris@908 173 return int(m_fixedOrderLayers.size()) + 1; // the 1 is for me
Chris@127 174 }
Chris@127 175
Chris@127 176 const PropertyContainer *
Chris@806 177 View::getPropertyContainer(int i) const
Chris@127 178 {
Chris@127 179 return (const PropertyContainer *)(((View *)this)->
Chris@127 180 getPropertyContainer(i));
Chris@127 181 }
Chris@127 182
Chris@127 183 PropertyContainer *
Chris@806 184 View::getPropertyContainer(int i)
Chris@127 185 {
Chris@127 186 if (i == 0) return m_propertyContainer;
Chris@837 187 return m_fixedOrderLayers[i-1];
Chris@127 188 }
Chris@127 189
Chris@127 190 bool
Chris@904 191 View::getValueExtents(QString unit, double &min, double &max, bool &log) const
Chris@127 192 {
Chris@127 193 bool have = false;
Chris@127 194
Chris@835 195 for (LayerList::const_iterator i = m_layerStack.begin();
Chris@835 196 i != m_layerStack.end(); ++i) {
Chris@127 197
Chris@127 198 QString layerUnit;
Chris@904 199 double layerMin = 0.0, layerMax = 0.0;
Chris@904 200 double displayMin = 0.0, displayMax = 0.0;
Chris@127 201 bool layerLog = false;
Chris@127 202
Chris@127 203 if ((*i)->getValueExtents(layerMin, layerMax, layerLog, layerUnit) &&
Chris@127 204 layerUnit.toLower() == unit.toLower()) {
Chris@127 205
Chris@127 206 if ((*i)->getDisplayExtents(displayMin, displayMax)) {
Chris@127 207
Chris@127 208 min = displayMin;
Chris@127 209 max = displayMax;
Chris@127 210 log = layerLog;
Chris@127 211 have = true;
Chris@127 212 break;
Chris@127 213
Chris@127 214 } else {
Chris@127 215
Chris@127 216 if (!have || layerMin < min) min = layerMin;
Chris@127 217 if (!have || layerMax > max) max = layerMax;
Chris@127 218 if (layerLog) log = true;
Chris@127 219 have = true;
Chris@127 220 }
Chris@127 221 }
Chris@127 222 }
Chris@127 223
Chris@127 224 return have;
Chris@127 225 }
Chris@127 226
Chris@127 227 int
Chris@127 228 View::getTextLabelHeight(const Layer *layer, QPainter &paint) const
Chris@127 229 {
Chris@127 230 std::map<int, Layer *> sortedLayers;
Chris@127 231
Chris@835 232 for (LayerList::const_iterator i = m_layerStack.begin();
Chris@835 233 i != m_layerStack.end(); ++i) {
Chris@127 234 if ((*i)->needsTextLabelHeight()) {
Chris@127 235 sortedLayers[getObjectExportId(*i)] = *i;
Chris@127 236 }
Chris@127 237 }
Chris@127 238
Chris@127 239 int y = 15 + paint.fontMetrics().ascent();
Chris@127 240
Chris@127 241 for (std::map<int, Layer *>::const_iterator i = sortedLayers.begin();
Chris@127 242 i != sortedLayers.end(); ++i) {
Chris@127 243 if (i->second == layer) return y;
Chris@127 244 y += paint.fontMetrics().height();
Chris@127 245 }
Chris@127 246
Chris@127 247 return y;
Chris@127 248 }
Chris@127 249
Chris@127 250 void
Chris@127 251 View::propertyContainerSelected(View *client, PropertyContainer *pc)
Chris@127 252 {
Chris@127 253 if (client != this) return;
Chris@127 254
Chris@127 255 if (pc == m_propertyContainer) {
Chris@127 256 if (m_haveSelectedLayer) {
Chris@127 257 m_haveSelectedLayer = false;
Chris@127 258 update();
Chris@127 259 }
Chris@127 260 return;
Chris@127 261 }
Chris@127 262
Chris@127 263 delete m_cache;
Chris@127 264 m_cache = 0;
Chris@127 265
Chris@127 266 Layer *selectedLayer = 0;
Chris@127 267
Chris@835 268 for (LayerList::iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
Chris@127 269 if (*i == pc) {
Chris@127 270 selectedLayer = *i;
Chris@835 271 m_layerStack.erase(i);
Chris@127 272 break;
Chris@127 273 }
Chris@127 274 }
Chris@127 275
Chris@127 276 if (selectedLayer) {
Chris@127 277 m_haveSelectedLayer = true;
Chris@835 278 m_layerStack.push_back(selectedLayer);
Chris@127 279 update();
Chris@127 280 } else {
Chris@127 281 m_haveSelectedLayer = false;
Chris@127 282 }
Chris@298 283
Chris@298 284 emit propertyContainerSelected(pc);
Chris@127 285 }
Chris@127 286
Chris@127 287 void
Chris@127 288 View::toolModeChanged()
Chris@127 289 {
Chris@587 290 // SVDEBUG << "View::toolModeChanged(" << m_manager->getToolMode() << ")" << endl;
Chris@127 291 }
Chris@127 292
Chris@133 293 void
Chris@133 294 View::overlayModeChanged()
Chris@133 295 {
Chris@206 296 delete m_cache;
Chris@206 297 m_cache = 0;
Chris@133 298 update();
Chris@133 299 }
Chris@133 300
Chris@133 301 void
Chris@133 302 View::zoomWheelsEnabledChanged()
Chris@133 303 {
Chris@133 304 // subclass might override this
Chris@133 305 }
Chris@133 306
Chris@908 307 sv_frame_t
Chris@127 308 View::getStartFrame() const
Chris@127 309 {
Chris@313 310 return getFrameForX(0);
Chris@127 311 }
Chris@127 312
Chris@908 313 sv_frame_t
Chris@127 314 View::getEndFrame() const
Chris@127 315 {
Chris@127 316 return getFrameForX(width()) - 1;
Chris@127 317 }
Chris@127 318
Chris@127 319 void
Chris@908 320 View::setStartFrame(sv_frame_t f)
Chris@127 321 {
Chris@127 322 setCentreFrame(f + m_zoomLevel * (width() / 2));
Chris@127 323 }
Chris@127 324
Chris@127 325 bool
Chris@908 326 View::setCentreFrame(sv_frame_t f, bool e)
Chris@127 327 {
Chris@127 328 bool changeVisible = false;
Chris@127 329
Chris@127 330 if (m_centreFrame != f) {
Chris@127 331
Chris@908 332 int formerPixel = int(m_centreFrame / m_zoomLevel);
Chris@127 333
Chris@127 334 m_centreFrame = f;
Chris@127 335
Chris@908 336 int newPixel = int(m_centreFrame / m_zoomLevel);
Chris@127 337
Chris@127 338 if (newPixel != formerPixel) {
Chris@127 339
Chris@127 340 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 341 cout << "View(" << this << ")::setCentreFrame: newPixel " << newPixel << ", formerPixel " << formerPixel << endl;
Chris@127 342 #endif
Chris@127 343 update();
Chris@127 344
Chris@127 345 changeVisible = true;
Chris@127 346 }
Chris@127 347
Chris@333 348 if (e) {
Chris@908 349 sv_frame_t rf = alignToReference(f);
Chris@830 350 #ifdef DEBUG_VIEW
Chris@682 351 cerr << "View[" << this << "]::setCentreFrame(" << f
Chris@333 352 << "): emitting centreFrameChanged("
Chris@682 353 << rf << ")" << endl;
Chris@355 354 #endif
Chris@333 355 emit centreFrameChanged(rf, m_followPan, m_followPlay);
Chris@333 356 }
Chris@127 357 }
Chris@127 358
Chris@127 359 return changeVisible;
Chris@127 360 }
Chris@127 361
Chris@127 362 int
Chris@908 363 View::getXForFrame(sv_frame_t frame) const
Chris@127 364 {
Chris@908 365 return int((frame - getStartFrame()) / m_zoomLevel);
Chris@127 366 }
Chris@127 367
Chris@908 368 sv_frame_t
Chris@127 369 View::getFrameForX(int x) const
Chris@127 370 {
Chris@1020 371 sv_frame_t z = m_zoomLevel; // nb not just int, or multiplication may overflow
Chris@908 372 sv_frame_t frame = m_centreFrame - (width()/2) * z;
Chris@354 373
Chris@1020 374 frame = (frame / z) * z; // this is start frame
Chris@1020 375 frame = frame + x * z;
Chris@1020 376
Chris@355 377 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@1020 378 cerr << "View::getFrameForX(" << x << "): z = " << z << ", m_centreFrame = " << m_centreFrame << ", width() = " << width() << ", frame = " << frame << endl;
Chris@355 379 #endif
Chris@354 380
Chris@1020 381 return frame;
Chris@127 382 }
Chris@127 383
Chris@904 384 double
Chris@904 385 View::getYForFrequency(double frequency,
Chris@904 386 double minf,
Chris@904 387 double maxf,
Chris@127 388 bool logarithmic) const
Chris@127 389 {
Chris@382 390 Profiler profiler("View::getYForFrequency");
Chris@382 391
Chris@127 392 int h = height();
Chris@127 393
Chris@127 394 if (logarithmic) {
Chris@127 395
Chris@904 396 static double lastminf = 0.0, lastmaxf = 0.0;
Chris@904 397 static double logminf = 0.0, logmaxf = 0.0;
Chris@127 398
Chris@127 399 if (lastminf != minf) {
Chris@127 400 lastminf = (minf == 0.0 ? 1.0 : minf);
Chris@908 401 logminf = log10(minf);
Chris@127 402 }
Chris@127 403 if (lastmaxf != maxf) {
Chris@127 404 lastmaxf = (maxf < lastminf ? lastminf : maxf);
Chris@908 405 logmaxf = log10(maxf);
Chris@127 406 }
Chris@127 407
Chris@127 408 if (logminf == logmaxf) return 0;
Chris@908 409 return h - (h * (log10(frequency) - logminf)) / (logmaxf - logminf);
Chris@127 410
Chris@127 411 } else {
Chris@127 412
Chris@127 413 if (minf == maxf) return 0;
Chris@127 414 return h - (h * (frequency - minf)) / (maxf - minf);
Chris@127 415 }
Chris@127 416 }
Chris@127 417
Chris@904 418 double
Chris@1085 419 View::getFrequencyForY(double y,
Chris@904 420 double minf,
Chris@904 421 double maxf,
Chris@127 422 bool logarithmic) const
Chris@127 423 {
Chris@1085 424 double h = height();
Chris@127 425
Chris@127 426 if (logarithmic) {
Chris@127 427
Chris@904 428 static double lastminf = 0.0, lastmaxf = 0.0;
Chris@904 429 static double logminf = 0.0, logmaxf = 0.0;
Chris@127 430
Chris@127 431 if (lastminf != minf) {
Chris@127 432 lastminf = (minf == 0.0 ? 1.0 : minf);
Chris@908 433 logminf = log10(minf);
Chris@127 434 }
Chris@127 435 if (lastmaxf != maxf) {
Chris@127 436 lastmaxf = (maxf < lastminf ? lastminf : maxf);
Chris@908 437 logmaxf = log10(maxf);
Chris@127 438 }
Chris@127 439
Chris@127 440 if (logminf == logmaxf) return 0;
Chris@908 441 return pow(10.0, logminf + ((logmaxf - logminf) * (h - y)) / h);
Chris@127 442
Chris@127 443 } else {
Chris@127 444
Chris@127 445 if (minf == maxf) return 0;
Chris@127 446 return minf + ((h - y) * (maxf - minf)) / h;
Chris@127 447 }
Chris@127 448 }
Chris@127 449
Chris@127 450 int
Chris@127 451 View::getZoomLevel() const
Chris@127 452 {
Chris@127 453 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 454 // cout << "zoom level: " << m_zoomLevel << endl;
Chris@127 455 #endif
Chris@127 456 return m_zoomLevel;
Chris@127 457 }
Chris@127 458
Chris@956 459 int
Chris@956 460 View::effectiveDevicePixelRatio() const
Chris@956 461 {
Chris@956 462 #ifdef Q_OS_MAC
Chris@956 463 int dpratio = devicePixelRatio();
Chris@956 464 if (dpratio > 1) {
Chris@956 465 QSettings settings;
Chris@956 466 settings.beginGroup("Preferences");
Chris@956 467 if (!settings.value("scaledHiDpi", true).toBool()) {
Chris@956 468 dpratio = 1;
Chris@956 469 }
Chris@956 470 settings.endGroup();
Chris@956 471 }
Chris@956 472 return dpratio;
Chris@956 473 #else
Chris@956 474 return 1;
Chris@956 475 #endif
Chris@956 476 }
Chris@956 477
Chris@127 478 void
Chris@806 479 View::setZoomLevel(int z)
Chris@127 480 {
Chris@956 481 int dpratio = effectiveDevicePixelRatio();
Chris@950 482 if (z < dpratio) return;
Chris@462 483 if (z < 1) z = 1;
Chris@127 484 if (m_zoomLevel != int(z)) {
Chris@127 485 m_zoomLevel = z;
Chris@222 486 emit zoomLevelChanged(z, m_followZoom);
Chris@127 487 update();
Chris@127 488 }
Chris@127 489 }
Chris@127 490
Chris@224 491 bool
Chris@224 492 View::hasLightBackground() const
Chris@224 493 {
Chris@287 494 bool darkPalette = false;
Chris@292 495 if (m_manager) darkPalette = m_manager->getGlobalDarkBackground();
Chris@287 496
Chris@287 497 Layer::ColourSignificance maxSignificance = Layer::ColourAbsent;
Chris@287 498 bool mostSignificantHasDarkBackground = false;
Chris@287 499
Chris@835 500 for (LayerList::const_iterator i = m_layerStack.begin();
Chris@835 501 i != m_layerStack.end(); ++i) {
Chris@287 502
Chris@287 503 Layer::ColourSignificance s = (*i)->getLayerColourSignificance();
Chris@287 504 bool light = (*i)->hasLightBackground();
Chris@287 505
Chris@287 506 if (int(s) > int(maxSignificance)) {
Chris@287 507 maxSignificance = s;
Chris@287 508 mostSignificantHasDarkBackground = !light;
Chris@287 509 } else if (s == maxSignificance && !light) {
Chris@287 510 mostSignificantHasDarkBackground = true;
Chris@287 511 }
Chris@224 512 }
Chris@287 513
Chris@287 514 if (int(maxSignificance) >= int(Layer::ColourAndBackgroundSignificant)) {
Chris@287 515 return !mostSignificantHasDarkBackground;
Chris@287 516 } else {
Chris@287 517 return !darkPalette;
Chris@287 518 }
Chris@287 519 }
Chris@287 520
Chris@287 521 QColor
Chris@287 522 View::getBackground() const
Chris@287 523 {
Chris@287 524 bool light = hasLightBackground();
Chris@287 525
Chris@287 526 QColor widgetbg = palette().window().color();
Chris@287 527 bool widgetLight =
Chris@287 528 (widgetbg.red() + widgetbg.green() + widgetbg.blue()) > 384;
Chris@287 529
Chris@296 530 if (widgetLight == light) {
Chris@296 531 if (widgetLight) {
Chris@296 532 return widgetbg.light();
Chris@296 533 } else {
Chris@296 534 return widgetbg.dark();
Chris@296 535 }
Chris@296 536 }
Chris@287 537 else if (light) return Qt::white;
Chris@287 538 else return Qt::black;
Chris@287 539 }
Chris@287 540
Chris@287 541 QColor
Chris@287 542 View::getForeground() const
Chris@287 543 {
Chris@287 544 bool light = hasLightBackground();
Chris@287 545
Chris@287 546 QColor widgetfg = palette().text().color();
Chris@287 547 bool widgetLight =
Chris@287 548 (widgetfg.red() + widgetfg.green() + widgetfg.blue()) > 384;
Chris@287 549
Chris@287 550 if (widgetLight != light) return widgetfg;
Chris@287 551 else if (light) return Qt::black;
Chris@287 552 else return Qt::white;
Chris@224 553 }
Chris@224 554
Chris@127 555 void
Chris@127 556 View::addLayer(Layer *layer)
Chris@127 557 {
Chris@127 558 delete m_cache;
Chris@127 559 m_cache = 0;
Chris@127 560
Chris@287 561 SingleColourLayer *scl = dynamic_cast<SingleColourLayer *>(layer);
Chris@287 562 if (scl) scl->setDefaultColourFor(this);
Chris@287 563
Chris@836 564 m_fixedOrderLayers.push_back(layer);
Chris@835 565 m_layerStack.push_back(layer);
Chris@127 566
Chris@555 567 QProgressBar *pb = new QProgressBar(this);
Chris@555 568 pb->setMinimum(0);
Chris@555 569 pb->setMaximum(0);
Chris@555 570 pb->setFixedWidth(80);
Chris@555 571 pb->setTextVisible(false);
Chris@555 572
Chris@797 573 QPushButton *cancel = new QPushButton(this);
Chris@797 574 cancel->setIcon(IconLoader().load("fileclose"));
Chris@797 575 cancel->setFlat(true);
Chris@797 576 cancel->setFixedSize(QSize(20, 20));
Chris@797 577 connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked()));
Chris@797 578
Chris@555 579 ProgressBarRec pbr;
Chris@797 580 pbr.cancel = cancel;
Chris@555 581 pbr.bar = pb;
Chris@555 582 pbr.lastCheck = 0;
Chris@555 583 pbr.checkTimer = new QTimer();
Chris@555 584 connect(pbr.checkTimer, SIGNAL(timeout()), this,
Chris@555 585 SLOT(progressCheckStalledTimerElapsed()));
Chris@555 586
Chris@555 587 m_progressBars[layer] = pbr;
Chris@555 588
Chris@555 589 QFont f(pb->font());
Chris@339 590 int fs = Preferences::getInstance()->getViewFontSize();
Chris@339 591 f.setPointSize(std::min(fs, int(ceil(fs * 0.85))));
Chris@339 592
Chris@797 593 cancel->hide();
Chris@797 594
Chris@555 595 pb->setFont(f);
Chris@555 596 pb->hide();
Chris@127 597
Chris@127 598 connect(layer, SIGNAL(layerParametersChanged()),
Chris@127 599 this, SLOT(layerParametersChanged()));
Chris@197 600 connect(layer, SIGNAL(layerParameterRangesChanged()),
Chris@197 601 this, SLOT(layerParameterRangesChanged()));
Chris@268 602 connect(layer, SIGNAL(layerMeasurementRectsChanged()),
Chris@268 603 this, SLOT(layerMeasurementRectsChanged()));
Chris@127 604 connect(layer, SIGNAL(layerNameChanged()),
Chris@127 605 this, SLOT(layerNameChanged()));
Chris@127 606 connect(layer, SIGNAL(modelChanged()),
Chris@127 607 this, SLOT(modelChanged()));
Chris@127 608 connect(layer, SIGNAL(modelCompletionChanged()),
Chris@127 609 this, SLOT(modelCompletionChanged()));
Chris@320 610 connect(layer, SIGNAL(modelAlignmentCompletionChanged()),
Chris@320 611 this, SLOT(modelAlignmentCompletionChanged()));
Chris@908 612 connect(layer, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)),
Chris@908 613 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t)));
Chris@127 614 connect(layer, SIGNAL(modelReplaced()),
Chris@127 615 this, SLOT(modelReplaced()));
Chris@127 616
Chris@127 617 update();
Chris@127 618
Chris@127 619 emit propertyContainerAdded(layer);
Chris@127 620 }
Chris@127 621
Chris@127 622 void
Chris@127 623 View::removeLayer(Layer *layer)
Chris@127 624 {
Chris@127 625 if (m_deleting) {
Chris@127 626 return;
Chris@127 627 }
Chris@127 628
Chris@127 629 delete m_cache;
Chris@127 630 m_cache = 0;
Chris@127 631
Chris@836 632 for (LayerList::iterator i = m_fixedOrderLayers.begin();
Chris@836 633 i != m_fixedOrderLayers.end();
Chris@836 634 ++i) {
Chris@836 635 if (*i == layer) {
Chris@836 636 m_fixedOrderLayers.erase(i);
Chris@836 637 break;
Chris@836 638 }
Chris@836 639 }
Chris@836 640
Chris@836 641 for (LayerList::iterator i = m_layerStack.begin();
Chris@836 642 i != m_layerStack.end();
Chris@836 643 ++i) {
Chris@127 644 if (*i == layer) {
Chris@835 645 m_layerStack.erase(i);
Chris@127 646 if (m_progressBars.find(layer) != m_progressBars.end()) {
Chris@555 647 delete m_progressBars[layer].bar;
Chris@797 648 delete m_progressBars[layer].cancel;
Chris@555 649 delete m_progressBars[layer].checkTimer;
Chris@127 650 m_progressBars.erase(layer);
Chris@127 651 }
Chris@127 652 break;
Chris@127 653 }
Chris@127 654 }
Chris@127 655
Chris@197 656 disconnect(layer, SIGNAL(layerParametersChanged()),
Chris@197 657 this, SLOT(layerParametersChanged()));
Chris@197 658 disconnect(layer, SIGNAL(layerParameterRangesChanged()),
Chris@197 659 this, SLOT(layerParameterRangesChanged()));
Chris@197 660 disconnect(layer, SIGNAL(layerNameChanged()),
Chris@197 661 this, SLOT(layerNameChanged()));
Chris@197 662 disconnect(layer, SIGNAL(modelChanged()),
Chris@197 663 this, SLOT(modelChanged()));
Chris@197 664 disconnect(layer, SIGNAL(modelCompletionChanged()),
Chris@197 665 this, SLOT(modelCompletionChanged()));
Chris@320 666 disconnect(layer, SIGNAL(modelAlignmentCompletionChanged()),
Chris@320 667 this, SLOT(modelAlignmentCompletionChanged()));
Chris@908 668 disconnect(layer, SIGNAL(modelChangedWithin(sv_frame_t, sv_frame_t)),
Chris@908 669 this, SLOT(modelChangedWithin(sv_frame_t, sv_frame_t)));
Chris@197 670 disconnect(layer, SIGNAL(modelReplaced()),
Chris@197 671 this, SLOT(modelReplaced()));
Chris@197 672
Chris@127 673 update();
Chris@127 674
Chris@127 675 emit propertyContainerRemoved(layer);
Chris@127 676 }
Chris@127 677
Chris@127 678 Layer *
Chris@834 679 View::getInteractionLayer()
Chris@834 680 {
Chris@834 681 Layer *sl = getSelectedLayer();
Chris@834 682 if (sl && !(sl->isLayerDormant(this))) {
Chris@834 683 return sl;
Chris@834 684 }
Chris@835 685 if (!m_layerStack.empty()) {
Chris@834 686 int n = getLayerCount();
Chris@834 687 while (n > 0) {
Chris@834 688 --n;
Chris@834 689 Layer *layer = getLayer(n);
Chris@834 690 if (!(layer->isLayerDormant(this))) {
Chris@834 691 return layer;
Chris@834 692 }
Chris@834 693 }
Chris@834 694 }
Chris@834 695 return 0;
Chris@834 696 }
Chris@834 697
Chris@841 698 const Layer *
Chris@841 699 View::getInteractionLayer() const
Chris@841 700 {
Chris@841 701 return const_cast<const Layer *>(const_cast<View *>(this)->getInteractionLayer());
Chris@841 702 }
Chris@841 703
Chris@834 704 Layer *
Chris@127 705 View::getSelectedLayer()
Chris@127 706 {
Chris@835 707 if (m_haveSelectedLayer && !m_layerStack.empty()) {
Chris@839 708 return getLayer(getLayerCount() - 1);
Chris@127 709 } else {
Chris@127 710 return 0;
Chris@127 711 }
Chris@127 712 }
Chris@127 713
Chris@127 714 const Layer *
Chris@127 715 View::getSelectedLayer() const
Chris@127 716 {
Chris@127 717 return const_cast<const Layer *>(const_cast<View *>(this)->getSelectedLayer());
Chris@127 718 }
Chris@127 719
Chris@127 720 void
Chris@127 721 View::setViewManager(ViewManager *manager)
Chris@127 722 {
Chris@127 723 if (m_manager) {
Chris@908 724 m_manager->disconnect(this, SLOT(globalCentreFrameChanged(sv_frame_t)));
Chris@908 725 m_manager->disconnect(this, SLOT(viewCentreFrameChanged(View *, sv_frame_t)));
Chris@908 726 m_manager->disconnect(this, SLOT(viewManagerPlaybackFrameChanged(sv_frame_t)));
Chris@806 727 m_manager->disconnect(this, SLOT(viewZoomLevelChanged(View *, int, bool)));
Chris@211 728 m_manager->disconnect(this, SLOT(toolModeChanged()));
Chris@211 729 m_manager->disconnect(this, SLOT(selectionChanged()));
Chris@211 730 m_manager->disconnect(this, SLOT(overlayModeChanged()));
Chris@211 731 m_manager->disconnect(this, SLOT(zoomWheelsEnabledChanged()));
Chris@908 732 disconnect(m_manager, SLOT(viewCentreFrameChanged(sv_frame_t, bool, PlaybackFollowMode)));
Chris@806 733 disconnect(m_manager, SLOT(zoomLevelChanged(int, bool)));
Chris@127 734 }
Chris@127 735
Chris@127 736 m_manager = manager;
Chris@127 737
Chris@908 738 connect(m_manager, SIGNAL(globalCentreFrameChanged(sv_frame_t)),
Chris@908 739 this, SLOT(globalCentreFrameChanged(sv_frame_t)));
Chris@908 740 connect(m_manager, SIGNAL(viewCentreFrameChanged(View *, sv_frame_t)),
Chris@908 741 this, SLOT(viewCentreFrameChanged(View *, sv_frame_t)));
Chris@908 742 connect(m_manager, SIGNAL(playbackFrameChanged(sv_frame_t)),
Chris@908 743 this, SLOT(viewManagerPlaybackFrameChanged(sv_frame_t)));
Chris@806 744
Chris@806 745 connect(m_manager, SIGNAL(viewZoomLevelChanged(View *, int, bool)),
Chris@806 746 this, SLOT(viewZoomLevelChanged(View *, int, bool)));
Chris@211 747
Chris@127 748 connect(m_manager, SIGNAL(toolModeChanged()),
Chris@127 749 this, SLOT(toolModeChanged()));
Chris@127 750 connect(m_manager, SIGNAL(selectionChanged()),
Chris@127 751 this, SLOT(selectionChanged()));
Chris@127 752 connect(m_manager, SIGNAL(inProgressSelectionChanged()),
Chris@127 753 this, SLOT(selectionChanged()));
Chris@127 754 connect(m_manager, SIGNAL(overlayModeChanged()),
Chris@133 755 this, SLOT(overlayModeChanged()));
Chris@607 756 connect(m_manager, SIGNAL(showCentreLineChanged()),
Chris@607 757 this, SLOT(overlayModeChanged()));
Chris@133 758 connect(m_manager, SIGNAL(zoomWheelsEnabledChanged()),
Chris@133 759 this, SLOT(zoomWheelsEnabledChanged()));
Chris@127 760
Chris@908 761 connect(this, SIGNAL(centreFrameChanged(sv_frame_t, bool,
Chris@211 762 PlaybackFollowMode)),
Chris@908 763 m_manager, SLOT(viewCentreFrameChanged(sv_frame_t, bool,
Chris@211 764 PlaybackFollowMode)));
Chris@211 765
Chris@806 766 connect(this, SIGNAL(zoomLevelChanged(int, bool)),
Chris@806 767 m_manager, SLOT(viewZoomLevelChanged(int, bool)));
Chris@127 768
Chris@815 769 switch (m_followPlay) {
Chris@815 770
Chris@815 771 case PlaybackScrollPage:
Chris@815 772 case PlaybackScrollPageWithCentre:
Chris@364 773 setCentreFrame(m_manager->getGlobalCentreFrame(), false);
Chris@815 774 break;
Chris@815 775
Chris@815 776 case PlaybackScrollContinuous:
Chris@236 777 setCentreFrame(m_manager->getPlaybackFrame(), false);
Chris@815 778 break;
Chris@815 779
Chris@815 780 case PlaybackIgnore:
Chris@815 781 if (m_followPan) {
Chris@815 782 setCentreFrame(m_manager->getGlobalCentreFrame(), false);
Chris@815 783 }
Chris@815 784 break;
Chris@236 785 }
Chris@516 786
Chris@236 787 if (m_followZoom) setZoomLevel(m_manager->getGlobalZoom());
Chris@236 788
Chris@511 789 movePlayPointer(getAlignedPlaybackFrame());
Chris@511 790
Chris@127 791 toolModeChanged();
Chris@127 792 }
Chris@127 793
Chris@127 794 void
Chris@908 795 View::setViewManager(ViewManager *vm, sv_frame_t initialCentreFrame)
Chris@516 796 {
Chris@516 797 setViewManager(vm);
Chris@516 798 setCentreFrame(initialCentreFrame, false);
Chris@516 799 }
Chris@516 800
Chris@516 801 void
Chris@127 802 View::setFollowGlobalPan(bool f)
Chris@127 803 {
Chris@127 804 m_followPan = f;
Chris@127 805 emit propertyContainerPropertyChanged(m_propertyContainer);
Chris@127 806 }
Chris@127 807
Chris@127 808 void
Chris@127 809 View::setFollowGlobalZoom(bool f)
Chris@127 810 {
Chris@127 811 m_followZoom = f;
Chris@127 812 emit propertyContainerPropertyChanged(m_propertyContainer);
Chris@127 813 }
Chris@127 814
Chris@127 815 void
Chris@127 816 View::setPlaybackFollow(PlaybackFollowMode m)
Chris@127 817 {
Chris@127 818 m_followPlay = m;
Chris@127 819 emit propertyContainerPropertyChanged(m_propertyContainer);
Chris@127 820 }
Chris@127 821
Chris@127 822 void
Chris@127 823 View::modelChanged()
Chris@127 824 {
Chris@127 825 QObject *obj = sender();
Chris@127 826
Chris@127 827 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 828 cerr << "View(" << this << ")::modelChanged()" << endl;
Chris@127 829 #endif
Chris@127 830
Chris@127 831 // If the model that has changed is not used by any of the cached
Chris@127 832 // layers, we won't need to recreate the cache
Chris@127 833
Chris@127 834 bool recreate = false;
Chris@127 835
Chris@127 836 bool discard;
Chris@127 837 LayerList scrollables = getScrollableBackLayers(false, discard);
Chris@127 838 for (LayerList::const_iterator i = scrollables.begin();
Chris@127 839 i != scrollables.end(); ++i) {
Chris@127 840 if (*i == obj || (*i)->getModel() == obj) {
Chris@127 841 recreate = true;
Chris@127 842 break;
Chris@127 843 }
Chris@127 844 }
Chris@127 845
Chris@127 846 if (recreate) {
Chris@127 847 delete m_cache;
Chris@127 848 m_cache = 0;
Chris@127 849 }
Chris@127 850
Chris@336 851 emit layerModelChanged();
Chris@336 852
Chris@127 853 checkProgress(obj);
Chris@127 854
Chris@127 855 update();
Chris@127 856 }
Chris@127 857
Chris@127 858 void
Chris@908 859 View::modelChangedWithin(sv_frame_t startFrame, sv_frame_t endFrame)
Chris@127 860 {
Chris@127 861 QObject *obj = sender();
Chris@127 862
Chris@908 863 sv_frame_t myStartFrame = getStartFrame();
Chris@908 864 sv_frame_t myEndFrame = getEndFrame();
Chris@127 865
Chris@127 866 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@806 867 cerr << "View(" << this << ")::modelChangedWithin(" << startFrame << "," << endFrame << ") [me " << myStartFrame << "," << myEndFrame << "]" << endl;
Chris@127 868 #endif
Chris@127 869
Chris@908 870 if (myStartFrame > 0 && endFrame < myStartFrame) {
Chris@127 871 checkProgress(obj);
Chris@127 872 return;
Chris@127 873 }
Chris@127 874 if (startFrame > myEndFrame) {
Chris@127 875 checkProgress(obj);
Chris@127 876 return;
Chris@127 877 }
Chris@127 878
Chris@127 879 // If the model that has changed is not used by any of the cached
Chris@127 880 // layers, we won't need to recreate the cache
Chris@127 881
Chris@127 882 bool recreate = false;
Chris@127 883
Chris@127 884 bool discard;
Chris@127 885 LayerList scrollables = getScrollableBackLayers(false, discard);
Chris@127 886 for (LayerList::const_iterator i = scrollables.begin();
Chris@127 887 i != scrollables.end(); ++i) {
Chris@127 888 if (*i == obj || (*i)->getModel() == obj) {
Chris@127 889 recreate = true;
Chris@127 890 break;
Chris@127 891 }
Chris@127 892 }
Chris@127 893
Chris@127 894 if (recreate) {
Chris@127 895 delete m_cache;
Chris@127 896 m_cache = 0;
Chris@127 897 }
Chris@127 898
Chris@806 899 if (startFrame < myStartFrame) startFrame = myStartFrame;
Chris@127 900 if (endFrame > myEndFrame) endFrame = myEndFrame;
Chris@127 901
Chris@127 902 checkProgress(obj);
Chris@127 903
Chris@127 904 update();
Chris@127 905 }
Chris@127 906
Chris@127 907 void
Chris@127 908 View::modelCompletionChanged()
Chris@127 909 {
Chris@682 910 // cerr << "View(" << this << ")::modelCompletionChanged()" << endl;
Chris@301 911
Chris@127 912 QObject *obj = sender();
Chris@127 913 checkProgress(obj);
Chris@127 914 }
Chris@127 915
Chris@127 916 void
Chris@320 917 View::modelAlignmentCompletionChanged()
Chris@320 918 {
Chris@682 919 // cerr << "View(" << this << ")::modelAlignmentCompletionChanged()" << endl;
Chris@320 920
Chris@320 921 QObject *obj = sender();
Chris@320 922 checkProgress(obj);
Chris@320 923 }
Chris@320 924
Chris@320 925 void
Chris@127 926 View::modelReplaced()
Chris@127 927 {
Chris@127 928 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 929 cerr << "View(" << this << ")::modelReplaced()" << endl;
Chris@127 930 #endif
Chris@127 931 delete m_cache;
Chris@127 932 m_cache = 0;
Chris@127 933
Chris@127 934 update();
Chris@127 935 }
Chris@127 936
Chris@127 937 void
Chris@127 938 View::layerParametersChanged()
Chris@127 939 {
Chris@127 940 Layer *layer = dynamic_cast<Layer *>(sender());
Chris@127 941
Chris@127 942 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@587 943 SVDEBUG << "View::layerParametersChanged()" << endl;
Chris@127 944 #endif
Chris@127 945
Chris@127 946 delete m_cache;
Chris@127 947 m_cache = 0;
Chris@127 948 update();
Chris@127 949
Chris@127 950 if (layer) {
Chris@127 951 emit propertyContainerPropertyChanged(layer);
Chris@127 952 }
Chris@127 953 }
Chris@127 954
Chris@127 955 void
Chris@197 956 View::layerParameterRangesChanged()
Chris@197 957 {
Chris@197 958 Layer *layer = dynamic_cast<Layer *>(sender());
Chris@197 959 if (layer) emit propertyContainerPropertyRangeChanged(layer);
Chris@197 960 }
Chris@197 961
Chris@197 962 void
Chris@268 963 View::layerMeasurementRectsChanged()
Chris@268 964 {
Chris@268 965 Layer *layer = dynamic_cast<Layer *>(sender());
Chris@268 966 if (layer) update();
Chris@268 967 }
Chris@268 968
Chris@268 969 void
Chris@127 970 View::layerNameChanged()
Chris@127 971 {
Chris@127 972 Layer *layer = dynamic_cast<Layer *>(sender());
Chris@127 973 if (layer) emit propertyContainerNameChanged(layer);
Chris@127 974 }
Chris@127 975
Chris@127 976 void
Chris@908 977 View::globalCentreFrameChanged(sv_frame_t rf)
Chris@127 978 {
Chris@211 979 if (m_followPan) {
Chris@908 980 sv_frame_t f = alignFromReference(rf);
Chris@830 981 #ifdef DEBUG_VIEW
Chris@682 982 cerr << "View[" << this << "]::globalCentreFrameChanged(" << rf
Chris@682 983 << "): setting centre frame to " << f << endl;
Chris@363 984 #endif
Chris@333 985 setCentreFrame(f, false);
Chris@127 986 }
Chris@127 987 }
Chris@127 988
Chris@127 989 void
Chris@908 990 View::viewCentreFrameChanged(View *, sv_frame_t )
Chris@211 991 {
Chris@211 992 // We do nothing with this, but a subclass might
Chris@211 993 }
Chris@211 994
Chris@211 995 void
Chris@908 996 View::viewManagerPlaybackFrameChanged(sv_frame_t f)
Chris@127 997 {
Chris@127 998 if (m_manager) {
Chris@127 999 if (sender() != m_manager) return;
Chris@127 1000 }
Chris@127 1001
Chris@830 1002 #ifdef DEBUG_VIEW
Chris@830 1003 cerr << "View::viewManagerPlaybackFrameChanged(" << f << ")" << endl;
Chris@830 1004 #endif
Chris@830 1005
Chris@301 1006 f = getAlignedPlaybackFrame();
Chris@301 1007
Chris@830 1008 #ifdef DEBUG_VIEW
Chris@951 1009 cerr << " -> aligned frame = " << f << endl;
Chris@830 1010 #endif
Chris@830 1011
Chris@511 1012 movePlayPointer(f);
Chris@511 1013 }
Chris@511 1014
Chris@511 1015 void
Chris@908 1016 View::movePlayPointer(sv_frame_t newFrame)
Chris@511 1017 {
Chris@830 1018 #ifdef DEBUG_VIEW
Chris@830 1019 cerr << "View(" << this << ")::movePlayPointer(" << newFrame << ")" << endl;
Chris@830 1020 #endif
Chris@830 1021
Chris@511 1022 if (m_playPointerFrame == newFrame) return;
Chris@511 1023 bool visibleChange =
Chris@511 1024 (getXForFrame(m_playPointerFrame) != getXForFrame(newFrame));
Chris@908 1025 sv_frame_t oldPlayPointerFrame = m_playPointerFrame;
Chris@511 1026 m_playPointerFrame = newFrame;
Chris@511 1027 if (!visibleChange) return;
Chris@127 1028
Chris@513 1029 bool somethingGoingOn =
Chris@513 1030 ((QApplication::mouseButtons() != Qt::NoButton) ||
Chris@513 1031 (QApplication::keyboardModifiers() & Qt::AltModifier));
Chris@513 1032
Chris@789 1033 bool pointerInVisibleArea =
Chris@789 1034 long(m_playPointerFrame) >= getStartFrame() &&
Chris@789 1035 (m_playPointerFrame < getEndFrame() ||
Chris@789 1036 // include old pointer location so we know to refresh when moving out
Chris@789 1037 oldPlayPointerFrame < getEndFrame());
Chris@789 1038
Chris@127 1039 switch (m_followPlay) {
Chris@127 1040
Chris@127 1041 case PlaybackScrollContinuous:
Chris@513 1042 if (!somethingGoingOn) {
Chris@511 1043 setCentreFrame(m_playPointerFrame, false);
Chris@127 1044 }
Chris@127 1045 break;
Chris@127 1046
Chris@127 1047 case PlaybackScrollPage:
Chris@815 1048 case PlaybackScrollPageWithCentre:
Chris@789 1049
Chris@789 1050 if (!pointerInVisibleArea && somethingGoingOn) {
Chris@789 1051
Chris@789 1052 m_followPlayIsDetached = true;
Chris@789 1053
Chris@789 1054 } else if (!pointerInVisibleArea && m_followPlayIsDetached) {
Chris@789 1055
Chris@789 1056 // do nothing; we aren't tracking until the pointer comes back in
Chris@789 1057
Chris@789 1058 } else {
Chris@789 1059
Chris@789 1060 int xold = getXForFrame(oldPlayPointerFrame);
Chris@789 1061 update(xold - 4, 0, 9, height());
Chris@789 1062
Chris@908 1063 sv_frame_t w = getEndFrame() - getStartFrame();
Chris@789 1064 w -= w/5;
Chris@908 1065 sv_frame_t sf = (m_playPointerFrame / w) * w - w/8;
Chris@789 1066
Chris@789 1067 if (m_manager &&
Chris@789 1068 m_manager->isPlaying() &&
Chris@789 1069 m_manager->getPlaySelectionMode()) {
Chris@789 1070 MultiSelection::SelectionList selections = m_manager->getSelections();
Chris@789 1071 if (!selections.empty()) {
Chris@908 1072 sv_frame_t selectionStart = selections.begin()->getStartFrame();
Chris@808 1073 if (sf < selectionStart - w / 10) {
Chris@808 1074 sf = selectionStart - w / 10;
Chris@789 1075 }
Chris@789 1076 }
Chris@789 1077 }
Chris@127 1078
Chris@127 1079 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@789 1080 cerr << "PlaybackScrollPage: f = " << m_playPointerFrame << ", sf = " << sf << ", start frame "
Chris@789 1081 << getStartFrame() << endl;
Chris@127 1082 #endif
Chris@127 1083
Chris@789 1084 // We don't consider scrolling unless the pointer is outside
Chris@789 1085 // the central visible range already
Chris@789 1086
Chris@789 1087 int xnew = getXForFrame(m_playPointerFrame);
Chris@127 1088
Chris@127 1089 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@789 1090 cerr << "xnew = " << xnew << ", width = " << width() << endl;
Chris@127 1091 #endif
Chris@127 1092
Chris@789 1093 bool shouldScroll = (xnew > (width() * 7) / 8);
Chris@789 1094
Chris@789 1095 if (!m_followPlayIsDetached && (xnew < width() / 8)) {
Chris@789 1096 shouldScroll = true;
Chris@789 1097 }
Chris@789 1098
Chris@789 1099 if (xnew > width() / 8) {
Chris@789 1100 m_followPlayIsDetached = false;
Chris@791 1101 } else if (somethingGoingOn) {
Chris@791 1102 m_followPlayIsDetached = true;
Chris@789 1103 }
Chris@789 1104
Chris@789 1105 if (!somethingGoingOn && shouldScroll) {
Chris@908 1106 sv_frame_t offset = getFrameForX(width()/2) - getStartFrame();
Chris@908 1107 sv_frame_t newCentre = sf + offset;
Chris@789 1108 bool changed = setCentreFrame(newCentre, false);
Chris@789 1109 if (changed) {
Chris@789 1110 xold = getXForFrame(oldPlayPointerFrame);
Chris@789 1111 update(xold - 4, 0, 9, height());
Chris@789 1112 }
Chris@789 1113 }
Chris@789 1114
Chris@789 1115 update(xnew - 4, 0, 9, height());
Chris@789 1116 }
Chris@789 1117 break;
Chris@127 1118
Chris@127 1119 case PlaybackIgnore:
Chris@806 1120 if (m_playPointerFrame >= getStartFrame() &&
Chris@511 1121 m_playPointerFrame < getEndFrame()) {
Chris@127 1122 update();
Chris@127 1123 }
Chris@127 1124 break;
Chris@127 1125 }
Chris@127 1126 }
Chris@127 1127
Chris@127 1128 void
Chris@806 1129 View::viewZoomLevelChanged(View *p, int z, bool locked)
Chris@127 1130 {
Chris@244 1131 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 1132 cerr << "View[" << this << "]: viewZoomLevelChanged(" << p << ", " << z << ", " << locked << ")" << endl;
Chris@244 1133 #endif
Chris@127 1134 if (m_followZoom && p != this && locked) {
Chris@222 1135 setZoomLevel(z);
Chris@127 1136 }
Chris@127 1137 }
Chris@127 1138
Chris@127 1139 void
Chris@127 1140 View::selectionChanged()
Chris@127 1141 {
Chris@127 1142 if (m_selectionCached) {
Chris@127 1143 delete m_cache;
Chris@127 1144 m_cache = 0;
Chris@127 1145 m_selectionCached = false;
Chris@127 1146 }
Chris@127 1147 update();
Chris@127 1148 }
Chris@127 1149
Chris@908 1150 sv_frame_t
Chris@222 1151 View::getFirstVisibleFrame() const
Chris@222 1152 {
Chris@908 1153 sv_frame_t f0 = getStartFrame();
Chris@908 1154 sv_frame_t f = getModelsStartFrame();
Chris@806 1155 if (f0 < 0 || f0 < f) return f;
Chris@222 1156 return f0;
Chris@222 1157 }
Chris@222 1158
Chris@908 1159 sv_frame_t
Chris@222 1160 View::getLastVisibleFrame() const
Chris@222 1161 {
Chris@908 1162 sv_frame_t f0 = getEndFrame();
Chris@908 1163 sv_frame_t f = getModelsEndFrame();
Chris@222 1164 if (f0 > f) return f;
Chris@222 1165 return f0;
Chris@222 1166 }
Chris@222 1167
Chris@908 1168 sv_frame_t
Chris@127 1169 View::getModelsStartFrame() const
Chris@127 1170 {
Chris@127 1171 bool first = true;
Chris@908 1172 sv_frame_t startFrame = 0;
Chris@127 1173
Chris@835 1174 for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
Chris@127 1175
Chris@127 1176 if ((*i)->getModel() && (*i)->getModel()->isOK()) {
Chris@127 1177
Chris@908 1178 sv_frame_t thisStartFrame = (*i)->getModel()->getStartFrame();
Chris@127 1179
Chris@127 1180 if (first || thisStartFrame < startFrame) {
Chris@127 1181 startFrame = thisStartFrame;
Chris@127 1182 }
Chris@127 1183 first = false;
Chris@127 1184 }
Chris@127 1185 }
Chris@127 1186 return startFrame;
Chris@127 1187 }
Chris@127 1188
Chris@908 1189 sv_frame_t
Chris@127 1190 View::getModelsEndFrame() const
Chris@127 1191 {
Chris@127 1192 bool first = true;
Chris@908 1193 sv_frame_t endFrame = 0;
Chris@127 1194
Chris@835 1195 for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
Chris@127 1196
Chris@127 1197 if ((*i)->getModel() && (*i)->getModel()->isOK()) {
Chris@127 1198
Chris@908 1199 sv_frame_t thisEndFrame = (*i)->getModel()->getEndFrame();
Chris@127 1200
Chris@127 1201 if (first || thisEndFrame > endFrame) {
Chris@127 1202 endFrame = thisEndFrame;
Chris@127 1203 }
Chris@127 1204 first = false;
Chris@127 1205 }
Chris@127 1206 }
Chris@127 1207
Chris@127 1208 if (first) return getModelsStartFrame();
Chris@127 1209 return endFrame;
Chris@127 1210 }
Chris@127 1211
Chris@908 1212 sv_samplerate_t
Chris@127 1213 View::getModelsSampleRate() const
Chris@127 1214 {
Chris@127 1215 //!!! Just go for the first, for now. If we were supporting
Chris@127 1216 // multiple samplerates, we'd probably want to do frame/time
Chris@127 1217 // conversion in the model
Chris@127 1218
Chris@159 1219 //!!! nah, this wants to always return the sr of the main model!
Chris@159 1220
Chris@835 1221 for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
Chris@127 1222 if ((*i)->getModel() && (*i)->getModel()->isOK()) {
Chris@127 1223 return (*i)->getModel()->getSampleRate();
Chris@127 1224 }
Chris@127 1225 }
Chris@127 1226 return 0;
Chris@127 1227 }
Chris@127 1228
Chris@315 1229 View::ModelSet
Chris@315 1230 View::getModels()
Chris@315 1231 {
Chris@315 1232 ModelSet models;
Chris@315 1233
Chris@315 1234 for (int i = 0; i < getLayerCount(); ++i) {
Chris@315 1235
Chris@315 1236 Layer *layer = getLayer(i);
Chris@315 1237
Chris@315 1238 if (dynamic_cast<TimeRulerLayer *>(layer)) {
Chris@315 1239 continue;
Chris@315 1240 }
Chris@315 1241
Chris@315 1242 if (layer && layer->getModel()) {
Chris@315 1243 Model *model = layer->getModel();
Chris@315 1244 models.insert(model);
Chris@315 1245 }
Chris@315 1246 }
Chris@315 1247
Chris@315 1248 return models;
Chris@315 1249 }
Chris@315 1250
Chris@320 1251 Model *
Chris@320 1252 View::getAligningModel() const
Chris@301 1253 {
Chris@320 1254 if (!m_manager ||
Chris@320 1255 !m_manager->getAlignMode() ||
Chris@314 1256 !m_manager->getPlaybackModel()) {
Chris@320 1257 return 0;
Chris@314 1258 }
Chris@301 1259
Chris@320 1260 Model *anyModel = 0;
Chris@359 1261 Model *alignedModel = 0;
Chris@320 1262 Model *goodModel = 0;
Chris@301 1263
Chris@835 1264 for (LayerList::const_iterator i = m_layerStack.begin();
Chris@835 1265 i != m_layerStack.end(); ++i) {
Chris@320 1266
Chris@320 1267 Layer *layer = *i;
Chris@320 1268
Chris@320 1269 if (!layer) continue;
Chris@320 1270 if (dynamic_cast<TimeRulerLayer *>(layer)) continue;
Chris@301 1271
Chris@301 1272 Model *model = (*i)->getModel();
Chris@301 1273 if (!model) continue;
Chris@301 1274
Chris@359 1275 anyModel = model;
Chris@359 1276
Chris@320 1277 if (model->getAlignmentReference()) {
Chris@359 1278 alignedModel = model;
Chris@320 1279 if (layer->isLayerOpaque() ||
Chris@320 1280 dynamic_cast<RangeSummarisableTimeValueModel *>(model)) {
Chris@320 1281 goodModel = model;
Chris@320 1282 }
Chris@301 1283 }
Chris@320 1284 }
Chris@301 1285
Chris@320 1286 if (goodModel) return goodModel;
Chris@359 1287 else if (alignedModel) return alignedModel;
Chris@320 1288 else return anyModel;
Chris@320 1289 }
Chris@320 1290
Chris@908 1291 sv_frame_t
Chris@908 1292 View::alignFromReference(sv_frame_t f) const
Chris@320 1293 {
Chris@856 1294 if (!m_manager || !m_manager->getAlignMode()) return f;
Chris@320 1295 Model *aligningModel = getAligningModel();
Chris@320 1296 if (!aligningModel) return f;
Chris@320 1297 return aligningModel->alignFromReference(f);
Chris@320 1298 }
Chris@320 1299
Chris@908 1300 sv_frame_t
Chris@908 1301 View::alignToReference(sv_frame_t f) const
Chris@320 1302 {
Chris@321 1303 if (!m_manager->getAlignMode()) return f;
Chris@320 1304 Model *aligningModel = getAligningModel();
Chris@320 1305 if (!aligningModel) return f;
Chris@320 1306 return aligningModel->alignToReference(f);
Chris@320 1307 }
Chris@320 1308
Chris@908 1309 sv_frame_t
Chris@320 1310 View::getAlignedPlaybackFrame() const
Chris@320 1311 {
Chris@856 1312 if (!m_manager) return 0;
Chris@908 1313 sv_frame_t pf = m_manager->getPlaybackFrame();
Chris@321 1314 if (!m_manager->getAlignMode()) return pf;
Chris@321 1315
Chris@320 1316 Model *aligningModel = getAligningModel();
Chris@320 1317 if (!aligningModel) return pf;
Chris@830 1318
Chris@908 1319 sv_frame_t af = aligningModel->alignFromReference(pf);
Chris@301 1320
Chris@301 1321 return af;
Chris@301 1322 }
Chris@301 1323
Chris@127 1324 bool
Chris@127 1325 View::areLayersScrollable() const
Chris@127 1326 {
Chris@127 1327 // True iff all views are scrollable
Chris@835 1328 for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
Chris@127 1329 if (!(*i)->isLayerScrollable(this)) return false;
Chris@127 1330 }
Chris@127 1331 return true;
Chris@127 1332 }
Chris@127 1333
Chris@127 1334 View::LayerList
Chris@127 1335 View::getScrollableBackLayers(bool testChanged, bool &changed) const
Chris@127 1336 {
Chris@127 1337 changed = false;
Chris@127 1338
Chris@127 1339 // We want a list of all the scrollable layers that are behind the
Chris@127 1340 // backmost non-scrollable layer.
Chris@127 1341
Chris@127 1342 LayerList scrollables;
Chris@127 1343 bool metUnscrollable = false;
Chris@127 1344
Chris@835 1345 for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
Chris@587 1346 // SVDEBUG << "View::getScrollableBackLayers: calling isLayerDormant on layer " << *i << endl;
Chris@682 1347 // cerr << "(name is " << (*i)->objectName() << ")"
Chris@682 1348 // << endl;
Chris@587 1349 // SVDEBUG << "View::getScrollableBackLayers: I am " << this << endl;
Chris@127 1350 if ((*i)->isLayerDormant(this)) continue;
Chris@127 1351 if ((*i)->isLayerOpaque()) {
Chris@127 1352 // You can't see anything behind an opaque layer!
Chris@127 1353 scrollables.clear();
Chris@127 1354 if (metUnscrollable) break;
Chris@127 1355 }
Chris@127 1356 if (!metUnscrollable && (*i)->isLayerScrollable(this)) {
Chris@127 1357 scrollables.push_back(*i);
Chris@127 1358 } else {
Chris@127 1359 metUnscrollable = true;
Chris@127 1360 }
Chris@127 1361 }
Chris@127 1362
Chris@127 1363 if (testChanged && scrollables != m_lastScrollableBackLayers) {
Chris@127 1364 m_lastScrollableBackLayers = scrollables;
Chris@127 1365 changed = true;
Chris@127 1366 }
Chris@127 1367 return scrollables;
Chris@127 1368 }
Chris@127 1369
Chris@127 1370 View::LayerList
Chris@127 1371 View::getNonScrollableFrontLayers(bool testChanged, bool &changed) const
Chris@127 1372 {
Chris@127 1373 changed = false;
Chris@127 1374 LayerList nonScrollables;
Chris@127 1375
Chris@127 1376 // Everything in front of the first non-scrollable from the back
Chris@127 1377 // should also be considered non-scrollable
Chris@127 1378
Chris@127 1379 bool started = false;
Chris@127 1380
Chris@835 1381 for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
Chris@127 1382 if ((*i)->isLayerDormant(this)) continue;
Chris@127 1383 if (!started && (*i)->isLayerScrollable(this)) {
Chris@127 1384 continue;
Chris@127 1385 }
Chris@127 1386 started = true;
Chris@127 1387 if ((*i)->isLayerOpaque()) {
Chris@127 1388 // You can't see anything behind an opaque layer!
Chris@127 1389 nonScrollables.clear();
Chris@127 1390 }
Chris@127 1391 nonScrollables.push_back(*i);
Chris@127 1392 }
Chris@127 1393
Chris@127 1394 if (testChanged && nonScrollables != m_lastNonScrollableBackLayers) {
Chris@127 1395 m_lastNonScrollableBackLayers = nonScrollables;
Chris@127 1396 changed = true;
Chris@127 1397 }
Chris@127 1398
Chris@127 1399 return nonScrollables;
Chris@127 1400 }
Chris@127 1401
Chris@806 1402 int
Chris@806 1403 View::getZoomConstraintBlockSize(int blockSize,
Chris@127 1404 ZoomConstraint::RoundingDirection dir)
Chris@127 1405 const
Chris@127 1406 {
Chris@806 1407 int candidate = blockSize;
Chris@127 1408 bool haveCandidate = false;
Chris@127 1409
Chris@127 1410 PowerOfSqrtTwoZoomConstraint defaultZoomConstraint;
Chris@127 1411
Chris@835 1412 for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
Chris@127 1413
Chris@127 1414 const ZoomConstraint *zoomConstraint = (*i)->getZoomConstraint();
Chris@127 1415 if (!zoomConstraint) zoomConstraint = &defaultZoomConstraint;
Chris@127 1416
Chris@806 1417 int thisBlockSize =
Chris@127 1418 zoomConstraint->getNearestBlockSize(blockSize, dir);
Chris@127 1419
Chris@127 1420 // Go for the block size that's furthest from the one
Chris@127 1421 // passed in. Most of the time, that's what we want.
Chris@127 1422 if (!haveCandidate ||
Chris@127 1423 (thisBlockSize > blockSize && thisBlockSize > candidate) ||
Chris@127 1424 (thisBlockSize < blockSize && thisBlockSize < candidate)) {
Chris@127 1425 candidate = thisBlockSize;
Chris@127 1426 haveCandidate = true;
Chris@127 1427 }
Chris@127 1428 }
Chris@127 1429
Chris@127 1430 return candidate;
Chris@127 1431 }
Chris@127 1432
Chris@183 1433 bool
Chris@183 1434 View::areLayerColoursSignificant() const
Chris@183 1435 {
Chris@835 1436 for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
Chris@287 1437 if ((*i)->getLayerColourSignificance() ==
Chris@287 1438 Layer::ColourHasMeaningfulValue) return true;
Chris@183 1439 if ((*i)->isLayerOpaque()) break;
Chris@183 1440 }
Chris@183 1441 return false;
Chris@183 1442 }
Chris@183 1443
Chris@217 1444 bool
Chris@217 1445 View::hasTopLayerTimeXAxis() const
Chris@217 1446 {
Chris@835 1447 LayerList::const_iterator i = m_layerStack.end();
Chris@835 1448 if (i == m_layerStack.begin()) return false;
Chris@217 1449 --i;
Chris@217 1450 return (*i)->hasTimeXAxis();
Chris@217 1451 }
Chris@217 1452
Chris@127 1453 void
Chris@127 1454 View::zoom(bool in)
Chris@127 1455 {
Chris@127 1456 int newZoomLevel = m_zoomLevel;
Chris@127 1457
Chris@127 1458 if (in) {
Chris@127 1459 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel - 1,
Chris@127 1460 ZoomConstraint::RoundDown);
Chris@127 1461 } else {
Chris@127 1462 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel + 1,
Chris@127 1463 ZoomConstraint::RoundUp);
Chris@127 1464 }
Chris@127 1465
Chris@127 1466 if (newZoomLevel != m_zoomLevel) {
Chris@127 1467 setZoomLevel(newZoomLevel);
Chris@127 1468 }
Chris@127 1469 }
Chris@127 1470
Chris@127 1471 void
Chris@510 1472 View::scroll(bool right, bool lots, bool e)
Chris@127 1473 {
Chris@908 1474 sv_frame_t delta;
Chris@127 1475 if (lots) {
Chris@127 1476 delta = (getEndFrame() - getStartFrame()) / 2;
Chris@127 1477 } else {
Chris@127 1478 delta = (getEndFrame() - getStartFrame()) / 20;
Chris@127 1479 }
Chris@127 1480 if (right) delta = -delta;
Chris@127 1481
Chris@908 1482 if (m_centreFrame < delta) {
Chris@510 1483 setCentreFrame(0, e);
Chris@908 1484 } else if (m_centreFrame - delta >= getModelsEndFrame()) {
Chris@510 1485 setCentreFrame(getModelsEndFrame(), e);
Chris@127 1486 } else {
Chris@510 1487 setCentreFrame(m_centreFrame - delta, e);
Chris@127 1488 }
Chris@127 1489 }
Chris@127 1490
Chris@127 1491 void
Chris@797 1492 View::cancelClicked()
Chris@797 1493 {
Chris@797 1494 QPushButton *cancel = qobject_cast<QPushButton *>(sender());
Chris@797 1495 if (!cancel) return;
Chris@797 1496
Chris@797 1497 for (ProgressMap::iterator i = m_progressBars.begin();
Chris@797 1498 i != m_progressBars.end(); ++i) {
Chris@797 1499
Chris@797 1500 if (i->second.cancel == cancel) {
Chris@797 1501
Chris@797 1502 Layer *layer = i->first;
Chris@797 1503 Model *model = layer->getModel();
Chris@797 1504
Chris@797 1505 if (model) model->abandon();
Chris@797 1506 }
Chris@797 1507 }
Chris@797 1508 }
Chris@797 1509
Chris@797 1510 void
Chris@127 1511 View::checkProgress(void *object)
Chris@127 1512 {
Chris@127 1513 if (!m_showProgress) return;
Chris@127 1514
Chris@127 1515 int ph = height();
Chris@127 1516
Chris@555 1517 for (ProgressMap::iterator i = m_progressBars.begin();
Chris@127 1518 i != m_progressBars.end(); ++i) {
Chris@127 1519
Chris@555 1520 QProgressBar *pb = i->second.bar;
Chris@797 1521 QPushButton *cancel = i->second.cancel;
Chris@555 1522
Chris@127 1523 if (i->first == object) {
Chris@127 1524
Chris@555 1525 // The timer is used to test for stalls. If the progress
Chris@555 1526 // bar does not get updated for some length of time, the
Chris@555 1527 // timer prompts it to go back into "indeterminate" mode
Chris@555 1528 QTimer *timer = i->second.checkTimer;
Chris@555 1529
Chris@127 1530 int completion = i->first->getCompletion(this);
Chris@301 1531 QString text = i->first->getPropertyContainerName();
Chris@583 1532 QString error = i->first->getError(this);
Chris@583 1533
Chris@583 1534 if (error != "" && error != m_lastError) {
Chris@583 1535 QMessageBox::critical(this, tr("Layer rendering error"), error);
Chris@583 1536 m_lastError = error;
Chris@583 1537 }
Chris@301 1538
Chris@387 1539 Model *model = i->first->getModel();
Chris@387 1540 RangeSummarisableTimeValueModel *wfm =
Chris@387 1541 dynamic_cast<RangeSummarisableTimeValueModel *>(model);
Chris@387 1542
Chris@388 1543 if (completion > 0) {
Chris@555 1544 pb->setMaximum(100); // was 0, for indeterminate start
Chris@388 1545 }
Chris@388 1546
Chris@301 1547 if (completion >= 100) {
Chris@301 1548
Chris@301 1549 //!!!
Chris@326 1550 if (wfm ||
Chris@776 1551 (model &&
Chris@776 1552 (wfm = dynamic_cast<RangeSummarisableTimeValueModel *>
Chris@776 1553 (model->getSourceModel())))) {
Chris@301 1554 completion = wfm->getAlignmentCompletion();
Chris@587 1555 // SVDEBUG << "View::checkProgress: Alignment completion = " << completion << endl;
Chris@301 1556 if (completion < 100) {
Chris@301 1557 text = tr("Alignment");
Chris@301 1558 }
Chris@301 1559 }
Chris@387 1560
Chris@387 1561 } else if (wfm) {
Chris@387 1562 update(); // ensure duration &c gets updated
Chris@301 1563 }
Chris@127 1564
Chris@127 1565 if (completion >= 100) {
Chris@127 1566
Chris@555 1567 pb->hide();
Chris@797 1568 cancel->hide();
Chris@555 1569 timer->stop();
Chris@127 1570
Chris@127 1571 } else {
Chris@127 1572
Chris@682 1573 // cerr << "progress = " << completion << endl;
Chris@555 1574
Chris@555 1575 if (!pb->isVisible()) {
Chris@555 1576 i->second.lastCheck = 0;
Chris@555 1577 timer->setInterval(2000);
Chris@555 1578 timer->start();
Chris@555 1579 }
Chris@555 1580
Chris@797 1581 cancel->move(0, ph - pb->height()/2 - 10);
Chris@797 1582 cancel->show();
Chris@797 1583
Chris@555 1584 pb->setValue(completion);
Chris@797 1585 pb->move(20, ph - pb->height());
Chris@555 1586
Chris@555 1587 pb->show();
Chris@555 1588 pb->update();
Chris@555 1589
Chris@555 1590 ph -= pb->height();
Chris@127 1591 }
Chris@127 1592 } else {
Chris@555 1593 if (pb->isVisible()) {
Chris@555 1594 ph -= pb->height();
Chris@127 1595 }
Chris@127 1596 }
Chris@127 1597 }
Chris@127 1598 }
Chris@127 1599
Chris@555 1600 void
Chris@555 1601 View::progressCheckStalledTimerElapsed()
Chris@555 1602 {
Chris@555 1603 QObject *s = sender();
Chris@555 1604 QTimer *t = qobject_cast<QTimer *>(s);
Chris@555 1605 if (!t) return;
Chris@555 1606 for (ProgressMap::iterator i = m_progressBars.begin();
Chris@555 1607 i != m_progressBars.end(); ++i) {
Chris@555 1608 if (i->second.checkTimer == t) {
Chris@555 1609 int value = i->second.bar->value();
Chris@555 1610 if (value > 0 && value == i->second.lastCheck) {
Chris@555 1611 i->second.bar->setMaximum(0); // indeterminate
Chris@555 1612 }
Chris@555 1613 i->second.lastCheck = value;
Chris@555 1614 return;
Chris@555 1615 }
Chris@555 1616 }
Chris@555 1617 }
Chris@555 1618
Chris@384 1619 int
Chris@384 1620 View::getProgressBarWidth() const
Chris@384 1621 {
Chris@384 1622 for (ProgressMap::const_iterator i = m_progressBars.begin();
Chris@384 1623 i != m_progressBars.end(); ++i) {
Chris@555 1624 if (i->second.bar && i->second.bar->isVisible()) {
Chris@555 1625 return i->second.bar->width();
Chris@555 1626 }
Chris@384 1627 }
Chris@384 1628
Chris@384 1629 return 0;
Chris@384 1630 }
Chris@384 1631
Chris@127 1632 void
Chris@339 1633 View::setPaintFont(QPainter &paint)
Chris@339 1634 {
Chris@955 1635 int scaleFactor = 1;
Chris@956 1636 int dpratio = effectiveDevicePixelRatio();
Chris@955 1637 if (dpratio > 1) {
Chris@955 1638 QPaintDevice *dev = paint.device();
Chris@955 1639 if (dynamic_cast<QPixmap *>(dev) || dynamic_cast<QImage *>(dev)) {
Chris@955 1640 scaleFactor = dpratio;
Chris@955 1641 }
Chris@955 1642 }
Chris@955 1643
Chris@339 1644 QFont font(paint.font());
Chris@955 1645 font.setPointSize(Preferences::getInstance()->getViewFontSize()
Chris@955 1646 * scaleFactor);
Chris@339 1647 paint.setFont(font);
Chris@339 1648 }
Chris@339 1649
Chris@915 1650 QRect
Chris@915 1651 View::getPaintRect() const
Chris@915 1652 {
Chris@919 1653 return rect();
Chris@915 1654 }
Chris@915 1655
Chris@339 1656 void
Chris@127 1657 View::paintEvent(QPaintEvent *e)
Chris@127 1658 {
Chris@127 1659 // Profiler prof("View::paintEvent", false);
Chris@800 1660 // cerr << "View::paintEvent: centre frame is " << m_centreFrame << endl;
matthiasm@785 1661
Chris@835 1662 if (m_layerStack.empty()) {
Chris@127 1663 QFrame::paintEvent(e);
Chris@127 1664 return;
Chris@127 1665 }
Chris@127 1666
Chris@127 1667 // ensure our constraints are met
Chris@137 1668
Chris@137 1669 /*!!! Should we do this only if we have layers that can't support other
Chris@137 1670 zoom levels?
Chris@137 1671
Chris@127 1672 m_zoomLevel = getZoomConstraintBlockSize(m_zoomLevel,
Chris@127 1673 ZoomConstraint::RoundUp);
Chris@137 1674 */
Chris@127 1675
Chris@127 1676 QPainter paint;
Chris@127 1677 bool repaintCache = false;
Chris@127 1678 bool paintedCacheRect = false;
Chris@127 1679
Chris@127 1680 QRect cacheRect(rect());
Chris@127 1681
Chris@127 1682 if (e) {
Chris@127 1683 cacheRect &= e->rect();
Chris@127 1684 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 1685 cerr << "paint rect " << cacheRect.width() << "x" << cacheRect.height()
Chris@682 1686 << ", my rect " << width() << "x" << height() << endl;
Chris@127 1687 #endif
Chris@127 1688 }
Chris@127 1689
Chris@127 1690 QRect nonCacheRect(cacheRect);
Chris@127 1691
Chris@956 1692 int dpratio = effectiveDevicePixelRatio();
Chris@953 1693
Chris@127 1694 // If not all layers are scrollable, but some of the back layers
Chris@127 1695 // are, we should store only those in the cache.
Chris@127 1696
Chris@127 1697 bool layersChanged = false;
Chris@127 1698 LayerList scrollables = getScrollableBackLayers(true, layersChanged);
Chris@127 1699 LayerList nonScrollables = getNonScrollableFrontLayers(true, layersChanged);
Chris@127 1700 bool selectionCacheable = nonScrollables.empty();
Chris@127 1701 bool haveSelections = m_manager && !m_manager->getSelections().empty();
Chris@127 1702
Chris@127 1703 // If all the non-scrollable layers are non-opaque, then we draw
Chris@127 1704 // the selection rectangle behind them and cache it. If any are
Chris@953 1705 // opaque, however, or if our device-pixel ratio is not 1 (so we
Chris@953 1706 // need to paint direct to the widget), then we can't cache.
Chris@127 1707 //
Chris@953 1708 if (dpratio == 1) {
Chris@953 1709
Chris@953 1710 if (!selectionCacheable) {
Chris@953 1711 selectionCacheable = true;
Chris@953 1712 for (LayerList::const_iterator i = nonScrollables.begin();
Chris@953 1713 i != nonScrollables.end(); ++i) {
Chris@953 1714 if ((*i)->isLayerOpaque()) {
Chris@953 1715 selectionCacheable = false;
Chris@953 1716 break;
Chris@953 1717 }
Chris@953 1718 }
Chris@953 1719 }
Chris@953 1720
Chris@953 1721 if (selectionCacheable) {
Chris@953 1722 QPoint localPos;
Chris@953 1723 bool closeToLeft, closeToRight;
Chris@953 1724 if (shouldIlluminateLocalSelection
Chris@953 1725 (localPos, closeToLeft, closeToRight)) {
Chris@953 1726 selectionCacheable = false;
Chris@953 1727 }
Chris@953 1728 }
Chris@953 1729
Chris@953 1730 } else {
Chris@953 1731
Chris@953 1732 selectionCacheable = false;
Chris@127 1733 }
Chris@127 1734
Chris@127 1735 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 1736 cerr << "View(" << this << ")::paintEvent: have " << scrollables.size()
Chris@127 1737 << " scrollable back layers and " << nonScrollables.size()
Chris@682 1738 << " non-scrollable front layers" << endl;
Chris@682 1739 cerr << "haveSelections " << haveSelections << ", selectionCacheable "
Chris@682 1740 << selectionCacheable << ", m_selectionCached " << m_selectionCached << endl;
Chris@127 1741 #endif
Chris@127 1742
Chris@127 1743 if (layersChanged || scrollables.empty() ||
Chris@127 1744 (haveSelections && (selectionCacheable != m_selectionCached))) {
Chris@127 1745 delete m_cache;
Chris@127 1746 m_cache = 0;
Chris@127 1747 m_selectionCached = false;
Chris@127 1748 }
Chris@127 1749
Chris@952 1750 QSize scaledCacheSize(scaledSize(size(), dpratio));
Chris@952 1751 QRect scaledCacheRect(scaledRect(cacheRect, dpratio));
Chris@952 1752
Chris@952 1753 if (!m_buffer || scaledCacheSize != m_buffer->size()) {
Chris@952 1754 delete m_buffer;
Chris@952 1755 m_buffer = new QPixmap(scaledCacheSize);
Chris@952 1756 }
Chris@952 1757
Chris@127 1758 if (!scrollables.empty()) {
Chris@244 1759
Chris@244 1760 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 1761 cerr << "View(" << this << "): cache " << m_cache << ", cache zoom "
Chris@682 1762 << m_cacheZoomLevel << ", zoom " << m_zoomLevel << endl;
Chris@244 1763 #endif
Chris@244 1764
Chris@127 1765 if (!m_cache ||
Chris@127 1766 m_cacheZoomLevel != m_zoomLevel ||
Chris@914 1767 scaledCacheSize != m_cache->size()) {
Chris@127 1768
Chris@127 1769 // cache is not valid
Chris@127 1770
Chris@127 1771 if (cacheRect.width() < width()/10) {
Chris@244 1772 delete m_cache;
Chris@244 1773 m_cache = 0;
Chris@127 1774 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 1775 cerr << "View(" << this << ")::paintEvent: small repaint, not bothering to recreate cache" << endl;
Chris@127 1776 #endif
Chris@127 1777 } else {
Chris@127 1778 delete m_cache;
Chris@914 1779 m_cache = new QPixmap(scaledCacheSize);
Chris@127 1780 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 1781 cerr << "View(" << this << ")::paintEvent: recreated cache" << endl;
Chris@127 1782 #endif
Chris@127 1783 cacheRect = rect();
Chris@127 1784 repaintCache = true;
Chris@127 1785 }
Chris@127 1786
Chris@127 1787 } else if (m_cacheCentreFrame != m_centreFrame) {
Chris@127 1788
Chris@806 1789 int dx =
Chris@127 1790 getXForFrame(m_cacheCentreFrame) -
Chris@127 1791 getXForFrame(m_centreFrame);
Chris@127 1792
Chris@127 1793 if (dx > -width() && dx < width()) {
Chris@127 1794 static QPixmap *tmpPixmap = 0;
Chris@914 1795 if (!tmpPixmap || tmpPixmap->size() != scaledCacheSize) {
Chris@127 1796 delete tmpPixmap;
Chris@914 1797 tmpPixmap = new QPixmap(scaledCacheSize);
Chris@127 1798 }
Chris@127 1799 paint.begin(tmpPixmap);
Chris@127 1800 paint.drawPixmap(0, 0, *m_cache);
Chris@127 1801 paint.end();
Chris@127 1802 paint.begin(m_cache);
Chris@127 1803 paint.drawPixmap(dx, 0, *tmpPixmap);
Chris@127 1804 paint.end();
Chris@127 1805 if (dx < 0) {
Chris@127 1806 cacheRect = QRect(width() + dx, 0, -dx, height());
Chris@127 1807 } else {
Chris@127 1808 cacheRect = QRect(0, 0, dx, height());
Chris@127 1809 }
Chris@127 1810 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 1811 cerr << "View(" << this << ")::paintEvent: scrolled cache by " << dx << endl;
Chris@127 1812 #endif
Chris@127 1813 } else {
Chris@127 1814 cacheRect = rect();
Chris@127 1815 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 1816 cerr << "View(" << this << ")::paintEvent: scrolling too far" << endl;
Chris@127 1817 #endif
Chris@127 1818 }
Chris@127 1819 repaintCache = true;
Chris@127 1820
Chris@127 1821 } else {
Chris@127 1822 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 1823 cerr << "View(" << this << ")::paintEvent: cache is good" << endl;
Chris@127 1824 #endif
Chris@952 1825 paint.begin(m_buffer);
Chris@952 1826 paint.drawPixmap(scaledCacheRect, *m_cache, scaledCacheRect);
Chris@127 1827 paint.end();
Chris@127 1828 QFrame::paintEvent(e);
Chris@127 1829 paintedCacheRect = true;
Chris@127 1830 }
Chris@127 1831
Chris@127 1832 m_cacheCentreFrame = m_centreFrame;
Chris@127 1833 m_cacheZoomLevel = m_zoomLevel;
Chris@127 1834 }
Chris@127 1835
Chris@127 1836 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@682 1837 // cerr << "View(" << this << ")::paintEvent: cacheRect " << cacheRect << ", nonCacheRect " << (nonCacheRect | cacheRect) << ", repaintCache " << repaintCache << ", paintedCacheRect " << paintedCacheRect << endl;
Chris@127 1838 #endif
Chris@127 1839
Chris@127 1840 // Scrollable (cacheable) items first
Chris@127 1841
Chris@919 1842 ViewProxy proxy(this, dpratio);
Chris@919 1843
Chris@127 1844 if (!paintedCacheRect) {
Chris@127 1845
Chris@914 1846 QRect rectToPaint;
Chris@914 1847
Chris@914 1848 if (repaintCache) {
Chris@914 1849 paint.begin(m_cache);
Chris@914 1850 rectToPaint = scaledCacheRect;
Chris@914 1851 } else {
Chris@952 1852 paint.begin(m_buffer);
Chris@952 1853 rectToPaint = scaledCacheRect;
Chris@914 1854 }
Chris@914 1855
Chris@339 1856 setPaintFont(paint);
Chris@914 1857 paint.setClipRect(rectToPaint);
Chris@287 1858
Chris@287 1859 paint.setPen(getBackground());
Chris@287 1860 paint.setBrush(getBackground());
Chris@914 1861 paint.drawRect(rectToPaint);
Chris@127 1862
Chris@287 1863 paint.setPen(getForeground());
Chris@127 1864 paint.setBrush(Qt::NoBrush);
Chris@127 1865
Chris@127 1866 for (LayerList::iterator i = scrollables.begin(); i != scrollables.end(); ++i) {
Chris@127 1867 paint.setRenderHint(QPainter::Antialiasing, false);
Chris@127 1868 paint.save();
Chris@951 1869 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@951 1870 cerr << "Painting scrollable layer " << *i << " using proxy with repaintCache = " << repaintCache << ", dpratio = " << dpratio << ", rectToPaint = " << rectToPaint.x() << "," << rectToPaint.y() << " " << rectToPaint.width() << "x" << rectToPaint.height() << endl;
Chris@951 1871 #endif
Chris@919 1872 (*i)->paint(&proxy, paint, rectToPaint);
Chris@127 1873 paint.restore();
Chris@127 1874 }
Chris@127 1875
Chris@127 1876 if (haveSelections && selectionCacheable) {
Chris@127 1877 drawSelections(paint);
Chris@127 1878 m_selectionCached = repaintCache;
Chris@127 1879 }
Chris@127 1880
Chris@127 1881 paint.end();
Chris@127 1882
Chris@127 1883 if (repaintCache) {
Chris@127 1884 cacheRect |= (e ? e->rect() : rect());
Chris@952 1885 scaledCacheRect = scaledRect(cacheRect, dpratio);
Chris@952 1886 paint.begin(m_buffer);
Chris@952 1887 paint.drawPixmap(scaledCacheRect, *m_cache, scaledCacheRect);
Chris@127 1888 paint.end();
Chris@127 1889 }
Chris@127 1890 }
Chris@127 1891
Chris@127 1892 // Now non-cacheable items. We always need to redraw the
Chris@127 1893 // non-cacheable items across at least the area we drew of the
Chris@127 1894 // cacheable items.
Chris@127 1895
Chris@127 1896 nonCacheRect |= cacheRect;
Chris@127 1897
Chris@952 1898 QRect scaledNonCacheRect = scaledRect(nonCacheRect, dpratio);
Chris@952 1899
Chris@952 1900 paint.begin(m_buffer);
Chris@952 1901 paint.setClipRect(scaledNonCacheRect);
Chris@339 1902 setPaintFont(paint);
Chris@127 1903 if (scrollables.empty()) {
Chris@287 1904 paint.setPen(getBackground());
Chris@287 1905 paint.setBrush(getBackground());
Chris@952 1906 paint.drawRect(scaledNonCacheRect);
Chris@127 1907 }
Chris@127 1908
Chris@287 1909 paint.setPen(getForeground());
Chris@127 1910 paint.setBrush(Qt::NoBrush);
Chris@127 1911
Chris@127 1912 for (LayerList::iterator i = nonScrollables.begin(); i != nonScrollables.end(); ++i) {
Chris@127 1913 // Profiler profiler2("View::paintEvent non-cacheable");
Chris@951 1914 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@951 1915 cerr << "Painting non-scrollable layer " << *i << " without proxy with repaintCache = " << repaintCache << ", dpratio = " << dpratio << ", rectToPaint = " << nonCacheRect.x() << "," << nonCacheRect.y() << " " << nonCacheRect.width() << "x" << nonCacheRect.height() << endl;
Chris@951 1916 #endif
Chris@952 1917 (*i)->paint(&proxy, paint, scaledNonCacheRect);
Chris@127 1918 }
Chris@127 1919
Chris@127 1920 paint.end();
Chris@953 1921
Chris@953 1922 paint.begin(this);
Chris@953 1923 QRect finalPaintRect = e ? e->rect() : rect();
Chris@953 1924 paint.drawPixmap(finalPaintRect, *m_buffer, scaledRect(finalPaintRect, dpratio));
Chris@953 1925 paint.end();
Chris@953 1926
Chris@953 1927 paint.begin(this);
Chris@339 1928 setPaintFont(paint);
Chris@953 1929 if (e) paint.setClipRect(e->rect());
Chris@127 1930 if (!m_selectionCached) {
Chris@127 1931 drawSelections(paint);
Chris@127 1932 }
Chris@127 1933 paint.end();
Chris@127 1934
Chris@211 1935 bool showPlayPointer = true;
Chris@211 1936 if (m_followPlay == PlaybackScrollContinuous) {
Chris@211 1937 showPlayPointer = false;
Chris@806 1938 } else if (m_playPointerFrame <= getStartFrame() ||
Chris@211 1939 m_playPointerFrame >= getEndFrame()) {
Chris@211 1940 showPlayPointer = false;
Chris@211 1941 } else if (m_manager && !m_manager->isPlaying()) {
Chris@211 1942 if (m_playPointerFrame == getCentreFrame() &&
Chris@787 1943 m_manager->shouldShowCentreLine() &&
Chris@211 1944 m_followPlay != PlaybackIgnore) {
Chris@787 1945 // Don't show the play pointer when it is redundant with
Chris@787 1946 // the centre line
Chris@211 1947 showPlayPointer = false;
Chris@211 1948 }
Chris@211 1949 }
Chris@952 1950
Chris@211 1951 if (showPlayPointer) {
Chris@127 1952
Chris@127 1953 paint.begin(this);
Chris@127 1954
Chris@211 1955 int playx = getXForFrame(m_playPointerFrame);
Chris@211 1956
Chris@287 1957 paint.setPen(getForeground());
Chris@211 1958 paint.drawLine(playx - 1, 0, playx - 1, height() - 1);
Chris@211 1959 paint.drawLine(playx + 1, 0, playx + 1, height() - 1);
Chris@211 1960 paint.drawPoint(playx, 0);
Chris@211 1961 paint.drawPoint(playx, height() - 1);
Chris@287 1962 paint.setPen(getBackground());
Chris@211 1963 paint.drawLine(playx, 1, playx, height() - 2);
Chris@127 1964
Chris@127 1965 paint.end();
Chris@127 1966 }
Chris@127 1967
Chris@127 1968 QFrame::paintEvent(e);
Chris@127 1969 }
Chris@127 1970
Chris@127 1971 void
Chris@127 1972 View::drawSelections(QPainter &paint)
Chris@127 1973 {
Chris@217 1974 if (!hasTopLayerTimeXAxis()) return;
Chris@217 1975
Chris@127 1976 MultiSelection::SelectionList selections;
Chris@127 1977
Chris@127 1978 if (m_manager) {
Chris@127 1979 selections = m_manager->getSelections();
Chris@127 1980 if (m_manager->haveInProgressSelection()) {
Chris@127 1981 bool exclusive;
Chris@127 1982 Selection inProgressSelection =
Chris@127 1983 m_manager->getInProgressSelection(exclusive);
Chris@127 1984 if (exclusive) selections.clear();
Chris@127 1985 selections.insert(inProgressSelection);
Chris@127 1986 }
Chris@127 1987 }
Chris@127 1988
Chris@127 1989 paint.save();
Chris@183 1990
Chris@183 1991 bool translucent = !areLayerColoursSignificant();
Chris@183 1992
Chris@183 1993 if (translucent) {
Chris@183 1994 paint.setBrush(QColor(150, 150, 255, 80));
Chris@183 1995 } else {
Chris@183 1996 paint.setBrush(Qt::NoBrush);
Chris@183 1997 }
Chris@127 1998
Chris@908 1999 sv_samplerate_t sampleRate = getModelsSampleRate();
Chris@127 2000
Chris@127 2001 QPoint localPos;
Chris@908 2002 sv_frame_t illuminateFrame = -1;
Chris@127 2003 bool closeToLeft, closeToRight;
Chris@127 2004
Chris@127 2005 if (shouldIlluminateLocalSelection(localPos, closeToLeft, closeToRight)) {
Chris@127 2006 illuminateFrame = getFrameForX(localPos.x());
Chris@127 2007 }
Chris@127 2008
Chris@127 2009 const QFontMetrics &metrics = paint.fontMetrics();
Chris@127 2010
Chris@127 2011 for (MultiSelection::SelectionList::iterator i = selections.begin();
Chris@127 2012 i != selections.end(); ++i) {
Chris@127 2013
Chris@333 2014 int p0 = getXForFrame(alignFromReference(i->getStartFrame()));
Chris@333 2015 int p1 = getXForFrame(alignFromReference(i->getEndFrame()));
Chris@127 2016
Chris@127 2017 if (p1 < 0 || p0 > width()) continue;
Chris@127 2018
Chris@127 2019 #ifdef DEBUG_VIEW_WIDGET_PAINT
Chris@587 2020 SVDEBUG << "View::drawSelections: " << p0 << ",-1 [" << (p1-p0) << "x" << (height()+1) << "]" << endl;
Chris@127 2021 #endif
Chris@127 2022
Chris@127 2023 bool illuminateThis =
Chris@127 2024 (illuminateFrame >= 0 && i->contains(illuminateFrame));
Chris@127 2025
Chris@127 2026 paint.setPen(QColor(150, 150, 255));
Chris@183 2027
Chris@183 2028 if (translucent && shouldLabelSelections()) {
Chris@183 2029 paint.drawRect(p0, -1, p1 - p0, height() + 1);
Chris@183 2030 } else {
Chris@183 2031 // Make the top & bottom lines of the box visible if we
Chris@183 2032 // are lacking some of the other visual cues. There's no
Chris@183 2033 // particular logic to this, it's just a question of what
Chris@183 2034 // I happen to think looks nice.
Chris@183 2035 paint.drawRect(p0, 0, p1 - p0, height() - 1);
Chris@183 2036 }
Chris@127 2037
Chris@127 2038 if (illuminateThis) {
Chris@127 2039 paint.save();
Chris@287 2040 paint.setPen(QPen(getForeground(), 2));
Chris@127 2041 if (closeToLeft) {
Chris@127 2042 paint.drawLine(p0, 1, p1, 1);
Chris@127 2043 paint.drawLine(p0, 0, p0, height());
Chris@127 2044 paint.drawLine(p0, height() - 1, p1, height() - 1);
Chris@127 2045 } else if (closeToRight) {
Chris@127 2046 paint.drawLine(p0, 1, p1, 1);
Chris@127 2047 paint.drawLine(p1, 0, p1, height());
Chris@127 2048 paint.drawLine(p0, height() - 1, p1, height() - 1);
Chris@127 2049 } else {
Chris@127 2050 paint.setBrush(Qt::NoBrush);
Chris@127 2051 paint.drawRect(p0, 1, p1 - p0, height() - 2);
Chris@127 2052 }
Chris@127 2053 paint.restore();
Chris@127 2054 }
Chris@127 2055
Chris@127 2056 if (sampleRate && shouldLabelSelections() && m_manager &&
Chris@189 2057 m_manager->shouldShowSelectionExtents()) {
Chris@127 2058
Chris@127 2059 QString startText = QString("%1 / %2")
Chris@127 2060 .arg(QString::fromStdString
Chris@127 2061 (RealTime::frame2RealTime
Chris@127 2062 (i->getStartFrame(), sampleRate).toText(true)))
Chris@127 2063 .arg(i->getStartFrame());
Chris@127 2064
Chris@127 2065 QString endText = QString(" %1 / %2")
Chris@127 2066 .arg(QString::fromStdString
Chris@127 2067 (RealTime::frame2RealTime
Chris@127 2068 (i->getEndFrame(), sampleRate).toText(true)))
Chris@127 2069 .arg(i->getEndFrame());
Chris@127 2070
Chris@127 2071 QString durationText = QString("(%1 / %2) ")
Chris@127 2072 .arg(QString::fromStdString
Chris@127 2073 (RealTime::frame2RealTime
Chris@127 2074 (i->getEndFrame() - i->getStartFrame(), sampleRate)
Chris@127 2075 .toText(true)))
Chris@127 2076 .arg(i->getEndFrame() - i->getStartFrame());
Chris@127 2077
Chris@127 2078 int sw = metrics.width(startText),
Chris@127 2079 ew = metrics.width(endText),
Chris@127 2080 dw = metrics.width(durationText);
Chris@127 2081
Chris@127 2082 int sy = metrics.ascent() + metrics.height() + 4;
Chris@127 2083 int ey = sy;
Chris@127 2084 int dy = sy + metrics.height();
Chris@127 2085
Chris@127 2086 int sx = p0 + 2;
Chris@127 2087 int ex = sx;
Chris@127 2088 int dx = sx;
Chris@127 2089
Chris@501 2090 bool durationBothEnds = true;
Chris@501 2091
Chris@127 2092 if (sw + ew > (p1 - p0)) {
Chris@127 2093 ey += metrics.height();
Chris@127 2094 dy += metrics.height();
Chris@501 2095 durationBothEnds = false;
Chris@127 2096 }
Chris@127 2097
Chris@127 2098 if (ew < (p1 - p0)) {
Chris@127 2099 ex = p1 - 2 - ew;
Chris@127 2100 }
Chris@127 2101
Chris@127 2102 if (dw < (p1 - p0)) {
Chris@127 2103 dx = p1 - 2 - dw;
Chris@127 2104 }
Chris@127 2105
Chris@1193 2106 PaintAssistant::drawVisibleText(this, paint, sx, sy, startText,
Chris@1193 2107 PaintAssistant::OutlinedText);
Chris@1193 2108 PaintAssistant::drawVisibleText(this, paint, ex, ey, endText,
Chris@1193 2109 PaintAssistant::OutlinedText);
Chris@1193 2110 PaintAssistant::drawVisibleText(this, paint, dx, dy, durationText,
Chris@1193 2111 PaintAssistant::OutlinedText);
Chris@501 2112 if (durationBothEnds) {
Chris@1193 2113 PaintAssistant::drawVisibleText(this, paint, sx, dy, durationText,
Chris@1193 2114 PaintAssistant::OutlinedText);
Chris@501 2115 }
Chris@127 2116 }
Chris@127 2117 }
Chris@127 2118
Chris@127 2119 paint.restore();
Chris@127 2120 }
Chris@127 2121
Chris@267 2122 void
Chris@270 2123 View::drawMeasurementRect(QPainter &paint, const Layer *topLayer, QRect r,
Chris@270 2124 bool focus) const
Chris@267 2125 {
Chris@587 2126 // SVDEBUG << "View::drawMeasurementRect(" << r.x() << "," << r.y() << " "
Chris@585 2127 // << r.width() << "x" << r.height() << ")" << endl;
Chris@268 2128
Chris@267 2129 if (r.x() + r.width() < 0 || r.x() >= width()) return;
Chris@267 2130
Chris@270 2131 if (r.width() != 0 || r.height() != 0) {
Chris@270 2132 paint.save();
Chris@270 2133 if (focus) {
Chris@270 2134 paint.setPen(Qt::NoPen);
Chris@272 2135 QColor brushColour(Qt::black);
Chris@272 2136 brushColour.setAlpha(hasLightBackground() ? 15 : 40);
Chris@270 2137 paint.setBrush(brushColour);
Chris@270 2138 if (r.x() > 0) {
Chris@270 2139 paint.drawRect(0, 0, r.x(), height());
Chris@270 2140 }
Chris@270 2141 if (r.x() + r.width() < width()) {
Chris@270 2142 paint.drawRect(r.x() + r.width(), 0, width()-r.x()-r.width(), height());
Chris@270 2143 }
Chris@270 2144 if (r.y() > 0) {
Chris@270 2145 paint.drawRect(r.x(), 0, r.width(), r.y());
Chris@270 2146 }
Chris@270 2147 if (r.y() + r.height() < height()) {
Chris@270 2148 paint.drawRect(r.x(), r.y() + r.height(), r.width(), height()-r.y()-r.height());
Chris@270 2149 }
Chris@270 2150 paint.setBrush(Qt::NoBrush);
Chris@270 2151 }
Chris@270 2152 paint.setPen(Qt::green);
Chris@270 2153 paint.drawRect(r);
Chris@270 2154 paint.restore();
Chris@270 2155 } else {
Chris@270 2156 paint.save();
Chris@270 2157 paint.setPen(Qt::green);
Chris@270 2158 paint.drawPoint(r.x(), r.y());
Chris@270 2159 paint.restore();
Chris@270 2160 }
Chris@270 2161
Chris@270 2162 if (!focus) return;
Chris@270 2163
Chris@278 2164 paint.save();
Chris@278 2165 QFont fn = paint.font();
Chris@278 2166 if (fn.pointSize() > 8) {
Chris@278 2167 fn.setPointSize(fn.pointSize() - 1);
Chris@278 2168 paint.setFont(fn);
Chris@278 2169 }
Chris@278 2170
Chris@267 2171 int fontHeight = paint.fontMetrics().height();
Chris@267 2172 int fontAscent = paint.fontMetrics().ascent();
Chris@267 2173
Chris@904 2174 double v0, v1;
Chris@267 2175 QString u0, u1;
Chris@267 2176 bool b0 = false, b1 = false;
Chris@267 2177
Chris@267 2178 QString axs, ays, bxs, bys, dxs, dys;
Chris@267 2179
Chris@267 2180 int axx, axy, bxx, bxy, dxx, dxy;
Chris@267 2181 int aw = 0, bw = 0, dw = 0;
Chris@267 2182
Chris@267 2183 int labelCount = 0;
Chris@267 2184
Chris@362 2185 // top-left point, x-coord
Chris@362 2186
Chris@267 2187 if ((b0 = topLayer->getXScaleValue(this, r.x(), v0, u0))) {
Chris@267 2188 axs = QString("%1 %2").arg(v0).arg(u0);
Chris@278 2189 if (u0 == "Hz" && Pitch::isFrequencyInMidiRange(v0)) {
Chris@278 2190 axs = QString("%1 (%2)").arg(axs)
Chris@278 2191 .arg(Pitch::getPitchLabelForFrequency(v0));
Chris@278 2192 }
Chris@267 2193 aw = paint.fontMetrics().width(axs);
Chris@267 2194 ++labelCount;
Chris@267 2195 }
Chris@362 2196
Chris@362 2197 // bottom-right point, x-coord
Chris@267 2198
Chris@267 2199 if (r.width() > 0) {
Chris@267 2200 if ((b1 = topLayer->getXScaleValue(this, r.x() + r.width(), v1, u1))) {
Chris@267 2201 bxs = QString("%1 %2").arg(v1).arg(u1);
Chris@278 2202 if (u1 == "Hz" && Pitch::isFrequencyInMidiRange(v1)) {
Chris@278 2203 bxs = QString("%1 (%2)").arg(bxs)
Chris@278 2204 .arg(Pitch::getPitchLabelForFrequency(v1));
Chris@278 2205 }
Chris@267 2206 bw = paint.fontMetrics().width(bxs);
Chris@267 2207 }
Chris@267 2208 }
Chris@362 2209
Chris@362 2210 // dimension, width
Chris@267 2211
Chris@283 2212 if (b0 && b1 && v1 != v0 && u0 == u1) {
Chris@362 2213 dxs = QString("[%1 %2]").arg(fabs(v1 - v0)).arg(u1);
Chris@267 2214 dw = paint.fontMetrics().width(dxs);
Chris@267 2215 }
Chris@267 2216
Chris@267 2217 b0 = false;
Chris@267 2218 b1 = false;
Chris@267 2219
Chris@362 2220 // top-left point, y-coord
Chris@362 2221
Chris@267 2222 if ((b0 = topLayer->getYScaleValue(this, r.y(), v0, u0))) {
Chris@267 2223 ays = QString("%1 %2").arg(v0).arg(u0);
Chris@278 2224 if (u0 == "Hz" && Pitch::isFrequencyInMidiRange(v0)) {
Chris@278 2225 ays = QString("%1 (%2)").arg(ays)
Chris@278 2226 .arg(Pitch::getPitchLabelForFrequency(v0));
Chris@278 2227 }
Chris@267 2228 aw = std::max(aw, paint.fontMetrics().width(ays));
Chris@267 2229 ++labelCount;
Chris@267 2230 }
Chris@267 2231
Chris@362 2232 // bottom-right point, y-coord
Chris@362 2233
Chris@267 2234 if (r.height() > 0) {
Chris@267 2235 if ((b1 = topLayer->getYScaleValue(this, r.y() + r.height(), v1, u1))) {
Chris@267 2236 bys = QString("%1 %2").arg(v1).arg(u1);
Chris@278 2237 if (u1 == "Hz" && Pitch::isFrequencyInMidiRange(v1)) {
Chris@278 2238 bys = QString("%1 (%2)").arg(bys)
Chris@278 2239 .arg(Pitch::getPitchLabelForFrequency(v1));
Chris@278 2240 }
Chris@267 2241 bw = std::max(bw, paint.fontMetrics().width(bys));
Chris@267 2242 }
Chris@267 2243 }
Chris@274 2244
Chris@274 2245 bool bd = false;
Chris@904 2246 double dy = 0.f;
Chris@274 2247 QString du;
Chris@274 2248
Chris@362 2249 // dimension, height
Chris@362 2250
Chris@274 2251 if ((bd = topLayer->getYScaleDifference(this, r.y(), r.y() + r.height(),
Chris@283 2252 dy, du)) &&
Chris@283 2253 dy != 0) {
Chris@274 2254 if (du != "") {
Chris@362 2255 if (du == "Hz") {
Chris@362 2256 int semis;
Chris@904 2257 double cents;
Chris@362 2258 semis = Pitch::getPitchForFrequencyDifference(v0, v1, &cents);
Chris@362 2259 dys = QString("[%1 %2 (%3)]")
Chris@362 2260 .arg(dy).arg(du)
Chris@362 2261 .arg(Pitch::getLabelForPitchRange(semis, cents));
Chris@362 2262 } else {
Chris@362 2263 dys = QString("[%1 %2]").arg(dy).arg(du);
Chris@362 2264 }
Chris@274 2265 } else {
Chris@362 2266 dys = QString("[%1]").arg(dy);
Chris@274 2267 }
Chris@267 2268 dw = std::max(dw, paint.fontMetrics().width(dys));
Chris@267 2269 }
Chris@267 2270
Chris@267 2271 int mw = r.width();
Chris@267 2272 int mh = r.height();
Chris@267 2273
Chris@267 2274 bool edgeLabelsInside = false;
Chris@267 2275 bool sizeLabelsInside = false;
Chris@267 2276
Chris@267 2277 if (mw < std::max(aw, std::max(bw, dw)) + 4) {
Chris@267 2278 // defaults stand
Chris@267 2279 } else if (mw < aw + bw + 4) {
Chris@267 2280 if (mh > fontHeight * labelCount * 3 + 4) {
Chris@267 2281 edgeLabelsInside = true;
Chris@267 2282 sizeLabelsInside = true;
Chris@267 2283 } else if (mh > fontHeight * labelCount * 2 + 4) {
Chris@267 2284 edgeLabelsInside = true;
Chris@267 2285 }
Chris@267 2286 } else if (mw < aw + bw + dw + 4) {
Chris@267 2287 if (mh > fontHeight * labelCount * 3 + 4) {
Chris@267 2288 edgeLabelsInside = true;
Chris@267 2289 sizeLabelsInside = true;
Chris@267 2290 } else if (mh > fontHeight * labelCount + 4) {
Chris@267 2291 edgeLabelsInside = true;
Chris@267 2292 }
Chris@267 2293 } else {
Chris@267 2294 if (mh > fontHeight * labelCount + 4) {
Chris@267 2295 edgeLabelsInside = true;
Chris@267 2296 sizeLabelsInside = true;
Chris@267 2297 }
Chris@267 2298 }
Chris@267 2299
Chris@267 2300 if (edgeLabelsInside) {
Chris@267 2301
Chris@267 2302 axx = r.x() + 2;
Chris@267 2303 axy = r.y() + fontAscent + 2;
Chris@267 2304
Chris@267 2305 bxx = r.x() + r.width() - bw - 2;
Chris@267 2306 bxy = r.y() + r.height() - (labelCount-1) * fontHeight - 2;
Chris@267 2307
Chris@267 2308 } else {
Chris@267 2309
Chris@267 2310 axx = r.x() - aw - 2;
Chris@267 2311 axy = r.y() + fontAscent;
Chris@267 2312
Chris@267 2313 bxx = r.x() + r.width() + 2;
Chris@267 2314 bxy = r.y() + r.height() - (labelCount-1) * fontHeight;
Chris@267 2315 }
Chris@267 2316
Chris@267 2317 dxx = r.width()/2 + r.x() - dw/2;
Chris@267 2318
Chris@267 2319 if (sizeLabelsInside) {
Chris@267 2320
Chris@267 2321 dxy = r.height()/2 + r.y() - (labelCount * fontHeight)/2 + fontAscent;
Chris@267 2322
Chris@267 2323 } else {
Chris@267 2324
Chris@267 2325 dxy = r.y() + r.height() + fontAscent + 2;
Chris@267 2326 }
Chris@267 2327
Chris@267 2328 if (axs != "") {
Chris@1078 2329 PaintAssistant::drawVisibleText(this, paint, axx, axy, axs, PaintAssistant::OutlinedText);
Chris@267 2330 axy += fontHeight;
Chris@267 2331 }
Chris@267 2332
Chris@267 2333 if (ays != "") {
Chris@1078 2334 PaintAssistant::drawVisibleText(this, paint, axx, axy, ays, PaintAssistant::OutlinedText);
Chris@267 2335 axy += fontHeight;
Chris@267 2336 }
Chris@267 2337
Chris@267 2338 if (bxs != "") {
Chris@1078 2339 PaintAssistant::drawVisibleText(this, paint, bxx, bxy, bxs, PaintAssistant::OutlinedText);
Chris@267 2340 bxy += fontHeight;
Chris@267 2341 }
Chris@267 2342
Chris@267 2343 if (bys != "") {
Chris@1078 2344 PaintAssistant::drawVisibleText(this, paint, bxx, bxy, bys, PaintAssistant::OutlinedText);
Chris@267 2345 bxy += fontHeight;
Chris@267 2346 }
Chris@267 2347
Chris@267 2348 if (dxs != "") {
Chris@1078 2349 PaintAssistant::drawVisibleText(this, paint, dxx, dxy, dxs, PaintAssistant::OutlinedText);
Chris@267 2350 dxy += fontHeight;
Chris@267 2351 }
Chris@267 2352
Chris@267 2353 if (dys != "") {
Chris@1078 2354 PaintAssistant::drawVisibleText(this, paint, dxx, dxy, dys, PaintAssistant::OutlinedText);
Chris@267 2355 dxy += fontHeight;
Chris@267 2356 }
Chris@278 2357
Chris@278 2358 paint.restore();
Chris@267 2359 }
Chris@267 2360
Chris@227 2361 bool
Chris@908 2362 View::render(QPainter &paint, int xorigin, sv_frame_t f0, sv_frame_t f1)
Chris@227 2363 {
Chris@908 2364 int x0 = int(f0 / m_zoomLevel);
Chris@908 2365 int x1 = int(f1 / m_zoomLevel);
Chris@806 2366
Chris@806 2367 int w = x1 - x0;
Chris@806 2368
Chris@908 2369 sv_frame_t origCentreFrame = m_centreFrame;
Chris@227 2370
Chris@227 2371 bool someLayersIncomplete = false;
Chris@227 2372
Chris@835 2373 for (LayerList::iterator i = m_layerStack.begin();
Chris@835 2374 i != m_layerStack.end(); ++i) {
Chris@227 2375
Chris@227 2376 int c = (*i)->getCompletion(this);
Chris@227 2377 if (c < 100) {
Chris@227 2378 someLayersIncomplete = true;
Chris@227 2379 break;
Chris@227 2380 }
Chris@227 2381 }
Chris@227 2382
Chris@227 2383 if (someLayersIncomplete) {
Chris@227 2384
Chris@227 2385 QProgressDialog progress(tr("Waiting for layers to be ready..."),
Chris@227 2386 tr("Cancel"), 0, 100, this);
Chris@227 2387
Chris@227 2388 int layerCompletion = 0;
Chris@227 2389
Chris@227 2390 while (layerCompletion < 100) {
Chris@227 2391
Chris@835 2392 for (LayerList::iterator i = m_layerStack.begin();
Chris@835 2393 i != m_layerStack.end(); ++i) {
Chris@227 2394
Chris@227 2395 int c = (*i)->getCompletion(this);
Chris@835 2396 if (i == m_layerStack.begin() || c < layerCompletion) {
Chris@227 2397 layerCompletion = c;
Chris@227 2398 }
Chris@227 2399 }
Chris@227 2400
Chris@227 2401 if (layerCompletion >= 100) break;
Chris@227 2402
Chris@227 2403 progress.setValue(layerCompletion);
Chris@227 2404 qApp->processEvents();
Chris@227 2405 if (progress.wasCanceled()) {
Chris@227 2406 update();
Chris@227 2407 return false;
Chris@227 2408 }
Chris@227 2409
Chris@227 2410 usleep(50000);
Chris@227 2411 }
Chris@227 2412 }
Chris@227 2413
Chris@227 2414 QProgressDialog progress(tr("Rendering image..."),
Chris@227 2415 tr("Cancel"), 0, w / width(), this);
Chris@227 2416
Chris@806 2417 for (int x = 0; x < w; x += width()) {
Chris@227 2418
Chris@227 2419 progress.setValue(x / width());
Chris@227 2420 qApp->processEvents();
Chris@227 2421 if (progress.wasCanceled()) {
Chris@227 2422 m_centreFrame = origCentreFrame;
Chris@227 2423 update();
Chris@227 2424 return false;
Chris@227 2425 }
Chris@227 2426
Chris@229 2427 m_centreFrame = f0 + (x + width()/2) * m_zoomLevel;
Chris@227 2428
Chris@227 2429 QRect chunk(0, 0, width(), height());
Chris@227 2430
Chris@287 2431 paint.setPen(getBackground());
Chris@287 2432 paint.setBrush(getBackground());
Chris@227 2433
Chris@229 2434 paint.drawRect(QRect(xorigin + x, 0, width(), height()));
Chris@227 2435
Chris@287 2436 paint.setPen(getForeground());
Chris@227 2437 paint.setBrush(Qt::NoBrush);
Chris@227 2438
Chris@835 2439 for (LayerList::iterator i = m_layerStack.begin();
Chris@835 2440 i != m_layerStack.end(); ++i) {
Chris@919 2441 if (!((*i)->isLayerDormant(this))){
Chris@919 2442
Chris@919 2443 paint.setRenderHint(QPainter::Antialiasing, false);
Chris@919 2444
Chris@919 2445 paint.save();
Chris@919 2446 paint.translate(xorigin + x, 0);
Chris@919 2447
Chris@919 2448 cerr << "Centre frame now: " << m_centreFrame << " drawing to " << chunk.x() + x + xorigin << ", " << chunk.width() << endl;
Chris@919 2449
Chris@919 2450 (*i)->setSynchronousPainting(true);
Chris@919 2451
Chris@919 2452 (*i)->paint(this, paint, chunk);
Chris@919 2453
Chris@919 2454 (*i)->setSynchronousPainting(false);
Chris@919 2455
Chris@919 2456 paint.restore();
Chris@919 2457 }
Chris@227 2458 }
Chris@227 2459 }
Chris@227 2460
Chris@227 2461 m_centreFrame = origCentreFrame;
Chris@227 2462 update();
Chris@227 2463 return true;
Chris@227 2464 }
Chris@227 2465
Chris@227 2466 QImage *
Chris@1202 2467 View::renderToNewImage()
Chris@227 2468 {
Chris@908 2469 sv_frame_t f0 = getModelsStartFrame();
Chris@908 2470 sv_frame_t f1 = getModelsEndFrame();
Chris@227 2471
Chris@1202 2472 return renderPartToNewImage(f0, f1);
Chris@229 2473 }
Chris@229 2474
Chris@229 2475 QImage *
Chris@1202 2476 View::renderPartToNewImage(sv_frame_t f0, sv_frame_t f1)
Chris@229 2477 {
Chris@908 2478 int x0 = int(f0 / getZoomLevel());
Chris@908 2479 int x1 = int(f1 / getZoomLevel());
Chris@227 2480
Chris@227 2481 QImage *image = new QImage(x1 - x0, height(), QImage::Format_RGB32);
Chris@227 2482
Chris@227 2483 QPainter *paint = new QPainter(image);
Chris@229 2484 if (!render(*paint, 0, f0, f1)) {
Chris@227 2485 delete paint;
Chris@227 2486 delete image;
Chris@227 2487 return 0;
Chris@227 2488 } else {
Chris@227 2489 delete paint;
Chris@227 2490 return image;
Chris@227 2491 }
Chris@227 2492 }
Chris@227 2493
Chris@229 2494 QSize
Chris@1202 2495 View::getRenderedImageSize()
Chris@229 2496 {
Chris@908 2497 sv_frame_t f0 = getModelsStartFrame();
Chris@908 2498 sv_frame_t f1 = getModelsEndFrame();
Chris@229 2499
Chris@1202 2500 return getRenderedPartImageSize(f0, f1);
Chris@229 2501 }
Chris@229 2502
Chris@229 2503 QSize
Chris@1202 2504 View::getRenderedPartImageSize(sv_frame_t f0, sv_frame_t f1)
Chris@229 2505 {
Chris@908 2506 int x0 = int(f0 / getZoomLevel());
Chris@908 2507 int x1 = int(f1 / getZoomLevel());
Chris@229 2508
Chris@229 2509 return QSize(x1 - x0, height());
Chris@229 2510 }
Chris@229 2511
Chris@1202 2512 bool
Chris@1202 2513 View::renderToSvgFile(QString filename)
Chris@1202 2514 {
Chris@1202 2515 sv_frame_t f0 = getModelsStartFrame();
Chris@1202 2516 sv_frame_t f1 = getModelsEndFrame();
Chris@1202 2517
Chris@1202 2518 return renderPartToSvgFile(filename, f0, f1);
Chris@1202 2519 }
Chris@1202 2520
Chris@1202 2521 bool
Chris@1202 2522 View::renderPartToSvgFile(QString filename, sv_frame_t f0, sv_frame_t f1)
Chris@1202 2523 {
Chris@1202 2524 int x0 = int(f0 / getZoomLevel());
Chris@1202 2525 int x1 = int(f1 / getZoomLevel());
Chris@1202 2526
Chris@1202 2527 QSvgGenerator generator;
Chris@1202 2528 generator.setFileName(filename);
Chris@1202 2529 generator.setSize(QSize(x1 - x0, height()));
Chris@1202 2530 generator.setViewBox(QRect(0, 0, x1 - x0, height()));
Chris@1202 2531 generator.setTitle(tr("Exported image from %1")
Chris@1202 2532 .arg(QApplication::applicationName()));
Chris@1202 2533
Chris@1202 2534 QPainter paint;
Chris@1202 2535 paint.begin(&generator);
Chris@1202 2536 bool result = render(paint, 0, f0, f1);
Chris@1202 2537 paint.end();
Chris@1202 2538 return result;
Chris@1202 2539 }
Chris@1202 2540
Chris@316 2541 void
Chris@316 2542 View::toXml(QTextStream &stream,
Chris@316 2543 QString indent, QString extraAttributes) const
Chris@127 2544 {
Chris@316 2545 stream << indent;
Chris@127 2546
Chris@316 2547 stream << QString("<view "
Chris@316 2548 "centre=\"%1\" "
Chris@316 2549 "zoom=\"%2\" "
Chris@316 2550 "followPan=\"%3\" "
Chris@316 2551 "followZoom=\"%4\" "
Chris@316 2552 "tracking=\"%5\" "
Chris@316 2553 " %6>\n")
Chris@127 2554 .arg(m_centreFrame)
Chris@127 2555 .arg(m_zoomLevel)
Chris@127 2556 .arg(m_followPan)
Chris@127 2557 .arg(m_followZoom)
Chris@127 2558 .arg(m_followPlay == PlaybackScrollContinuous ? "scroll" :
Chris@815 2559 m_followPlay == PlaybackScrollPageWithCentre ? "page" :
Chris@815 2560 m_followPlay == PlaybackScrollPage ? "daw" :
Chris@815 2561 "ignore")
Chris@127 2562 .arg(extraAttributes);
Chris@127 2563
Chris@838 2564 for (int i = 0; i < (int)m_fixedOrderLayers.size(); ++i) {
Chris@838 2565 bool visible = !m_fixedOrderLayers[i]->isLayerDormant(this);
Chris@838 2566 m_fixedOrderLayers[i]->toBriefXml(stream, indent + " ",
Chris@838 2567 QString("visible=\"%1\"")
Chris@838 2568 .arg(visible ? "true" : "false"));
Chris@127 2569 }
Chris@127 2570
Chris@316 2571 stream << indent + "</view>\n";
Chris@127 2572 }
Chris@127 2573
Chris@127 2574 ViewPropertyContainer::ViewPropertyContainer(View *v) :
Chris@127 2575 m_v(v)
Chris@127 2576 {
Chris@728 2577 // cerr << "ViewPropertyContainer: " << this << " is owned by View " << v << endl;
Chris@127 2578 connect(m_v, SIGNAL(propertyChanged(PropertyContainer::PropertyName)),
Chris@127 2579 this, SIGNAL(propertyChanged(PropertyContainer::PropertyName)));
Chris@127 2580 }
Chris@127 2581
Chris@728 2582 ViewPropertyContainer::~ViewPropertyContainer()
Chris@728 2583 {
Chris@728 2584 }