annotate view/Pane.cpp @ 183:5f86ae638b04

* Omit translucent blue fill for selection rectangles that are superimposed over layers that use colours for meaningful purposes such as the spectrogram (CHARM change request)
author Chris Cannam
date Fri, 24 Nov 2006 16:56:15 +0000
parents 42118892f428
children e7cf6044c2a0
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@182 7 This file copyright 2006 Chris Cannam and QMUL.
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 "Pane.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/RealTime.h"
Chris@127 21 #include "base/Profiler.h"
Chris@128 22 #include "ViewManager.h"
Chris@127 23 #include "base/CommandHistory.h"
Chris@127 24 #include "layer/WaveformLayer.h"
Chris@127 25
Chris@127 26 #include <QPaintEvent>
Chris@127 27 #include <QPainter>
Chris@127 28 #include <iostream>
Chris@127 29 #include <cmath>
Chris@127 30
Chris@133 31 //!!! for HUD -- pull out into a separate class
Chris@133 32 #include <QFrame>
Chris@133 33 #include <QGridLayout>
Chris@133 34 #include <QPushButton>
Chris@133 35 #include "widgets/Thumbwheel.h"
Chris@172 36 #include "widgets/Panner.h"
Chris@133 37
Chris@127 38 using std::cerr;
Chris@127 39 using std::endl;
Chris@127 40
Chris@127 41 Pane::Pane(QWidget *w) :
Chris@127 42 View(w, true),
Chris@127 43 m_identifyFeatures(false),
Chris@127 44 m_clickedInRange(false),
Chris@127 45 m_shiftPressed(false),
Chris@127 46 m_ctrlPressed(false),
Chris@127 47 m_navigating(false),
Chris@127 48 m_resizing(false),
Chris@133 49 m_centreLineVisible(true),
Chris@133 50 m_headsUpDisplay(0)
Chris@127 51 {
Chris@127 52 setObjectName("Pane");
Chris@127 53 setMouseTracking(true);
Chris@133 54
Chris@133 55 updateHeadsUpDisplay();
Chris@133 56 }
Chris@133 57
Chris@133 58 void
Chris@133 59 Pane::updateHeadsUpDisplay()
Chris@133 60 {
Chris@132 61 /*
Chris@132 62 int count = 0;
Chris@132 63 int currentLevel = 1;
Chris@132 64 int level = 1;
Chris@132 65 while (true) {
Chris@132 66 if (getZoomLevel() == level) currentLevel = count;
Chris@132 67 int newLevel = getZoomConstraintBlockSize(level + 1,
Chris@132 68 ZoomConstraint::RoundUp);
Chris@132 69 if (newLevel == level) break;
Chris@132 70 if (newLevel == 131072) break; //!!! just because
Chris@132 71 level = newLevel;
Chris@132 72 ++count;
Chris@132 73 }
Chris@132 74
Chris@132 75 std::cerr << "Have " << count+1 << " zoom levels" << std::endl;
Chris@132 76 */
Chris@133 77
Chris@133 78 if (!m_headsUpDisplay) {
Chris@133 79
Chris@133 80 m_headsUpDisplay = new QFrame(this);
Chris@133 81
Chris@133 82 QGridLayout *layout = new QGridLayout;
Chris@133 83 layout->setMargin(0);
Chris@133 84 layout->setSpacing(0);
Chris@133 85 m_headsUpDisplay->setLayout(layout);
Chris@133 86
Chris@133 87 m_hthumb = new Thumbwheel(Qt::Horizontal);
Chris@173 88 layout->addWidget(m_hthumb, 1, 0, 1, 2);
Chris@133 89 m_hthumb->setFixedWidth(70);
Chris@133 90 m_hthumb->setFixedHeight(16);
Chris@133 91 m_hthumb->setDefaultValue(0);
Chris@165 92 m_hthumb->setSpeed(0.6);
Chris@133 93 connect(m_hthumb, SIGNAL(valueChanged(int)), this,
Chris@133 94 SLOT(horizontalThumbwheelMoved(int)));
Chris@172 95
Chris@172 96 m_vpan = new Panner;
Chris@172 97 layout->addWidget(m_vpan, 0, 1);
Chris@173 98 m_vpan->setFixedWidth(12);
Chris@172 99 m_vpan->setFixedHeight(70);
Chris@174 100 m_vpan->setAlpha(80, 130);
Chris@174 101 connect(m_vpan, SIGNAL(rectExtentsChanged(float, float, float, float)),
Chris@174 102 this, SLOT(verticalPannerMoved(float, float, float, float)));
Chris@172 103
Chris@133 104 m_vthumb = new Thumbwheel(Qt::Vertical);
Chris@172 105 layout->addWidget(m_vthumb, 0, 2);
Chris@133 106 m_vthumb->setFixedWidth(16);
Chris@133 107 m_vthumb->setFixedHeight(70);
Chris@133 108 connect(m_vthumb, SIGNAL(valueChanged(int)), this,
Chris@133 109 SLOT(verticalThumbwheelMoved(int)));
Chris@133 110
Chris@133 111 QPushButton *reset = new QPushButton;
Chris@133 112 reset->setFixedHeight(16);
Chris@133 113 reset->setFixedWidth(16);
Chris@172 114 layout->addWidget(reset, 1, 2);
Chris@133 115 connect(reset, SIGNAL(clicked()), m_hthumb, SLOT(resetToDefault()));
Chris@133 116 connect(reset, SIGNAL(clicked()), m_vthumb, SLOT(resetToDefault()));
Chris@133 117 }
Chris@133 118
Chris@133 119 int count = 0;
Chris@133 120 int current = 0;
Chris@133 121 int level = 1;
Chris@133 122
Chris@137 123 //!!! pull out into function (presumably in View)
Chris@137 124 bool haveConstraint = false;
Chris@137 125 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end();
Chris@137 126 ++i) {
Chris@137 127 if ((*i)->getZoomConstraint() && !(*i)->supportsOtherZoomLevels()) {
Chris@137 128 haveConstraint = true;
Chris@137 129 break;
Chris@137 130 }
Chris@137 131 }
Chris@137 132
Chris@137 133 if (haveConstraint) {
Chris@137 134 while (true) {
Chris@137 135 if (getZoomLevel() == level) current = count;
Chris@137 136 int newLevel = getZoomConstraintBlockSize(level + 1,
Chris@137 137 ZoomConstraint::RoundUp);
Chris@137 138 if (newLevel == level) break;
Chris@137 139 level = newLevel;
Chris@137 140 if (++count == 50) break;
Chris@137 141 }
Chris@137 142 } else {
Chris@137 143 // if we have no particular constraints, we can really spread out
Chris@137 144 while (true) {
Chris@137 145 if (getZoomLevel() >= level) current = count;
Chris@137 146 int step = level / 10;
Chris@137 147 int pwr = 0;
Chris@137 148 while (step > 0) {
Chris@137 149 ++pwr;
Chris@137 150 step /= 2;
Chris@137 151 }
Chris@137 152 step = 1;
Chris@137 153 while (pwr > 0) {
Chris@137 154 step *= 2;
Chris@137 155 --pwr;
Chris@137 156 }
Chris@154 157 // std::cerr << level << std::endl;
Chris@137 158 level += step;
Chris@137 159 if (++count == 100 || level > 262144) break;
Chris@137 160 }
Chris@133 161 }
Chris@133 162
Chris@133 163 // std::cerr << "Have " << count << " zoom levels" << std::endl;
Chris@133 164
Chris@133 165 m_hthumb->setMinimumValue(0);
Chris@133 166 m_hthumb->setMaximumValue(count);
Chris@133 167 m_hthumb->setValue(count - current);
Chris@133 168
Chris@133 169 // std::cerr << "set value to " << count-current << std::endl;
Chris@133 170
Chris@133 171 // std::cerr << "default value is " << m_hthumb->getDefaultValue() << std::endl;
Chris@133 172
Chris@133 173 if (count != 50 && m_hthumb->getDefaultValue() == 0) {
Chris@133 174 m_hthumb->setDefaultValue(count - current);
Chris@133 175 // std::cerr << "set default value to " << m_hthumb->getDefaultValue() << std::endl;
Chris@133 176 }
Chris@133 177
Chris@133 178 Layer *layer = 0;
Chris@133 179 if (getLayerCount() > 0) layer = getLayer(getLayerCount() - 1);
Chris@133 180 if (layer) {
Chris@133 181 int defaultStep = 0;
Chris@133 182 int max = layer->getVerticalZoomSteps(defaultStep);
Chris@133 183 if (max == 0) {
Chris@133 184 m_vthumb->hide();
Chris@133 185 } else {
Chris@133 186 m_vthumb->show();
Chris@133 187 m_vthumb->setMinimumValue(0);
Chris@133 188 m_vthumb->setMaximumValue(max);
Chris@133 189 m_vthumb->setDefaultValue(defaultStep);
Chris@133 190 m_vthumb->setValue(layer->getCurrentVerticalZoomStep());
Chris@135 191
Chris@135 192 std::cerr << "Vertical thumbwheel: min 0, max " << max
Chris@135 193 << ", default " << defaultStep << ", value "
Chris@135 194 << m_vthumb->getValue() << std::endl;
Chris@135 195
Chris@133 196 }
Chris@133 197 }
Chris@133 198
Chris@174 199 updateVerticalPanner();
Chris@174 200
Chris@133 201 if (m_manager && m_manager->getZoomWheelsEnabled() &&
Chris@133 202 width() > 120 && height() > 100) {
Chris@165 203 if (!m_headsUpDisplay->isVisible()) {
Chris@165 204 m_headsUpDisplay->show();
Chris@165 205 connect(m_manager, SIGNAL(zoomLevelChanged()),
Chris@165 206 this, SLOT(zoomLevelChanged()));
Chris@165 207 }
Chris@133 208 if (m_vthumb->isVisible()) {
Chris@133 209 m_headsUpDisplay->move(width() - 86, height() - 86);
Chris@133 210 } else {
Chris@133 211 m_headsUpDisplay->move(width() - 86, height() - 51);
Chris@133 212 }
Chris@133 213 } else {
Chris@133 214 m_headsUpDisplay->hide();
Chris@133 215 if (m_manager) {
Chris@133 216 disconnect(m_manager, SIGNAL(zoomLevelChanged()),
Chris@133 217 this, SLOT(zoomLevelChanged()));
Chris@133 218 }
Chris@133 219 }
Chris@127 220 }
Chris@127 221
Chris@174 222 void
Chris@174 223 Pane::updateVerticalPanner()
Chris@174 224 {
Chris@174 225 if (!m_vpan || !m_manager || !m_manager->getZoomWheelsEnabled()) return;
Chris@174 226
Chris@174 227 float vmin, vmax, dmin, dmax;
Chris@174 228 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax) && vmax != vmin) {
Chris@174 229 float y0 = (dmin - vmin) / (vmax - vmin);
Chris@174 230 float y1 = (dmax - vmin) / (vmax - vmin);
Chris@174 231 m_vpan->blockSignals(true);
Chris@174 232 m_vpan->setRectExtents(0, 1.0 - y1, 1, y1 - y0);
Chris@174 233 m_vpan->blockSignals(false);
Chris@174 234 m_vpan->show();
Chris@174 235 } else {
Chris@174 236 m_vpan->hide();
Chris@174 237 }
Chris@174 238 }
Chris@174 239
Chris@127 240 bool
Chris@127 241 Pane::shouldIlluminateLocalFeatures(const Layer *layer, QPoint &pos) const
Chris@127 242 {
Chris@127 243 QPoint discard;
Chris@127 244 bool b0, b1;
Chris@127 245
Chris@127 246 if (layer == getSelectedLayer() &&
Chris@127 247 !shouldIlluminateLocalSelection(discard, b0, b1)) {
Chris@127 248
Chris@127 249 pos = m_identifyPoint;
Chris@127 250 return m_identifyFeatures;
Chris@127 251 }
Chris@127 252
Chris@127 253 return false;
Chris@127 254 }
Chris@127 255
Chris@127 256 bool
Chris@127 257 Pane::shouldIlluminateLocalSelection(QPoint &pos,
Chris@127 258 bool &closeToLeft,
Chris@127 259 bool &closeToRight) const
Chris@127 260 {
Chris@127 261 if (m_identifyFeatures &&
Chris@127 262 m_manager &&
Chris@127 263 m_manager->getToolMode() == ViewManager::EditMode &&
Chris@127 264 !m_manager->getSelections().empty() &&
Chris@127 265 !selectionIsBeingEdited()) {
Chris@127 266
Chris@127 267 Selection s(getSelectionAt(m_identifyPoint.x(),
Chris@127 268 closeToLeft, closeToRight));
Chris@127 269
Chris@127 270 if (!s.isEmpty()) {
Chris@127 271 if (getSelectedLayer() && getSelectedLayer()->isLayerEditable()) {
Chris@127 272
Chris@127 273 pos = m_identifyPoint;
Chris@127 274 return true;
Chris@127 275 }
Chris@127 276 }
Chris@127 277 }
Chris@127 278
Chris@127 279 return false;
Chris@127 280 }
Chris@127 281
Chris@127 282 bool
Chris@127 283 Pane::selectionIsBeingEdited() const
Chris@127 284 {
Chris@127 285 if (!m_editingSelection.isEmpty()) {
Chris@127 286 if (m_mousePos != m_clickPos &&
Chris@127 287 getFrameForX(m_mousePos.x()) != getFrameForX(m_clickPos.x())) {
Chris@127 288 return true;
Chris@127 289 }
Chris@127 290 }
Chris@127 291 return false;
Chris@127 292 }
Chris@127 293
Chris@127 294 void
Chris@127 295 Pane::setCentreLineVisible(bool visible)
Chris@127 296 {
Chris@127 297 m_centreLineVisible = visible;
Chris@127 298 update();
Chris@127 299 }
Chris@127 300
Chris@127 301 void
Chris@127 302 Pane::paintEvent(QPaintEvent *e)
Chris@127 303 {
Chris@127 304 // Profiler profiler("Pane::paintEvent", true);
Chris@127 305
Chris@127 306 QPainter paint;
Chris@127 307
Chris@127 308 QRect r(rect());
Chris@127 309
Chris@127 310 if (e) {
Chris@127 311 r = e->rect();
Chris@127 312 }
Chris@127 313 /*
Chris@127 314 paint.begin(this);
Chris@127 315 paint.setClipRect(r);
Chris@127 316
Chris@127 317 if (hasLightBackground()) {
Chris@127 318 paint.setPen(Qt::white);
Chris@127 319 paint.setBrush(Qt::white);
Chris@127 320 } else {
Chris@127 321 paint.setPen(Qt::black);
Chris@127 322 paint.setBrush(Qt::black);
Chris@127 323 }
Chris@127 324 paint.drawRect(r);
Chris@127 325
Chris@127 326 paint.end();
Chris@127 327 */
Chris@127 328 View::paintEvent(e);
Chris@127 329
Chris@127 330 paint.begin(this);
Chris@127 331
Chris@127 332 if (e) {
Chris@127 333 paint.setClipRect(r);
Chris@127 334 }
Chris@127 335
Chris@127 336 const Model *waveformModel = 0; // just for reporting purposes
Chris@127 337 int verticalScaleWidth = 0;
Chris@127 338
Chris@127 339 int fontHeight = paint.fontMetrics().height();
Chris@127 340 int fontAscent = paint.fontMetrics().ascent();
Chris@127 341
Chris@127 342 if (m_manager &&
Chris@127 343 !m_manager->isPlaying() &&
Chris@127 344 m_manager->getToolMode() == ViewManager::SelectMode) {
Chris@127 345
Chris@127 346 for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) {
Chris@127 347 --vi;
Chris@127 348
Chris@127 349 std::vector<QRect> crosshairExtents;
Chris@127 350
Chris@127 351 if ((*vi)->getCrosshairExtents(this, paint, m_identifyPoint,
Chris@127 352 crosshairExtents)) {
Chris@127 353 (*vi)->paintCrosshairs(this, paint, m_identifyPoint);
Chris@127 354 break;
Chris@127 355 } else if ((*vi)->isLayerOpaque()) {
Chris@127 356 break;
Chris@127 357 }
Chris@127 358 }
Chris@127 359 }
Chris@127 360
Chris@127 361 for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) {
Chris@127 362 --vi;
Chris@127 363
Chris@127 364 if (dynamic_cast<WaveformLayer *>(*vi)) {
Chris@127 365 waveformModel = (*vi)->getModel();
Chris@127 366 }
Chris@127 367
Chris@127 368 if (!m_manager ||
Chris@127 369 m_manager->getOverlayMode() == ViewManager::NoOverlays) {
Chris@127 370 break;
Chris@127 371 }
Chris@127 372
Chris@127 373 verticalScaleWidth = (*vi)->getVerticalScaleWidth(this, paint);
Chris@127 374
Chris@127 375 if (verticalScaleWidth > 0 && r.left() < verticalScaleWidth) {
Chris@127 376
Chris@127 377 // Profiler profiler("Pane::paintEvent - painting vertical scale", true);
Chris@127 378
Chris@127 379 // std::cerr << "Pane::paintEvent: calling paint.save() in vertical scale block" << std::endl;
Chris@127 380 paint.save();
Chris@127 381
Chris@127 382 paint.setPen(Qt::black);
Chris@127 383 paint.setBrush(Qt::white);
Chris@127 384 paint.drawRect(0, -1, verticalScaleWidth, height()+1);
Chris@127 385
Chris@127 386 paint.setBrush(Qt::NoBrush);
Chris@127 387 (*vi)->paintVerticalScale
Chris@127 388 (this, paint, QRect(0, 0, verticalScaleWidth, height()));
Chris@127 389
Chris@127 390 paint.restore();
Chris@127 391 }
Chris@127 392
Chris@127 393 if (m_identifyFeatures) {
Chris@127 394
Chris@127 395 QPoint pos = m_identifyPoint;
Chris@127 396 QString desc = (*vi)->getFeatureDescription(this, pos);
Chris@127 397
Chris@127 398 if (desc != "") {
Chris@127 399
Chris@127 400 paint.save();
Chris@127 401
Chris@127 402 int tabStop =
Chris@127 403 paint.fontMetrics().width(tr("Some lengthy prefix:"));
Chris@127 404
Chris@127 405 QRect boundingRect =
Chris@127 406 paint.fontMetrics().boundingRect
Chris@127 407 (rect(),
Chris@127 408 Qt::AlignRight | Qt::AlignTop | Qt::TextExpandTabs,
Chris@127 409 desc, tabStop);
Chris@127 410
Chris@127 411 if (hasLightBackground()) {
Chris@127 412 paint.setPen(Qt::NoPen);
Chris@127 413 paint.setBrush(QColor(250, 250, 250, 200));
Chris@127 414 } else {
Chris@127 415 paint.setPen(Qt::NoPen);
Chris@127 416 paint.setBrush(QColor(50, 50, 50, 200));
Chris@127 417 }
Chris@127 418
Chris@127 419 int extra = paint.fontMetrics().descent();
Chris@127 420 paint.drawRect(width() - boundingRect.width() - 10 - extra,
Chris@127 421 10 - extra,
Chris@127 422 boundingRect.width() + 2 * extra,
Chris@127 423 boundingRect.height() + extra);
Chris@127 424
Chris@127 425 if (hasLightBackground()) {
Chris@127 426 paint.setPen(QColor(150, 20, 0));
Chris@127 427 } else {
Chris@127 428 paint.setPen(QColor(255, 150, 100));
Chris@127 429 }
Chris@127 430
Chris@127 431 QTextOption option;
Chris@127 432 option.setWrapMode(QTextOption::NoWrap);
Chris@127 433 option.setAlignment(Qt::AlignRight | Qt::AlignTop);
Chris@127 434 option.setTabStop(tabStop);
Chris@127 435 paint.drawText(QRectF(width() - boundingRect.width() - 10, 10,
Chris@127 436 boundingRect.width(),
Chris@127 437 boundingRect.height()),
Chris@127 438 desc,
Chris@127 439 option);
Chris@127 440
Chris@127 441 paint.restore();
Chris@127 442 }
Chris@127 443 }
Chris@127 444
Chris@127 445 break;
Chris@127 446 }
Chris@127 447
Chris@127 448 int sampleRate = getModelsSampleRate();
Chris@127 449 paint.setBrush(Qt::NoBrush);
Chris@127 450
Chris@127 451 if (m_centreLineVisible) {
Chris@127 452
Chris@127 453 if (hasLightBackground()) {
Chris@127 454 paint.setPen(QColor(50, 50, 50));
Chris@127 455 } else {
Chris@127 456 paint.setPen(QColor(200, 200, 200));
Chris@127 457 }
Chris@127 458 paint.drawLine(width() / 2, 0, width() / 2, height() - 1);
Chris@127 459
Chris@127 460 paint.setPen(QColor(50, 50, 50));
Chris@127 461
Chris@127 462 int y = height() - fontHeight
Chris@127 463 + fontAscent - 6;
Chris@127 464
Chris@127 465 LayerList::iterator vi = m_layers.end();
Chris@127 466
Chris@127 467 if (vi != m_layers.begin()) {
Chris@127 468
Chris@127 469 switch ((*--vi)->getPreferredFrameCountPosition()) {
Chris@127 470
Chris@127 471 case Layer::PositionTop:
Chris@127 472 y = fontAscent + 6;
Chris@127 473 break;
Chris@127 474
Chris@127 475 case Layer::PositionMiddle:
Chris@127 476 y = (height() - fontHeight) / 2
Chris@127 477 + fontAscent;
Chris@127 478 break;
Chris@127 479
Chris@127 480 case Layer::PositionBottom:
Chris@127 481 // y already set correctly
Chris@127 482 break;
Chris@127 483 }
Chris@127 484 }
Chris@127 485
Chris@127 486 if (m_manager &&
Chris@127 487 m_manager->getOverlayMode() != ViewManager::NoOverlays) {
Chris@127 488
Chris@127 489 if (sampleRate) {
Chris@127 490
Chris@127 491 QString text(QString::fromStdString
Chris@127 492 (RealTime::frame2RealTime
Chris@127 493 (m_centreFrame, sampleRate).toText(true)));
Chris@127 494
Chris@127 495 int tw = paint.fontMetrics().width(text);
Chris@127 496 int x = width()/2 - 4 - tw;
Chris@127 497
Chris@127 498 drawVisibleText(paint, x, y, text, OutlinedText);
Chris@127 499 }
Chris@127 500
Chris@127 501 QString text = QString("%1").arg(m_centreFrame);
Chris@127 502
Chris@127 503 int tw = paint.fontMetrics().width(text);
Chris@127 504 int x = width()/2 + 4;
Chris@127 505
Chris@127 506 drawVisibleText(paint, x, y, text, OutlinedText);
Chris@127 507 }
Chris@127 508
Chris@127 509 } else {
Chris@127 510
Chris@127 511 paint.setPen(QColor(50, 50, 50));
Chris@127 512 }
Chris@127 513
Chris@127 514 if (waveformModel &&
Chris@127 515 m_manager &&
Chris@127 516 m_manager->getOverlayMode() != ViewManager::NoOverlays &&
Chris@127 517 r.y() + r.height() >= height() - fontHeight - 6) {
Chris@127 518
Chris@150 519 size_t modelRate = waveformModel->getSampleRate();
Chris@127 520 size_t mainModelRate = m_manager->getMainModelSampleRate();
Chris@127 521 size_t playbackRate = m_manager->getPlaybackSampleRate();
Chris@127 522
Chris@127 523 QString srNote = "";
Chris@127 524
Chris@127 525 // Show (R) for waveform models that will be resampled on
Chris@127 526 // playback, and (X) for waveform models that will be played
Chris@127 527 // at the wrong rate because their rate differs from that of
Chris@127 528 // the main model.
Chris@127 529
Chris@150 530 if (modelRate == mainModelRate) {
Chris@150 531 if (modelRate != playbackRate) srNote = " " + tr("(R)");
Chris@127 532 } else {
Chris@150 533 // std::cerr << "Sample rate = " << modelRate << ", main model rate = " << mainModelRate << std::endl;
Chris@127 534 srNote = " " + tr("(X)");
Chris@127 535 }
Chris@127 536
Chris@127 537 QString desc = tr("%1 / %2Hz%3")
Chris@127 538 .arg(RealTime::frame2RealTime(waveformModel->getEndFrame(),
Chris@127 539 sampleRate)
Chris@127 540 .toText(false).c_str())
Chris@150 541 .arg(modelRate)
Chris@127 542 .arg(srNote);
Chris@127 543
Chris@127 544 if (r.x() < verticalScaleWidth + 5 + paint.fontMetrics().width(desc)) {
Chris@127 545 drawVisibleText(paint, verticalScaleWidth + 5,
Chris@127 546 height() - fontHeight + fontAscent - 6,
Chris@127 547 desc, OutlinedText);
Chris@127 548 }
Chris@127 549 }
Chris@127 550
Chris@127 551 if (m_manager &&
Chris@127 552 m_manager->getOverlayMode() == ViewManager::AllOverlays &&
Chris@127 553 r.y() + r.height() >= height() - m_layers.size() * fontHeight - 6) {
Chris@127 554
Chris@127 555 std::vector<QString> texts;
Chris@127 556 int maxTextWidth = 0;
Chris@127 557
Chris@127 558 for (LayerList::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
Chris@127 559
Chris@127 560 QString text = (*i)->getLayerPresentationName();
Chris@127 561 int tw = paint.fontMetrics().width(text);
Chris@127 562 bool reduced = false;
Chris@127 563 while (tw > width() / 3 && text.length() > 4) {
Chris@127 564 if (!reduced && text.length() > 8) {
Chris@127 565 text = text.left(text.length() - 4);
Chris@127 566 } else {
Chris@127 567 text = text.left(text.length() - 2);
Chris@127 568 }
Chris@127 569 reduced = true;
Chris@127 570 tw = paint.fontMetrics().width(text + "...");
Chris@127 571 }
Chris@127 572 if (reduced) {
Chris@127 573 texts.push_back(text + "...");
Chris@127 574 } else {
Chris@127 575 texts.push_back(text);
Chris@127 576 }
Chris@127 577 if (tw > maxTextWidth) maxTextWidth = tw;
Chris@127 578 }
Chris@127 579
Chris@127 580 int lly = height() - 6;
Chris@133 581 int llx = width() - maxTextWidth - 5;
Chris@127 582
Chris@133 583 if (m_manager->getZoomWheelsEnabled()) {
Chris@133 584 lly -= 20;
Chris@173 585 llx -= 36;
Chris@133 586 }
Chris@133 587
Chris@133 588 if (r.x() + r.width() >= llx) {
Chris@127 589
Chris@127 590 for (int i = 0; i < texts.size(); ++i) {
Chris@127 591
Chris@127 592 if (i == texts.size() - 1) {
Chris@127 593 paint.setPen(Qt::black);
Chris@127 594 }
Chris@127 595
Chris@133 596 drawVisibleText(paint, llx,
Chris@127 597 lly - fontHeight + fontAscent,
Chris@127 598 texts[i], OutlinedText);
Chris@127 599
Chris@127 600 lly -= fontHeight;
Chris@127 601 }
Chris@127 602 }
Chris@127 603 }
Chris@127 604
Chris@127 605 if (m_clickedInRange && m_shiftPressed) {
Chris@127 606 if (m_manager && (m_manager->getToolMode() == ViewManager::NavigateMode)) {
Chris@127 607 //!!! be nice if this looked a bit more in keeping with the
Chris@127 608 //selection block
Chris@127 609 paint.setPen(Qt::blue);
Chris@127 610 paint.drawRect(m_clickPos.x(), m_clickPos.y(),
Chris@127 611 m_mousePos.x() - m_clickPos.x(),
Chris@127 612 m_mousePos.y() - m_clickPos.y());
Chris@127 613 }
Chris@127 614 }
Chris@127 615
Chris@127 616 if (selectionIsBeingEdited()) {
Chris@127 617
Chris@127 618 int offset = m_mousePos.x() - m_clickPos.x();
Chris@127 619 int p0 = getXForFrame(m_editingSelection.getStartFrame()) + offset;
Chris@127 620 int p1 = getXForFrame(m_editingSelection.getEndFrame()) + offset;
Chris@127 621
Chris@127 622 if (m_editingSelectionEdge < 0) {
Chris@127 623 p1 = getXForFrame(m_editingSelection.getEndFrame());
Chris@127 624 } else if (m_editingSelectionEdge > 0) {
Chris@127 625 p0 = getXForFrame(m_editingSelection.getStartFrame());
Chris@127 626 }
Chris@127 627
Chris@127 628 paint.save();
Chris@127 629 if (hasLightBackground()) {
Chris@127 630 paint.setPen(QPen(Qt::black, 2));
Chris@127 631 } else {
Chris@127 632 paint.setPen(QPen(Qt::white, 2));
Chris@127 633 }
Chris@127 634
Chris@127 635 //!!! duplicating display policy with View::drawSelections
Chris@127 636
Chris@127 637 if (m_editingSelectionEdge < 0) {
Chris@127 638 paint.drawLine(p0, 1, p1, 1);
Chris@127 639 paint.drawLine(p0, 0, p0, height());
Chris@127 640 paint.drawLine(p0, height() - 1, p1, height() - 1);
Chris@127 641 } else if (m_editingSelectionEdge > 0) {
Chris@127 642 paint.drawLine(p0, 1, p1, 1);
Chris@127 643 paint.drawLine(p1, 0, p1, height());
Chris@127 644 paint.drawLine(p0, height() - 1, p1, height() - 1);
Chris@127 645 } else {
Chris@127 646 paint.setBrush(Qt::NoBrush);
Chris@127 647 paint.drawRect(p0, 1, p1 - p0, height() - 2);
Chris@127 648 }
Chris@127 649 paint.restore();
Chris@127 650 }
Chris@127 651
Chris@127 652 paint.end();
Chris@127 653 }
Chris@127 654
Chris@127 655 Selection
Chris@127 656 Pane::getSelectionAt(int x, bool &closeToLeftEdge, bool &closeToRightEdge) const
Chris@127 657 {
Chris@127 658 closeToLeftEdge = closeToRightEdge = false;
Chris@127 659
Chris@127 660 if (!m_manager) return Selection();
Chris@127 661
Chris@127 662 long testFrame = getFrameForX(x - 5);
Chris@127 663 if (testFrame < 0) {
Chris@127 664 testFrame = getFrameForX(x);
Chris@127 665 if (testFrame < 0) return Selection();
Chris@127 666 }
Chris@127 667
Chris@127 668 Selection selection = m_manager->getContainingSelection(testFrame, true);
Chris@127 669 if (selection.isEmpty()) return selection;
Chris@127 670
Chris@127 671 int lx = getXForFrame(selection.getStartFrame());
Chris@127 672 int rx = getXForFrame(selection.getEndFrame());
Chris@127 673
Chris@127 674 int fuzz = 2;
Chris@127 675 if (x < lx - fuzz || x > rx + fuzz) return Selection();
Chris@127 676
Chris@127 677 int width = rx - lx;
Chris@127 678 fuzz = 3;
Chris@127 679 if (width < 12) fuzz = width / 4;
Chris@127 680 if (fuzz < 1) fuzz = 1;
Chris@127 681
Chris@127 682 if (x < lx + fuzz) closeToLeftEdge = true;
Chris@127 683 if (x > rx - fuzz) closeToRightEdge = true;
Chris@127 684
Chris@127 685 return selection;
Chris@127 686 }
Chris@127 687
Chris@174 688 bool
Chris@174 689 Pane::canTopLayerMoveVertical()
Chris@174 690 {
Chris@174 691 float vmin, vmax, dmin, dmax;
Chris@174 692 if (!getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) return false;
Chris@174 693 if (dmin <= vmin && dmax >= vmax) return false;
Chris@174 694 return true;
Chris@174 695 }
Chris@174 696
Chris@174 697 bool
Chris@174 698 Pane::getTopLayerDisplayExtents(float &vmin, float &vmax,
Chris@174 699 float &dmin, float &dmax)
Chris@174 700 {
Chris@174 701 Layer *layer = 0;
Chris@174 702 if (getLayerCount() > 0) layer = getLayer(getLayerCount() - 1);
Chris@174 703 if (!layer) return false;
Chris@174 704 bool vlog;
Chris@174 705 QString vunit;
Chris@174 706 return (layer->getValueExtents(vmin, vmax, vlog, vunit) &&
Chris@174 707 layer->getDisplayExtents(dmin, dmax));
Chris@174 708 }
Chris@174 709
Chris@174 710 bool
Chris@174 711 Pane::setTopLayerDisplayExtents(float dmin, float dmax)
Chris@174 712 {
Chris@174 713 Layer *layer = 0;
Chris@174 714 if (getLayerCount() > 0) layer = getLayer(getLayerCount() - 1);
Chris@174 715 if (!layer) return false;
Chris@174 716 return layer->setDisplayExtents(dmin, dmax);
Chris@174 717 }
Chris@174 718
Chris@127 719 void
Chris@127 720 Pane::mousePressEvent(QMouseEvent *e)
Chris@127 721 {
Chris@127 722 if (e->buttons() & Qt::RightButton) {
Chris@127 723 emit rightButtonMenuRequested(mapToGlobal(e->pos()));
Chris@127 724 return;
Chris@127 725 }
Chris@127 726
Chris@127 727 m_clickPos = e->pos();
Chris@127 728 m_clickedInRange = true;
Chris@127 729 m_editingSelection = Selection();
Chris@127 730 m_editingSelectionEdge = 0;
Chris@127 731 m_shiftPressed = (e->modifiers() & Qt::ShiftModifier);
Chris@127 732 m_ctrlPressed = (e->modifiers() & Qt::ControlModifier);
Chris@150 733 m_dragMode = UnresolvedDrag;
Chris@127 734
Chris@127 735 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@127 736 if (m_manager) mode = m_manager->getToolMode();
Chris@127 737
Chris@127 738 m_navigating = false;
Chris@127 739
Chris@127 740 if (mode == ViewManager::NavigateMode || (e->buttons() & Qt::MidButton)) {
Chris@127 741
Chris@127 742 if (mode != ViewManager::NavigateMode) {
Chris@127 743 setCursor(Qt::PointingHandCursor);
Chris@127 744 }
Chris@127 745
Chris@127 746 m_navigating = true;
Chris@127 747 m_dragCentreFrame = m_centreFrame;
Chris@136 748 m_dragStartMinValue = 0;
Chris@174 749
Chris@174 750 float vmin, vmax, dmin, dmax;
Chris@174 751 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) {
Chris@174 752 m_dragStartMinValue = dmin;
Chris@136 753 }
Chris@136 754
Chris@127 755 } else if (mode == ViewManager::SelectMode) {
Chris@127 756
Chris@127 757 bool closeToLeft = false, closeToRight = false;
Chris@127 758 Selection selection = getSelectionAt(e->x(), closeToLeft, closeToRight);
Chris@127 759
Chris@127 760 if ((closeToLeft || closeToRight) && !(closeToLeft && closeToRight)) {
Chris@127 761
Chris@127 762 m_manager->removeSelection(selection);
Chris@127 763
Chris@127 764 if (closeToLeft) {
Chris@127 765 m_selectionStartFrame = selection.getEndFrame();
Chris@127 766 } else {
Chris@127 767 m_selectionStartFrame = selection.getStartFrame();
Chris@127 768 }
Chris@127 769
Chris@127 770 m_manager->setInProgressSelection(selection, false);
Chris@127 771 m_resizing = true;
Chris@127 772
Chris@127 773 } else {
Chris@127 774
Chris@127 775 int mouseFrame = getFrameForX(e->x());
Chris@127 776 size_t resolution = 1;
Chris@127 777 int snapFrame = mouseFrame;
Chris@127 778
Chris@127 779 Layer *layer = getSelectedLayer();
Chris@127 780 if (layer && !m_shiftPressed) {
Chris@127 781 layer->snapToFeatureFrame(this, snapFrame,
Chris@127 782 resolution, Layer::SnapLeft);
Chris@127 783 }
Chris@127 784
Chris@127 785 if (snapFrame < 0) snapFrame = 0;
Chris@127 786 m_selectionStartFrame = snapFrame;
Chris@127 787 if (m_manager) {
Chris@127 788 m_manager->setInProgressSelection(Selection(snapFrame,
Chris@127 789 snapFrame + resolution),
Chris@127 790 !m_ctrlPressed);
Chris@127 791 }
Chris@127 792
Chris@127 793 m_resizing = false;
Chris@127 794 }
Chris@127 795
Chris@127 796 update();
Chris@127 797
Chris@127 798 } else if (mode == ViewManager::DrawMode) {
Chris@127 799
Chris@127 800 Layer *layer = getSelectedLayer();
Chris@127 801 if (layer && layer->isLayerEditable()) {
Chris@127 802 layer->drawStart(this, e);
Chris@127 803 }
Chris@127 804
Chris@127 805 } else if (mode == ViewManager::EditMode) {
Chris@127 806
Chris@127 807 if (!editSelectionStart(e)) {
Chris@127 808 Layer *layer = getSelectedLayer();
Chris@127 809 if (layer && layer->isLayerEditable()) {
Chris@127 810 layer->editStart(this, e);
Chris@127 811 }
Chris@127 812 }
Chris@127 813 }
Chris@127 814
Chris@127 815 emit paneInteractedWith();
Chris@127 816 }
Chris@127 817
Chris@127 818 void
Chris@127 819 Pane::mouseReleaseEvent(QMouseEvent *e)
Chris@127 820 {
Chris@127 821 if (e->buttons() & Qt::RightButton) {
Chris@127 822 return;
Chris@127 823 }
Chris@127 824
Chris@127 825 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@127 826 if (m_manager) mode = m_manager->getToolMode();
Chris@127 827
Chris@127 828 if (m_clickedInRange) {
Chris@127 829 mouseMoveEvent(e);
Chris@127 830 }
Chris@127 831
Chris@127 832 if (m_navigating || mode == ViewManager::NavigateMode) {
Chris@127 833
Chris@127 834 m_navigating = false;
Chris@127 835
Chris@127 836 if (mode != ViewManager::NavigateMode) {
Chris@127 837 // restore cursor
Chris@127 838 toolModeChanged();
Chris@127 839 }
Chris@127 840
Chris@127 841 if (m_shiftPressed) {
Chris@127 842
Chris@127 843 int x0 = std::min(m_clickPos.x(), m_mousePos.x());
Chris@127 844 int x1 = std::max(m_clickPos.x(), m_mousePos.x());
Chris@127 845
Chris@127 846 int y0 = std::min(m_clickPos.y(), m_mousePos.y());
Chris@127 847 int y1 = std::max(m_clickPos.y(), m_mousePos.y());
Chris@127 848
Chris@174 849 zoomToRegion(x0, y0, x1, y1);
Chris@127 850 }
Chris@127 851
Chris@127 852 } else if (mode == ViewManager::SelectMode) {
Chris@127 853
Chris@127 854 if (m_manager && m_manager->haveInProgressSelection()) {
Chris@127 855
Chris@127 856 bool exclusive;
Chris@127 857 Selection selection = m_manager->getInProgressSelection(exclusive);
Chris@127 858
Chris@127 859 if (selection.getEndFrame() < selection.getStartFrame() + 2) {
Chris@127 860 selection = Selection();
Chris@127 861 }
Chris@127 862
Chris@127 863 m_manager->clearInProgressSelection();
Chris@127 864
Chris@127 865 if (exclusive) {
Chris@127 866 m_manager->setSelection(selection);
Chris@127 867 } else {
Chris@127 868 m_manager->addSelection(selection);
Chris@127 869 }
Chris@127 870 }
Chris@127 871
Chris@127 872 update();
Chris@127 873
Chris@127 874 } else if (mode == ViewManager::DrawMode) {
Chris@127 875
Chris@127 876 Layer *layer = getSelectedLayer();
Chris@127 877 if (layer && layer->isLayerEditable()) {
Chris@127 878 layer->drawEnd(this, e);
Chris@127 879 update();
Chris@127 880 }
Chris@127 881
Chris@127 882 } else if (mode == ViewManager::EditMode) {
Chris@127 883
Chris@127 884 if (!editSelectionEnd(e)) {
Chris@127 885 Layer *layer = getSelectedLayer();
Chris@127 886 if (layer && layer->isLayerEditable()) {
Chris@127 887 layer->editEnd(this, e);
Chris@127 888 update();
Chris@127 889 }
Chris@127 890 }
Chris@127 891 }
Chris@127 892
Chris@127 893 m_clickedInRange = false;
Chris@127 894
Chris@127 895 emit paneInteractedWith();
Chris@127 896 }
Chris@127 897
Chris@127 898 void
Chris@127 899 Pane::mouseMoveEvent(QMouseEvent *e)
Chris@127 900 {
Chris@127 901 if (e->buttons() & Qt::RightButton) {
Chris@127 902 return;
Chris@127 903 }
Chris@127 904
Chris@127 905 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@127 906 if (m_manager) mode = m_manager->getToolMode();
Chris@127 907
Chris@127 908 QPoint prevPoint = m_identifyPoint;
Chris@127 909 m_identifyPoint = e->pos();
Chris@127 910
Chris@127 911 if (!m_clickedInRange) {
Chris@127 912
Chris@127 913 if (mode == ViewManager::SelectMode) {
Chris@127 914 bool closeToLeft = false, closeToRight = false;
Chris@127 915 getSelectionAt(e->x(), closeToLeft, closeToRight);
Chris@127 916 if ((closeToLeft || closeToRight) && !(closeToLeft && closeToRight)) {
Chris@127 917 setCursor(Qt::SizeHorCursor);
Chris@127 918 } else {
Chris@127 919 setCursor(Qt::ArrowCursor);
Chris@127 920 }
Chris@127 921 }
Chris@127 922
Chris@127 923 if (!m_manager->isPlaying()) {
Chris@127 924
Chris@174 925 if (getSelectedLayer()) {
Chris@127 926
Chris@174 927 bool previouslyIdentifying = m_identifyFeatures;
Chris@174 928 m_identifyFeatures = true;
Chris@174 929
Chris@174 930 if (m_identifyFeatures != previouslyIdentifying ||
Chris@174 931 m_identifyPoint != prevPoint) {
Chris@174 932 update();
Chris@174 933 }
Chris@174 934 }
Chris@127 935 }
Chris@127 936
Chris@127 937 return;
Chris@127 938 }
Chris@127 939
Chris@127 940 if (m_navigating || mode == ViewManager::NavigateMode) {
Chris@127 941
Chris@127 942 if (m_shiftPressed) {
Chris@127 943
Chris@127 944 m_mousePos = e->pos();
Chris@127 945 update();
Chris@127 946
Chris@127 947 } else {
Chris@127 948
Chris@174 949 dragTopLayer(e);
Chris@150 950 }
Chris@127 951
Chris@127 952 } else if (mode == ViewManager::SelectMode) {
Chris@127 953
Chris@174 954 dragExtendSelection(e);
Chris@127 955
Chris@127 956 } else if (mode == ViewManager::DrawMode) {
Chris@127 957
Chris@127 958 Layer *layer = getSelectedLayer();
Chris@127 959 if (layer && layer->isLayerEditable()) {
Chris@127 960 layer->drawDrag(this, e);
Chris@127 961 }
Chris@127 962
Chris@127 963 } else if (mode == ViewManager::EditMode) {
Chris@127 964
Chris@127 965 if (!editSelectionDrag(e)) {
Chris@127 966 Layer *layer = getSelectedLayer();
Chris@127 967 if (layer && layer->isLayerEditable()) {
Chris@127 968 layer->editDrag(this, e);
Chris@127 969 }
Chris@127 970 }
Chris@127 971 }
Chris@127 972 }
Chris@127 973
Chris@127 974 void
Chris@174 975 Pane::zoomToRegion(int x0, int y0, int x1, int y1)
Chris@174 976 {
Chris@174 977 int w = x1 - x0;
Chris@174 978
Chris@174 979 long newStartFrame = getFrameForX(x0);
Chris@174 980
Chris@174 981 long visibleFrames = getEndFrame() - getStartFrame();
Chris@174 982 if (newStartFrame <= -visibleFrames) {
Chris@174 983 newStartFrame = -visibleFrames + 1;
Chris@174 984 }
Chris@174 985
Chris@174 986 if (newStartFrame >= long(getModelsEndFrame())) {
Chris@174 987 newStartFrame = getModelsEndFrame() - 1;
Chris@174 988 }
Chris@174 989
Chris@174 990 float ratio = float(w) / float(width());
Chris@174 991 // std::cerr << "ratio: " << ratio << std::endl;
Chris@174 992 size_t newZoomLevel = (size_t)nearbyint(m_zoomLevel * ratio);
Chris@174 993 if (newZoomLevel < 1) newZoomLevel = 1;
Chris@174 994
Chris@174 995 // std::cerr << "start: " << m_startFrame << ", level " << m_zoomLevel << std::endl;
Chris@174 996 setZoomLevel(getZoomConstraintBlockSize(newZoomLevel));
Chris@174 997 setStartFrame(newStartFrame);
Chris@174 998
Chris@174 999 QString unit;
Chris@174 1000 float min, max;
Chris@174 1001 bool log;
Chris@174 1002 Layer *layer = 0;
Chris@174 1003 for (LayerList::const_iterator i = m_layers.begin();
Chris@174 1004 i != m_layers.end(); ++i) {
Chris@174 1005 if ((*i)->getValueExtents(min, max, log, unit) &&
Chris@174 1006 (*i)->getDisplayExtents(min, max)) {
Chris@174 1007 layer = *i;
Chris@174 1008 break;
Chris@174 1009 }
Chris@174 1010 }
Chris@174 1011
Chris@174 1012 if (layer) {
Chris@174 1013 if (log) {
Chris@174 1014 min = (min < 0.0) ? -log10f(-min) : (min == 0.0) ? 0.0 : log10f(min);
Chris@174 1015 max = (max < 0.0) ? -log10f(-max) : (max == 0.0) ? 0.0 : log10f(max);
Chris@174 1016 }
Chris@174 1017 float rmin = min + ((max - min) * (height() - y1)) / height();
Chris@174 1018 float rmax = min + ((max - min) * (height() - y0)) / height();
Chris@174 1019 std::cerr << "min: " << min << ", max: " << max << ", y0: " << y0 << ", y1: " << y1 << ", h: " << height() << ", rmin: " << rmin << ", rmax: " << rmax << std::endl;
Chris@174 1020 if (log) {
Chris@174 1021 rmin = powf(10, rmin);
Chris@174 1022 rmax = powf(10, rmax);
Chris@174 1023 }
Chris@174 1024 std::cerr << "finally: rmin: " << rmin << ", rmax: " << rmax << " " << unit.toStdString() << std::endl;
Chris@174 1025
Chris@174 1026 layer->setDisplayExtents(rmin, rmax);
Chris@174 1027 updateVerticalPanner();
Chris@174 1028 }
Chris@174 1029 }
Chris@174 1030
Chris@174 1031 void
Chris@174 1032 Pane::dragTopLayer(QMouseEvent *e)
Chris@174 1033 {
Chris@174 1034 // We need to avoid making it too easy to drag both
Chris@174 1035 // horizontally and vertically, in the case where the
Chris@174 1036 // mouse is moved "mostly" in horizontal or vertical axis
Chris@174 1037 // with only a small variation in the other axis. This is
Chris@174 1038 // particularly important during playback (when we want to
Chris@174 1039 // avoid small horizontal motions) or in slow refresh
Chris@174 1040 // layers like spectrogram (when we want to avoid small
Chris@174 1041 // vertical motions).
Chris@174 1042 //
Chris@174 1043 // To this end we have horizontal and vertical thresholds
Chris@174 1044 // and a series of states: unresolved, horizontally or
Chris@174 1045 // vertically constrained, free.
Chris@174 1046 //
Chris@174 1047 // When the mouse first moves, we're unresolved: we
Chris@174 1048 // restrict ourselves to whichever direction seems safest,
Chris@174 1049 // until the mouse has passed a small threshold distance
Chris@174 1050 // from the click point. Then we lock in to one of the
Chris@174 1051 // constrained modes, based on which axis that distance
Chris@174 1052 // was measured in first. Finally, if it turns out we've
Chris@174 1053 // also moved more than a certain larger distance in the
Chris@174 1054 // other direction as well, we may switch into free mode.
Chris@174 1055 //
Chris@174 1056 // If the top layer is incapable of being dragged
Chris@174 1057 // vertically, the logic is short circuited.
Chris@174 1058
Chris@174 1059 int xdiff = e->x() - m_clickPos.x();
Chris@174 1060 int ydiff = e->y() - m_clickPos.y();
Chris@174 1061 int smallThreshold = 10, bigThreshold = 50;
Chris@174 1062
Chris@174 1063 bool canMoveVertical = canTopLayerMoveVertical();
Chris@174 1064 bool canMoveHorizontal = true;
Chris@174 1065
Chris@174 1066 if (!canMoveHorizontal) {
Chris@174 1067 m_dragMode = HorizontalDrag;
Chris@174 1068 }
Chris@174 1069
Chris@174 1070 if (m_dragMode == UnresolvedDrag) {
Chris@174 1071
Chris@174 1072 if (abs(ydiff) > smallThreshold &&
Chris@174 1073 abs(ydiff) > abs(xdiff) * 2) {
Chris@174 1074 m_dragMode = VerticalDrag;
Chris@174 1075 } else if (abs(xdiff) > smallThreshold &&
Chris@174 1076 abs(xdiff) > abs(ydiff) * 2) {
Chris@174 1077 m_dragMode = HorizontalDrag;
Chris@174 1078 } else if (abs(xdiff) > smallThreshold &&
Chris@174 1079 abs(ydiff) > smallThreshold) {
Chris@174 1080 m_dragMode = FreeDrag;
Chris@174 1081 } else {
Chris@174 1082 // When playing, we don't want to disturb the play
Chris@174 1083 // position too easily; when not playing, we don't
Chris@174 1084 // want to move up/down too easily
Chris@174 1085 if (m_manager && m_manager->isPlaying()) {
Chris@174 1086 canMoveHorizontal = false;
Chris@174 1087 } else {
Chris@174 1088 canMoveVertical = false;
Chris@174 1089 }
Chris@174 1090 }
Chris@174 1091 }
Chris@174 1092
Chris@174 1093 if (m_dragMode == VerticalDrag) {
Chris@174 1094 if (abs(xdiff) > bigThreshold) m_dragMode = FreeDrag;
Chris@174 1095 else canMoveHorizontal = false;
Chris@174 1096 }
Chris@174 1097
Chris@174 1098 if (m_dragMode == HorizontalDrag && canMoveVertical) {
Chris@174 1099 if (abs(ydiff) > bigThreshold) m_dragMode = FreeDrag;
Chris@174 1100 else canMoveVertical = false;
Chris@174 1101 }
Chris@174 1102
Chris@174 1103 if (canMoveHorizontal) {
Chris@174 1104
Chris@174 1105 long frameOff = getFrameForX(e->x()) - getFrameForX(m_clickPos.x());
Chris@174 1106
Chris@174 1107 size_t newCentreFrame = m_dragCentreFrame;
Chris@174 1108
Chris@174 1109 if (frameOff < 0) {
Chris@174 1110 newCentreFrame -= frameOff;
Chris@174 1111 } else if (newCentreFrame >= size_t(frameOff)) {
Chris@174 1112 newCentreFrame -= frameOff;
Chris@174 1113 } else {
Chris@174 1114 newCentreFrame = 0;
Chris@174 1115 }
Chris@174 1116
Chris@174 1117 if (newCentreFrame >= getModelsEndFrame()) {
Chris@174 1118 newCentreFrame = getModelsEndFrame();
Chris@174 1119 if (newCentreFrame > 0) --newCentreFrame;
Chris@174 1120 }
Chris@174 1121
Chris@174 1122 if (getXForFrame(m_centreFrame) != getXForFrame(newCentreFrame)) {
Chris@174 1123 setCentreFrame(newCentreFrame);
Chris@174 1124 }
Chris@174 1125 }
Chris@174 1126
Chris@174 1127 if (canMoveVertical) {
Chris@174 1128
Chris@174 1129 float vmin = 0.f, vmax = 0.f;
Chris@174 1130 float dmin = 0.f, dmax = 0.f;
Chris@174 1131
Chris@174 1132 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) {
Chris@174 1133
Chris@174 1134 std::cerr << "ydiff = " << ydiff << std::endl;
Chris@174 1135
Chris@174 1136 float perpix = (dmax - dmin) / height();
Chris@174 1137 float valdiff = ydiff * perpix;
Chris@174 1138 std::cerr << "valdiff = " << valdiff << std::endl;
Chris@174 1139
Chris@174 1140 float newmin = m_dragStartMinValue + valdiff;
Chris@174 1141 float newmax = m_dragStartMinValue + (dmax - dmin) + valdiff;
Chris@174 1142 if (newmin < vmin) {
Chris@174 1143 newmax += vmin - newmin;
Chris@174 1144 newmin += vmin - newmin;
Chris@174 1145 }
Chris@174 1146 if (newmax > vmax) {
Chris@174 1147 newmin -= newmax - vmax;
Chris@174 1148 newmax -= newmax - vmax;
Chris@174 1149 }
Chris@174 1150 std::cerr << "(" << dmin << ", " << dmax << ") -> ("
Chris@174 1151 << newmin << ", " << newmax << ") (drag start " << m_dragStartMinValue << ")" << std::endl;
Chris@174 1152
Chris@174 1153 setTopLayerDisplayExtents(newmin, newmax);
Chris@174 1154 updateVerticalPanner();
Chris@174 1155 }
Chris@174 1156 }
Chris@174 1157 }
Chris@174 1158
Chris@174 1159 void
Chris@174 1160 Pane::dragExtendSelection(QMouseEvent *e)
Chris@174 1161 {
Chris@174 1162 int mouseFrame = getFrameForX(e->x());
Chris@174 1163 size_t resolution = 1;
Chris@174 1164 int snapFrameLeft = mouseFrame;
Chris@174 1165 int snapFrameRight = mouseFrame;
Chris@174 1166
Chris@174 1167 Layer *layer = getSelectedLayer();
Chris@174 1168 if (layer && !m_shiftPressed) {
Chris@174 1169 layer->snapToFeatureFrame(this, snapFrameLeft,
Chris@174 1170 resolution, Layer::SnapLeft);
Chris@174 1171 layer->snapToFeatureFrame(this, snapFrameRight,
Chris@174 1172 resolution, Layer::SnapRight);
Chris@174 1173 }
Chris@174 1174
Chris@174 1175 // std::cerr << "snap: frame = " << mouseFrame << ", start frame = " << m_selectionStartFrame << ", left = " << snapFrameLeft << ", right = " << snapFrameRight << std::endl;
Chris@174 1176
Chris@174 1177 if (snapFrameLeft < 0) snapFrameLeft = 0;
Chris@174 1178 if (snapFrameRight < 0) snapFrameRight = 0;
Chris@174 1179
Chris@174 1180 size_t min, max;
Chris@174 1181
Chris@174 1182 if (m_selectionStartFrame > snapFrameLeft) {
Chris@174 1183 min = snapFrameLeft;
Chris@174 1184 max = m_selectionStartFrame;
Chris@174 1185 } else if (snapFrameRight > m_selectionStartFrame) {
Chris@174 1186 min = m_selectionStartFrame;
Chris@174 1187 max = snapFrameRight;
Chris@174 1188 } else {
Chris@174 1189 min = snapFrameLeft;
Chris@174 1190 max = snapFrameRight;
Chris@174 1191 }
Chris@174 1192
Chris@174 1193 if (m_manager) {
Chris@174 1194 m_manager->setInProgressSelection(Selection(min, max),
Chris@174 1195 !m_resizing && !m_ctrlPressed);
Chris@174 1196 }
Chris@174 1197
Chris@174 1198 bool doScroll = false;
Chris@174 1199 if (!m_manager) doScroll = true;
Chris@174 1200 if (!m_manager->isPlaying()) doScroll = true;
Chris@174 1201 if (m_followPlay != PlaybackScrollContinuous) doScroll = true;
Chris@174 1202
Chris@174 1203 if (doScroll) {
Chris@174 1204 int offset = mouseFrame - getStartFrame();
Chris@174 1205 int available = getEndFrame() - getStartFrame();
Chris@174 1206 if (offset >= available * 0.95) {
Chris@174 1207 int move = int(offset - available * 0.95) + 1;
Chris@174 1208 setCentreFrame(m_centreFrame + move);
Chris@174 1209 } else if (offset <= available * 0.10) {
Chris@174 1210 int move = int(available * 0.10 - offset) + 1;
Chris@174 1211 if (m_centreFrame > move) {
Chris@174 1212 setCentreFrame(m_centreFrame - move);
Chris@174 1213 } else {
Chris@174 1214 setCentreFrame(0);
Chris@174 1215 }
Chris@174 1216 }
Chris@174 1217 }
Chris@174 1218
Chris@174 1219 update();
Chris@174 1220 }
Chris@174 1221
Chris@174 1222 void
Chris@127 1223 Pane::mouseDoubleClickEvent(QMouseEvent *e)
Chris@127 1224 {
Chris@127 1225 if (e->buttons() & Qt::RightButton) {
Chris@127 1226 return;
Chris@127 1227 }
Chris@127 1228
Chris@127 1229 // std::cerr << "mouseDoubleClickEvent" << std::endl;
Chris@127 1230
Chris@127 1231 m_clickPos = e->pos();
Chris@127 1232 m_clickedInRange = true;
Chris@127 1233 m_shiftPressed = (e->modifiers() & Qt::ShiftModifier);
Chris@127 1234 m_ctrlPressed = (e->modifiers() & Qt::ControlModifier);
Chris@127 1235
Chris@127 1236 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@127 1237 if (m_manager) mode = m_manager->getToolMode();
Chris@127 1238
Chris@127 1239 if (mode == ViewManager::NavigateMode ||
Chris@127 1240 mode == ViewManager::EditMode) {
Chris@127 1241
Chris@127 1242 Layer *layer = getSelectedLayer();
Chris@127 1243 if (layer && layer->isLayerEditable()) {
Chris@127 1244 layer->editOpen(this, e);
Chris@127 1245 }
Chris@127 1246 }
Chris@127 1247 }
Chris@127 1248
Chris@127 1249 void
Chris@127 1250 Pane::leaveEvent(QEvent *)
Chris@127 1251 {
Chris@127 1252 bool previouslyIdentifying = m_identifyFeatures;
Chris@127 1253 m_identifyFeatures = false;
Chris@127 1254 if (previouslyIdentifying) update();
Chris@127 1255 }
Chris@127 1256
Chris@127 1257 void
Chris@133 1258 Pane::resizeEvent(QResizeEvent *)
Chris@133 1259 {
Chris@133 1260 updateHeadsUpDisplay();
Chris@133 1261 }
Chris@133 1262
Chris@133 1263 void
Chris@127 1264 Pane::wheelEvent(QWheelEvent *e)
Chris@127 1265 {
Chris@127 1266 //std::cerr << "wheelEvent, delta " << e->delta() << std::endl;
Chris@127 1267
Chris@127 1268 int count = e->delta();
Chris@127 1269
Chris@127 1270 if (count > 0) {
Chris@127 1271 if (count >= 120) count /= 120;
Chris@127 1272 else count = 1;
Chris@127 1273 }
Chris@127 1274
Chris@127 1275 if (count < 0) {
Chris@127 1276 if (count <= -120) count /= 120;
Chris@127 1277 else count = -1;
Chris@127 1278 }
Chris@127 1279
Chris@127 1280 if (e->modifiers() & Qt::ControlModifier) {
Chris@127 1281
Chris@127 1282 // Scroll left or right, rapidly
Chris@127 1283
Chris@127 1284 if (getStartFrame() < 0 &&
Chris@127 1285 getEndFrame() >= getModelsEndFrame()) return;
Chris@127 1286
Chris@127 1287 long delta = ((width() / 2) * count * m_zoomLevel);
Chris@127 1288
Chris@127 1289 if (int(m_centreFrame) < delta) {
Chris@127 1290 setCentreFrame(0);
Chris@127 1291 } else if (int(m_centreFrame) - delta >= int(getModelsEndFrame())) {
Chris@127 1292 setCentreFrame(getModelsEndFrame());
Chris@127 1293 } else {
Chris@127 1294 setCentreFrame(m_centreFrame - delta);
Chris@127 1295 }
Chris@127 1296
Chris@127 1297 } else {
Chris@127 1298
Chris@127 1299 // Zoom in or out
Chris@127 1300
Chris@127 1301 int newZoomLevel = m_zoomLevel;
Chris@127 1302
Chris@127 1303 while (count > 0) {
Chris@127 1304 if (newZoomLevel <= 2) {
Chris@127 1305 newZoomLevel = 1;
Chris@127 1306 break;
Chris@127 1307 }
Chris@127 1308 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel - 1,
Chris@127 1309 ZoomConstraint::RoundDown);
Chris@127 1310 --count;
Chris@127 1311 }
Chris@127 1312
Chris@127 1313 while (count < 0) {
Chris@127 1314 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel + 1,
Chris@127 1315 ZoomConstraint::RoundUp);
Chris@127 1316 ++count;
Chris@127 1317 }
Chris@127 1318
Chris@127 1319 if (newZoomLevel != m_zoomLevel) {
Chris@127 1320 setZoomLevel(newZoomLevel);
Chris@127 1321 }
Chris@127 1322 }
Chris@127 1323
Chris@127 1324 emit paneInteractedWith();
Chris@127 1325 }
Chris@127 1326
Chris@132 1327 void
Chris@132 1328 Pane::horizontalThumbwheelMoved(int value)
Chris@132 1329 {
Chris@137 1330 //!!! dupe with updateHeadsUpDisplay
Chris@137 1331
Chris@132 1332 int count = 0;
Chris@132 1333 int level = 1;
Chris@137 1334
Chris@137 1335
Chris@137 1336 //!!! pull out into function (presumably in View)
Chris@137 1337 bool haveConstraint = false;
Chris@137 1338 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end();
Chris@137 1339 ++i) {
Chris@137 1340 if ((*i)->getZoomConstraint() && !(*i)->supportsOtherZoomLevels()) {
Chris@137 1341 haveConstraint = true;
Chris@137 1342 break;
Chris@137 1343 }
Chris@132 1344 }
Chris@132 1345
Chris@137 1346 if (haveConstraint) {
Chris@137 1347 while (true) {
Chris@137 1348 if (m_hthumb->getMaximumValue() - value == count) break;
Chris@137 1349 int newLevel = getZoomConstraintBlockSize(level + 1,
Chris@137 1350 ZoomConstraint::RoundUp);
Chris@137 1351 if (newLevel == level) break;
Chris@137 1352 level = newLevel;
Chris@137 1353 if (++count == 50) break;
Chris@137 1354 }
Chris@137 1355 } else {
Chris@137 1356 while (true) {
Chris@137 1357 if (m_hthumb->getMaximumValue() - value == count) break;
Chris@137 1358 int step = level / 10;
Chris@137 1359 int pwr = 0;
Chris@137 1360 while (step > 0) {
Chris@137 1361 ++pwr;
Chris@137 1362 step /= 2;
Chris@137 1363 }
Chris@137 1364 step = 1;
Chris@137 1365 while (pwr > 0) {
Chris@137 1366 step *= 2;
Chris@137 1367 --pwr;
Chris@137 1368 }
Chris@137 1369 // std::cerr << level << std::endl;
Chris@137 1370 level += step;
Chris@137 1371 if (++count == 100 || level > 262144) break;
Chris@137 1372 }
Chris@137 1373 }
Chris@137 1374
Chris@137 1375 std::cerr << "new level is " << level << std::endl;
Chris@132 1376 setZoomLevel(level);
Chris@132 1377 }
Chris@132 1378
Chris@132 1379 void
Chris@132 1380 Pane::verticalThumbwheelMoved(int value)
Chris@132 1381 {
Chris@133 1382 Layer *layer = 0;
Chris@133 1383 if (getLayerCount() > 0) layer = getLayer(getLayerCount() - 1);
Chris@133 1384 if (layer) {
Chris@133 1385 int defaultStep = 0;
Chris@133 1386 int max = layer->getVerticalZoomSteps(defaultStep);
Chris@133 1387 if (max == 0) {
Chris@133 1388 updateHeadsUpDisplay();
Chris@133 1389 return;
Chris@133 1390 }
Chris@133 1391 if (value > max) {
Chris@133 1392 value = max;
Chris@133 1393 }
Chris@133 1394 layer->setVerticalZoomStep(value);
Chris@174 1395 updateVerticalPanner();
Chris@133 1396 }
Chris@132 1397 }
Chris@132 1398
Chris@174 1399 void
Chris@174 1400 Pane::verticalPannerMoved(float x0, float y0, float w, float h)
Chris@174 1401 {
Chris@174 1402 float vmin, vmax, dmin, dmax;
Chris@174 1403 if (!getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) return;
Chris@174 1404 float y1 = y0 + h;
Chris@174 1405 float newmax = vmin + ((1.0 - y0) * (vmax - vmin));
Chris@174 1406 float newmin = vmin + ((1.0 - y1) * (vmax - vmin));
Chris@174 1407 std::cerr << "verticalPannerMoved: (" << x0 << "," << y0 << "," << w
Chris@174 1408 << "," << h << ") -> (" << newmin << "," << newmax << ")" << std::endl;
Chris@174 1409 setTopLayerDisplayExtents(newmin, newmax);
Chris@174 1410 }
Chris@174 1411
Chris@127 1412 bool
Chris@127 1413 Pane::editSelectionStart(QMouseEvent *e)
Chris@127 1414 {
Chris@127 1415 if (!m_identifyFeatures ||
Chris@127 1416 !m_manager ||
Chris@127 1417 m_manager->getToolMode() != ViewManager::EditMode) {
Chris@127 1418 return false;
Chris@127 1419 }
Chris@127 1420
Chris@127 1421 bool closeToLeft, closeToRight;
Chris@127 1422 Selection s(getSelectionAt(e->x(), closeToLeft, closeToRight));
Chris@127 1423 if (s.isEmpty()) return false;
Chris@127 1424 m_editingSelection = s;
Chris@127 1425 m_editingSelectionEdge = (closeToLeft ? -1 : closeToRight ? 1 : 0);
Chris@127 1426 m_mousePos = e->pos();
Chris@127 1427 return true;
Chris@127 1428 }
Chris@127 1429
Chris@127 1430 bool
Chris@127 1431 Pane::editSelectionDrag(QMouseEvent *e)
Chris@127 1432 {
Chris@127 1433 if (m_editingSelection.isEmpty()) return false;
Chris@127 1434 m_mousePos = e->pos();
Chris@127 1435 update();
Chris@127 1436 return true;
Chris@127 1437 }
Chris@127 1438
Chris@127 1439 bool
Chris@127 1440 Pane::editSelectionEnd(QMouseEvent *e)
Chris@127 1441 {
Chris@127 1442 if (m_editingSelection.isEmpty()) return false;
Chris@127 1443
Chris@127 1444 int offset = m_mousePos.x() - m_clickPos.x();
Chris@127 1445 Layer *layer = getSelectedLayer();
Chris@127 1446
Chris@127 1447 if (offset == 0 || !layer) {
Chris@127 1448 m_editingSelection = Selection();
Chris@127 1449 return true;
Chris@127 1450 }
Chris@127 1451
Chris@127 1452 int p0 = getXForFrame(m_editingSelection.getStartFrame()) + offset;
Chris@127 1453 int p1 = getXForFrame(m_editingSelection.getEndFrame()) + offset;
Chris@127 1454
Chris@127 1455 long f0 = getFrameForX(p0);
Chris@127 1456 long f1 = getFrameForX(p1);
Chris@127 1457
Chris@127 1458 Selection newSelection(f0, f1);
Chris@127 1459
Chris@127 1460 if (m_editingSelectionEdge == 0) {
Chris@127 1461
Chris@127 1462 CommandHistory::getInstance()->startCompoundOperation
Chris@127 1463 (tr("Drag Selection"), true);
Chris@127 1464
Chris@127 1465 layer->moveSelection(m_editingSelection, f0);
Chris@127 1466
Chris@127 1467 } else {
Chris@127 1468
Chris@127 1469 CommandHistory::getInstance()->startCompoundOperation
Chris@127 1470 (tr("Resize Selection"), true);
Chris@127 1471
Chris@127 1472 if (m_editingSelectionEdge < 0) {
Chris@127 1473 f1 = m_editingSelection.getEndFrame();
Chris@127 1474 } else {
Chris@127 1475 f0 = m_editingSelection.getStartFrame();
Chris@127 1476 }
Chris@127 1477
Chris@127 1478 newSelection = Selection(f0, f1);
Chris@127 1479 layer->resizeSelection(m_editingSelection, newSelection);
Chris@127 1480 }
Chris@127 1481
Chris@127 1482 m_manager->removeSelection(m_editingSelection);
Chris@127 1483 m_manager->addSelection(newSelection);
Chris@127 1484
Chris@127 1485 CommandHistory::getInstance()->endCompoundOperation();
Chris@127 1486
Chris@127 1487 m_editingSelection = Selection();
Chris@127 1488 return true;
Chris@127 1489 }
Chris@127 1490
Chris@127 1491 void
Chris@127 1492 Pane::toolModeChanged()
Chris@127 1493 {
Chris@127 1494 ViewManager::ToolMode mode = m_manager->getToolMode();
Chris@127 1495 // std::cerr << "Pane::toolModeChanged(" << mode << ")" << std::endl;
Chris@127 1496
Chris@127 1497 switch (mode) {
Chris@127 1498
Chris@127 1499 case ViewManager::NavigateMode:
Chris@127 1500 setCursor(Qt::PointingHandCursor);
Chris@127 1501 break;
Chris@127 1502
Chris@127 1503 case ViewManager::SelectMode:
Chris@127 1504 setCursor(Qt::ArrowCursor);
Chris@127 1505 break;
Chris@127 1506
Chris@127 1507 case ViewManager::EditMode:
Chris@127 1508 setCursor(Qt::UpArrowCursor);
Chris@127 1509 break;
Chris@127 1510
Chris@127 1511 case ViewManager::DrawMode:
Chris@127 1512 setCursor(Qt::CrossCursor);
Chris@127 1513 break;
Chris@127 1514 /*
Chris@127 1515 case ViewManager::TextMode:
Chris@127 1516 setCursor(Qt::IBeamCursor);
Chris@127 1517 break;
Chris@127 1518 */
Chris@127 1519 }
Chris@127 1520 }
Chris@127 1521
Chris@133 1522 void
Chris@133 1523 Pane::zoomWheelsEnabledChanged()
Chris@133 1524 {
Chris@133 1525 updateHeadsUpDisplay();
Chris@133 1526 update();
Chris@133 1527 }
Chris@133 1528
Chris@133 1529 void
Chris@133 1530 Pane::zoomLevelChanged()
Chris@133 1531 {
Chris@133 1532 if (m_manager && m_manager->getZoomWheelsEnabled()) {
Chris@133 1533 updateHeadsUpDisplay();
Chris@133 1534 }
Chris@133 1535 }
Chris@133 1536
Chris@133 1537 void
Chris@133 1538 Pane::propertyContainerSelected(View *v, PropertyContainer *pc)
Chris@133 1539 {
Chris@133 1540 Layer *layer = 0;
Chris@133 1541
Chris@133 1542 if (getLayerCount() > 0) {
Chris@133 1543 layer = getLayer(getLayerCount() - 1);
Chris@133 1544 disconnect(layer, SIGNAL(verticalZoomChanged()),
Chris@133 1545 this, SLOT(verticalZoomChanged()));
Chris@133 1546 }
Chris@133 1547
Chris@133 1548 View::propertyContainerSelected(v, pc);
Chris@133 1549 updateHeadsUpDisplay();
Chris@133 1550
Chris@133 1551 if (getLayerCount() > 0) {
Chris@133 1552 layer = getLayer(getLayerCount() - 1);
Chris@133 1553 connect(layer, SIGNAL(verticalZoomChanged()),
Chris@133 1554 this, SLOT(verticalZoomChanged()));
Chris@133 1555 }
Chris@133 1556 }
Chris@133 1557
Chris@133 1558 void
Chris@133 1559 Pane::verticalZoomChanged()
Chris@133 1560 {
Chris@133 1561 Layer *layer = 0;
Chris@133 1562
Chris@133 1563 if (getLayerCount() > 0) {
Chris@133 1564
Chris@133 1565 layer = getLayer(getLayerCount() - 1);
Chris@133 1566
Chris@133 1567 if (m_vthumb && m_vthumb->isVisible()) {
Chris@133 1568 m_vthumb->setValue(layer->getCurrentVerticalZoomStep());
Chris@133 1569 }
Chris@133 1570 }
Chris@133 1571 }
Chris@133 1572
Chris@127 1573 QString
Chris@127 1574 Pane::toXmlString(QString indent, QString extraAttributes) const
Chris@127 1575 {
Chris@127 1576 return View::toXmlString
Chris@127 1577 (indent,
Chris@127 1578 QString("type=\"pane\" centreLineVisible=\"%1\" height=\"%2\" %3")
Chris@127 1579 .arg(m_centreLineVisible).arg(height()).arg(extraAttributes));
Chris@127 1580 }
Chris@127 1581
Chris@127 1582
Chris@127 1583 #ifdef INCLUDE_MOCFILES
Chris@127 1584 #include "Pane.moc.cpp"
Chris@127 1585 #endif
Chris@127 1586