annotate view/View.cpp @ 282:d9319859a4cf tip

(none)
author benoitrigolleau
date Fri, 31 Oct 2008 11:00:24 +0000
parents 57c85a9d9b4a
children
rev   line source
lbajardsilogic@0 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
lbajardsilogic@0 2
lbajardsilogic@0 3 /*
lbajardsilogic@0 4 Sonic Visualiser
lbajardsilogic@0 5 An audio file viewer and annotation editor.
lbajardsilogic@0 6 Centre for Digital Music, Queen Mary, University of London.
lbajardsilogic@0 7 This file copyright 2006 Chris Cannam.
lbajardsilogic@0 8
lbajardsilogic@0 9 This program is free software; you can redistribute it and/or
lbajardsilogic@0 10 modify it under the terms of the GNU General Public License as
lbajardsilogic@0 11 published by the Free Software Foundation; either version 2 of the
lbajardsilogic@0 12 License, or (at your option) any later version. See the file
lbajardsilogic@0 13 COPYING included with this distribution for more information.
lbajardsilogic@0 14 */
lbajardsilogic@0 15
lbajardsilogic@0 16 #include "View.h"
lbajardsilogic@0 17 #include "layer/Layer.h"
lbajardsilogic@0 18 #include "data/model/Model.h"
lbajardsilogic@0 19 #include "base/ZoomConstraint.h"
lbajardsilogic@0 20 #include "base/Profiler.h"
lbajardsilogic@0 21
lbajardsilogic@0 22 #include "layer/TimeRulerLayer.h" //!!! damn, shouldn't be including that here
lbajardsilogic@0 23 #include "data/model/PowerOfSqrtTwoZoomConstraint.h" //!!! likewise
lbajardsilogic@0 24
lbajardsilogic@0 25 #include <QPainter>
lbajardsilogic@0 26 #include <QPaintEvent>
lbajardsilogic@0 27 #include <QRect>
lbajardsilogic@0 28 #include <QApplication>
lbajardsilogic@0 29 #include <QProgressDialog>
lbajardsilogic@0 30
lbajardsilogic@0 31 #include <iostream>
lbajardsilogic@0 32 #include <cassert>
lbajardsilogic@0 33 #include <math.h>
lbajardsilogic@0 34
lbajardsilogic@0 35 //#define DEBUG_VIEW_WIDGET_PAINT 1
lbajardsilogic@0 36
lbajardsilogic@0 37 using std::cerr;
lbajardsilogic@0 38 using std::endl;
lbajardsilogic@0 39
lbajardsilogic@0 40 View::View(QWidget *w, bool showProgress) :
lbajardsilogic@0 41 QFrame(w),
lbajardsilogic@0 42 m_centreFrame(0),
lbajardsilogic@0 43 m_zoomLevel(1024),
lbajardsilogic@0 44 m_followPan(true),
lbajardsilogic@0 45 m_followZoom(true),
lbajardsilogic@0 46 m_followPlay(PlaybackScrollPage),
lbajardsilogic@0 47 m_playPointerFrame(0),
lbajardsilogic@0 48 m_showProgress(showProgress),
lbajardsilogic@0 49 m_cache(0),
lbajardsilogic@0 50 m_cacheCentreFrame(0),
lbajardsilogic@0 51 m_cacheZoomLevel(1024),
lbajardsilogic@0 52 m_selectionCached(false),
lbajardsilogic@0 53 m_deleting(false),
lbajardsilogic@0 54 m_haveSelectedLayer(false),
lbajardsilogic@0 55 m_manager(0),
lbajardsilogic@0 56 m_propertyContainer(new ViewPropertyContainer(this))
lbajardsilogic@0 57 {
lbajardsilogic@0 58 }
lbajardsilogic@0 59
lbajardsilogic@0 60 View::~View()
lbajardsilogic@0 61 {
lbajardsilogic@0 62 // std::cerr << "View::~View(" << this << ")" << std::endl;
lbajardsilogic@0 63
lbajardsilogic@0 64 m_deleting = true;
lbajardsilogic@0 65 delete m_propertyContainer;
lbajardsilogic@0 66 }
lbajardsilogic@0 67
lbajardsilogic@0 68 PropertyContainer::PropertyList
lbajardsilogic@0 69 View::getProperties() const
lbajardsilogic@0 70 {
lbajardsilogic@0 71 PropertyContainer::PropertyList list;
lbajardsilogic@0 72 list.push_back("Global Scroll");
lbajardsilogic@0 73 list.push_back("Global Zoom");
lbajardsilogic@0 74 list.push_back("Follow Playback");
lbajardsilogic@0 75 return list;
lbajardsilogic@0 76 }
lbajardsilogic@0 77
lbajardsilogic@0 78 QString
lbajardsilogic@0 79 View::getPropertyLabel(const PropertyName &pn) const
lbajardsilogic@0 80 {
lbajardsilogic@0 81 if (pn == "Global Scroll") return tr("Global Scroll");
lbajardsilogic@0 82 if (pn == "Global Zoom") return tr("Global Zoom");
lbajardsilogic@0 83 if (pn == "Follow Playback") return tr("Follow Playback");
lbajardsilogic@0 84 return "";
lbajardsilogic@0 85 }
lbajardsilogic@0 86
lbajardsilogic@0 87 PropertyContainer::PropertyType
lbajardsilogic@0 88 View::getPropertyType(const PropertyContainer::PropertyName &name) const
lbajardsilogic@0 89 {
lbajardsilogic@0 90 if (name == "Global Scroll") return PropertyContainer::ToggleProperty;
lbajardsilogic@0 91 if (name == "Global Zoom") return PropertyContainer::ToggleProperty;
lbajardsilogic@0 92 if (name == "Follow Playback") return PropertyContainer::ValueProperty;
lbajardsilogic@0 93 return PropertyContainer::InvalidProperty;
lbajardsilogic@0 94 }
lbajardsilogic@0 95
lbajardsilogic@0 96 int
lbajardsilogic@0 97 View::getPropertyRangeAndValue(const PropertyContainer::PropertyName &name,
lbajardsilogic@0 98 int *min, int *max, int *deflt) const
lbajardsilogic@0 99 {
lbajardsilogic@0 100 if (deflt) *deflt = 1;
lbajardsilogic@0 101 if (name == "Global Scroll") return m_followPan;
lbajardsilogic@0 102 if (name == "Global Zoom") return m_followZoom;
lbajardsilogic@0 103 if (name == "Follow Playback") {
lbajardsilogic@0 104 if (min) *min = 0;
lbajardsilogic@0 105 if (max) *max = 2;
lbajardsilogic@0 106 if (deflt) *deflt = int(PlaybackScrollPage);
lbajardsilogic@0 107 return int(m_followPlay);
lbajardsilogic@0 108 }
lbajardsilogic@0 109 if (min) *min = 0;
lbajardsilogic@0 110 if (max) *max = 0;
lbajardsilogic@0 111 if (deflt) *deflt = 0;
lbajardsilogic@0 112 return 0;
lbajardsilogic@0 113 }
lbajardsilogic@0 114
lbajardsilogic@0 115 QString
lbajardsilogic@0 116 View::getPropertyValueLabel(const PropertyContainer::PropertyName &name,
lbajardsilogic@0 117 int value) const
lbajardsilogic@0 118 {
lbajardsilogic@0 119 if (name == "Follow Playback") {
lbajardsilogic@0 120 switch (value) {
lbajardsilogic@0 121 default:
lbajardsilogic@0 122 case 0: return tr("Scroll");
lbajardsilogic@0 123 case 1: return tr("Page");
lbajardsilogic@0 124 case 2: return tr("Off");
lbajardsilogic@0 125 }
lbajardsilogic@0 126 }
lbajardsilogic@0 127 return tr("<unknown>");
lbajardsilogic@0 128 }
lbajardsilogic@0 129
lbajardsilogic@0 130 void
lbajardsilogic@0 131 View::setProperty(const PropertyContainer::PropertyName &name, int value)
lbajardsilogic@0 132 {
lbajardsilogic@0 133 if (name == "Global Scroll") {
lbajardsilogic@0 134 setFollowGlobalPan(value != 0);
lbajardsilogic@0 135 } else if (name == "Global Zoom") {
lbajardsilogic@0 136 setFollowGlobalZoom(value != 0);
lbajardsilogic@0 137 } else if (name == "Follow Playback") {
lbajardsilogic@0 138 switch (value) {
lbajardsilogic@0 139 default:
lbajardsilogic@0 140 case 0: setPlaybackFollow(PlaybackScrollContinuous); break;
lbajardsilogic@0 141 case 1: setPlaybackFollow(PlaybackScrollPage); break;
lbajardsilogic@0 142 case 2: setPlaybackFollow(PlaybackIgnore); break;
lbajardsilogic@0 143 }
lbajardsilogic@0 144 }
lbajardsilogic@0 145 }
lbajardsilogic@0 146
lbajardsilogic@0 147 size_t
lbajardsilogic@0 148 View::getPropertyContainerCount() const
lbajardsilogic@0 149 {
lbajardsilogic@0 150 return m_layers.size() + 1; // the 1 is for me
lbajardsilogic@0 151 }
lbajardsilogic@0 152
lbajardsilogic@0 153 const PropertyContainer *
lbajardsilogic@0 154 View::getPropertyContainer(size_t i) const
lbajardsilogic@0 155 {
lbajardsilogic@0 156 return (const PropertyContainer *)(((View *)this)->
lbajardsilogic@0 157 getPropertyContainer(i));
lbajardsilogic@0 158 }
lbajardsilogic@0 159
lbajardsilogic@0 160 PropertyContainer *
lbajardsilogic@0 161 View::getPropertyContainer(size_t i)
lbajardsilogic@0 162 {
lbajardsilogic@0 163 if (i == 0) return m_propertyContainer;
lbajardsilogic@0 164 return m_layers[i-1];
lbajardsilogic@0 165 }
lbajardsilogic@0 166
lbajardsilogic@0 167 bool
lbajardsilogic@0 168 View::getValueExtents(QString unit, float &min, float &max, bool &log) const
lbajardsilogic@0 169 {
lbajardsilogic@0 170 bool have = false;
lbajardsilogic@0 171
lbajardsilogic@0 172 for (LayerList::const_iterator i = m_layers.begin();
lbajardsilogic@0 173 i != m_layers.end(); ++i) {
lbajardsilogic@0 174
lbajardsilogic@0 175 QString layerUnit;
lbajardsilogic@0 176 float layerMin = 0.0, layerMax = 0.0;
lbajardsilogic@0 177 float displayMin = 0.0, displayMax = 0.0;
lbajardsilogic@0 178 bool layerLog = false;
lbajardsilogic@0 179
lbajardsilogic@0 180 if ((*i)->getValueExtents(layerMin, layerMax, layerLog, layerUnit) &&
lbajardsilogic@0 181 layerUnit.toLower() == unit.toLower()) {
lbajardsilogic@0 182
lbajardsilogic@0 183 if ((*i)->getDisplayExtents(displayMin, displayMax)) {
lbajardsilogic@0 184
lbajardsilogic@0 185 min = displayMin;
lbajardsilogic@0 186 max = displayMax;
lbajardsilogic@0 187 log = layerLog;
lbajardsilogic@0 188 have = true;
lbajardsilogic@0 189 break;
lbajardsilogic@0 190
lbajardsilogic@0 191 } else {
lbajardsilogic@0 192
lbajardsilogic@0 193 if (!have || layerMin < min) min = layerMin;
lbajardsilogic@0 194 if (!have || layerMax > max) max = layerMax;
lbajardsilogic@0 195 if (layerLog) log = true;
lbajardsilogic@0 196 have = true;
lbajardsilogic@0 197 }
lbajardsilogic@0 198 }
lbajardsilogic@0 199 }
lbajardsilogic@0 200
lbajardsilogic@0 201 return have;
lbajardsilogic@0 202 }
lbajardsilogic@0 203
lbajardsilogic@0 204 int
lbajardsilogic@0 205 View::getTextLabelHeight(const Layer *layer, QPainter &paint) const
lbajardsilogic@0 206 {
lbajardsilogic@0 207 std::map<int, Layer *> sortedLayers;
lbajardsilogic@0 208
lbajardsilogic@0 209 for (LayerList::const_iterator i = m_layers.begin();
lbajardsilogic@0 210 i != m_layers.end(); ++i) {
lbajardsilogic@0 211 if ((*i)->needsTextLabelHeight()) {
lbajardsilogic@0 212 sortedLayers[getObjectExportId(*i)] = *i;
lbajardsilogic@0 213 }
lbajardsilogic@0 214 }
lbajardsilogic@0 215
lbajardsilogic@0 216 int y = 15 + paint.fontMetrics().ascent();
lbajardsilogic@0 217
lbajardsilogic@0 218 for (std::map<int, Layer *>::const_iterator i = sortedLayers.begin();
lbajardsilogic@0 219 i != sortedLayers.end(); ++i) {
lbajardsilogic@0 220 if (i->second == layer) return y;
lbajardsilogic@0 221 y += paint.fontMetrics().height();
lbajardsilogic@0 222 }
lbajardsilogic@0 223
lbajardsilogic@0 224 return y;
lbajardsilogic@0 225 }
lbajardsilogic@0 226
lbajardsilogic@0 227 void
lbajardsilogic@0 228 View::propertyContainerSelected(View *client, PropertyContainer *pc)
lbajardsilogic@0 229 {
lbajardsilogic@0 230 if (client != this) return;
lbajardsilogic@0 231
lbajardsilogic@0 232 if (pc == m_propertyContainer) {
lbajardsilogic@0 233 if (m_haveSelectedLayer) {
lbajardsilogic@0 234 m_haveSelectedLayer = false;
lbajardsilogic@0 235 update();
lbajardsilogic@0 236 }
lbajardsilogic@0 237 return;
lbajardsilogic@0 238 }
lbajardsilogic@0 239
lbajardsilogic@0 240 delete m_cache;
lbajardsilogic@0 241 m_cache = 0;
lbajardsilogic@0 242
lbajardsilogic@0 243 Layer *selectedLayer = 0;
lbajardsilogic@0 244
lbajardsilogic@0 245 for (LayerList::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
lbajardsilogic@0 246 if (*i == pc) {
lbajardsilogic@0 247 selectedLayer = *i;
lbajardsilogic@0 248 m_layers.erase(i);
lbajardsilogic@0 249 break;
lbajardsilogic@0 250 }
lbajardsilogic@0 251 }
lbajardsilogic@0 252
lbajardsilogic@0 253 if (selectedLayer) {
lbajardsilogic@0 254 m_haveSelectedLayer = true;
lbajardsilogic@0 255 m_layers.push_back(selectedLayer);
lbajardsilogic@0 256 update();
lbajardsilogic@0 257 } else {
lbajardsilogic@0 258 m_haveSelectedLayer = false;
lbajardsilogic@0 259 }
lbajardsilogic@0 260 }
lbajardsilogic@0 261
lbajardsilogic@0 262 void
lbajardsilogic@0 263 View::toolModeChanged()
lbajardsilogic@0 264 {
lbajardsilogic@0 265 // std::cerr << "View::toolModeChanged(" << m_manager->getToolMode() << ")" << std::endl;
lbajardsilogic@0 266 }
lbajardsilogic@0 267
lbajardsilogic@0 268 void
lbajardsilogic@0 269 View::overlayModeChanged()
lbajardsilogic@0 270 {
lbajardsilogic@0 271 delete m_cache;
lbajardsilogic@0 272 m_cache = 0;
lbajardsilogic@0 273 update();
lbajardsilogic@0 274 }
lbajardsilogic@0 275
lbajardsilogic@0 276 void
lbajardsilogic@0 277 View::zoomWheelsEnabledChanged()
lbajardsilogic@0 278 {
lbajardsilogic@0 279 // subclass might override this
lbajardsilogic@0 280 }
lbajardsilogic@0 281
lbajardsilogic@0 282 long
lbajardsilogic@0 283 View::getStartFrame() const
lbajardsilogic@0 284 {
lbajardsilogic@0 285 size_t w2 = (width() / 2) * m_zoomLevel;
lbajardsilogic@0 286 size_t frame = m_centreFrame;
lbajardsilogic@0 287 if (frame >= w2) {
lbajardsilogic@0 288 frame -= w2;
lbajardsilogic@0 289 return (frame / m_zoomLevel * m_zoomLevel);
lbajardsilogic@0 290 } else {
lbajardsilogic@0 291 frame = w2 - frame;
lbajardsilogic@0 292 frame = frame / m_zoomLevel * m_zoomLevel;
lbajardsilogic@0 293 return -(long)frame - m_zoomLevel;
lbajardsilogic@0 294 }
lbajardsilogic@0 295 }
lbajardsilogic@0 296
lbajardsilogic@0 297 size_t
lbajardsilogic@0 298 View::getEndFrame() const
lbajardsilogic@0 299 {
lbajardsilogic@0 300 return getFrameForX(width()) - 1;
lbajardsilogic@0 301 }
lbajardsilogic@0 302
lbajardsilogic@0 303 void
lbajardsilogic@0 304 View::setStartFrame(long f)
lbajardsilogic@0 305 {
lbajardsilogic@0 306 setCentreFrame(f + m_zoomLevel * (width() / 2));
lbajardsilogic@0 307 }
lbajardsilogic@0 308
lbajardsilogic@0 309 bool
lbajardsilogic@0 310 View::setCentreFrame(size_t f, bool e)
lbajardsilogic@0 311 {
lbajardsilogic@0 312 bool changeVisible = false;
lbajardsilogic@0 313
lbajardsilogic@0 314 if (m_centreFrame != f) {
lbajardsilogic@0 315
lbajardsilogic@0 316 int formerPixel = m_centreFrame / m_zoomLevel;
lbajardsilogic@0 317
lbajardsilogic@0 318 m_centreFrame = f;
lbajardsilogic@0 319
lbajardsilogic@0 320 int newPixel = m_centreFrame / m_zoomLevel;
lbajardsilogic@0 321
lbajardsilogic@0 322 if (newPixel != formerPixel) {
lbajardsilogic@0 323
lbajardsilogic@0 324 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 325 std::cout << "View(" << this << ")::setCentreFrame: newPixel " << newPixel << ", formerPixel " << formerPixel << std::endl;
lbajardsilogic@0 326 #endif
lbajardsilogic@0 327 update();
lbajardsilogic@0 328
lbajardsilogic@0 329 changeVisible = true;
lbajardsilogic@0 330 }
lbajardsilogic@0 331
lbajardsilogic@0 332 if (e) emit centreFrameChanged(f, m_followPan, m_followPlay);
lbajardsilogic@0 333 }
lbajardsilogic@0 334
lbajardsilogic@0 335 return changeVisible;
lbajardsilogic@0 336 }
lbajardsilogic@0 337
lbajardsilogic@0 338 int
lbajardsilogic@0 339 View::getXForFrame(long frame) const
lbajardsilogic@0 340 {
lbajardsilogic@0 341 return (frame - getStartFrame()) / m_zoomLevel;
lbajardsilogic@0 342 }
lbajardsilogic@0 343
lbajardsilogic@0 344 long
lbajardsilogic@0 345 View::getFrameForX(int x) const
lbajardsilogic@0 346 {
lbajardsilogic@0 347 return (long(x) * long(m_zoomLevel)) + getStartFrame();
lbajardsilogic@0 348 }
lbajardsilogic@0 349
lbajardsilogic@0 350 float
lbajardsilogic@0 351 View::getYForFrequency(float frequency,
lbajardsilogic@0 352 float minf,
lbajardsilogic@0 353 float maxf,
lbajardsilogic@0 354 bool logarithmic) const
lbajardsilogic@0 355 {
lbajardsilogic@0 356 int h = height();
lbajardsilogic@0 357
lbajardsilogic@0 358 if (logarithmic) {
lbajardsilogic@0 359
lbajardsilogic@0 360 static float lastminf = 0.0, lastmaxf = 0.0;
lbajardsilogic@0 361 static float logminf = 0.0, logmaxf = 0.0;
lbajardsilogic@0 362
lbajardsilogic@0 363 if (lastminf != minf) {
lbajardsilogic@0 364 lastminf = (minf == 0.0 ? 1.0 : minf);
lbajardsilogic@0 365 logminf = log10f(minf);
lbajardsilogic@0 366 }
lbajardsilogic@0 367 if (lastmaxf != maxf) {
lbajardsilogic@0 368 lastmaxf = (maxf < lastminf ? lastminf : maxf);
lbajardsilogic@0 369 logmaxf = log10f(maxf);
lbajardsilogic@0 370 }
lbajardsilogic@0 371
lbajardsilogic@0 372 if (logminf == logmaxf) return 0;
lbajardsilogic@0 373 return h - (h * (log10f(frequency) - logminf)) / (logmaxf - logminf);
lbajardsilogic@0 374
lbajardsilogic@0 375 } else {
lbajardsilogic@0 376
lbajardsilogic@0 377 if (minf == maxf) return 0;
lbajardsilogic@0 378 return h - (h * (frequency - minf)) / (maxf - minf);
lbajardsilogic@0 379 }
lbajardsilogic@0 380 }
lbajardsilogic@0 381
lbajardsilogic@0 382 float
lbajardsilogic@0 383 View::getFrequencyForY(int y,
lbajardsilogic@0 384 float minf,
lbajardsilogic@0 385 float maxf,
lbajardsilogic@0 386 bool logarithmic) const
lbajardsilogic@0 387 {
lbajardsilogic@0 388 int h = height();
lbajardsilogic@0 389
lbajardsilogic@0 390 if (logarithmic) {
lbajardsilogic@0 391
lbajardsilogic@0 392 static float lastminf = 0.0, lastmaxf = 0.0;
lbajardsilogic@0 393 static float logminf = 0.0, logmaxf = 0.0;
lbajardsilogic@0 394
lbajardsilogic@0 395 if (lastminf != minf) {
lbajardsilogic@0 396 lastminf = (minf == 0.0 ? 1.0 : minf);
lbajardsilogic@0 397 logminf = log10f(minf);
lbajardsilogic@0 398 }
lbajardsilogic@0 399 if (lastmaxf != maxf) {
lbajardsilogic@0 400 lastmaxf = (maxf < lastminf ? lastminf : maxf);
lbajardsilogic@0 401 logmaxf = log10f(maxf);
lbajardsilogic@0 402 }
lbajardsilogic@0 403
lbajardsilogic@0 404 if (logminf == logmaxf) return 0;
lbajardsilogic@0 405 return pow(10.f, logminf + ((logmaxf - logminf) * (h - y)) / h);
lbajardsilogic@0 406
lbajardsilogic@0 407 } else {
lbajardsilogic@0 408
lbajardsilogic@0 409 if (minf == maxf) return 0;
lbajardsilogic@0 410 return minf + ((h - y) * (maxf - minf)) / h;
lbajardsilogic@0 411 }
lbajardsilogic@0 412 }
lbajardsilogic@0 413
lbajardsilogic@0 414 int
lbajardsilogic@0 415 View::getZoomLevel() const
lbajardsilogic@0 416 {
lbajardsilogic@0 417 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 418 // std::cout << "zoom level: " << m_zoomLevel << std::endl;
lbajardsilogic@0 419 #endif
lbajardsilogic@0 420 return m_zoomLevel;
lbajardsilogic@0 421 }
lbajardsilogic@0 422
lbajardsilogic@0 423 void
lbajardsilogic@0 424 View::setZoomLevel(size_t z)
lbajardsilogic@0 425 {
lbajardsilogic@0 426 if (m_zoomLevel != int(z)) {
lbajardsilogic@0 427 m_zoomLevel = z;
lbajardsilogic@0 428 emit zoomLevelChanged(z, m_followZoom);
lbajardsilogic@0 429 update();
lbajardsilogic@0 430 }
lbajardsilogic@0 431 }
lbajardsilogic@0 432
lbajardsilogic@0 433 bool
lbajardsilogic@0 434 View::hasLightBackground() const
lbajardsilogic@0 435 {
lbajardsilogic@0 436 for (LayerList::const_iterator i = m_layers.begin();
lbajardsilogic@0 437 i != m_layers.end(); ++i) {
lbajardsilogic@0 438 if (!(*i)->hasLightBackground()) return false;
lbajardsilogic@0 439 }
lbajardsilogic@0 440 return true;
lbajardsilogic@0 441 }
lbajardsilogic@0 442
lbajardsilogic@0 443 View::LayerProgressBar::LayerProgressBar(QWidget *parent) :
lbajardsilogic@0 444 QProgressBar(parent)
lbajardsilogic@0 445 {
lbajardsilogic@0 446 QFont f(font());
lbajardsilogic@0 447 f.setPointSize(f.pointSize() * 8 / 10);
lbajardsilogic@0 448 setFont(f);
lbajardsilogic@0 449 }
lbajardsilogic@0 450
lbajardsilogic@0 451 void
lbajardsilogic@0 452 View::addLayer(Layer *layer)
lbajardsilogic@0 453 {
lbajardsilogic@0 454 delete m_cache;
lbajardsilogic@0 455 m_cache = 0;
lbajardsilogic@0 456
lbajardsilogic@0 457 m_layers.push_back(layer);
lbajardsilogic@0 458
lbajardsilogic@0 459 m_progressBars[layer] = new LayerProgressBar(this);
lbajardsilogic@0 460 m_progressBars[layer]->setMinimum(0);
lbajardsilogic@0 461 m_progressBars[layer]->setMaximum(100);
lbajardsilogic@0 462 m_progressBars[layer]->setMinimumWidth(80);
lbajardsilogic@0 463 m_progressBars[layer]->hide();
lbajardsilogic@0 464
lbajardsilogic@0 465 connect(layer, SIGNAL(layerParametersChanged()),
lbajardsilogic@0 466 this, SLOT(layerParametersChanged()));
lbajardsilogic@0 467 connect(layer, SIGNAL(layerParameterRangesChanged()),
lbajardsilogic@0 468 this, SLOT(layerParameterRangesChanged()));
lbajardsilogic@0 469 connect(layer, SIGNAL(layerNameChanged()),
lbajardsilogic@0 470 this, SLOT(layerNameChanged()));
lbajardsilogic@0 471 connect(layer, SIGNAL(modelChanged()),
lbajardsilogic@0 472 this, SLOT(modelChanged()));
lbajardsilogic@0 473 connect(layer, SIGNAL(modelCompletionChanged()),
lbajardsilogic@0 474 this, SLOT(modelCompletionChanged()));
lbajardsilogic@0 475 connect(layer, SIGNAL(modelChanged(size_t, size_t)),
lbajardsilogic@0 476 this, SLOT(modelChanged(size_t, size_t)));
lbajardsilogic@0 477 connect(layer, SIGNAL(modelReplaced()),
lbajardsilogic@0 478 this, SLOT(modelReplaced()));
lbajardsilogic@0 479
lbajardsilogic@0 480 update();
lbajardsilogic@0 481
lbajardsilogic@0 482 emit propertyContainerAdded(layer);
lbajardsilogic@0 483 }
lbajardsilogic@0 484
lbajardsilogic@0 485 void
lbajardsilogic@0 486 View::removeLayer(Layer *layer)
lbajardsilogic@0 487 {
lbajardsilogic@0 488 if (m_deleting) {
lbajardsilogic@0 489 return;
lbajardsilogic@0 490 }
lbajardsilogic@0 491
lbajardsilogic@0 492 delete m_cache;
lbajardsilogic@0 493 m_cache = 0;
lbajardsilogic@0 494
lbajardsilogic@0 495 for (LayerList::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
lbajardsilogic@0 496 if (*i == layer) {
lbajardsilogic@0 497 m_layers.erase(i);
lbajardsilogic@0 498 if (m_progressBars.find(layer) != m_progressBars.end()) {
benoitrigolleau@59 499 delete m_progressBars[layer];
benoitrigolleau@59 500 m_progressBars.erase(layer);
lbajardsilogic@0 501 }
lbajardsilogic@0 502 break;
lbajardsilogic@0 503 }
lbajardsilogic@0 504 }
lbajardsilogic@0 505
lbajardsilogic@0 506 disconnect(layer, SIGNAL(layerParametersChanged()),
lbajardsilogic@0 507 this, SLOT(layerParametersChanged()));
lbajardsilogic@0 508 disconnect(layer, SIGNAL(layerParameterRangesChanged()),
lbajardsilogic@0 509 this, SLOT(layerParameterRangesChanged()));
lbajardsilogic@0 510 disconnect(layer, SIGNAL(layerNameChanged()),
lbajardsilogic@0 511 this, SLOT(layerNameChanged()));
lbajardsilogic@0 512 disconnect(layer, SIGNAL(modelChanged()),
lbajardsilogic@0 513 this, SLOT(modelChanged()));
lbajardsilogic@0 514 disconnect(layer, SIGNAL(modelCompletionChanged()),
lbajardsilogic@0 515 this, SLOT(modelCompletionChanged()));
lbajardsilogic@0 516 disconnect(layer, SIGNAL(modelChanged(size_t, size_t)),
lbajardsilogic@0 517 this, SLOT(modelChanged(size_t, size_t)));
lbajardsilogic@0 518 disconnect(layer, SIGNAL(modelReplaced()),
lbajardsilogic@0 519 this, SLOT(modelReplaced()));
lbajardsilogic@0 520
lbajardsilogic@0 521 update();
lbajardsilogic@0 522
lbajardsilogic@0 523 emit propertyContainerRemoved(layer);
lbajardsilogic@0 524 }
lbajardsilogic@0 525
lbajardsilogic@0 526 Layer *
lbajardsilogic@0 527 View::getSelectedLayer()
lbajardsilogic@0 528 {
lbajardsilogic@0 529 if (m_haveSelectedLayer && !m_layers.empty()) {
lbajardsilogic@0 530 return getLayer(getLayerCount() - 1);
lbajardsilogic@0 531 } else {
lbajardsilogic@0 532 return 0;
lbajardsilogic@0 533 }
lbajardsilogic@0 534 }
lbajardsilogic@0 535
lbajardsilogic@0 536 const Layer *
lbajardsilogic@0 537 View::getSelectedLayer() const
lbajardsilogic@0 538 {
lbajardsilogic@0 539 return const_cast<const Layer *>(const_cast<View *>(this)->getSelectedLayer());
lbajardsilogic@0 540 }
lbajardsilogic@0 541
lbajardsilogic@0 542 void
lbajardsilogic@0 543 View::setViewManager(ViewManager *manager)
lbajardsilogic@0 544 {
lbajardsilogic@0 545 if (m_manager) {
lbajardsilogic@0 546 m_manager->disconnect(this, SLOT(globalCentreFrameChanged(unsigned long)));
lbajardsilogic@0 547 m_manager->disconnect(this, SLOT(viewCentreFrameChanged(View *, unsigned long)));
lbajardsilogic@0 548 m_manager->disconnect(this, SLOT(viewManagerPlaybackFrameChanged(unsigned long)));
lbajardsilogic@0 549 m_manager->disconnect(this, SLOT(viewZoomLevelChanged(View *, unsigned long, bool)));
lbajardsilogic@0 550 m_manager->disconnect(this, SLOT(toolModeChanged()));
lbajardsilogic@0 551 m_manager->disconnect(this, SLOT(selectionChanged()));
lbajardsilogic@0 552 m_manager->disconnect(this, SLOT(overlayModeChanged()));
lbajardsilogic@0 553 m_manager->disconnect(this, SLOT(zoomWheelsEnabledChanged()));
lbajardsilogic@0 554 disconnect(m_manager, SLOT(viewCentreFrameChanged(unsigned long, bool, PlaybackFollowMode)));
lbajardsilogic@0 555 disconnect(m_manager, SLOT(zoomLevelChanged(unsigned long, bool)));
lbajardsilogic@0 556 }
lbajardsilogic@0 557
lbajardsilogic@0 558 m_manager = manager;
lbajardsilogic@0 559
lbajardsilogic@0 560 connect(m_manager, SIGNAL(globalCentreFrameChanged(unsigned long)),
lbajardsilogic@0 561 this, SLOT(globalCentreFrameChanged(unsigned long)));
lbajardsilogic@0 562 connect(m_manager, SIGNAL(viewCentreFrameChanged(View *, unsigned long)),
lbajardsilogic@0 563 this, SLOT(viewCentreFrameChanged(View *, unsigned long)));
lbajardsilogic@0 564 connect(m_manager, SIGNAL(playbackFrameChanged(unsigned long)),
lbajardsilogic@0 565 this, SLOT(viewManagerPlaybackFrameChanged(unsigned long)));
lbajardsilogic@0 566
lbajardsilogic@0 567 connect(m_manager, SIGNAL(viewZoomLevelChanged(View *, unsigned long, bool)),
lbajardsilogic@0 568 this, SLOT(viewZoomLevelChanged(View *, unsigned long, bool)));
lbajardsilogic@0 569
lbajardsilogic@0 570 connect(m_manager, SIGNAL(toolModeChanged()),
lbajardsilogic@0 571 this, SLOT(toolModeChanged()));
lbajardsilogic@0 572 connect(m_manager, SIGNAL(selectionChanged()),
lbajardsilogic@0 573 this, SLOT(selectionChanged()));
lbajardsilogic@0 574 connect(m_manager, SIGNAL(inProgressSelectionChanged()),
lbajardsilogic@0 575 this, SLOT(selectionChanged()));
lbajardsilogic@0 576 connect(m_manager, SIGNAL(overlayModeChanged()),
lbajardsilogic@0 577 this, SLOT(overlayModeChanged()));
lbajardsilogic@0 578 connect(m_manager, SIGNAL(zoomWheelsEnabledChanged()),
lbajardsilogic@0 579 this, SLOT(zoomWheelsEnabledChanged()));
lbajardsilogic@0 580
lbajardsilogic@0 581 connect(this, SIGNAL(centreFrameChanged(unsigned long, bool,
lbajardsilogic@0 582 PlaybackFollowMode)),
lbajardsilogic@0 583 m_manager, SLOT(viewCentreFrameChanged(unsigned long, bool,
lbajardsilogic@0 584 PlaybackFollowMode)));
lbajardsilogic@0 585
lbajardsilogic@0 586 connect(this, SIGNAL(zoomLevelChanged(unsigned long, bool)),
lbajardsilogic@0 587 m_manager, SLOT(viewZoomLevelChanged(unsigned long, bool)));
lbajardsilogic@0 588
lbajardsilogic@0 589 if (m_followPlay != PlaybackIgnore) {
lbajardsilogic@0 590 // std::cerr << "View::setViewManager: setting centre frame to playback frame: " << m_manager->getPlaybackFrame() << std::endl;
lbajardsilogic@0 591 setCentreFrame(m_manager->getPlaybackFrame(), false);
lbajardsilogic@0 592 } else if (m_followPan) {
lbajardsilogic@0 593 // std::cerr << "View::setViewManager: setting centre frame to global centre frame: " << m_manager->getGlobalCentreFrame() << std::endl;
lbajardsilogic@0 594 setCentreFrame(m_manager->getGlobalCentreFrame(), false);
lbajardsilogic@0 595 }
lbajardsilogic@0 596 if (m_followZoom) setZoomLevel(m_manager->getGlobalZoom());
lbajardsilogic@0 597
lbajardsilogic@0 598 toolModeChanged();
lbajardsilogic@0 599 }
lbajardsilogic@0 600
lbajardsilogic@0 601 void
lbajardsilogic@0 602 View::setFollowGlobalPan(bool f)
lbajardsilogic@0 603 {
lbajardsilogic@0 604 m_followPan = f;
lbajardsilogic@0 605 emit propertyContainerPropertyChanged(m_propertyContainer);
lbajardsilogic@0 606 }
lbajardsilogic@0 607
lbajardsilogic@0 608 void
lbajardsilogic@0 609 View::setFollowGlobalZoom(bool f)
lbajardsilogic@0 610 {
lbajardsilogic@0 611 m_followZoom = f;
lbajardsilogic@0 612 emit propertyContainerPropertyChanged(m_propertyContainer);
lbajardsilogic@0 613 }
lbajardsilogic@0 614
lbajardsilogic@0 615 void
lbajardsilogic@0 616 View::drawVisibleText(QPainter &paint, int x, int y, QString text, TextStyle style)
lbajardsilogic@0 617 {
lbajardsilogic@0 618 if (style == OutlinedText) {
lbajardsilogic@0 619
lbajardsilogic@0 620 QColor origPenColour = paint.pen().color();
lbajardsilogic@0 621 QColor penColour = origPenColour;
lbajardsilogic@0 622 QColor surroundColour = Qt::white; //palette().background().color();
lbajardsilogic@0 623
lbajardsilogic@0 624 if (!hasLightBackground()) {
lbajardsilogic@0 625 int h, s, v;
lbajardsilogic@0 626 penColour.getHsv(&h, &s, &v);
lbajardsilogic@0 627 penColour = QColor::fromHsv(h, s, 255 - v);
lbajardsilogic@0 628 surroundColour = Qt::black;
lbajardsilogic@0 629 }
lbajardsilogic@0 630
lbajardsilogic@0 631 paint.setPen(surroundColour);
lbajardsilogic@0 632
lbajardsilogic@0 633 for (int dx = -1; dx <= 1; ++dx) {
lbajardsilogic@0 634 for (int dy = -1; dy <= 1; ++dy) {
lbajardsilogic@0 635 if (!(dx || dy)) continue;
lbajardsilogic@0 636 paint.drawText(x + dx, y + dy, text);
lbajardsilogic@0 637 }
lbajardsilogic@0 638 }
lbajardsilogic@0 639
lbajardsilogic@0 640 paint.setPen(penColour);
lbajardsilogic@0 641
lbajardsilogic@0 642 paint.drawText(x, y, text);
lbajardsilogic@0 643
lbajardsilogic@0 644 paint.setPen(origPenColour);
lbajardsilogic@0 645
lbajardsilogic@0 646 } else {
lbajardsilogic@0 647
lbajardsilogic@0 648 std::cerr << "ERROR: View::drawVisibleText: Boxed style not yet implemented!" << std::endl;
lbajardsilogic@0 649 }
lbajardsilogic@0 650 }
lbajardsilogic@0 651
lbajardsilogic@0 652 void
lbajardsilogic@0 653 View::setPlaybackFollow(PlaybackFollowMode m)
lbajardsilogic@0 654 {
lbajardsilogic@0 655 m_followPlay = m;
lbajardsilogic@0 656 emit propertyContainerPropertyChanged(m_propertyContainer);
lbajardsilogic@0 657 }
lbajardsilogic@0 658
lbajardsilogic@0 659 void
lbajardsilogic@0 660 View::modelChanged()
lbajardsilogic@0 661 {
lbajardsilogic@0 662 QObject *obj = sender();
lbajardsilogic@0 663
lbajardsilogic@0 664 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 665 std::cerr << "View(" << this << ")::modelChanged()" << std::endl;
lbajardsilogic@0 666 #endif
lbajardsilogic@0 667
lbajardsilogic@0 668 // If the model that has changed is not used by any of the cached
lbajardsilogic@0 669 // layers, we won't need to recreate the cache
lbajardsilogic@0 670
lbajardsilogic@0 671 bool recreate = false;
lbajardsilogic@0 672
lbajardsilogic@0 673 bool discard;
lbajardsilogic@0 674 LayerList scrollables = getScrollableBackLayers(false, discard);
lbajardsilogic@0 675 for (LayerList::const_iterator i = scrollables.begin();
lbajardsilogic@0 676 i != scrollables.end(); ++i) {
lbajardsilogic@0 677 if (*i == obj || (*i)->getModel() == obj) {
lbajardsilogic@0 678 recreate = true;
lbajardsilogic@0 679 break;
lbajardsilogic@0 680 }
lbajardsilogic@0 681 }
lbajardsilogic@0 682
lbajardsilogic@0 683 if (recreate) {
lbajardsilogic@0 684 delete m_cache;
lbajardsilogic@0 685 m_cache = 0;
lbajardsilogic@0 686 }
lbajardsilogic@0 687
lbajardsilogic@0 688 checkProgress(obj);
lbajardsilogic@0 689
lbajardsilogic@0 690 update();
lbajardsilogic@0 691 }
lbajardsilogic@0 692
lbajardsilogic@0 693 void
lbajardsilogic@0 694 View::modelChanged(size_t startFrame, size_t endFrame)
lbajardsilogic@0 695 {
lbajardsilogic@0 696 QObject *obj = sender();
lbajardsilogic@0 697
lbajardsilogic@0 698 long myStartFrame = getStartFrame();
lbajardsilogic@0 699 size_t myEndFrame = getEndFrame();
lbajardsilogic@0 700
lbajardsilogic@0 701 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 702 std::cerr << "View(" << this << ")::modelChanged(" << startFrame << "," << endFrame << ") [me " << myStartFrame << "," << myEndFrame << "]" << std::endl;
lbajardsilogic@0 703 #endif
lbajardsilogic@0 704
lbajardsilogic@0 705 if (myStartFrame > 0 && endFrame < size_t(myStartFrame)) {
lbajardsilogic@0 706 checkProgress(obj);
lbajardsilogic@0 707 return;
lbajardsilogic@0 708 }
lbajardsilogic@0 709 if (startFrame > myEndFrame) {
lbajardsilogic@0 710 checkProgress(obj);
lbajardsilogic@0 711 return;
lbajardsilogic@0 712 }
lbajardsilogic@0 713
lbajardsilogic@0 714 // If the model that has changed is not used by any of the cached
lbajardsilogic@0 715 // layers, we won't need to recreate the cache
lbajardsilogic@0 716
lbajardsilogic@0 717 bool recreate = false;
lbajardsilogic@0 718
lbajardsilogic@0 719 bool discard;
lbajardsilogic@0 720 LayerList scrollables = getScrollableBackLayers(false, discard);
lbajardsilogic@0 721 for (LayerList::const_iterator i = scrollables.begin();
lbajardsilogic@0 722 i != scrollables.end(); ++i) {
lbajardsilogic@0 723 if (*i == obj || (*i)->getModel() == obj) {
lbajardsilogic@0 724 recreate = true;
lbajardsilogic@0 725 break;
lbajardsilogic@0 726 }
lbajardsilogic@0 727 }
lbajardsilogic@0 728
lbajardsilogic@0 729 if (recreate) {
lbajardsilogic@0 730 delete m_cache;
lbajardsilogic@0 731 m_cache = 0;
lbajardsilogic@0 732 }
lbajardsilogic@0 733
lbajardsilogic@0 734 if (long(startFrame) < myStartFrame) startFrame = myStartFrame;
lbajardsilogic@0 735 if (endFrame > myEndFrame) endFrame = myEndFrame;
lbajardsilogic@0 736
lbajardsilogic@0 737 checkProgress(obj);
lbajardsilogic@0 738
lbajardsilogic@0 739 update();
lbajardsilogic@0 740 }
lbajardsilogic@0 741
lbajardsilogic@0 742 void
lbajardsilogic@0 743 View::modelCompletionChanged()
lbajardsilogic@0 744 {
lbajardsilogic@0 745 QObject *obj = sender();
lbajardsilogic@0 746 checkProgress(obj);
lbajardsilogic@0 747 }
lbajardsilogic@0 748
lbajardsilogic@0 749 void
lbajardsilogic@0 750 View::modelReplaced()
lbajardsilogic@0 751 {
lbajardsilogic@0 752 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 753 std::cerr << "View(" << this << ")::modelReplaced()" << std::endl;
lbajardsilogic@0 754 #endif
lbajardsilogic@0 755 delete m_cache;
lbajardsilogic@0 756 m_cache = 0;
lbajardsilogic@0 757
lbajardsilogic@0 758 update();
lbajardsilogic@0 759 }
lbajardsilogic@0 760
lbajardsilogic@0 761 void
lbajardsilogic@0 762 View::layerParametersChanged()
lbajardsilogic@0 763 {
lbajardsilogic@0 764 Layer *layer = dynamic_cast<Layer *>(sender());
lbajardsilogic@0 765
lbajardsilogic@0 766 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 767 std::cerr << "View::layerParametersChanged()" << std::endl;
lbajardsilogic@0 768 #endif
lbajardsilogic@0 769
lbajardsilogic@0 770 delete m_cache;
lbajardsilogic@0 771 m_cache = 0;
lbajardsilogic@0 772 update();
lbajardsilogic@0 773
lbajardsilogic@0 774 if (layer) {
lbajardsilogic@0 775 emit propertyContainerPropertyChanged(layer);
lbajardsilogic@0 776 }
lbajardsilogic@0 777 }
lbajardsilogic@0 778
lbajardsilogic@0 779 void
lbajardsilogic@0 780 View::layerParameterRangesChanged()
lbajardsilogic@0 781 {
lbajardsilogic@0 782 Layer *layer = dynamic_cast<Layer *>(sender());
lbajardsilogic@0 783 if (layer) emit propertyContainerPropertyRangeChanged(layer);
lbajardsilogic@0 784 }
lbajardsilogic@0 785
lbajardsilogic@0 786 void
lbajardsilogic@0 787 View::layerNameChanged()
lbajardsilogic@0 788 {
lbajardsilogic@0 789 Layer *layer = dynamic_cast<Layer *>(sender());
lbajardsilogic@0 790 if (layer) emit propertyContainerNameChanged(layer);
lbajardsilogic@0 791 }
lbajardsilogic@0 792
lbajardsilogic@0 793 void
lbajardsilogic@0 794 View::globalCentreFrameChanged(unsigned long f)
lbajardsilogic@0 795 {
lbajardsilogic@0 796 if (m_followPan) {
lbajardsilogic@0 797 setCentreFrame(f, false);
lbajardsilogic@0 798 }
lbajardsilogic@0 799 }
lbajardsilogic@0 800
lbajardsilogic@0 801 void
lbajardsilogic@0 802 View::viewCentreFrameChanged(View *, unsigned long )
lbajardsilogic@0 803 {
lbajardsilogic@0 804 // We do nothing with this, but a subclass might
lbajardsilogic@0 805 }
lbajardsilogic@0 806
lbajardsilogic@0 807 void
lbajardsilogic@0 808 View::viewManagerPlaybackFrameChanged(unsigned long f)
lbajardsilogic@0 809 {
lbajardsilogic@0 810 if (m_manager) {
lbajardsilogic@0 811 if (sender() != m_manager) return;
lbajardsilogic@0 812 }
lbajardsilogic@0 813
lbajardsilogic@0 814 if (m_playPointerFrame == f) return;
lbajardsilogic@0 815 bool visible = (getXForFrame(m_playPointerFrame) != getXForFrame(f));
lbajardsilogic@0 816 size_t oldPlayPointerFrame = m_playPointerFrame;
lbajardsilogic@0 817 m_playPointerFrame = f;
lbajardsilogic@0 818 if (!visible) return;
lbajardsilogic@0 819
lbajardsilogic@0 820 switch (m_followPlay) {
lbajardsilogic@0 821
lbajardsilogic@0 822 case PlaybackScrollContinuous:
lbajardsilogic@0 823 if (QApplication::mouseButtons() == Qt::NoButton) {
lbajardsilogic@0 824 setCentreFrame(f, false);
lbajardsilogic@0 825 }
lbajardsilogic@0 826 break;
lbajardsilogic@0 827
lbajardsilogic@0 828 case PlaybackScrollPage:
lbajardsilogic@0 829 {
lbajardsilogic@0 830 int xold = getXForFrame(oldPlayPointerFrame);
lbajardsilogic@0 831 update(xold - 1, 0, 3, height());
lbajardsilogic@0 832
lbajardsilogic@0 833 long w = getEndFrame() - getStartFrame();
lbajardsilogic@0 834 w -= w/5;
lbajardsilogic@0 835 long sf = (f / w) * w - w/8;
lbajardsilogic@0 836
lbajardsilogic@0 837 if (m_manager &&
lbajardsilogic@0 838 m_manager->isPlaying() &&
lbajardsilogic@0 839 m_manager->getPlaySelectionMode()) {
lbajardsilogic@0 840 MultiSelection::SelectionList selections = m_manager->getSelections();
lbajardsilogic@0 841 if (!selections.empty()) {
lbajardsilogic@0 842 size_t selectionStart = selections.begin()->getStartFrame();
lbajardsilogic@0 843 if (sf < long(selectionStart) - w / 10) {
lbajardsilogic@0 844 sf = long(selectionStart) - w / 10;
lbajardsilogic@0 845 }
lbajardsilogic@0 846 }
lbajardsilogic@0 847 }
lbajardsilogic@0 848
lbajardsilogic@0 849 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 850 std::cerr << "PlaybackScrollPage: f = " << f << ", sf = " << sf << ", start frame "
lbajardsilogic@0 851 << getStartFrame() << std::endl;
lbajardsilogic@0 852 #endif
lbajardsilogic@0 853
lbajardsilogic@0 854 // We don't consider scrolling unless the pointer is outside
lbajardsilogic@0 855 // the clearly visible range already
lbajardsilogic@0 856
lbajardsilogic@0 857 int xnew = getXForFrame(m_playPointerFrame);
lbajardsilogic@0 858
lbajardsilogic@0 859 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 860 std::cerr << "xnew = " << xnew << ", width = " << width() << std::endl;
lbajardsilogic@0 861 #endif
lbajardsilogic@0 862
lbajardsilogic@0 863 if (xnew < width()/8 || xnew > (width()*7)/8) {
lbajardsilogic@0 864 if (QApplication::mouseButtons() == Qt::NoButton) {
lbajardsilogic@0 865 long offset = getFrameForX(width()/2) - getStartFrame();
lbajardsilogic@0 866 long newCentre = sf + offset;
lbajardsilogic@0 867 bool changed = setCentreFrame(newCentre, false);
lbajardsilogic@0 868 if (changed) {
lbajardsilogic@0 869 xold = getXForFrame(oldPlayPointerFrame);
lbajardsilogic@0 870 update(xold - 1, 0, 3, height());
lbajardsilogic@0 871 }
lbajardsilogic@0 872 }
lbajardsilogic@0 873 }
lbajardsilogic@0 874
lbajardsilogic@0 875 update(xnew - 1, 0, 3, height());
lbajardsilogic@0 876
lbajardsilogic@0 877 break;
lbajardsilogic@0 878 }
lbajardsilogic@0 879
lbajardsilogic@0 880 case PlaybackIgnore:
lbajardsilogic@0 881 if (long(f) >= getStartFrame() && f < getEndFrame()) {
lbajardsilogic@0 882 update();
lbajardsilogic@0 883 }
lbajardsilogic@0 884 break;
lbajardsilogic@0 885 }
lbajardsilogic@0 886 }
lbajardsilogic@0 887
lbajardsilogic@0 888 void
lbajardsilogic@0 889 View::viewZoomLevelChanged(View *p, unsigned long z, bool locked)
lbajardsilogic@0 890 {
lbajardsilogic@0 891 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 892 std::cerr << "View[" << this << "]: viewZoomLevelChanged(" << p << ", " << z << ", " << locked << ")" << std::endl;
lbajardsilogic@0 893 #endif
lbajardsilogic@0 894 if (m_followZoom && p != this && locked) {
lbajardsilogic@0 895 setZoomLevel(z);
lbajardsilogic@0 896 }
lbajardsilogic@0 897 }
lbajardsilogic@0 898
lbajardsilogic@0 899 void
lbajardsilogic@0 900 View::selectionChanged()
lbajardsilogic@0 901 {
lbajardsilogic@0 902 if (m_selectionCached) {
lbajardsilogic@0 903 delete m_cache;
lbajardsilogic@0 904 m_cache = 0;
lbajardsilogic@0 905 m_selectionCached = false;
lbajardsilogic@0 906 }
lbajardsilogic@0 907 update();
lbajardsilogic@0 908 }
lbajardsilogic@0 909
lbajardsilogic@0 910 size_t
lbajardsilogic@0 911 View::getFirstVisibleFrame() const
lbajardsilogic@0 912 {
lbajardsilogic@0 913 long f0 = getStartFrame();
lbajardsilogic@0 914 size_t f = getModelsStartFrame();
lbajardsilogic@0 915 if (f0 < 0 || f0 < long(f)) return f;
lbajardsilogic@0 916 return f0;
lbajardsilogic@0 917 }
lbajardsilogic@0 918
lbajardsilogic@0 919 size_t
lbajardsilogic@0 920 View::getLastVisibleFrame() const
lbajardsilogic@0 921 {
lbajardsilogic@0 922 size_t f0 = getEndFrame();
lbajardsilogic@0 923 size_t f = getModelsEndFrame();
lbajardsilogic@0 924 if (f0 > f) return f;
lbajardsilogic@0 925 return f0;
lbajardsilogic@0 926 }
lbajardsilogic@0 927
lbajardsilogic@0 928 size_t
lbajardsilogic@0 929 View::getModelsStartFrame() const
lbajardsilogic@0 930 {
lbajardsilogic@0 931 bool first = true;
lbajardsilogic@0 932 size_t startFrame = 0;
lbajardsilogic@0 933
lbajardsilogic@0 934 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
lbajardsilogic@0 935
lbajardsilogic@0 936 if ((*i)->getModel() && (*i)->getModel()->isOK()) {
lbajardsilogic@0 937
lbajardsilogic@0 938 size_t thisStartFrame = (*i)->getModel()->getStartFrame();
lbajardsilogic@0 939
lbajardsilogic@0 940 if (first || thisStartFrame < startFrame) {
lbajardsilogic@0 941 startFrame = thisStartFrame;
lbajardsilogic@0 942 }
lbajardsilogic@0 943 first = false;
lbajardsilogic@0 944 }
lbajardsilogic@0 945 }
lbajardsilogic@0 946 return startFrame;
lbajardsilogic@0 947 }
lbajardsilogic@0 948
lbajardsilogic@0 949 size_t
lbajardsilogic@0 950 View::getModelsEndFrame() const
lbajardsilogic@0 951 {
lbajardsilogic@0 952 bool first = true;
lbajardsilogic@0 953 size_t endFrame = 0;
lbajardsilogic@0 954
lbajardsilogic@0 955 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
lbajardsilogic@0 956
lbajardsilogic@0 957 if ((*i)->getModel() && (*i)->getModel()->isOK()) {
lbajardsilogic@0 958
lbajardsilogic@0 959 size_t thisEndFrame = (*i)->getModel()->getEndFrame();
lbajardsilogic@0 960
lbajardsilogic@0 961 if (first || thisEndFrame > endFrame) {
lbajardsilogic@0 962 endFrame = thisEndFrame;
lbajardsilogic@0 963 }
lbajardsilogic@0 964 first = false;
lbajardsilogic@0 965 }
lbajardsilogic@0 966 }
lbajardsilogic@0 967
lbajardsilogic@0 968 if (first) return getModelsStartFrame();
lbajardsilogic@0 969 return endFrame;
lbajardsilogic@0 970 }
lbajardsilogic@0 971
lbajardsilogic@0 972 int
lbajardsilogic@0 973 View::getModelsSampleRate() const
lbajardsilogic@0 974 {
lbajardsilogic@0 975 //!!! Just go for the first, for now. If we were supporting
lbajardsilogic@0 976 // multiple samplerates, we'd probably want to do frame/time
lbajardsilogic@0 977 // conversion in the model
lbajardsilogic@0 978
lbajardsilogic@0 979 //!!! nah, this wants to always return the sr of the main model!
lbajardsilogic@0 980
lbajardsilogic@0 981 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
lbajardsilogic@0 982 if ((*i)->getModel() && (*i)->getModel()->isOK()) {
lbajardsilogic@0 983 return (*i)->getModel()->getSampleRate();
lbajardsilogic@0 984 }
lbajardsilogic@0 985 }
lbajardsilogic@0 986 return 0;
lbajardsilogic@0 987 }
lbajardsilogic@0 988
lbajardsilogic@0 989 bool
lbajardsilogic@0 990 View::areLayersScrollable() const
lbajardsilogic@0 991 {
lbajardsilogic@0 992 // True iff all views are scrollable
lbajardsilogic@0 993 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
lbajardsilogic@0 994 if (!(*i)->isLayerScrollable(this)) return false;
lbajardsilogic@0 995 }
lbajardsilogic@0 996 return true;
lbajardsilogic@0 997 }
lbajardsilogic@0 998
lbajardsilogic@0 999 View::LayerList
lbajardsilogic@0 1000 View::getScrollableBackLayers(bool testChanged, bool &changed) const
lbajardsilogic@0 1001 {
lbajardsilogic@0 1002 changed = false;
lbajardsilogic@0 1003
lbajardsilogic@0 1004 // We want a list of all the scrollable layers that are behind the
lbajardsilogic@0 1005 // backmost non-scrollable layer.
lbajardsilogic@0 1006
lbajardsilogic@0 1007 LayerList scrollables;
lbajardsilogic@0 1008 bool metUnscrollable = false;
lbajardsilogic@0 1009
lbajardsilogic@0 1010 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
lbajardsilogic@0 1011 // std::cerr << "View::getScrollableBackLayers: calling isLayerDormant on layer " << *i << std::endl;
lbajardsilogic@0 1012 // std::cerr << "(name is " << (*i)->objectName().toStdString() << ")"
lbajardsilogic@0 1013 // << std::endl;
lbajardsilogic@0 1014 // std::cerr << "View::getScrollableBackLayers: I am " << this << std::endl;
lbajardsilogic@0 1015 if ((*i)->isLayerDormant(this)) continue;
lbajardsilogic@0 1016 if ((*i)->isLayerOpaque()) {
lbajardsilogic@0 1017 // You can't see anything behind an opaque layer!
lbajardsilogic@0 1018 scrollables.clear();
lbajardsilogic@0 1019 if (metUnscrollable) break;
lbajardsilogic@0 1020 }
lbajardsilogic@0 1021 if (!metUnscrollable && (*i)->isLayerScrollable(this)) {
lbajardsilogic@0 1022 scrollables.push_back(*i);
lbajardsilogic@0 1023 } else {
lbajardsilogic@0 1024 metUnscrollable = true;
lbajardsilogic@0 1025 }
lbajardsilogic@0 1026 }
lbajardsilogic@0 1027
lbajardsilogic@0 1028 if (testChanged && scrollables != m_lastScrollableBackLayers) {
lbajardsilogic@0 1029 m_lastScrollableBackLayers = scrollables;
lbajardsilogic@0 1030 changed = true;
lbajardsilogic@0 1031 }
lbajardsilogic@0 1032 return scrollables;
lbajardsilogic@0 1033 }
lbajardsilogic@0 1034
lbajardsilogic@0 1035 View::LayerList
lbajardsilogic@0 1036 View::getNonScrollableFrontLayers(bool testChanged, bool &changed) const
lbajardsilogic@0 1037 {
lbajardsilogic@0 1038 changed = false;
lbajardsilogic@0 1039 LayerList nonScrollables;
lbajardsilogic@0 1040
lbajardsilogic@0 1041 // Everything in front of the first non-scrollable from the back
lbajardsilogic@0 1042 // should also be considered non-scrollable
lbajardsilogic@0 1043
lbajardsilogic@0 1044 bool started = false;
lbajardsilogic@0 1045
lbajardsilogic@0 1046 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
lbajardsilogic@0 1047 if ((*i)->isLayerDormant(this)) continue;
lbajardsilogic@0 1048 if (!started && (*i)->isLayerScrollable(this)) {
lbajardsilogic@0 1049 continue;
lbajardsilogic@0 1050 }
lbajardsilogic@0 1051 started = true;
lbajardsilogic@0 1052 if ((*i)->isLayerOpaque()) {
lbajardsilogic@0 1053 // You can't see anything behind an opaque layer!
lbajardsilogic@0 1054 nonScrollables.clear();
lbajardsilogic@0 1055 }
lbajardsilogic@0 1056 nonScrollables.push_back(*i);
lbajardsilogic@0 1057 }
lbajardsilogic@0 1058
lbajardsilogic@0 1059 if (testChanged && nonScrollables != m_lastNonScrollableBackLayers) {
lbajardsilogic@0 1060 m_lastNonScrollableBackLayers = nonScrollables;
lbajardsilogic@0 1061 changed = true;
lbajardsilogic@0 1062 }
lbajardsilogic@0 1063
lbajardsilogic@0 1064 return nonScrollables;
lbajardsilogic@0 1065 }
lbajardsilogic@0 1066
lbajardsilogic@0 1067 size_t
lbajardsilogic@0 1068 View::getZoomConstraintBlockSize(size_t blockSize,
lbajardsilogic@0 1069 ZoomConstraint::RoundingDirection dir)
lbajardsilogic@0 1070 const
lbajardsilogic@0 1071 {
lbajardsilogic@0 1072 size_t candidate = blockSize;
lbajardsilogic@0 1073 bool haveCandidate = false;
lbajardsilogic@0 1074
lbajardsilogic@0 1075 PowerOfSqrtTwoZoomConstraint defaultZoomConstraint;
lbajardsilogic@0 1076
lbajardsilogic@0 1077 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
lbajardsilogic@0 1078
lbajardsilogic@0 1079 const ZoomConstraint *zoomConstraint = (*i)->getZoomConstraint();
lbajardsilogic@0 1080 if (!zoomConstraint) zoomConstraint = &defaultZoomConstraint;
lbajardsilogic@0 1081
lbajardsilogic@0 1082 size_t thisBlockSize =
lbajardsilogic@0 1083 zoomConstraint->getNearestBlockSize(blockSize, dir);
lbajardsilogic@0 1084
lbajardsilogic@0 1085 // Go for the block size that's furthest from the one
lbajardsilogic@0 1086 // passed in. Most of the time, that's what we want.
lbajardsilogic@0 1087 if (!haveCandidate ||
lbajardsilogic@0 1088 (thisBlockSize > blockSize && thisBlockSize > candidate) ||
lbajardsilogic@0 1089 (thisBlockSize < blockSize && thisBlockSize < candidate)) {
lbajardsilogic@0 1090 candidate = thisBlockSize;
lbajardsilogic@0 1091 haveCandidate = true;
lbajardsilogic@0 1092 }
lbajardsilogic@0 1093 }
lbajardsilogic@0 1094
lbajardsilogic@0 1095 return candidate;
lbajardsilogic@0 1096 }
lbajardsilogic@0 1097
lbajardsilogic@0 1098 bool
lbajardsilogic@0 1099 View::areLayerColoursSignificant() const
lbajardsilogic@0 1100 {
lbajardsilogic@0 1101 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
lbajardsilogic@0 1102 if ((*i)->isLayerColourSignificant()) return true;
lbajardsilogic@0 1103 if ((*i)->isLayerOpaque()) break;
lbajardsilogic@0 1104 }
lbajardsilogic@0 1105 return false;
lbajardsilogic@0 1106 }
lbajardsilogic@0 1107
lbajardsilogic@0 1108 bool
lbajardsilogic@0 1109 View::hasTopLayerTimeXAxis() const
lbajardsilogic@0 1110 {
lbajardsilogic@0 1111 LayerList::const_iterator i = m_layers.end();
lbajardsilogic@0 1112 if (i == m_layers.begin()) return false;
lbajardsilogic@0 1113 --i;
lbajardsilogic@0 1114 return (*i)->hasTimeXAxis();
lbajardsilogic@0 1115 }
lbajardsilogic@0 1116
lbajardsilogic@0 1117 void
lbajardsilogic@0 1118 View::zoom(bool in)
lbajardsilogic@0 1119 {
lbajardsilogic@0 1120 int newZoomLevel = m_zoomLevel;
lbajardsilogic@0 1121
lbajardsilogic@0 1122 if (in) {
lbajardsilogic@0 1123 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel - 1,
lbajardsilogic@0 1124 ZoomConstraint::RoundDown);
lbajardsilogic@0 1125 } else {
lbajardsilogic@0 1126 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel + 1,
lbajardsilogic@0 1127 ZoomConstraint::RoundUp);
lbajardsilogic@0 1128 }
lbajardsilogic@0 1129
lbajardsilogic@0 1130 if (newZoomLevel != m_zoomLevel) {
lbajardsilogic@0 1131 setZoomLevel(newZoomLevel);
lbajardsilogic@0 1132 }
lbajardsilogic@0 1133 }
lbajardsilogic@0 1134
lbajardsilogic@0 1135 void
lbajardsilogic@0 1136 View::scroll(bool right, bool lots)
lbajardsilogic@0 1137 {
lbajardsilogic@0 1138 long delta;
lbajardsilogic@0 1139 if (lots) {
lbajardsilogic@0 1140 delta = (getEndFrame() - getStartFrame()) / 2;
lbajardsilogic@0 1141 } else {
lbajardsilogic@0 1142 delta = (getEndFrame() - getStartFrame()) / 20;
lbajardsilogic@0 1143 }
lbajardsilogic@0 1144 if (right) delta = -delta;
lbajardsilogic@0 1145
lbajardsilogic@0 1146 if (int(m_centreFrame) < delta) {
lbajardsilogic@0 1147 setCentreFrame(0);
lbajardsilogic@0 1148 } else if (int(m_centreFrame) - delta >= int(getModelsEndFrame())) {
lbajardsilogic@0 1149 setCentreFrame(getModelsEndFrame());
lbajardsilogic@0 1150 } else {
lbajardsilogic@0 1151 setCentreFrame(m_centreFrame - delta);
lbajardsilogic@0 1152 }
lbajardsilogic@0 1153 }
lbajardsilogic@0 1154
lbajardsilogic@0 1155 void
lbajardsilogic@0 1156 View::checkProgress(void *object)
lbajardsilogic@0 1157 {
lbajardsilogic@0 1158 if (!m_showProgress) return;
lbajardsilogic@0 1159
lbajardsilogic@0 1160 int ph = height();
lbajardsilogic@0 1161
lbajardsilogic@0 1162 for (ProgressMap::const_iterator i = m_progressBars.begin();
lbajardsilogic@0 1163 i != m_progressBars.end(); ++i) {
lbajardsilogic@0 1164
lbajardsilogic@0 1165 if (i->first == object) {
lbajardsilogic@0 1166
lbajardsilogic@0 1167 int completion = i->first->getCompletion(this);
lbajardsilogic@0 1168
lbajardsilogic@0 1169 if (completion >= 100) {
lbajardsilogic@0 1170
lbajardsilogic@0 1171 i->second->hide();
lbajardsilogic@0 1172
lbajardsilogic@0 1173 } else {
lbajardsilogic@0 1174
lbajardsilogic@0 1175 i->second->setText(i->first->getPropertyContainerName());
lbajardsilogic@0 1176
lbajardsilogic@0 1177 i->second->setValue(completion);
lbajardsilogic@0 1178 i->second->move(0, ph - i->second->height());
lbajardsilogic@0 1179
lbajardsilogic@0 1180 i->second->show();
lbajardsilogic@0 1181 i->second->update();
lbajardsilogic@0 1182
lbajardsilogic@0 1183 ph -= i->second->height();
lbajardsilogic@0 1184 }
lbajardsilogic@0 1185 } else {
lbajardsilogic@0 1186 if (i->second->isVisible()) {
lbajardsilogic@0 1187 ph -= i->second->height();
lbajardsilogic@0 1188 }
lbajardsilogic@0 1189 }
lbajardsilogic@0 1190 }
lbajardsilogic@0 1191 }
lbajardsilogic@0 1192
lbajardsilogic@0 1193 void
lbajardsilogic@0 1194 View::paintEvent(QPaintEvent *e)
lbajardsilogic@0 1195 {
lbajardsilogic@0 1196 // Profiler prof("View::paintEvent", false);
lbajardsilogic@0 1197 // std::cerr << "View::paintEvent: centre frame is " << m_centreFrame << std::endl;
lbajardsilogic@0 1198
lbajardsilogic@0 1199 if (m_layers.empty()) {
lbajardsilogic@0 1200 QFrame::paintEvent(e);
lbajardsilogic@0 1201 return;
lbajardsilogic@0 1202 }
lbajardsilogic@0 1203
lbajardsilogic@0 1204 // ensure our constraints are met
lbajardsilogic@0 1205
lbajardsilogic@0 1206 /*!!! Should we do this only if we have layers that can't support other
lbajardsilogic@0 1207 zoom levels?
lbajardsilogic@0 1208
lbajardsilogic@0 1209 m_zoomLevel = getZoomConstraintBlockSize(m_zoomLevel,
lbajardsilogic@0 1210 ZoomConstraint::RoundUp);
lbajardsilogic@0 1211 */
lbajardsilogic@0 1212
lbajardsilogic@0 1213 QPainter paint;
lbajardsilogic@0 1214 bool repaintCache = false;
lbajardsilogic@0 1215 bool paintedCacheRect = false;
lbajardsilogic@0 1216
lbajardsilogic@0 1217 QRect cacheRect(rect());
lbajardsilogic@0 1218
lbajardsilogic@0 1219 if (e) {
lbajardsilogic@0 1220 cacheRect &= e->rect();
lbajardsilogic@0 1221 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 1222 std::cerr << "paint rect " << cacheRect.width() << "x" << cacheRect.height()
lbajardsilogic@0 1223 << ", my rect " << width() << "x" << height() << std::endl;
lbajardsilogic@0 1224 #endif
lbajardsilogic@0 1225 }
lbajardsilogic@0 1226
lbajardsilogic@0 1227 QRect nonCacheRect(cacheRect);
lbajardsilogic@0 1228
lbajardsilogic@0 1229 // If not all layers are scrollable, but some of the back layers
lbajardsilogic@0 1230 // are, we should store only those in the cache.
lbajardsilogic@0 1231
lbajardsilogic@0 1232 bool layersChanged = false;
lbajardsilogic@0 1233 LayerList scrollables = getScrollableBackLayers(true, layersChanged);
lbajardsilogic@0 1234 LayerList nonScrollables = getNonScrollableFrontLayers(true, layersChanged);
lbajardsilogic@0 1235 bool selectionCacheable = nonScrollables.empty();
lbajardsilogic@0 1236 bool haveSelections = m_manager && !m_manager->getSelections().empty();
lbajardsilogic@0 1237 bool selectionDrawn = false;
lbajardsilogic@0 1238
lbajardsilogic@0 1239 // If all the non-scrollable layers are non-opaque, then we draw
lbajardsilogic@0 1240 // the selection rectangle behind them and cache it. If any are
lbajardsilogic@0 1241 // opaque, however, we can't cache.
lbajardsilogic@0 1242 //
lbajardsilogic@0 1243 if (!selectionCacheable) {
lbajardsilogic@0 1244 selectionCacheable = true;
lbajardsilogic@0 1245 for (LayerList::const_iterator i = nonScrollables.begin();
lbajardsilogic@0 1246 i != nonScrollables.end(); ++i) {
lbajardsilogic@0 1247 if ((*i)->isLayerOpaque()) {
lbajardsilogic@0 1248 selectionCacheable = false;
lbajardsilogic@0 1249 break;
lbajardsilogic@0 1250 }
lbajardsilogic@0 1251 }
lbajardsilogic@0 1252 }
lbajardsilogic@0 1253
lbajardsilogic@0 1254 if (selectionCacheable) {
lbajardsilogic@0 1255 QPoint localPos;
lbajardsilogic@0 1256 bool closeToLeft, closeToRight;
lbajardsilogic@0 1257 if (shouldIlluminateLocalSelection(localPos, closeToLeft, closeToRight)) {
lbajardsilogic@0 1258 selectionCacheable = false;
lbajardsilogic@0 1259 }
lbajardsilogic@0 1260 }
lbajardsilogic@0 1261
lbajardsilogic@0 1262 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 1263 std::cerr << "View(" << this << ")::paintEvent: have " << scrollables.size()
lbajardsilogic@0 1264 << " scrollable back layers and " << nonScrollables.size()
lbajardsilogic@0 1265 << " non-scrollable front layers" << std::endl;
lbajardsilogic@0 1266 std::cerr << "haveSelections " << haveSelections << ", selectionCacheable "
lbajardsilogic@0 1267 << selectionCacheable << ", m_selectionCached " << m_selectionCached << std::endl;
lbajardsilogic@0 1268 #endif
lbajardsilogic@0 1269
lbajardsilogic@0 1270 if (layersChanged || scrollables.empty() ||
lbajardsilogic@0 1271 (haveSelections && (selectionCacheable != m_selectionCached))) {
lbajardsilogic@0 1272 delete m_cache;
lbajardsilogic@0 1273 m_cache = 0;
lbajardsilogic@0 1274 m_selectionCached = false;
lbajardsilogic@0 1275 }
lbajardsilogic@0 1276
lbajardsilogic@0 1277 if (!scrollables.empty()) {
lbajardsilogic@0 1278
lbajardsilogic@0 1279 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 1280 std::cerr << "View(" << this << "): cache " << m_cache << ", cache zoom "
lbajardsilogic@0 1281 << m_cacheZoomLevel << ", zoom " << m_zoomLevel << std::endl;
lbajardsilogic@0 1282 #endif
lbajardsilogic@0 1283
lbajardsilogic@0 1284 if (!m_cache ||
lbajardsilogic@0 1285 m_cacheZoomLevel != m_zoomLevel ||
lbajardsilogic@0 1286 width() != m_cache->width() ||
lbajardsilogic@0 1287 height() != m_cache->height()) {
lbajardsilogic@0 1288
lbajardsilogic@0 1289 // cache is not valid
lbajardsilogic@0 1290
lbajardsilogic@0 1291 if (cacheRect.width() < width()/10) {
lbajardsilogic@0 1292 delete m_cache;
lbajardsilogic@0 1293 m_cache = 0;
lbajardsilogic@0 1294 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 1295 std::cerr << "View(" << this << ")::paintEvent: small repaint, not bothering to recreate cache" << std::endl;
lbajardsilogic@0 1296 #endif
lbajardsilogic@0 1297 } else {
lbajardsilogic@0 1298 delete m_cache;
lbajardsilogic@0 1299 m_cache = new QPixmap(width(), height());
lbajardsilogic@0 1300 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 1301 std::cerr << "View(" << this << ")::paintEvent: recreated cache" << std::endl;
lbajardsilogic@0 1302 #endif
lbajardsilogic@0 1303 cacheRect = rect();
lbajardsilogic@0 1304 repaintCache = true;
lbajardsilogic@0 1305 }
lbajardsilogic@0 1306
lbajardsilogic@0 1307 } else if (m_cacheCentreFrame != m_centreFrame) {
lbajardsilogic@0 1308
lbajardsilogic@0 1309 long dx =
lbajardsilogic@0 1310 getXForFrame(m_cacheCentreFrame) -
lbajardsilogic@0 1311 getXForFrame(m_centreFrame);
lbajardsilogic@0 1312
lbajardsilogic@0 1313 if (dx > -width() && dx < width()) {
lbajardsilogic@0 1314 #if defined(Q_WS_WIN32) || defined(Q_WS_MAC)
lbajardsilogic@0 1315 // Copying a pixmap to itself doesn't work properly on Windows
lbajardsilogic@0 1316 // or Mac (it only works when moving in one direction)
lbajardsilogic@0 1317 static QPixmap *tmpPixmap = 0;
lbajardsilogic@0 1318 if (!tmpPixmap ||
lbajardsilogic@0 1319 tmpPixmap->width() != width() ||
lbajardsilogic@0 1320 tmpPixmap->height() != height()) {
lbajardsilogic@0 1321 delete tmpPixmap;
lbajardsilogic@0 1322 tmpPixmap = new QPixmap(width(), height());
lbajardsilogic@0 1323 }
lbajardsilogic@0 1324 paint.begin(tmpPixmap);
lbajardsilogic@0 1325 paint.drawPixmap(0, 0, *m_cache);
lbajardsilogic@0 1326 paint.end();
lbajardsilogic@0 1327 paint.begin(m_cache);
lbajardsilogic@0 1328 paint.drawPixmap(dx, 0, *tmpPixmap);
lbajardsilogic@0 1329 paint.end();
lbajardsilogic@0 1330 #else
lbajardsilogic@0 1331 // But it seems to be fine on X11
lbajardsilogic@0 1332 paint.begin(m_cache);
lbajardsilogic@0 1333 paint.drawPixmap(dx, 0, *m_cache);
lbajardsilogic@0 1334 paint.end();
lbajardsilogic@0 1335 #endif
lbajardsilogic@0 1336
lbajardsilogic@0 1337 if (dx < 0) {
lbajardsilogic@0 1338 cacheRect = QRect(width() + dx, 0, -dx, height());
lbajardsilogic@0 1339 } else {
lbajardsilogic@0 1340 cacheRect = QRect(0, 0, dx, height());
lbajardsilogic@0 1341 }
lbajardsilogic@0 1342 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 1343 std::cerr << "View(" << this << ")::paintEvent: scrolled cache by " << dx << std::endl;
lbajardsilogic@0 1344 #endif
lbajardsilogic@0 1345 } else {
lbajardsilogic@0 1346 cacheRect = rect();
lbajardsilogic@0 1347 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 1348 std::cerr << "View(" << this << ")::paintEvent: scrolling too far" << std::endl;
lbajardsilogic@0 1349 #endif
lbajardsilogic@0 1350 }
lbajardsilogic@0 1351 repaintCache = true;
lbajardsilogic@0 1352
lbajardsilogic@0 1353 } else {
lbajardsilogic@0 1354 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 1355 std::cerr << "View(" << this << ")::paintEvent: cache is good" << std::endl;
lbajardsilogic@0 1356 #endif
lbajardsilogic@0 1357 paint.begin(this);
lbajardsilogic@0 1358 paint.drawPixmap(cacheRect, *m_cache, cacheRect);
lbajardsilogic@0 1359 paint.end();
lbajardsilogic@0 1360 QFrame::paintEvent(e);
lbajardsilogic@0 1361 paintedCacheRect = true;
lbajardsilogic@0 1362 }
lbajardsilogic@0 1363
lbajardsilogic@0 1364 m_cacheCentreFrame = m_centreFrame;
lbajardsilogic@0 1365 m_cacheZoomLevel = m_zoomLevel;
lbajardsilogic@0 1366 }
lbajardsilogic@0 1367
lbajardsilogic@0 1368 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 1369 // std::cerr << "View(" << this << ")::paintEvent: cacheRect " << cacheRect << ", nonCacheRect " << (nonCacheRect | cacheRect) << ", repaintCache " << repaintCache << ", paintedCacheRect " << paintedCacheRect << std::endl;
lbajardsilogic@0 1370 #endif
lbajardsilogic@0 1371
lbajardsilogic@0 1372 // Scrollable (cacheable) items first
lbajardsilogic@0 1373
lbajardsilogic@0 1374 if (!paintedCacheRect) {
lbajardsilogic@0 1375
lbajardsilogic@0 1376 if (repaintCache) paint.begin(m_cache);
lbajardsilogic@0 1377 else paint.begin(this);
lbajardsilogic@0 1378
lbajardsilogic@0 1379 paint.setClipRect(cacheRect);
lbajardsilogic@0 1380
lbajardsilogic@0 1381 if (hasLightBackground()) {
lbajardsilogic@0 1382 paint.setPen(Qt::white);
lbajardsilogic@0 1383 paint.setBrush(Qt::white);
lbajardsilogic@0 1384 } else {
lbajardsilogic@0 1385 paint.setPen(Qt::black);
lbajardsilogic@0 1386 paint.setBrush(Qt::black);
lbajardsilogic@0 1387 }
lbajardsilogic@0 1388 paint.drawRect(cacheRect);
lbajardsilogic@0 1389
lbajardsilogic@0 1390 paint.setPen(Qt::black);
lbajardsilogic@0 1391 paint.setBrush(Qt::NoBrush);
lbajardsilogic@0 1392
lbajardsilogic@0 1393 for (LayerList::iterator i = scrollables.begin(); i != scrollables.end(); ++i) {
lbajardsilogic@0 1394 paint.setRenderHint(QPainter::Antialiasing, false);
lbajardsilogic@0 1395 paint.save();
lbajardsilogic@0 1396 (*i)->paint(this, paint, cacheRect);
lbajardsilogic@0 1397 paint.restore();
lbajardsilogic@0 1398 }
lbajardsilogic@0 1399
lbajardsilogic@0 1400 if (haveSelections && selectionCacheable) {
lbajardsilogic@0 1401 drawSelections(paint);
lbajardsilogic@0 1402 m_selectionCached = repaintCache;
lbajardsilogic@0 1403 selectionDrawn = true;
lbajardsilogic@0 1404 }
lbajardsilogic@0 1405
lbajardsilogic@0 1406 paint.end();
lbajardsilogic@0 1407
lbajardsilogic@0 1408 if (repaintCache) {
lbajardsilogic@0 1409 cacheRect |= (e ? e->rect() : rect());
lbajardsilogic@0 1410 paint.begin(this);
lbajardsilogic@0 1411 paint.drawPixmap(cacheRect, *m_cache, cacheRect);
lbajardsilogic@0 1412 paint.end();
lbajardsilogic@0 1413 }
lbajardsilogic@0 1414 }
lbajardsilogic@0 1415
lbajardsilogic@0 1416 // Now non-cacheable items. We always need to redraw the
lbajardsilogic@0 1417 // non-cacheable items across at least the area we drew of the
lbajardsilogic@0 1418 // cacheable items.
lbajardsilogic@0 1419
lbajardsilogic@0 1420 nonCacheRect |= cacheRect;
lbajardsilogic@0 1421
lbajardsilogic@0 1422 paint.begin(this);
lbajardsilogic@0 1423 paint.setClipRect(nonCacheRect);
lbajardsilogic@0 1424
lbajardsilogic@0 1425 if (scrollables.empty()) {
lbajardsilogic@0 1426 if (hasLightBackground()) {
lbajardsilogic@0 1427 paint.setPen(Qt::white);
lbajardsilogic@0 1428 paint.setBrush(Qt::white);
lbajardsilogic@0 1429 } else {
lbajardsilogic@0 1430 paint.setPen(Qt::black);
lbajardsilogic@0 1431 paint.setBrush(Qt::black);
lbajardsilogic@0 1432 }
lbajardsilogic@0 1433 paint.drawRect(nonCacheRect);
lbajardsilogic@0 1434 }
lbajardsilogic@0 1435
lbajardsilogic@0 1436 paint.setPen(Qt::black);
lbajardsilogic@0 1437 paint.setBrush(Qt::NoBrush);
lbajardsilogic@0 1438
lbajardsilogic@0 1439 for (LayerList::iterator i = nonScrollables.begin(); i != nonScrollables.end(); ++i) {
lbajardsilogic@0 1440 // Profiler profiler2("View::paintEvent non-cacheable");
lbajardsilogic@0 1441 (*i)->paint(this, paint, nonCacheRect);
lbajardsilogic@0 1442 }
lbajardsilogic@0 1443
lbajardsilogic@0 1444 paint.end();
lbajardsilogic@0 1445
lbajardsilogic@0 1446 paint.begin(this);
lbajardsilogic@0 1447 if (e) paint.setClipRect(e->rect());
lbajardsilogic@0 1448 if (!m_selectionCached) {
lbajardsilogic@0 1449 drawSelections(paint);
lbajardsilogic@0 1450 }
lbajardsilogic@0 1451 paint.end();
lbajardsilogic@0 1452
lbajardsilogic@0 1453 bool showPlayPointer = true;
lbajardsilogic@0 1454 if (m_followPlay == PlaybackScrollContinuous) {
lbajardsilogic@0 1455 showPlayPointer = false;
lbajardsilogic@0 1456 } else if (long(m_playPointerFrame) <= getStartFrame() ||
lbajardsilogic@0 1457 m_playPointerFrame >= getEndFrame()) {
lbajardsilogic@0 1458 showPlayPointer = false;
lbajardsilogic@0 1459 } else if (m_manager && !m_manager->isPlaying()) {
lbajardsilogic@0 1460 if (m_playPointerFrame == getCentreFrame() &&
lbajardsilogic@0 1461 m_followPlay != PlaybackIgnore) {
lbajardsilogic@0 1462 showPlayPointer = false;
lbajardsilogic@0 1463 }
lbajardsilogic@0 1464 }
lbajardsilogic@0 1465
lbajardsilogic@0 1466 if (showPlayPointer) {
lbajardsilogic@0 1467
lbajardsilogic@0 1468 paint.begin(this);
lbajardsilogic@0 1469
lbajardsilogic@0 1470 int playx = getXForFrame(m_playPointerFrame);
lbajardsilogic@0 1471
lbajardsilogic@0 1472 paint.setPen(Qt::black);
lbajardsilogic@0 1473 paint.drawLine(playx - 1, 0, playx - 1, height() - 1);
lbajardsilogic@0 1474 paint.drawLine(playx + 1, 0, playx + 1, height() - 1);
lbajardsilogic@0 1475 paint.drawPoint(playx, 0);
lbajardsilogic@0 1476 paint.drawPoint(playx, height() - 1);
lbajardsilogic@0 1477 paint.setPen(Qt::white);
lbajardsilogic@0 1478 paint.drawLine(playx, 1, playx, height() - 2);
lbajardsilogic@0 1479
lbajardsilogic@0 1480 paint.end();
lbajardsilogic@0 1481 }
lbajardsilogic@0 1482
lbajardsilogic@0 1483 QFrame::paintEvent(e);
lbajardsilogic@0 1484 }
lbajardsilogic@0 1485
lbajardsilogic@0 1486 void
lbajardsilogic@0 1487 View::drawSelections(QPainter &paint)
lbajardsilogic@0 1488 {
lbajardsilogic@0 1489 if (!hasTopLayerTimeXAxis()) return;
lbajardsilogic@0 1490
lbajardsilogic@0 1491 MultiSelection::SelectionList selections;
lbajardsilogic@0 1492
lbajardsilogic@0 1493 if (m_manager) {
lbajardsilogic@0 1494 selections = m_manager->getSelections();
lbajardsilogic@0 1495 if (m_manager->haveInProgressSelection()) {
lbajardsilogic@0 1496 bool exclusive;
lbajardsilogic@0 1497 Selection inProgressSelection =
lbajardsilogic@0 1498 m_manager->getInProgressSelection(exclusive);
lbajardsilogic@0 1499 if (exclusive) selections.clear();
lbajardsilogic@0 1500 selections.insert(inProgressSelection);
lbajardsilogic@0 1501 }
lbajardsilogic@0 1502 }
lbajardsilogic@0 1503
lbajardsilogic@0 1504 paint.save();
lbajardsilogic@0 1505
lbajardsilogic@0 1506 bool translucent = !areLayerColoursSignificant();
lbajardsilogic@0 1507
lbajardsilogic@0 1508 if (translucent) {
lbajardsilogic@0 1509 paint.setBrush(QColor(150, 150, 255, 80));
lbajardsilogic@0 1510 } else {
lbajardsilogic@0 1511 paint.setBrush(Qt::NoBrush);
lbajardsilogic@0 1512 }
lbajardsilogic@0 1513
lbajardsilogic@0 1514 int sampleRate = getModelsSampleRate();
lbajardsilogic@0 1515
lbajardsilogic@0 1516 QPoint localPos;
lbajardsilogic@0 1517 long illuminateFrame = -1;
lbajardsilogic@0 1518 bool closeToLeft, closeToRight;
lbajardsilogic@0 1519
lbajardsilogic@0 1520 if (shouldIlluminateLocalSelection(localPos, closeToLeft, closeToRight)) {
lbajardsilogic@0 1521 illuminateFrame = getFrameForX(localPos.x());
lbajardsilogic@0 1522 }
lbajardsilogic@0 1523
lbajardsilogic@0 1524 const QFontMetrics &metrics = paint.fontMetrics();
lbajardsilogic@0 1525
lbajardsilogic@0 1526 for (MultiSelection::SelectionList::iterator i = selections.begin();
lbajardsilogic@0 1527 i != selections.end(); ++i) {
lbajardsilogic@0 1528
lbajardsilogic@0 1529 int p0 = getXForFrame(i->getStartFrame());
lbajardsilogic@0 1530 int p1 = getXForFrame(i->getEndFrame());
lbajardsilogic@0 1531
lbajardsilogic@0 1532 if (p1 < 0 || p0 > width()) continue;
lbajardsilogic@0 1533
lbajardsilogic@0 1534 #ifdef DEBUG_VIEW_WIDGET_PAINT
lbajardsilogic@0 1535 std::cerr << "View::drawSelections: " << p0 << ",-1 [" << (p1-p0) << "x" << (height()+1) << "]" << std::endl;
lbajardsilogic@0 1536 #endif
lbajardsilogic@0 1537
lbajardsilogic@0 1538 bool illuminateThis =
lbajardsilogic@0 1539 (illuminateFrame >= 0 && i->contains(illuminateFrame));
lbajardsilogic@0 1540
lbajardsilogic@0 1541 paint.setPen(QColor(150, 150, 255));
lbajardsilogic@0 1542
lbajardsilogic@0 1543 if (translucent && shouldLabelSelections()) {
lbajardsilogic@0 1544 paint.drawRect(p0, -1, p1 - p0, height() + 1);
lbajardsilogic@0 1545 } else {
lbajardsilogic@0 1546 // Make the top & bottom lines of the box visible if we
lbajardsilogic@0 1547 // are lacking some of the other visual cues. There's no
lbajardsilogic@0 1548 // particular logic to this, it's just a question of what
lbajardsilogic@0 1549 // I happen to think looks nice.
lbajardsilogic@0 1550 paint.drawRect(p0, 0, p1 - p0, height() - 1);
lbajardsilogic@0 1551 }
lbajardsilogic@0 1552
lbajardsilogic@0 1553 if (illuminateThis) {
lbajardsilogic@0 1554 paint.save();
lbajardsilogic@0 1555 if (hasLightBackground()) {
lbajardsilogic@0 1556 paint.setPen(QPen(Qt::black, 2));
lbajardsilogic@0 1557 } else {
lbajardsilogic@0 1558 paint.setPen(QPen(Qt::white, 2));
lbajardsilogic@0 1559 }
lbajardsilogic@0 1560 if (closeToLeft) {
lbajardsilogic@0 1561 paint.drawLine(p0, 1, p1, 1);
lbajardsilogic@0 1562 paint.drawLine(p0, 0, p0, height());
lbajardsilogic@0 1563 paint.drawLine(p0, height() - 1, p1, height() - 1);
lbajardsilogic@0 1564 } else if (closeToRight) {
lbajardsilogic@0 1565 paint.drawLine(p0, 1, p1, 1);
lbajardsilogic@0 1566 paint.drawLine(p1, 0, p1, height());
lbajardsilogic@0 1567 paint.drawLine(p0, height() - 1, p1, height() - 1);
lbajardsilogic@0 1568 } else {
lbajardsilogic@0 1569 paint.setBrush(Qt::NoBrush);
lbajardsilogic@0 1570 paint.drawRect(p0, 1, p1 - p0, height() - 2);
lbajardsilogic@0 1571 }
lbajardsilogic@0 1572 paint.restore();
lbajardsilogic@0 1573 }
lbajardsilogic@0 1574
lbajardsilogic@0 1575 if (sampleRate && shouldLabelSelections() && m_manager &&
lbajardsilogic@0 1576 m_manager->shouldShowSelectionExtents()) {
lbajardsilogic@0 1577
lbajardsilogic@0 1578 QString startText = QString("%1 / %2")
lbajardsilogic@0 1579 .arg(QString::fromStdString
lbajardsilogic@0 1580 (RealTime::frame2RealTime
lbajardsilogic@0 1581 (i->getStartFrame(), sampleRate).toText(true)))
lbajardsilogic@0 1582 .arg(i->getStartFrame());
lbajardsilogic@0 1583
lbajardsilogic@0 1584 QString endText = QString(" %1 / %2")
lbajardsilogic@0 1585 .arg(QString::fromStdString
lbajardsilogic@0 1586 (RealTime::frame2RealTime
lbajardsilogic@0 1587 (i->getEndFrame(), sampleRate).toText(true)))
lbajardsilogic@0 1588 .arg(i->getEndFrame());
lbajardsilogic@0 1589
lbajardsilogic@0 1590 QString durationText = QString("(%1 / %2) ")
lbajardsilogic@0 1591 .arg(QString::fromStdString
lbajardsilogic@0 1592 (RealTime::frame2RealTime
lbajardsilogic@0 1593 (i->getEndFrame() - i->getStartFrame(), sampleRate)
lbajardsilogic@0 1594 .toText(true)))
lbajardsilogic@0 1595 .arg(i->getEndFrame() - i->getStartFrame());
lbajardsilogic@0 1596
lbajardsilogic@0 1597 int sw = metrics.width(startText),
lbajardsilogic@0 1598 ew = metrics.width(endText),
lbajardsilogic@0 1599 dw = metrics.width(durationText);
lbajardsilogic@0 1600
lbajardsilogic@0 1601 int sy = metrics.ascent() + metrics.height() + 4;
lbajardsilogic@0 1602 int ey = sy;
lbajardsilogic@0 1603 int dy = sy + metrics.height();
lbajardsilogic@0 1604
lbajardsilogic@0 1605 int sx = p0 + 2;
lbajardsilogic@0 1606 int ex = sx;
lbajardsilogic@0 1607 int dx = sx;
lbajardsilogic@0 1608
lbajardsilogic@0 1609 if (sw + ew > (p1 - p0)) {
lbajardsilogic@0 1610 ey += metrics.height();
lbajardsilogic@0 1611 dy += metrics.height();
lbajardsilogic@0 1612 }
lbajardsilogic@0 1613
lbajardsilogic@0 1614 if (ew < (p1 - p0)) {
lbajardsilogic@0 1615 ex = p1 - 2 - ew;
lbajardsilogic@0 1616 }
lbajardsilogic@0 1617
lbajardsilogic@0 1618 if (dw < (p1 - p0)) {
lbajardsilogic@0 1619 dx = p1 - 2 - dw;
lbajardsilogic@0 1620 }
lbajardsilogic@0 1621
lbajardsilogic@0 1622 paint.drawText(sx, sy, startText);
lbajardsilogic@0 1623 paint.drawText(ex, ey, endText);
lbajardsilogic@0 1624 paint.drawText(dx, dy, durationText);
lbajardsilogic@0 1625 }
lbajardsilogic@0 1626 }
lbajardsilogic@0 1627
lbajardsilogic@0 1628 paint.restore();
lbajardsilogic@0 1629 }
lbajardsilogic@0 1630
lbajardsilogic@0 1631 bool
lbajardsilogic@0 1632 View::render(QPainter &paint, int xorigin, size_t f0, size_t f1)
lbajardsilogic@0 1633 {
lbajardsilogic@0 1634 size_t x0 = f0 / m_zoomLevel;
lbajardsilogic@0 1635 size_t x1 = f1 / m_zoomLevel;
lbajardsilogic@0 1636
lbajardsilogic@0 1637 size_t w = x1 - x0;
lbajardsilogic@0 1638
lbajardsilogic@0 1639 size_t origCentreFrame = m_centreFrame;
lbajardsilogic@0 1640
lbajardsilogic@0 1641 bool someLayersIncomplete = false;
lbajardsilogic@0 1642
lbajardsilogic@0 1643 for (LayerList::iterator i = m_layers.begin();
lbajardsilogic@0 1644 i != m_layers.end(); ++i) {
lbajardsilogic@0 1645
lbajardsilogic@0 1646 int c = (*i)->getCompletion(this);
lbajardsilogic@0 1647 if (c < 100) {
lbajardsilogic@0 1648 someLayersIncomplete = true;
lbajardsilogic@0 1649 break;
lbajardsilogic@0 1650 }
lbajardsilogic@0 1651 }
lbajardsilogic@0 1652
lbajardsilogic@0 1653 if (someLayersIncomplete) {
lbajardsilogic@0 1654
lbajardsilogic@0 1655 QProgressDialog progress(tr("Waiting for layers to be ready..."),
lbajardsilogic@0 1656 tr("Cancel"), 0, 100, this);
lbajardsilogic@0 1657
lbajardsilogic@0 1658 int layerCompletion = 0;
lbajardsilogic@0 1659
lbajardsilogic@0 1660 while (layerCompletion < 100) {
lbajardsilogic@0 1661
lbajardsilogic@0 1662 for (LayerList::iterator i = m_layers.begin();
lbajardsilogic@0 1663 i != m_layers.end(); ++i) {
lbajardsilogic@0 1664
lbajardsilogic@0 1665 int c = (*i)->getCompletion(this);
lbajardsilogic@0 1666 if (i == m_layers.begin() || c < layerCompletion) {
lbajardsilogic@0 1667 layerCompletion = c;
lbajardsilogic@0 1668 }
lbajardsilogic@0 1669 }
lbajardsilogic@0 1670
lbajardsilogic@0 1671 if (layerCompletion >= 100) break;
lbajardsilogic@0 1672
lbajardsilogic@0 1673 progress.setValue(layerCompletion);
lbajardsilogic@0 1674 qApp->processEvents();
lbajardsilogic@0 1675 if (progress.wasCanceled()) {
lbajardsilogic@0 1676 update();
lbajardsilogic@0 1677 return false;
lbajardsilogic@0 1678 }
lbajardsilogic@0 1679
lbajardsilogic@0 1680 usleep(50000);
lbajardsilogic@0 1681 }
lbajardsilogic@0 1682 }
lbajardsilogic@0 1683
lbajardsilogic@0 1684 QProgressDialog progress(tr("Rendering image..."),
lbajardsilogic@0 1685 tr("Cancel"), 0, w / width(), this);
lbajardsilogic@0 1686
lbajardsilogic@0 1687 for (size_t x = 0; x < w; x += width()) {
lbajardsilogic@0 1688
lbajardsilogic@0 1689 progress.setValue(x / width());
lbajardsilogic@0 1690 qApp->processEvents();
lbajardsilogic@0 1691 if (progress.wasCanceled()) {
lbajardsilogic@0 1692 m_centreFrame = origCentreFrame;
lbajardsilogic@0 1693 update();
lbajardsilogic@0 1694 return false;
lbajardsilogic@0 1695 }
lbajardsilogic@0 1696
lbajardsilogic@0 1697 m_centreFrame = f0 + (x + width()/2) * m_zoomLevel;
lbajardsilogic@0 1698
lbajardsilogic@0 1699 QRect chunk(0, 0, width(), height());
lbajardsilogic@0 1700
lbajardsilogic@0 1701 if (hasLightBackground()) {
lbajardsilogic@0 1702 paint.setPen(Qt::white);
lbajardsilogic@0 1703 paint.setBrush(Qt::white);
lbajardsilogic@0 1704 } else {
lbajardsilogic@0 1705 paint.setPen(Qt::black);
lbajardsilogic@0 1706 paint.setBrush(Qt::black);
lbajardsilogic@0 1707 }
lbajardsilogic@0 1708
lbajardsilogic@0 1709 paint.drawRect(QRect(xorigin + x, 0, width(), height()));
lbajardsilogic@0 1710
lbajardsilogic@0 1711 paint.setPen(Qt::black);
lbajardsilogic@0 1712 paint.setBrush(Qt::NoBrush);
lbajardsilogic@0 1713
lbajardsilogic@0 1714 for (LayerList::iterator i = m_layers.begin();
lbajardsilogic@0 1715 i != m_layers.end(); ++i) {
lbajardsilogic@0 1716
lbajardsilogic@0 1717 paint.setRenderHint(QPainter::Antialiasing, false);
lbajardsilogic@0 1718
lbajardsilogic@0 1719 paint.save();
lbajardsilogic@0 1720 paint.translate(xorigin + x, 0);
lbajardsilogic@0 1721
lbajardsilogic@0 1722 std::cerr << "Centre frame now: " << m_centreFrame << " drawing to " << chunk.x() + x + xorigin << ", " << chunk.width() << std::endl;
lbajardsilogic@0 1723
lbajardsilogic@0 1724 (*i)->paint(this, paint, chunk);
lbajardsilogic@0 1725
lbajardsilogic@0 1726 paint.restore();
lbajardsilogic@0 1727 }
lbajardsilogic@0 1728 }
lbajardsilogic@0 1729
lbajardsilogic@0 1730 m_centreFrame = origCentreFrame;
lbajardsilogic@0 1731 update();
lbajardsilogic@0 1732 return true;
lbajardsilogic@0 1733 }
lbajardsilogic@0 1734
lbajardsilogic@0 1735 QImage *
lbajardsilogic@0 1736 View::toNewImage()
lbajardsilogic@0 1737 {
lbajardsilogic@0 1738 size_t f0 = getModelsStartFrame();
lbajardsilogic@0 1739 size_t f1 = getModelsEndFrame();
lbajardsilogic@0 1740
lbajardsilogic@0 1741 return toNewImage(f0, f1);
lbajardsilogic@0 1742 }
lbajardsilogic@0 1743
lbajardsilogic@0 1744 QImage *
lbajardsilogic@0 1745 View::toNewImage(size_t f0, size_t f1)
lbajardsilogic@0 1746 {
lbajardsilogic@0 1747 size_t x0 = f0 / getZoomLevel();
lbajardsilogic@0 1748 size_t x1 = f1 / getZoomLevel();
lbajardsilogic@0 1749
lbajardsilogic@0 1750 QImage *image = new QImage(x1 - x0, height(), QImage::Format_RGB32);
lbajardsilogic@0 1751
lbajardsilogic@0 1752 QPainter *paint = new QPainter(image);
lbajardsilogic@0 1753 if (!render(*paint, 0, f0, f1)) {
lbajardsilogic@0 1754 delete paint;
lbajardsilogic@0 1755 delete image;
lbajardsilogic@0 1756 return 0;
lbajardsilogic@0 1757 } else {
lbajardsilogic@0 1758 delete paint;
lbajardsilogic@0 1759 return image;
lbajardsilogic@0 1760 }
lbajardsilogic@0 1761 }
lbajardsilogic@0 1762
lbajardsilogic@0 1763 QSize
lbajardsilogic@0 1764 View::getImageSize()
lbajardsilogic@0 1765 {
lbajardsilogic@0 1766 size_t f0 = getModelsStartFrame();
lbajardsilogic@0 1767 size_t f1 = getModelsEndFrame();
lbajardsilogic@0 1768
lbajardsilogic@0 1769 return getImageSize(f0, f1);
lbajardsilogic@0 1770 }
lbajardsilogic@0 1771
lbajardsilogic@0 1772 QSize
lbajardsilogic@0 1773 View::getImageSize(size_t f0, size_t f1)
lbajardsilogic@0 1774 {
lbajardsilogic@0 1775 size_t x0 = f0 / getZoomLevel();
lbajardsilogic@0 1776 size_t x1 = f1 / getZoomLevel();
lbajardsilogic@0 1777
lbajardsilogic@0 1778 return QSize(x1 - x0, height());
lbajardsilogic@0 1779 }
lbajardsilogic@0 1780
lbajardsilogic@0 1781 QString
lbajardsilogic@0 1782 View::toXmlString(QString indent, QString extraAttributes) const
lbajardsilogic@0 1783 {
lbajardsilogic@0 1784 QString s;
lbajardsilogic@0 1785
lbajardsilogic@0 1786 s += indent;
lbajardsilogic@0 1787
lbajardsilogic@0 1788 s += QString("<view "
lbajardsilogic@0 1789 "centre=\"%1\" "
lbajardsilogic@0 1790 "zoom=\"%2\" "
lbajardsilogic@0 1791 "followPan=\"%3\" "
lbajardsilogic@0 1792 "followZoom=\"%4\" "
lbajardsilogic@0 1793 "tracking=\"%5\" "
lbajardsilogic@0 1794 " %6>\n")
lbajardsilogic@0 1795 .arg(m_centreFrame)
lbajardsilogic@0 1796 .arg(m_zoomLevel)
lbajardsilogic@0 1797 .arg(m_followPan)
lbajardsilogic@0 1798 .arg(m_followZoom)
lbajardsilogic@0 1799 .arg(m_followPlay == PlaybackScrollContinuous ? "scroll" :
lbajardsilogic@0 1800 m_followPlay == PlaybackScrollPage ? "page" : "ignore")
lbajardsilogic@0 1801 .arg(extraAttributes);
lbajardsilogic@0 1802
lbajardsilogic@0 1803 for (size_t i = 0; i < m_layers.size(); ++i) {
lbajardsilogic@0 1804 bool visible = !m_layers[i]->isLayerDormant(this);
lbajardsilogic@0 1805 s += m_layers[i]->toXmlString(indent + " ",
lbajardsilogic@0 1806 QString("visible=\"%1\"")
lbajardsilogic@0 1807 .arg(visible ? "true" : "false"));
lbajardsilogic@0 1808 }
lbajardsilogic@0 1809
lbajardsilogic@0 1810 s += indent + "</view>\n";
lbajardsilogic@0 1811
lbajardsilogic@0 1812 return s;
lbajardsilogic@0 1813 }
lbajardsilogic@0 1814
lbajardsilogic@23 1815 QString
lbajardsilogic@23 1816 View::toEasaierXmlString(QString indent, QString extraAttributes) const
lbajardsilogic@23 1817 {
lbajardsilogic@23 1818 QString s;
lbajardsilogic@23 1819
lbajardsilogic@23 1820 s += indent;
lbajardsilogic@23 1821
lbajardsilogic@23 1822 s += QString("<view "
lbajardsilogic@23 1823 "centre=\"%1\" "
lbajardsilogic@23 1824 "zoom=\"%2\" "
lbajardsilogic@23 1825 "followPan=\"%3\" "
lbajardsilogic@23 1826 "followZoom=\"%4\" "
lbajardsilogic@23 1827 "tracking=\"%5\" "
lbajardsilogic@23 1828 "light=\"%6\" %7>\n")
lbajardsilogic@23 1829 .arg(m_centreFrame)
lbajardsilogic@23 1830 .arg(m_zoomLevel)
lbajardsilogic@23 1831 .arg(m_followPan)
lbajardsilogic@23 1832 .arg(m_followZoom)
lbajardsilogic@23 1833 .arg(m_followPlay == PlaybackScrollContinuous ? "scroll" :
lbajardsilogic@23 1834 m_followPlay == PlaybackScrollPage ? "page" : "ignore")
lbajardsilogic@23 1835 .arg(m_lightBackground)
lbajardsilogic@23 1836 .arg(extraAttributes);
lbajardsilogic@23 1837
lbajardsilogic@23 1838 for (size_t i = 0; i < m_layers.size(); ++i) {
lbajardsilogic@23 1839 s += m_layers[i]->toEasaierXmlString(indent + " ");
lbajardsilogic@23 1840 }
lbajardsilogic@23 1841
lbajardsilogic@23 1842 s += indent + "</view>\n";
lbajardsilogic@23 1843
lbajardsilogic@23 1844 return s;
lbajardsilogic@23 1845 }
lbajardsilogic@23 1846
lbajardsilogic@0 1847 ViewPropertyContainer::ViewPropertyContainer(View *v) :
lbajardsilogic@0 1848 m_v(v)
lbajardsilogic@0 1849 {
lbajardsilogic@0 1850 connect(m_v, SIGNAL(propertyChanged(PropertyContainer::PropertyName)),
lbajardsilogic@0 1851 this, SIGNAL(propertyChanged(PropertyContainer::PropertyName)));
lbajardsilogic@0 1852 }
lbajardsilogic@0 1853