annotate view/Pane.cpp @ 494:b3140e9e0665

* Some fairly simplistic code to set up layer type properties based on RDF data about feature types (both when running transforms and when importing features from RDF files).
author Chris Cannam
date Thu, 12 Feb 2009 15:26:43 +0000
parents f60b6204856e
children dd6bd2d00f86
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@264 7 This file copyright 2006-2007 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@376 23 #include "widgets/CommandHistory.h"
Chris@376 24 #include "widgets/TextAbbrev.h"
Chris@338 25 #include "base/Preferences.h"
Chris@127 26 #include "layer/WaveformLayer.h"
Chris@127 27
Chris@326 28 //!!! ugh
Chris@326 29 #include "data/model/WaveFileModel.h"
Chris@326 30
Chris@127 31 #include <QPaintEvent>
Chris@127 32 #include <QPainter>
Chris@257 33 #include <QBitmap>
Chris@312 34 #include <QDragEnterEvent>
Chris@312 35 #include <QDropEvent>
Chris@257 36 #include <QCursor>
Chris@316 37 #include <QTextStream>
Chris@316 38
Chris@127 39 #include <iostream>
Chris@127 40 #include <cmath>
Chris@127 41
Chris@133 42 //!!! for HUD -- pull out into a separate class
Chris@133 43 #include <QFrame>
Chris@133 44 #include <QGridLayout>
Chris@133 45 #include <QPushButton>
Chris@133 46 #include "widgets/Thumbwheel.h"
Chris@172 47 #include "widgets/Panner.h"
Chris@188 48 #include "widgets/RangeInputDialog.h"
Chris@189 49 #include "widgets/NotifyingPushButton.h"
Chris@133 50
Chris@282 51 #include "widgets/KeyReference.h" //!!! should probably split KeyReference into a data class in base and another that shows the widget
Chris@282 52
Chris@363 53 //#define DEBUG_PANE
Chris@363 54
Chris@127 55 using std::cerr;
Chris@127 56 using std::endl;
Chris@127 57
Chris@267 58 QCursor *Pane::m_measureCursor1 = 0;
Chris@267 59 QCursor *Pane::m_measureCursor2 = 0;
Chris@262 60
Chris@127 61 Pane::Pane(QWidget *w) :
Chris@127 62 View(w, true),
Chris@127 63 m_identifyFeatures(false),
Chris@127 64 m_clickedInRange(false),
Chris@127 65 m_shiftPressed(false),
Chris@127 66 m_ctrlPressed(false),
Chris@127 67 m_navigating(false),
Chris@127 68 m_resizing(false),
Chris@343 69 m_editing(false),
Chris@343 70 m_releasing(false),
Chris@133 71 m_centreLineVisible(true),
Chris@222 72 m_scaleWidth(0),
Chris@237 73 m_headsUpDisplay(0),
Chris@237 74 m_vpan(0),
Chris@237 75 m_hthumb(0),
Chris@237 76 m_vthumb(0),
Chris@290 77 m_reset(0),
Chris@290 78 m_mouseInWidget(false)
Chris@127 79 {
Chris@127 80 setObjectName("Pane");
Chris@127 81 setMouseTracking(true);
Chris@312 82 setAcceptDrops(true);
Chris@133 83
Chris@133 84 updateHeadsUpDisplay();
Chris@456 85
Chris@456 86
Chris@460 87 // std::cerr << "Pane::Pane(" << this << ") returning" << std::endl;
Chris@133 88 }
Chris@133 89
Chris@133 90 void
Chris@133 91 Pane::updateHeadsUpDisplay()
Chris@133 92 {
Chris@382 93 Profiler profiler("Pane::updateHeadsUpDisplay");
Chris@187 94
Chris@192 95 if (!isVisible()) return;
Chris@192 96
Chris@132 97 /*
Chris@132 98 int count = 0;
Chris@132 99 int currentLevel = 1;
Chris@132 100 int level = 1;
Chris@132 101 while (true) {
Chris@132 102 if (getZoomLevel() == level) currentLevel = count;
Chris@132 103 int newLevel = getZoomConstraintBlockSize(level + 1,
Chris@132 104 ZoomConstraint::RoundUp);
Chris@132 105 if (newLevel == level) break;
Chris@132 106 if (newLevel == 131072) break; //!!! just because
Chris@132 107 level = newLevel;
Chris@132 108 ++count;
Chris@132 109 }
Chris@132 110
Chris@132 111 std::cerr << "Have " << count+1 << " zoom levels" << std::endl;
Chris@132 112 */
Chris@133 113
Chris@188 114 Layer *layer = 0;
Chris@188 115 if (getLayerCount() > 0) layer = getLayer(getLayerCount() - 1);
Chris@188 116
Chris@133 117 if (!m_headsUpDisplay) {
Chris@133 118
Chris@133 119 m_headsUpDisplay = new QFrame(this);
Chris@133 120
Chris@133 121 QGridLayout *layout = new QGridLayout;
Chris@133 122 layout->setMargin(0);
Chris@133 123 layout->setSpacing(0);
Chris@133 124 m_headsUpDisplay->setLayout(layout);
Chris@133 125
Chris@133 126 m_hthumb = new Thumbwheel(Qt::Horizontal);
Chris@187 127 m_hthumb->setObjectName(tr("Horizontal Zoom"));
Chris@260 128 m_hthumb->setCursor(Qt::ArrowCursor);
Chris@173 129 layout->addWidget(m_hthumb, 1, 0, 1, 2);
Chris@133 130 m_hthumb->setFixedWidth(70);
Chris@133 131 m_hthumb->setFixedHeight(16);
Chris@133 132 m_hthumb->setDefaultValue(0);
Chris@165 133 m_hthumb->setSpeed(0.6);
Chris@133 134 connect(m_hthumb, SIGNAL(valueChanged(int)), this,
Chris@133 135 SLOT(horizontalThumbwheelMoved(int)));
Chris@189 136 connect(m_hthumb, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
Chris@189 137 connect(m_hthumb, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
Chris@172 138
Chris@172 139 m_vpan = new Panner;
Chris@260 140 m_vpan->setCursor(Qt::ArrowCursor);
Chris@172 141 layout->addWidget(m_vpan, 0, 1);
Chris@173 142 m_vpan->setFixedWidth(12);
Chris@172 143 m_vpan->setFixedHeight(70);
Chris@174 144 m_vpan->setAlpha(80, 130);
Chris@174 145 connect(m_vpan, SIGNAL(rectExtentsChanged(float, float, float, float)),
Chris@174 146 this, SLOT(verticalPannerMoved(float, float, float, float)));
Chris@188 147 connect(m_vpan, SIGNAL(doubleClicked()),
Chris@188 148 this, SLOT(editVerticalPannerExtents()));
Chris@189 149 connect(m_vpan, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
Chris@189 150 connect(m_vpan, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
Chris@172 151
Chris@133 152 m_vthumb = new Thumbwheel(Qt::Vertical);
Chris@187 153 m_vthumb->setObjectName(tr("Vertical Zoom"));
Chris@260 154 m_vthumb->setCursor(Qt::ArrowCursor);
Chris@172 155 layout->addWidget(m_vthumb, 0, 2);
Chris@133 156 m_vthumb->setFixedWidth(16);
Chris@133 157 m_vthumb->setFixedHeight(70);
Chris@133 158 connect(m_vthumb, SIGNAL(valueChanged(int)), this,
Chris@133 159 SLOT(verticalThumbwheelMoved(int)));
Chris@189 160 connect(m_vthumb, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
Chris@189 161 connect(m_vthumb, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
Chris@133 162
Chris@188 163 if (layer) {
Chris@188 164 RangeMapper *rm = layer->getNewVerticalZoomRangeMapper();
Chris@188 165 if (rm) m_vthumb->setRangeMapper(rm);
Chris@188 166 }
Chris@188 167
Chris@189 168 m_reset = new NotifyingPushButton;
Chris@260 169 m_reset->setCursor(Qt::ArrowCursor);
Chris@189 170 m_reset->setFixedHeight(16);
Chris@189 171 m_reset->setFixedWidth(16);
Chris@189 172 layout->addWidget(m_reset, 1, 2);
Chris@492 173
Chris@492 174 layout->setColumnStretch(0, 20);
Chris@492 175
Chris@189 176 connect(m_reset, SIGNAL(clicked()), m_hthumb, SLOT(resetToDefault()));
Chris@189 177 connect(m_reset, SIGNAL(clicked()), m_vthumb, SLOT(resetToDefault()));
Chris@189 178 connect(m_reset, SIGNAL(clicked()), m_vpan, SLOT(resetToDefault()));
Chris@189 179 connect(m_reset, SIGNAL(mouseEntered()), this, SLOT(mouseEnteredWidget()));
Chris@189 180 connect(m_reset, SIGNAL(mouseLeft()), this, SLOT(mouseLeftWidget()));
Chris@133 181 }
Chris@133 182
Chris@133 183 int count = 0;
Chris@133 184 int current = 0;
Chris@133 185 int level = 1;
Chris@133 186
Chris@137 187 //!!! pull out into function (presumably in View)
Chris@137 188 bool haveConstraint = false;
Chris@137 189 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end();
Chris@137 190 ++i) {
Chris@137 191 if ((*i)->getZoomConstraint() && !(*i)->supportsOtherZoomLevels()) {
Chris@137 192 haveConstraint = true;
Chris@137 193 break;
Chris@137 194 }
Chris@137 195 }
Chris@137 196
Chris@137 197 if (haveConstraint) {
Chris@137 198 while (true) {
Chris@137 199 if (getZoomLevel() == level) current = count;
Chris@137 200 int newLevel = getZoomConstraintBlockSize(level + 1,
Chris@137 201 ZoomConstraint::RoundUp);
Chris@137 202 if (newLevel == level) break;
Chris@137 203 level = newLevel;
Chris@137 204 if (++count == 50) break;
Chris@137 205 }
Chris@137 206 } else {
Chris@137 207 // if we have no particular constraints, we can really spread out
Chris@137 208 while (true) {
Chris@137 209 if (getZoomLevel() >= level) current = count;
Chris@137 210 int step = level / 10;
Chris@137 211 int pwr = 0;
Chris@137 212 while (step > 0) {
Chris@137 213 ++pwr;
Chris@137 214 step /= 2;
Chris@137 215 }
Chris@137 216 step = 1;
Chris@137 217 while (pwr > 0) {
Chris@137 218 step *= 2;
Chris@137 219 --pwr;
Chris@137 220 }
Chris@154 221 // std::cerr << level << std::endl;
Chris@137 222 level += step;
Chris@137 223 if (++count == 100 || level > 262144) break;
Chris@137 224 }
Chris@133 225 }
Chris@133 226
Chris@133 227 // std::cerr << "Have " << count << " zoom levels" << std::endl;
Chris@133 228
Chris@133 229 m_hthumb->setMinimumValue(0);
Chris@133 230 m_hthumb->setMaximumValue(count);
Chris@133 231 m_hthumb->setValue(count - current);
Chris@133 232
Chris@133 233 // std::cerr << "set value to " << count-current << std::endl;
Chris@133 234
Chris@133 235 // std::cerr << "default value is " << m_hthumb->getDefaultValue() << std::endl;
Chris@133 236
Chris@133 237 if (count != 50 && m_hthumb->getDefaultValue() == 0) {
Chris@133 238 m_hthumb->setDefaultValue(count - current);
Chris@133 239 // std::cerr << "set default value to " << m_hthumb->getDefaultValue() << std::endl;
Chris@133 240 }
Chris@133 241
Chris@204 242 bool haveVThumb = false;
Chris@204 243
Chris@133 244 if (layer) {
Chris@133 245 int defaultStep = 0;
Chris@133 246 int max = layer->getVerticalZoomSteps(defaultStep);
Chris@133 247 if (max == 0) {
Chris@133 248 m_vthumb->hide();
Chris@133 249 } else {
Chris@204 250 haveVThumb = true;
Chris@133 251 m_vthumb->show();
Chris@187 252 m_vthumb->blockSignals(true);
Chris@133 253 m_vthumb->setMinimumValue(0);
Chris@133 254 m_vthumb->setMaximumValue(max);
Chris@133 255 m_vthumb->setDefaultValue(defaultStep);
Chris@133 256 m_vthumb->setValue(layer->getCurrentVerticalZoomStep());
Chris@187 257 m_vthumb->blockSignals(false);
Chris@135 258
Chris@205 259 // std::cerr << "Vertical thumbwheel: min 0, max " << max
Chris@205 260 // << ", default " << defaultStep << ", value "
Chris@205 261 // << m_vthumb->getValue() << std::endl;
Chris@135 262
Chris@133 263 }
Chris@133 264 }
Chris@133 265
Chris@174 266 updateVerticalPanner();
Chris@174 267
Chris@133 268 if (m_manager && m_manager->getZoomWheelsEnabled() &&
Chris@133 269 width() > 120 && height() > 100) {
Chris@165 270 if (!m_headsUpDisplay->isVisible()) {
Chris@165 271 m_headsUpDisplay->show();
Chris@165 272 }
Chris@204 273 if (haveVThumb) {
Chris@204 274 m_headsUpDisplay->setFixedHeight(m_vthumb->height() + m_hthumb->height());
Chris@133 275 m_headsUpDisplay->move(width() - 86, height() - 86);
Chris@133 276 } else {
Chris@204 277 m_headsUpDisplay->setFixedHeight(m_hthumb->height());
Chris@204 278 m_headsUpDisplay->move(width() - 86, height() - 16);
Chris@133 279 }
Chris@133 280 } else {
Chris@133 281 m_headsUpDisplay->hide();
Chris@133 282 }
Chris@127 283 }
Chris@127 284
Chris@174 285 void
Chris@174 286 Pane::updateVerticalPanner()
Chris@174 287 {
Chris@174 288 if (!m_vpan || !m_manager || !m_manager->getZoomWheelsEnabled()) return;
Chris@174 289
Chris@208 290 // In principle we should show or hide the panner on the basis of
Chris@208 291 // whether the top layer has adjustable display extents, and we do
Chris@208 292 // that below. However, we have no basis for layout of the panner
Chris@208 293 // if the vertical scroll wheel is not also present. So if we
Chris@208 294 // have no vertical scroll wheel, we should remove the panner as
Chris@208 295 // well. Ideally any layer that implements display extents should
Chris@208 296 // implement vertical zoom steps as well, but they don't all at
Chris@208 297 // the moment.
Chris@208 298
Chris@208 299 Layer *layer = 0;
Chris@208 300 if (getLayerCount() > 0) layer = getLayer(getLayerCount() - 1);
Chris@208 301 int discard;
Chris@208 302 if (layer && layer->getVerticalZoomSteps(discard) == 0) {
Chris@208 303 m_vpan->hide();
Chris@208 304 return;
Chris@208 305 }
Chris@208 306
Chris@174 307 float vmin, vmax, dmin, dmax;
Chris@174 308 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax) && vmax != vmin) {
Chris@174 309 float y0 = (dmin - vmin) / (vmax - vmin);
Chris@174 310 float y1 = (dmax - vmin) / (vmax - vmin);
Chris@174 311 m_vpan->blockSignals(true);
Chris@174 312 m_vpan->setRectExtents(0, 1.0 - y1, 1, y1 - y0);
Chris@174 313 m_vpan->blockSignals(false);
Chris@174 314 m_vpan->show();
Chris@174 315 } else {
Chris@174 316 m_vpan->hide();
Chris@174 317 }
Chris@174 318 }
Chris@174 319
Chris@127 320 bool
Chris@127 321 Pane::shouldIlluminateLocalFeatures(const Layer *layer, QPoint &pos) const
Chris@127 322 {
Chris@127 323 QPoint discard;
Chris@127 324 bool b0, b1;
Chris@127 325
Chris@262 326 if (m_manager && m_manager->getToolMode() == ViewManager::MeasureMode) {
Chris@262 327 return false;
Chris@262 328 }
Chris@262 329
Chris@326 330 if (m_manager && !m_manager->shouldIlluminateLocalFeatures()) {
Chris@326 331 return false;
Chris@326 332 }
Chris@326 333
Chris@127 334 if (layer == getSelectedLayer() &&
Chris@127 335 !shouldIlluminateLocalSelection(discard, b0, b1)) {
Chris@127 336
Chris@127 337 pos = m_identifyPoint;
Chris@127 338 return m_identifyFeatures;
Chris@127 339 }
Chris@127 340
Chris@127 341 return false;
Chris@127 342 }
Chris@127 343
Chris@127 344 bool
Chris@127 345 Pane::shouldIlluminateLocalSelection(QPoint &pos,
Chris@127 346 bool &closeToLeft,
Chris@127 347 bool &closeToRight) const
Chris@127 348 {
Chris@127 349 if (m_identifyFeatures &&
Chris@127 350 m_manager &&
Chris@127 351 m_manager->getToolMode() == ViewManager::EditMode &&
Chris@127 352 !m_manager->getSelections().empty() &&
Chris@127 353 !selectionIsBeingEdited()) {
Chris@127 354
Chris@127 355 Selection s(getSelectionAt(m_identifyPoint.x(),
Chris@127 356 closeToLeft, closeToRight));
Chris@127 357
Chris@127 358 if (!s.isEmpty()) {
Chris@127 359 if (getSelectedLayer() && getSelectedLayer()->isLayerEditable()) {
Chris@127 360
Chris@127 361 pos = m_identifyPoint;
Chris@127 362 return true;
Chris@127 363 }
Chris@127 364 }
Chris@127 365 }
Chris@127 366
Chris@127 367 return false;
Chris@127 368 }
Chris@127 369
Chris@127 370 bool
Chris@127 371 Pane::selectionIsBeingEdited() const
Chris@127 372 {
Chris@127 373 if (!m_editingSelection.isEmpty()) {
Chris@127 374 if (m_mousePos != m_clickPos &&
Chris@127 375 getFrameForX(m_mousePos.x()) != getFrameForX(m_clickPos.x())) {
Chris@127 376 return true;
Chris@127 377 }
Chris@127 378 }
Chris@127 379 return false;
Chris@127 380 }
Chris@127 381
Chris@127 382 void
Chris@127 383 Pane::setCentreLineVisible(bool visible)
Chris@127 384 {
Chris@127 385 m_centreLineVisible = visible;
Chris@127 386 update();
Chris@127 387 }
Chris@127 388
Chris@127 389 void
Chris@127 390 Pane::paintEvent(QPaintEvent *e)
Chris@127 391 {
Chris@127 392 // Profiler profiler("Pane::paintEvent", true);
Chris@127 393
Chris@127 394 QPainter paint;
Chris@127 395
Chris@127 396 QRect r(rect());
Chris@261 397 if (e) r = e->rect();
Chris@127 398
Chris@127 399 View::paintEvent(e);
Chris@127 400
Chris@127 401 paint.begin(this);
Chris@339 402 setPaintFont(paint);
Chris@338 403
Chris@261 404 if (e) paint.setClipRect(r);
Chris@127 405
Chris@259 406 ViewManager::ToolMode toolMode = m_manager->getToolMode();
Chris@259 407
Chris@127 408 if (m_manager &&
Chris@290 409 // !m_manager->isPlaying() &&
Chris@290 410 m_mouseInWidget &&
Chris@259 411 toolMode == ViewManager::MeasureMode) {
Chris@127 412
Chris@127 413 for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) {
Chris@127 414 --vi;
Chris@127 415
Chris@127 416 std::vector<QRect> crosshairExtents;
Chris@127 417
Chris@127 418 if ((*vi)->getCrosshairExtents(this, paint, m_identifyPoint,
Chris@127 419 crosshairExtents)) {
Chris@127 420 (*vi)->paintCrosshairs(this, paint, m_identifyPoint);
Chris@127 421 break;
Chris@127 422 } else if ((*vi)->isLayerOpaque()) {
Chris@127 423 break;
Chris@127 424 }
Chris@127 425 }
Chris@127 426 }
Chris@127 427
Chris@268 428 Layer *topLayer = getTopLayer();
Chris@277 429 bool haveSomeTimeXAxis = false;
Chris@268 430
Chris@258 431 const Model *waveformModel = 0; // just for reporting purposes
Chris@326 432 const Model *workModel = 0;
Chris@326 433
Chris@127 434 for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) {
Chris@127 435 --vi;
Chris@277 436 if (!haveSomeTimeXAxis && (*vi)->hasTimeXAxis()) {
Chris@277 437 haveSomeTimeXAxis = true;
Chris@277 438 }
Chris@127 439 if (dynamic_cast<WaveformLayer *>(*vi)) {
Chris@127 440 waveformModel = (*vi)->getModel();
Chris@326 441 workModel = waveformModel;
Chris@326 442 } else {
Chris@326 443 Model *m = (*vi)->getModel();
Chris@326 444 if (dynamic_cast<WaveFileModel *>(m)) {
Chris@326 445 workModel = m;
Chris@326 446 } else if (m && dynamic_cast<WaveFileModel *>(m->getSourceModel())) {
Chris@326 447 workModel = m->getSourceModel();
Chris@326 448 }
Chris@127 449 }
Chris@326 450
Chris@326 451 if (waveformModel && workModel && haveSomeTimeXAxis) break;
Chris@258 452 }
Chris@127 453
Chris@261 454 m_scaleWidth = 0;
Chris@261 455
Chris@261 456 if (m_manager && m_manager->shouldShowVerticalScale() && topLayer) {
Chris@261 457 drawVerticalScale(r, topLayer, paint);
Chris@261 458 }
Chris@261 459
Chris@326 460 if (m_identifyFeatures &&
Chris@326 461 m_manager && m_manager->shouldIlluminateLocalFeatures() &&
Chris@326 462 topLayer) {
Chris@261 463 drawFeatureDescription(topLayer, paint);
Chris@261 464 }
Chris@261 465
Chris@261 466 int sampleRate = getModelsSampleRate();
Chris@261 467 paint.setBrush(Qt::NoBrush);
Chris@261 468
Chris@261 469 if (m_centreLineVisible &&
Chris@261 470 m_manager &&
Chris@261 471 m_manager->shouldShowCentreLine()) {
Chris@277 472 drawCentreLine(sampleRate, paint, !haveSomeTimeXAxis);
Chris@261 473 }
Chris@261 474
Chris@261 475 paint.setPen(QColor(50, 50, 50));
Chris@261 476
Chris@261 477 if (waveformModel &&
Chris@261 478 m_manager &&
Chris@261 479 m_manager->shouldShowDuration()) {
Chris@261 480 drawDurationAndRate(r, waveformModel, sampleRate, paint);
Chris@261 481 }
Chris@261 482
Chris@326 483 bool haveWorkTitle = false;
Chris@326 484
Chris@326 485 if (workModel &&
Chris@326 486 m_manager &&
Chris@326 487 m_manager->shouldShowWorkTitle()) {
Chris@326 488 drawWorkTitle(r, paint, workModel);
Chris@326 489 haveWorkTitle = true;
Chris@326 490 }
Chris@326 491
Chris@326 492 if (workModel &&
Chris@320 493 m_manager &&
Chris@320 494 m_manager->getAlignMode()) {
Chris@326 495 drawAlignmentStatus(r, paint, workModel, haveWorkTitle);
Chris@320 496 }
Chris@320 497
Chris@261 498 if (m_manager &&
Chris@261 499 m_manager->shouldShowLayerNames()) {
Chris@261 500 drawLayerNames(r, paint);
Chris@261 501 }
Chris@261 502
Chris@262 503 if (m_shiftPressed && m_clickedInRange &&
Chris@283 504 (toolMode == ViewManager::NavigateMode || m_navigating)) {
Chris@261 505
Chris@261 506 //!!! be nice if this looked a bit more in keeping with the
Chris@261 507 //selection block
Chris@262 508
Chris@262 509 paint.setPen(Qt::blue);
Chris@262 510 //!!! shouldn't use clickPos -- needs to use a clicked frame
Chris@262 511 paint.drawRect(m_clickPos.x(), m_clickPos.y(),
Chris@262 512 m_mousePos.x() - m_clickPos.x(),
Chris@262 513 m_mousePos.y() - m_clickPos.y());
Chris@261 514
Chris@262 515 }
Chris@261 516
Chris@266 517 if (toolMode == ViewManager::MeasureMode && topLayer) {
Chris@272 518 bool showFocus = false;
Chris@272 519 if (!m_manager || !m_manager->isPlaying()) showFocus = true;
Chris@272 520 topLayer->paintMeasurementRects(this, paint, showFocus, m_identifyPoint);
Chris@261 521 }
Chris@261 522
Chris@261 523 if (selectionIsBeingEdited()) {
Chris@261 524 drawEditingSelection(paint);
Chris@261 525 }
Chris@261 526
Chris@261 527 paint.end();
Chris@261 528 }
Chris@261 529
Chris@276 530 size_t
Chris@276 531 Pane::getVerticalScaleWidth() const
Chris@276 532 {
Chris@276 533 if (m_scaleWidth > 0) return m_scaleWidth;
Chris@276 534 else return 0;
Chris@276 535 }
Chris@276 536
Chris@261 537 void
Chris@261 538 Pane::drawVerticalScale(QRect r, Layer *topLayer, QPainter &paint)
Chris@261 539 {
Chris@258 540 Layer *scaleLayer = 0;
Chris@258 541
Chris@261 542 float min, max;
Chris@261 543 bool log;
Chris@261 544 QString unit;
Chris@258 545
Chris@261 546 // If the top layer has no scale and reports no display
Chris@261 547 // extents, but does report a unit, then the scale should be
Chris@261 548 // drawn from any underlying layer with a scale and that unit.
Chris@261 549 // If the top layer has no scale and no value extents at all,
Chris@261 550 // then the scale should be drawn from any underlying layer
Chris@261 551 // with a scale regardless of unit.
Chris@258 552
Chris@261 553 int sw = topLayer->getVerticalScaleWidth(this, paint);
Chris@258 554
Chris@261 555 if (sw > 0) {
Chris@261 556 scaleLayer = topLayer;
Chris@261 557 m_scaleWidth = sw;
Chris@258 558
Chris@261 559 } else {
Chris@258 560
Chris@261 561 bool hasDisplayExtents = topLayer->getDisplayExtents(min, max);
Chris@261 562 bool hasValueExtents = topLayer->getValueExtents(min, max, log, unit);
Chris@261 563
Chris@261 564 if (!hasDisplayExtents) {
Chris@258 565
Chris@261 566 if (!hasValueExtents) {
Chris@258 567
Chris@261 568 for (LayerList::iterator vi = m_layers.end();
Chris@261 569 vi != m_layers.begin(); ) {
Chris@261 570
Chris@261 571 --vi;
Chris@261 572
Chris@261 573 if ((*vi) == topLayer) continue;
Chris@261 574
Chris@261 575 sw = (*vi)->getVerticalScaleWidth(this, paint);
Chris@261 576
Chris@261 577 if (sw > 0) {
Chris@261 578 scaleLayer = *vi;
Chris@261 579 m_scaleWidth = sw;
Chris@261 580 break;
Chris@261 581 }
Chris@261 582 }
Chris@261 583 } else if (unit != "") { // && hasValueExtents && !hasDisplayExtents
Chris@258 584
Chris@261 585 QString requireUnit = unit;
Chris@261 586
Chris@261 587 for (LayerList::iterator vi = m_layers.end();
Chris@261 588 vi != m_layers.begin(); ) {
Chris@258 589
Chris@261 590 --vi;
Chris@258 591
Chris@261 592 if ((*vi) == topLayer) continue;
Chris@258 593
Chris@261 594 if ((*vi)->getDisplayExtents(min, max)) {
Chris@261 595
Chris@261 596 // search no further than this: if the
Chris@261 597 // scale from this layer isn't suitable,
Chris@261 598 // we'll have to draw no scale (else we'd
Chris@261 599 // risk ending up with the wrong scale)
Chris@261 600
Chris@261 601 if ((*vi)->getValueExtents(min, max, log, unit) &&
Chris@261 602 unit == requireUnit) {
Chris@261 603
Chris@261 604 sw = (*vi)->getVerticalScaleWidth(this, paint);
Chris@261 605 if (sw > 0) {
Chris@261 606 scaleLayer = *vi;
Chris@261 607 m_scaleWidth = sw;
Chris@261 608 }
Chris@258 609 }
Chris@261 610 break;
Chris@258 611 }
Chris@258 612 }
Chris@258 613 }
Chris@127 614 }
Chris@258 615 }
Chris@127 616
Chris@258 617 if (!scaleLayer) m_scaleWidth = 0;
Chris@258 618
Chris@258 619 if (m_scaleWidth > 0 && r.left() < m_scaleWidth) {
Chris@127 620
Chris@127 621 // Profiler profiler("Pane::paintEvent - painting vertical scale", true);
Chris@127 622
Chris@127 623 // std::cerr << "Pane::paintEvent: calling paint.save() in vertical scale block" << std::endl;
Chris@258 624 paint.save();
Chris@258 625
Chris@287 626 paint.setPen(getForeground());
Chris@287 627 paint.setBrush(getBackground());
Chris@258 628 paint.drawRect(0, -1, m_scaleWidth, height()+1);
Chris@258 629
Chris@258 630 paint.setBrush(Qt::NoBrush);
Chris@258 631 scaleLayer->paintVerticalScale
Chris@258 632 (this, paint, QRect(0, 0, m_scaleWidth, height()));
Chris@258 633
Chris@258 634 paint.restore();
Chris@258 635 }
Chris@261 636 }
Chris@261 637
Chris@261 638 void
Chris@261 639 Pane::drawFeatureDescription(Layer *topLayer, QPainter &paint)
Chris@261 640 {
Chris@261 641 QPoint pos = m_identifyPoint;
Chris@261 642 QString desc = topLayer->getFeatureDescription(this, pos);
Chris@261 643
Chris@261 644 if (desc != "") {
Chris@261 645
Chris@261 646 paint.save();
Chris@261 647
Chris@261 648 int tabStop =
Chris@261 649 paint.fontMetrics().width(tr("Some lengthy prefix:"));
Chris@261 650
Chris@261 651 QRect boundingRect =
Chris@261 652 paint.fontMetrics().boundingRect
Chris@261 653 (rect(),
Chris@261 654 Qt::AlignRight | Qt::AlignTop | Qt::TextExpandTabs,
Chris@261 655 desc, tabStop);
Chris@261 656
Chris@261 657 if (hasLightBackground()) {
Chris@261 658 paint.setPen(Qt::NoPen);
Chris@261 659 paint.setBrush(QColor(250, 250, 250, 200));
Chris@261 660 } else {
Chris@261 661 paint.setPen(Qt::NoPen);
Chris@261 662 paint.setBrush(QColor(50, 50, 50, 200));
Chris@261 663 }
Chris@261 664
Chris@261 665 int extra = paint.fontMetrics().descent();
Chris@261 666 paint.drawRect(width() - boundingRect.width() - 10 - extra,
Chris@261 667 10 - extra,
Chris@261 668 boundingRect.width() + 2 * extra,
Chris@261 669 boundingRect.height() + extra);
Chris@261 670
Chris@261 671 if (hasLightBackground()) {
Chris@261 672 paint.setPen(QColor(150, 20, 0));
Chris@261 673 } else {
Chris@261 674 paint.setPen(QColor(255, 150, 100));
Chris@261 675 }
Chris@261 676
Chris@261 677 QTextOption option;
Chris@261 678 option.setWrapMode(QTextOption::NoWrap);
Chris@261 679 option.setAlignment(Qt::AlignRight | Qt::AlignTop);
Chris@261 680 option.setTabStop(tabStop);
Chris@261 681 paint.drawText(QRectF(width() - boundingRect.width() - 10, 10,
Chris@261 682 boundingRect.width(),
Chris@261 683 boundingRect.height()),
Chris@261 684 desc,
Chris@261 685 option);
Chris@261 686
Chris@261 687 paint.restore();
Chris@261 688 }
Chris@261 689 }
Chris@258 690
Chris@261 691 void
Chris@277 692 Pane::drawCentreLine(int sampleRate, QPainter &paint, bool omitLine)
Chris@261 693 {
Chris@261 694 int fontHeight = paint.fontMetrics().height();
Chris@261 695 int fontAscent = paint.fontMetrics().ascent();
Chris@261 696
Chris@261 697 QColor c = QColor(0, 0, 0);
Chris@261 698 if (!hasLightBackground()) {
Chris@261 699 c = QColor(240, 240, 240);
Chris@261 700 }
Chris@277 701
Chris@261 702 paint.setPen(c);
Chris@274 703 int x = width() / 2;
Chris@277 704
Chris@277 705 if (!omitLine) {
Chris@277 706 paint.drawLine(x, 0, x, height() - 1);
Chris@277 707 paint.drawLine(x-1, 1, x+1, 1);
Chris@277 708 paint.drawLine(x-2, 0, x+2, 0);
Chris@277 709 paint.drawLine(x-1, height() - 2, x+1, height() - 2);
Chris@277 710 paint.drawLine(x-2, height() - 1, x+2, height() - 1);
Chris@277 711 }
Chris@261 712
Chris@261 713 paint.setPen(QColor(50, 50, 50));
Chris@261 714
Chris@261 715 int y = height() - fontHeight + fontAscent - 6;
Chris@261 716
Chris@261 717 LayerList::iterator vi = m_layers.end();
Chris@261 718
Chris@261 719 if (vi != m_layers.begin()) {
Chris@261 720
Chris@261 721 switch ((*--vi)->getPreferredFrameCountPosition()) {
Chris@258 722
Chris@261 723 case Layer::PositionTop:
Chris@261 724 y = fontAscent + 6;
Chris@261 725 break;
Chris@258 726
Chris@261 727 case Layer::PositionMiddle:
Chris@261 728 y = (height() - fontHeight) / 2
Chris@261 729 + fontAscent;
Chris@261 730 break;
Chris@127 731
Chris@261 732 case Layer::PositionBottom:
Chris@261 733 // y already set correctly
Chris@261 734 break;
Chris@127 735 }
Chris@127 736 }
Chris@127 737
Chris@261 738 if (m_manager && m_manager->shouldShowFrameCount()) {
Chris@261 739
Chris@261 740 if (sampleRate) {
Chris@127 741
Chris@261 742 QString text(QString::fromStdString
Chris@261 743 (RealTime::frame2RealTime
Chris@261 744 (m_centreFrame, sampleRate).toText(true)));
Chris@127 745
Chris@261 746 int tw = paint.fontMetrics().width(text);
Chris@261 747 int x = width()/2 - 4 - tw;
Chris@127 748
Chris@127 749 drawVisibleText(paint, x, y, text, OutlinedText);
Chris@127 750 }
Chris@261 751
Chris@261 752 QString text = QString("%1").arg(m_centreFrame);
Chris@261 753
Chris@261 754 int x = width()/2 + 4;
Chris@261 755
Chris@261 756 drawVisibleText(paint, x, y, text, OutlinedText);
Chris@261 757 }
Chris@261 758 }
Chris@127 759
Chris@261 760 void
Chris@326 761 Pane::drawAlignmentStatus(QRect r, QPainter &paint, const Model *model,
Chris@326 762 bool down)
Chris@320 763 {
Chris@320 764 const Model *reference = model->getAlignmentReference();
Chris@320 765 /*
Chris@320 766 if (!reference) {
Chris@320 767 std::cerr << "Pane[" << this << "]::drawAlignmentStatus: No reference" << std::endl;
Chris@320 768 } else if (reference == model) {
Chris@320 769 std::cerr << "Pane[" << this << "]::drawAlignmentStatus: This is the reference model" << std::endl;
Chris@320 770 } else {
Chris@320 771 std::cerr << "Pane[" << this << "]::drawAlignmentStatus: This is not the reference" << std::endl;
Chris@320 772 }
Chris@320 773 */
Chris@320 774 QString text;
Chris@320 775 int completion = 100;
Chris@320 776
Chris@320 777 if (reference == model) {
Chris@320 778 text = tr("Reference");
Chris@320 779 } else if (!reference) {
Chris@320 780 text = tr("Unaligned");
Chris@320 781 } else {
Chris@320 782 completion = model->getAlignmentCompletion();
Chris@320 783 if (completion == 0) {
Chris@320 784 text = tr("Unaligned");
Chris@320 785 } else if (completion < 100) {
Chris@320 786 text = tr("Aligning: %1%").arg(completion);
Chris@320 787 } else {
Chris@320 788 text = tr("Aligned");
Chris@320 789 }
Chris@320 790 }
Chris@320 791
Chris@320 792 paint.save();
Chris@320 793 QFont font(paint.font());
Chris@320 794 font.setBold(true);
Chris@320 795 paint.setFont(font);
Chris@326 796 if (completion < 100) paint.setBrush(Qt::red);
Chris@326 797
Chris@326 798 int y = 5;
Chris@326 799 if (down) y += paint.fontMetrics().height();
Chris@326 800 int w = paint.fontMetrics().width(text);
Chris@326 801 int h = paint.fontMetrics().height();
Chris@326 802 if (r.top() > h + y || r.left() > w + m_scaleWidth + 5) {
Chris@326 803 paint.restore();
Chris@326 804 return;
Chris@326 805 }
Chris@320 806
Chris@320 807 drawVisibleText(paint, m_scaleWidth + 5,
Chris@326 808 paint.fontMetrics().ascent() + y, text, OutlinedText);
Chris@320 809
Chris@320 810 paint.restore();
Chris@320 811 }
Chris@320 812
Chris@320 813 void
Chris@320 814 Pane::modelAlignmentCompletionChanged()
Chris@320 815 {
Chris@320 816 View::modelAlignmentCompletionChanged();
Chris@320 817 update(QRect(0, 0, 300, 100));
Chris@320 818 }
Chris@320 819
Chris@320 820 void
Chris@326 821 Pane::drawWorkTitle(QRect r, QPainter &paint, const Model *model)
Chris@326 822 {
Chris@326 823 QString title = model->getTitle();
Chris@326 824 QString maker = model->getMaker();
Chris@327 825 //std::cerr << "Pane::drawWorkTitle: title=\"" << title.toStdString()
Chris@327 826 //<< "\", maker=\"" << maker.toStdString() << "\"" << std::endl;
Chris@326 827 if (title == "") return;
Chris@326 828
Chris@326 829 QString text = title;
Chris@326 830 if (maker != "") {
Chris@326 831 text = tr("%1 - %2").arg(title).arg(maker);
Chris@326 832 }
Chris@326 833
Chris@326 834 paint.save();
Chris@326 835 QFont font(paint.font());
Chris@326 836 font.setItalic(true);
Chris@326 837 paint.setFont(font);
Chris@326 838
Chris@326 839 int y = 5;
Chris@326 840 int w = paint.fontMetrics().width(text);
Chris@326 841 int h = paint.fontMetrics().height();
Chris@326 842 if (r.top() > h + y || r.left() > w + m_scaleWidth + 5) {
Chris@326 843 paint.restore();
Chris@326 844 return;
Chris@326 845 }
Chris@326 846
Chris@326 847 drawVisibleText(paint, m_scaleWidth + 5,
Chris@326 848 paint.fontMetrics().ascent() + y, text, OutlinedText);
Chris@326 849
Chris@326 850 paint.restore();
Chris@326 851 }
Chris@326 852
Chris@326 853 void
Chris@261 854 Pane::drawLayerNames(QRect r, QPainter &paint)
Chris@261 855 {
Chris@261 856 int fontHeight = paint.fontMetrics().height();
Chris@261 857 int fontAscent = paint.fontMetrics().ascent();
Chris@127 858
Chris@300 859 int lly = height() - 6;
Chris@300 860 if (m_manager->getZoomWheelsEnabled()) {
Chris@300 861 lly -= 20;
Chris@300 862 }
Chris@300 863
Chris@300 864 if (r.y() + r.height() < lly - int(m_layers.size()) * fontHeight) {
Chris@261 865 return;
Chris@127 866 }
Chris@127 867
Chris@294 868 QStringList texts;
Chris@299 869 std::vector<QPixmap> pixmaps;
Chris@294 870 for (LayerList::iterator i = m_layers.begin(); i != m_layers.end(); ++i) {
Chris@294 871 texts.push_back((*i)->getLayerPresentationName());
Chris@299 872 // std::cerr << "Pane " << this << ": Layer presentation name for " << *i << ": "
Chris@299 873 // << texts[texts.size()-1].toStdString() << std::endl;
Chris@299 874 pixmaps.push_back((*i)->getLayerPresentationPixmap
Chris@299 875 (QSize(fontAscent, fontAscent)));
Chris@294 876 }
Chris@127 877
Chris@294 878 int maxTextWidth = width() / 3;
Chris@294 879 texts = TextAbbrev::abbreviate(texts, paint.fontMetrics(), maxTextWidth);
Chris@294 880
Chris@261 881 int llx = width() - maxTextWidth - 5;
Chris@261 882 if (m_manager->getZoomWheelsEnabled()) {
Chris@261 883 llx -= 36;
Chris@261 884 }
Chris@261 885
Chris@300 886 if (r.x() + r.width() >= llx - fontAscent - 3) {
Chris@261 887
Chris@261 888 for (size_t i = 0; i < texts.size(); ++i) {
Chris@299 889
Chris@299 890 // std::cerr << "Pane "<< this << ": text " << i << ": " << texts[i].toStdString() << std::endl;
Chris@261 891
Chris@261 892 if (i + 1 == texts.size()) {
Chris@287 893 paint.setPen(getForeground());
Chris@261 894 }
Chris@261 895
Chris@261 896 drawVisibleText(paint, llx,
Chris@261 897 lly - fontHeight + fontAscent,
Chris@261 898 texts[i], OutlinedText);
Chris@299 899
Chris@299 900 if (!pixmaps[i].isNull()) {
Chris@299 901 paint.drawPixmap(llx - fontAscent - 3,
Chris@299 902 lly - fontHeight + (fontHeight-fontAscent)/2,
Chris@299 903 pixmaps[i]);
Chris@299 904 }
Chris@261 905
Chris@261 906 lly -= fontHeight;
Chris@261 907 }
Chris@261 908 }
Chris@261 909 }
Chris@127 910
Chris@261 911 void
Chris@261 912 Pane::drawEditingSelection(QPainter &paint)
Chris@261 913 {
Chris@261 914 int offset = m_mousePos.x() - m_clickPos.x();
Chris@261 915 int p0 = getXForFrame(m_editingSelection.getStartFrame()) + offset;
Chris@261 916 int p1 = getXForFrame(m_editingSelection.getEndFrame()) + offset;
Chris@261 917
Chris@261 918 if (m_editingSelectionEdge < 0) {
Chris@261 919 p1 = getXForFrame(m_editingSelection.getEndFrame());
Chris@261 920 } else if (m_editingSelectionEdge > 0) {
Chris@261 921 p0 = getXForFrame(m_editingSelection.getStartFrame());
Chris@127 922 }
Chris@127 923
Chris@261 924 paint.save();
Chris@287 925 paint.setPen(QPen(getForeground(), 2));
Chris@261 926
Chris@261 927 //!!! duplicating display policy with View::drawSelections
Chris@261 928
Chris@261 929 if (m_editingSelectionEdge < 0) {
Chris@261 930 paint.drawLine(p0, 1, p1, 1);
Chris@261 931 paint.drawLine(p0, 0, p0, height());
Chris@261 932 paint.drawLine(p0, height() - 1, p1, height() - 1);
Chris@261 933 } else if (m_editingSelectionEdge > 0) {
Chris@261 934 paint.drawLine(p0, 1, p1, 1);
Chris@261 935 paint.drawLine(p1, 0, p1, height());
Chris@261 936 paint.drawLine(p0, height() - 1, p1, height() - 1);
Chris@261 937 } else {
Chris@261 938 paint.setBrush(Qt::NoBrush);
Chris@261 939 paint.drawRect(p0, 1, p1 - p0, height() - 2);
Chris@261 940 }
Chris@261 941 paint.restore();
Chris@261 942 }
Chris@127 943
Chris@261 944 void
Chris@261 945 Pane::drawDurationAndRate(QRect r, const Model *waveformModel,
Chris@261 946 int sampleRate, QPainter &paint)
Chris@261 947 {
Chris@261 948 int fontHeight = paint.fontMetrics().height();
Chris@261 949 int fontAscent = paint.fontMetrics().ascent();
Chris@127 950
Chris@261 951 if (r.y() + r.height() < height() - fontHeight - 6) return;
Chris@127 952
Chris@261 953 size_t modelRate = waveformModel->getSampleRate();
Chris@301 954 size_t nativeRate = waveformModel->getNativeRate();
Chris@261 955 size_t playbackRate = m_manager->getPlaybackSampleRate();
Chris@261 956 size_t outputRate = m_manager->getOutputSampleRate();
Chris@261 957
Chris@261 958 QString srNote = "";
Chris@127 959
Chris@301 960 // Show (R) for waveform models that have been resampled or will
Chris@301 961 // be resampled on playback, and (X) for waveform models that will
Chris@301 962 // be played at the wrong rate because their rate differs from the
Chris@261 963 // current playback rate (which is not necessarily that of the
Chris@261 964 // main model).
Chris@127 965
Chris@261 966 if (playbackRate != 0) {
Chris@261 967 if (modelRate == playbackRate) {
Chris@301 968 if (modelRate != outputRate || modelRate != nativeRate) {
Chris@301 969 srNote = " " + tr("(R)");
Chris@301 970 }
Chris@261 971 } else {
Chris@261 972 srNote = " " + tr("(X)");
Chris@261 973 }
Chris@127 974 }
Chris@127 975
Chris@261 976 QString desc = tr("%1 / %2Hz%3")
Chris@261 977 .arg(RealTime::frame2RealTime(waveformModel->getEndFrame(),
Chris@261 978 sampleRate)
Chris@261 979 .toText(false).c_str())
Chris@301 980 .arg(nativeRate)
Chris@261 981 .arg(srNote);
Chris@261 982
Chris@384 983 int x = m_scaleWidth + 5;
Chris@384 984 int pbw = getProgressBarWidth();
Chris@384 985 if (x < pbw + 5) x = pbw + 5;
Chris@384 986
Chris@384 987 if (r.x() < x + paint.fontMetrics().width(desc)) {
Chris@384 988 drawVisibleText(paint, x,
Chris@261 989 height() - fontHeight + fontAscent - 6,
Chris@261 990 desc, OutlinedText);
Chris@261 991 }
Chris@127 992 }
Chris@127 993
Chris@227 994 bool
Chris@229 995 Pane::render(QPainter &paint, int xorigin, size_t f0, size_t f1)
Chris@227 996 {
Chris@229 997 if (!View::render(paint, xorigin + m_scaleWidth, f0, f1)) {
Chris@227 998 return false;
Chris@227 999 }
Chris@227 1000
Chris@227 1001 if (m_scaleWidth > 0) {
Chris@227 1002
Chris@227 1003 for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) {
Chris@227 1004 --vi;
Chris@227 1005
Chris@227 1006 paint.save();
Chris@227 1007
Chris@287 1008 paint.setPen(getForeground());
Chris@287 1009 paint.setBrush(getBackground());
Chris@229 1010 paint.drawRect(xorigin, -1, m_scaleWidth, height()+1);
Chris@227 1011
Chris@227 1012 paint.setBrush(Qt::NoBrush);
Chris@227 1013 (*vi)->paintVerticalScale
Chris@229 1014 (this, paint, QRect(xorigin, 0, m_scaleWidth, height()));
Chris@227 1015
Chris@227 1016 paint.restore();
Chris@227 1017 break;
Chris@227 1018 }
Chris@227 1019 }
Chris@227 1020
Chris@227 1021 return true;
Chris@227 1022 }
Chris@227 1023
Chris@227 1024 QImage *
Chris@229 1025 Pane::toNewImage(size_t f0, size_t f1)
Chris@227 1026 {
Chris@227 1027 size_t x0 = f0 / getZoomLevel();
Chris@227 1028 size_t x1 = f1 / getZoomLevel();
Chris@227 1029
Chris@227 1030 QImage *image = new QImage(x1 - x0 + m_scaleWidth,
Chris@227 1031 height(), QImage::Format_RGB32);
Chris@227 1032
Chris@227 1033 int formerScaleWidth = m_scaleWidth;
Chris@227 1034
Chris@227 1035 if (m_manager && m_manager->shouldShowVerticalScale()) {
Chris@227 1036 for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) {
Chris@227 1037 --vi;
Chris@227 1038 QPainter paint(image);
Chris@227 1039 m_scaleWidth = (*vi)->getVerticalScaleWidth(this, paint);
Chris@227 1040 break;
Chris@227 1041 }
Chris@227 1042 } else {
Chris@227 1043 m_scaleWidth = 0;
Chris@227 1044 }
Chris@227 1045
Chris@227 1046 if (m_scaleWidth != formerScaleWidth) {
Chris@227 1047 delete image;
Chris@227 1048 image = new QImage(x1 - x0 + m_scaleWidth,
Chris@227 1049 height(), QImage::Format_RGB32);
Chris@227 1050 }
Chris@227 1051
Chris@227 1052 QPainter *paint = new QPainter(image);
Chris@229 1053 if (!render(*paint, 0, f0, f1)) {
Chris@227 1054 delete paint;
Chris@227 1055 delete image;
Chris@227 1056 return 0;
Chris@227 1057 } else {
Chris@227 1058 delete paint;
Chris@227 1059 return image;
Chris@227 1060 }
Chris@227 1061 }
Chris@227 1062
Chris@229 1063 QSize
Chris@229 1064 Pane::getImageSize(size_t f0, size_t f1)
Chris@229 1065 {
Chris@229 1066 QSize s = View::getImageSize(f0, f1);
Chris@229 1067 QImage *image = new QImage(100, 100, QImage::Format_RGB32);
Chris@229 1068 QPainter paint(image);
Chris@229 1069
Chris@229 1070 int sw = 0;
Chris@229 1071 if (m_manager && m_manager->shouldShowVerticalScale()) {
Chris@229 1072 for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) {
Chris@229 1073 --vi;
Chris@229 1074 QPainter paint(image);
Chris@229 1075 sw = (*vi)->getVerticalScaleWidth(this, paint);
Chris@229 1076 break;
Chris@229 1077 }
Chris@229 1078 }
Chris@229 1079
Chris@229 1080 return QSize(sw + s.width(), s.height());
Chris@229 1081 }
Chris@229 1082
Chris@222 1083 size_t
Chris@222 1084 Pane::getFirstVisibleFrame() const
Chris@222 1085 {
Chris@222 1086 long f0 = getFrameForX(m_scaleWidth);
Chris@222 1087 size_t f = View::getFirstVisibleFrame();
Chris@222 1088 if (f0 < 0 || f0 < long(f)) return f;
Chris@222 1089 return f0;
Chris@222 1090 }
Chris@222 1091
Chris@127 1092 Selection
Chris@127 1093 Pane::getSelectionAt(int x, bool &closeToLeftEdge, bool &closeToRightEdge) const
Chris@127 1094 {
Chris@127 1095 closeToLeftEdge = closeToRightEdge = false;
Chris@127 1096
Chris@127 1097 if (!m_manager) return Selection();
Chris@127 1098
Chris@127 1099 long testFrame = getFrameForX(x - 5);
Chris@127 1100 if (testFrame < 0) {
Chris@127 1101 testFrame = getFrameForX(x);
Chris@127 1102 if (testFrame < 0) return Selection();
Chris@127 1103 }
Chris@127 1104
Chris@127 1105 Selection selection = m_manager->getContainingSelection(testFrame, true);
Chris@127 1106 if (selection.isEmpty()) return selection;
Chris@127 1107
Chris@127 1108 int lx = getXForFrame(selection.getStartFrame());
Chris@127 1109 int rx = getXForFrame(selection.getEndFrame());
Chris@127 1110
Chris@127 1111 int fuzz = 2;
Chris@127 1112 if (x < lx - fuzz || x > rx + fuzz) return Selection();
Chris@127 1113
Chris@127 1114 int width = rx - lx;
Chris@127 1115 fuzz = 3;
Chris@127 1116 if (width < 12) fuzz = width / 4;
Chris@127 1117 if (fuzz < 1) fuzz = 1;
Chris@127 1118
Chris@127 1119 if (x < lx + fuzz) closeToLeftEdge = true;
Chris@127 1120 if (x > rx - fuzz) closeToRightEdge = true;
Chris@127 1121
Chris@127 1122 return selection;
Chris@127 1123 }
Chris@127 1124
Chris@174 1125 bool
Chris@174 1126 Pane::canTopLayerMoveVertical()
Chris@174 1127 {
Chris@174 1128 float vmin, vmax, dmin, dmax;
Chris@174 1129 if (!getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) return false;
Chris@174 1130 if (dmin <= vmin && dmax >= vmax) return false;
Chris@174 1131 return true;
Chris@174 1132 }
Chris@174 1133
Chris@174 1134 bool
Chris@174 1135 Pane::getTopLayerDisplayExtents(float &vmin, float &vmax,
Chris@188 1136 float &dmin, float &dmax,
Chris@188 1137 QString *unit)
Chris@174 1138 {
Chris@268 1139 Layer *layer = getTopLayer();
Chris@174 1140 if (!layer) return false;
Chris@174 1141 bool vlog;
Chris@174 1142 QString vunit;
Chris@188 1143 bool rv = (layer->getValueExtents(vmin, vmax, vlog, vunit) &&
Chris@188 1144 layer->getDisplayExtents(dmin, dmax));
Chris@188 1145 if (unit) *unit = vunit;
Chris@188 1146 return rv;
Chris@174 1147 }
Chris@174 1148
Chris@174 1149 bool
Chris@174 1150 Pane::setTopLayerDisplayExtents(float dmin, float dmax)
Chris@174 1151 {
Chris@268 1152 Layer *layer = getTopLayer();
Chris@174 1153 if (!layer) return false;
Chris@174 1154 return layer->setDisplayExtents(dmin, dmax);
Chris@174 1155 }
Chris@174 1156
Chris@127 1157 void
Chris@282 1158 Pane::registerShortcuts(KeyReference &kr)
Chris@282 1159 {
Chris@282 1160 kr.setCategory(tr("Zoom"));
Chris@282 1161 kr.registerAlternativeShortcut(tr("Zoom In"), tr("Wheel Up"));
Chris@282 1162 kr.registerAlternativeShortcut(tr("Zoom Out"), tr("Wheel Down"));
Chris@282 1163
Chris@282 1164 kr.setCategory(tr("General Pane Mouse Actions"));
Chris@282 1165
Chris@282 1166 kr.registerShortcut(tr("Zoom"), tr("Wheel"),
Chris@282 1167 tr("Zoom in or out in time axis"));
Chris@408 1168 kr.registerShortcut(tr("Scroll"), tr("Ctrl+Wheel"),
Chris@282 1169 tr("Scroll rapidly left or right in time axis"));
Chris@282 1170 kr.registerShortcut(tr("Zoom Vertically"), tr("Shift+Wheel"),
Chris@282 1171 tr("Zoom in or out in the vertical axis"));
Chris@282 1172 kr.registerShortcut(tr("Scroll Vertically"), tr("Alt+Wheel"),
Chris@282 1173 tr("Scroll up or down in the vertical axis"));
Chris@282 1174 kr.registerShortcut(tr("Navigate"), tr("Middle"),
Chris@282 1175 tr("Click middle button and drag to navigate with any tool"));
Chris@282 1176 kr.registerShortcut(tr("Relocate"), tr("Double-Click Middle"),
Chris@282 1177 tr("Double-click middle button to relocate with any tool"));
Chris@282 1178 kr.registerShortcut(tr("Menu"), tr("Right"),
Chris@282 1179 tr("Show pane context menu"));
Chris@282 1180
Chris@282 1181 kr.setCategory(tr("Navigate Tool Mouse Actions"));
Chris@282 1182
Chris@282 1183 kr.registerShortcut(tr("Navigate"), tr("Left"),
Chris@282 1184 tr("Click left button and drag to move around"));
Chris@282 1185 kr.registerShortcut(tr("Zoom to Area"), tr("Shift+Left"),
Chris@282 1186 tr("Shift-click left button and drag to zoom to a rectangular area"));
Chris@282 1187 kr.registerShortcut(tr("Relocate"), tr("Double-Click Left"),
Chris@282 1188 tr("Double-click left button to jump to clicked location"));
Chris@282 1189 kr.registerShortcut(tr("Edit"), tr("Double-Click Left"),
Chris@282 1190 tr("Double-click left button on an item to edit it"));
Chris@282 1191
Chris@282 1192 kr.setCategory(tr("Select Tool Mouse Actions"));
Chris@282 1193 kr.registerShortcut(tr("Select"), tr("Left"),
Chris@282 1194 tr("Click left button and drag to select region; drag region edge to resize"));
Chris@282 1195 kr.registerShortcut(tr("Multi Select"), tr("Ctrl+Left"),
Chris@282 1196 tr("Ctrl-click left button and drag to select an additional region"));
Chris@283 1197 kr.registerShortcut(tr("Fine Select"), tr("Shift+Left"),
Chris@283 1198 tr("Shift-click left button and drag to select without snapping to items or grid"));
Chris@282 1199
Chris@282 1200 kr.setCategory(tr("Edit Tool Mouse Actions"));
Chris@282 1201 kr.registerShortcut(tr("Move"), tr("Left"),
Chris@282 1202 tr("Click left button on an item or selected region and drag to move"));
Chris@282 1203 kr.registerShortcut(tr("Edit"), tr("Double-Click Left"),
Chris@282 1204 tr("Double-click left button on an item to edit it"));
Chris@282 1205
Chris@282 1206 kr.setCategory(tr("Draw Tool Mouse Actions"));
Chris@282 1207 kr.registerShortcut(tr("Draw"), tr("Left"),
Chris@282 1208 tr("Click left button and drag to create new item"));
Chris@282 1209
Chris@282 1210 kr.setCategory(tr("Measure Tool Mouse Actions"));
Chris@282 1211 kr.registerShortcut(tr("Measure Area"), tr("Left"),
Chris@282 1212 tr("Click left button and drag to measure a rectangular area"));
Chris@282 1213 kr.registerShortcut(tr("Measure Item"), tr("Double-Click Left"),
Chris@282 1214 tr("Click left button and drag to measure extents of an item or shape"));
Chris@283 1215 kr.registerShortcut(tr("Zoom to Area"), tr("Shift+Left"),
Chris@283 1216 tr("Shift-click left button and drag to zoom to a rectangular area"));
Chris@282 1217 }
Chris@282 1218
Chris@282 1219 void
Chris@127 1220 Pane::mousePressEvent(QMouseEvent *e)
Chris@127 1221 {
Chris@127 1222 if (e->buttons() & Qt::RightButton) {
Chris@189 1223 emit contextHelpChanged("");
Chris@127 1224 emit rightButtonMenuRequested(mapToGlobal(e->pos()));
Chris@127 1225 return;
Chris@127 1226 }
Chris@127 1227
Chris@343 1228 // std::cerr << "mousePressEvent" << std::endl;
Chris@341 1229
Chris@127 1230 m_clickPos = e->pos();
Chris@262 1231 m_mousePos = m_clickPos;
Chris@127 1232 m_clickedInRange = true;
Chris@127 1233 m_editingSelection = Selection();
Chris@127 1234 m_editingSelectionEdge = 0;
Chris@127 1235 m_shiftPressed = (e->modifiers() & Qt::ShiftModifier);
Chris@127 1236 m_ctrlPressed = (e->modifiers() & Qt::ControlModifier);
Chris@150 1237 m_dragMode = UnresolvedDrag;
Chris@127 1238
Chris@127 1239 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@127 1240 if (m_manager) mode = m_manager->getToolMode();
Chris@127 1241
Chris@127 1242 m_navigating = false;
Chris@343 1243 m_resizing = false;
Chris@343 1244 m_editing = false;
Chris@343 1245 m_releasing = false;
Chris@127 1246
Chris@283 1247 if (mode == ViewManager::NavigateMode ||
Chris@283 1248 (e->buttons() & Qt::MidButton) ||
Chris@283 1249 (mode == ViewManager::MeasureMode &&
Chris@283 1250 (e->buttons() & Qt::LeftButton) && m_shiftPressed)) {
Chris@127 1251
Chris@127 1252 if (mode != ViewManager::NavigateMode) {
Chris@127 1253 setCursor(Qt::PointingHandCursor);
Chris@127 1254 }
Chris@127 1255
Chris@127 1256 m_navigating = true;
Chris@127 1257 m_dragCentreFrame = m_centreFrame;
Chris@136 1258 m_dragStartMinValue = 0;
Chris@174 1259
Chris@174 1260 float vmin, vmax, dmin, dmax;
Chris@174 1261 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) {
Chris@174 1262 m_dragStartMinValue = dmin;
Chris@136 1263 }
Chris@136 1264
Chris@127 1265 } else if (mode == ViewManager::SelectMode) {
Chris@127 1266
Chris@217 1267 if (!hasTopLayerTimeXAxis()) return;
Chris@217 1268
Chris@127 1269 bool closeToLeft = false, closeToRight = false;
Chris@127 1270 Selection selection = getSelectionAt(e->x(), closeToLeft, closeToRight);
Chris@127 1271
Chris@127 1272 if ((closeToLeft || closeToRight) && !(closeToLeft && closeToRight)) {
Chris@127 1273
Chris@127 1274 m_manager->removeSelection(selection);
Chris@127 1275
Chris@127 1276 if (closeToLeft) {
Chris@127 1277 m_selectionStartFrame = selection.getEndFrame();
Chris@127 1278 } else {
Chris@127 1279 m_selectionStartFrame = selection.getStartFrame();
Chris@127 1280 }
Chris@127 1281
Chris@127 1282 m_manager->setInProgressSelection(selection, false);
Chris@127 1283 m_resizing = true;
Chris@127 1284
Chris@127 1285 } else {
Chris@127 1286
Chris@127 1287 int mouseFrame = getFrameForX(e->x());
Chris@127 1288 size_t resolution = 1;
Chris@127 1289 int snapFrame = mouseFrame;
Chris@127 1290
Chris@127 1291 Layer *layer = getSelectedLayer();
Chris@127 1292 if (layer && !m_shiftPressed) {
Chris@127 1293 layer->snapToFeatureFrame(this, snapFrame,
Chris@127 1294 resolution, Layer::SnapLeft);
Chris@127 1295 }
Chris@127 1296
Chris@127 1297 if (snapFrame < 0) snapFrame = 0;
Chris@127 1298 m_selectionStartFrame = snapFrame;
Chris@127 1299 if (m_manager) {
Chris@333 1300 m_manager->setInProgressSelection
Chris@333 1301 (Selection(alignToReference(snapFrame),
Chris@333 1302 alignToReference(snapFrame + resolution)),
Chris@333 1303 !m_ctrlPressed);
Chris@127 1304 }
Chris@127 1305
Chris@127 1306 m_resizing = false;
Chris@127 1307 }
Chris@127 1308
Chris@127 1309 update();
Chris@127 1310
Chris@127 1311 } else if (mode == ViewManager::DrawMode) {
Chris@127 1312
Chris@127 1313 Layer *layer = getSelectedLayer();
Chris@127 1314 if (layer && layer->isLayerEditable()) {
Chris@127 1315 layer->drawStart(this, e);
Chris@127 1316 }
Chris@127 1317
Chris@335 1318 } else if (mode == ViewManager::EraseMode) {
Chris@335 1319
Chris@335 1320 Layer *layer = getSelectedLayer();
Chris@335 1321 if (layer && layer->isLayerEditable()) {
Chris@335 1322 layer->eraseStart(this, e);
Chris@335 1323 }
Chris@335 1324
Chris@127 1325 } else if (mode == ViewManager::EditMode) {
Chris@127 1326
Chris@343 1327 // Do nothing here -- we'll do it in mouseMoveEvent when the
Chris@343 1328 // drag threshold has been passed
Chris@262 1329
Chris@262 1330 } else if (mode == ViewManager::MeasureMode) {
Chris@262 1331
Chris@268 1332 Layer *layer = getTopLayer();
Chris@267 1333 if (layer) layer->measureStart(this, e);
Chris@262 1334 update();
Chris@127 1335 }
Chris@127 1336
Chris@127 1337 emit paneInteractedWith();
Chris@127 1338 }
Chris@127 1339
Chris@127 1340 void
Chris@127 1341 Pane::mouseReleaseEvent(QMouseEvent *e)
Chris@127 1342 {
Chris@127 1343 if (e->buttons() & Qt::RightButton) {
Chris@127 1344 return;
Chris@127 1345 }
Chris@127 1346
Chris@343 1347 // std::cerr << "mouseReleaseEvent" << std::endl;
Chris@341 1348
Chris@127 1349 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@127 1350 if (m_manager) mode = m_manager->getToolMode();
Chris@127 1351
Chris@343 1352 m_releasing = true;
Chris@343 1353
Chris@127 1354 if (m_clickedInRange) {
Chris@127 1355 mouseMoveEvent(e);
Chris@127 1356 }
Chris@127 1357
Chris@127 1358 if (m_navigating || mode == ViewManager::NavigateMode) {
Chris@127 1359
Chris@127 1360 m_navigating = false;
Chris@127 1361
Chris@127 1362 if (mode != ViewManager::NavigateMode) {
Chris@127 1363 // restore cursor
Chris@127 1364 toolModeChanged();
Chris@127 1365 }
Chris@127 1366
Chris@127 1367 if (m_shiftPressed) {
Chris@127 1368
Chris@127 1369 int x0 = std::min(m_clickPos.x(), m_mousePos.x());
Chris@127 1370 int x1 = std::max(m_clickPos.x(), m_mousePos.x());
Chris@127 1371
Chris@127 1372 int y0 = std::min(m_clickPos.y(), m_mousePos.y());
Chris@127 1373 int y1 = std::max(m_clickPos.y(), m_mousePos.y());
Chris@127 1374
Chris@174 1375 zoomToRegion(x0, y0, x1, y1);
Chris@127 1376 }
Chris@127 1377
Chris@127 1378 } else if (mode == ViewManager::SelectMode) {
Chris@127 1379
Chris@343 1380 if (!hasTopLayerTimeXAxis()) {
Chris@343 1381 m_releasing = false;
Chris@343 1382 return;
Chris@343 1383 }
Chris@217 1384
Chris@127 1385 if (m_manager && m_manager->haveInProgressSelection()) {
Chris@127 1386
Chris@127 1387 bool exclusive;
Chris@127 1388 Selection selection = m_manager->getInProgressSelection(exclusive);
Chris@127 1389
Chris@127 1390 if (selection.getEndFrame() < selection.getStartFrame() + 2) {
Chris@127 1391 selection = Selection();
Chris@127 1392 }
Chris@127 1393
Chris@127 1394 m_manager->clearInProgressSelection();
Chris@127 1395
Chris@127 1396 if (exclusive) {
Chris@127 1397 m_manager->setSelection(selection);
Chris@127 1398 } else {
Chris@127 1399 m_manager->addSelection(selection);
Chris@127 1400 }
Chris@127 1401 }
Chris@127 1402
Chris@127 1403 update();
Chris@127 1404
Chris@127 1405 } else if (mode == ViewManager::DrawMode) {
Chris@127 1406
Chris@127 1407 Layer *layer = getSelectedLayer();
Chris@127 1408 if (layer && layer->isLayerEditable()) {
Chris@127 1409 layer->drawEnd(this, e);
Chris@127 1410 update();
Chris@127 1411 }
Chris@127 1412
Chris@335 1413 } else if (mode == ViewManager::EraseMode) {
Chris@335 1414
Chris@335 1415 Layer *layer = getSelectedLayer();
Chris@335 1416 if (layer && layer->isLayerEditable()) {
Chris@335 1417 layer->eraseEnd(this, e);
Chris@335 1418 update();
Chris@335 1419 }
Chris@335 1420
Chris@127 1421 } else if (mode == ViewManager::EditMode) {
Chris@127 1422
Chris@343 1423 if (m_editing) {
Chris@343 1424 if (!editSelectionEnd(e)) {
Chris@343 1425 Layer *layer = getSelectedLayer();
Chris@343 1426 if (layer && layer->isLayerEditable()) {
Chris@343 1427 layer->editEnd(this, e);
Chris@343 1428 update();
Chris@343 1429 }
Chris@343 1430 }
Chris@343 1431 }
Chris@262 1432
Chris@262 1433 } else if (mode == ViewManager::MeasureMode) {
Chris@262 1434
Chris@268 1435 Layer *layer = getTopLayer();
Chris@267 1436 if (layer) layer->measureEnd(this, e);
Chris@267 1437 if (m_measureCursor1) setCursor(*m_measureCursor1);
Chris@267 1438 update();
Chris@127 1439 }
Chris@127 1440
Chris@127 1441 m_clickedInRange = false;
Chris@343 1442 m_releasing = false;
Chris@127 1443
Chris@127 1444 emit paneInteractedWith();
Chris@127 1445 }
Chris@127 1446
Chris@127 1447 void
Chris@127 1448 Pane::mouseMoveEvent(QMouseEvent *e)
Chris@127 1449 {
Chris@127 1450 if (e->buttons() & Qt::RightButton) {
Chris@127 1451 return;
Chris@127 1452 }
Chris@127 1453
Chris@343 1454 // std::cerr << "mouseMoveEvent" << std::endl;
Chris@341 1455
Chris@189 1456 updateContextHelp(&e->pos());
Chris@189 1457
Chris@343 1458 if (m_navigating && m_clickedInRange && !m_releasing) {
Chris@343 1459
Chris@343 1460 // if no buttons pressed, and not called from
Chris@343 1461 // mouseReleaseEvent, we want to reset clicked-ness (to avoid
Chris@343 1462 // annoying continual drags when we moved the mouse outside
Chris@343 1463 // the window after pressing button first time).
Chris@343 1464
Chris@343 1465 if (!(e->buttons() & Qt::LeftButton) &&
Chris@343 1466 !(e->buttons() & Qt::MidButton)) {
Chris@343 1467 m_clickedInRange = false;
Chris@343 1468 return;
Chris@343 1469 }
Chris@343 1470 }
Chris@343 1471
Chris@127 1472 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@127 1473 if (m_manager) mode = m_manager->getToolMode();
Chris@127 1474
Chris@127 1475 QPoint prevPoint = m_identifyPoint;
Chris@127 1476 m_identifyPoint = e->pos();
Chris@127 1477
Chris@127 1478 if (!m_clickedInRange) {
Chris@127 1479
Chris@217 1480 if (mode == ViewManager::SelectMode && hasTopLayerTimeXAxis()) {
Chris@127 1481 bool closeToLeft = false, closeToRight = false;
Chris@127 1482 getSelectionAt(e->x(), closeToLeft, closeToRight);
Chris@127 1483 if ((closeToLeft || closeToRight) && !(closeToLeft && closeToRight)) {
Chris@127 1484 setCursor(Qt::SizeHorCursor);
Chris@127 1485 } else {
Chris@127 1486 setCursor(Qt::ArrowCursor);
Chris@127 1487 }
Chris@127 1488 }
Chris@127 1489
Chris@127 1490 if (!m_manager->isPlaying()) {
Chris@127 1491
Chris@272 1492 bool updating = false;
Chris@272 1493
Chris@326 1494 if (getSelectedLayer() &&
Chris@326 1495 m_manager->shouldIlluminateLocalFeatures()) {
Chris@127 1496
Chris@174 1497 bool previouslyIdentifying = m_identifyFeatures;
Chris@174 1498 m_identifyFeatures = true;
Chris@174 1499
Chris@174 1500 if (m_identifyFeatures != previouslyIdentifying ||
Chris@174 1501 m_identifyPoint != prevPoint) {
Chris@174 1502 update();
Chris@272 1503 updating = true;
Chris@272 1504 }
Chris@272 1505 }
Chris@272 1506
Chris@272 1507 if (!updating && mode == ViewManager::MeasureMode &&
Chris@272 1508 m_manager && !m_manager->isPlaying()) {
Chris@272 1509
Chris@272 1510 Layer *layer = getTopLayer();
Chris@272 1511 if (layer && layer->nearestMeasurementRectChanged
Chris@272 1512 (this, prevPoint, m_identifyPoint)) {
Chris@272 1513 update();
Chris@174 1514 }
Chris@174 1515 }
Chris@127 1516 }
Chris@127 1517
Chris@127 1518 return;
Chris@127 1519 }
Chris@127 1520
Chris@127 1521 if (m_navigating || mode == ViewManager::NavigateMode) {
Chris@127 1522
Chris@127 1523 if (m_shiftPressed) {
Chris@127 1524
Chris@127 1525 m_mousePos = e->pos();
Chris@127 1526 update();
Chris@127 1527
Chris@127 1528 } else {
Chris@127 1529
Chris@174 1530 dragTopLayer(e);
Chris@150 1531 }
Chris@127 1532
Chris@127 1533 } else if (mode == ViewManager::SelectMode) {
Chris@127 1534
Chris@217 1535 if (!hasTopLayerTimeXAxis()) return;
Chris@217 1536
Chris@174 1537 dragExtendSelection(e);
Chris@127 1538
Chris@127 1539 } else if (mode == ViewManager::DrawMode) {
Chris@127 1540
Chris@127 1541 Layer *layer = getSelectedLayer();
Chris@127 1542 if (layer && layer->isLayerEditable()) {
Chris@127 1543 layer->drawDrag(this, e);
Chris@127 1544 }
Chris@127 1545
Chris@335 1546 } else if (mode == ViewManager::EraseMode) {
Chris@335 1547
Chris@335 1548 Layer *layer = getSelectedLayer();
Chris@335 1549 if (layer && layer->isLayerEditable()) {
Chris@335 1550 layer->eraseDrag(this, e);
Chris@335 1551 }
Chris@335 1552
Chris@127 1553 } else if (mode == ViewManager::EditMode) {
Chris@127 1554
Chris@343 1555 if (m_editing) {
Chris@343 1556 if (!editSelectionDrag(e)) {
Chris@343 1557 Layer *layer = getSelectedLayer();
Chris@343 1558 if (layer && layer->isLayerEditable()) {
Chris@343 1559 layer->editDrag(this, e);
Chris@343 1560 }
Chris@343 1561 }
Chris@343 1562 }
Chris@343 1563
Chris@343 1564 if (!m_editing) {
Chris@343 1565
Chris@387 1566 bool resist = true;
Chris@387 1567
Chris@387 1568 if ((e->modifiers() & Qt::ShiftModifier)) {
Chris@387 1569 m_shiftPressed = true;
Chris@387 1570 // ... but don't set it false if shift has been
Chris@387 1571 // released -- we want the state when we started
Chris@387 1572 // dragging to be used most of the time
Chris@387 1573 }
Chris@387 1574
Chris@387 1575 if (m_shiftPressed) resist = false;
Chris@387 1576
Chris@343 1577 DragMode newDragMode = updateDragMode
Chris@343 1578 (m_dragMode,
Chris@343 1579 m_clickPos,
Chris@343 1580 e->pos(),
Chris@387 1581 true, // can move horiz
Chris@387 1582 true, // can move vert
Chris@387 1583 resist, // resist horiz
Chris@387 1584 resist); // resist vert
Chris@343 1585
Chris@343 1586 if (newDragMode != UnresolvedDrag) {
Chris@343 1587
Chris@343 1588 m_editing = true;
Chris@343 1589
Chris@343 1590 QMouseEvent clickEvent(QEvent::MouseButtonPress,
Chris@343 1591 m_clickPos,
Chris@343 1592 Qt::NoButton,
Chris@343 1593 e->buttons(),
Chris@343 1594 e->modifiers());
Chris@343 1595
Chris@343 1596 if (!editSelectionStart(&clickEvent)) {
Chris@343 1597 Layer *layer = getSelectedLayer();
Chris@343 1598 if (layer && layer->isLayerEditable()) {
Chris@343 1599 layer->editStart(this, &clickEvent);
Chris@343 1600 }
Chris@343 1601 }
Chris@343 1602 }
Chris@343 1603 }
Chris@259 1604
Chris@259 1605 } else if (mode == ViewManager::MeasureMode) {
Chris@259 1606
Chris@267 1607 if (m_measureCursor2) setCursor(*m_measureCursor2);
Chris@266 1608
Chris@268 1609 Layer *layer = getTopLayer();
Chris@290 1610 if (layer) {
Chris@290 1611 layer->measureDrag(this, e);
Chris@290 1612 if (layer->hasTimeXAxis()) edgeScrollMaybe(e->x());
Chris@290 1613 }
Chris@267 1614
Chris@267 1615 update();
Chris@127 1616 }
Chris@127 1617 }
Chris@127 1618
Chris@127 1619 void
Chris@174 1620 Pane::zoomToRegion(int x0, int y0, int x1, int y1)
Chris@174 1621 {
Chris@174 1622 int w = x1 - x0;
Chris@174 1623
Chris@174 1624 long newStartFrame = getFrameForX(x0);
Chris@174 1625
Chris@174 1626 long visibleFrames = getEndFrame() - getStartFrame();
Chris@174 1627 if (newStartFrame <= -visibleFrames) {
Chris@174 1628 newStartFrame = -visibleFrames + 1;
Chris@174 1629 }
Chris@174 1630
Chris@174 1631 if (newStartFrame >= long(getModelsEndFrame())) {
Chris@174 1632 newStartFrame = getModelsEndFrame() - 1;
Chris@174 1633 }
Chris@174 1634
Chris@174 1635 float ratio = float(w) / float(width());
Chris@174 1636 // std::cerr << "ratio: " << ratio << std::endl;
Chris@174 1637 size_t newZoomLevel = (size_t)nearbyint(m_zoomLevel * ratio);
Chris@174 1638 if (newZoomLevel < 1) newZoomLevel = 1;
Chris@174 1639
Chris@174 1640 // std::cerr << "start: " << m_startFrame << ", level " << m_zoomLevel << std::endl;
Chris@174 1641 setZoomLevel(getZoomConstraintBlockSize(newZoomLevel));
Chris@174 1642 setStartFrame(newStartFrame);
Chris@174 1643
Chris@174 1644 QString unit;
Chris@174 1645 float min, max;
Chris@174 1646 bool log;
Chris@174 1647 Layer *layer = 0;
Chris@174 1648 for (LayerList::const_iterator i = m_layers.begin();
Chris@174 1649 i != m_layers.end(); ++i) {
Chris@174 1650 if ((*i)->getValueExtents(min, max, log, unit) &&
Chris@174 1651 (*i)->getDisplayExtents(min, max)) {
Chris@174 1652 layer = *i;
Chris@174 1653 break;
Chris@174 1654 }
Chris@174 1655 }
Chris@174 1656
Chris@174 1657 if (layer) {
Chris@174 1658 if (log) {
Chris@174 1659 min = (min < 0.0) ? -log10f(-min) : (min == 0.0) ? 0.0 : log10f(min);
Chris@174 1660 max = (max < 0.0) ? -log10f(-max) : (max == 0.0) ? 0.0 : log10f(max);
Chris@174 1661 }
Chris@174 1662 float rmin = min + ((max - min) * (height() - y1)) / height();
Chris@174 1663 float rmax = min + ((max - min) * (height() - y0)) / height();
Chris@174 1664 std::cerr << "min: " << min << ", max: " << max << ", y0: " << y0 << ", y1: " << y1 << ", h: " << height() << ", rmin: " << rmin << ", rmax: " << rmax << std::endl;
Chris@174 1665 if (log) {
Chris@174 1666 rmin = powf(10, rmin);
Chris@174 1667 rmax = powf(10, rmax);
Chris@174 1668 }
Chris@174 1669 std::cerr << "finally: rmin: " << rmin << ", rmax: " << rmax << " " << unit.toStdString() << std::endl;
Chris@174 1670
Chris@174 1671 layer->setDisplayExtents(rmin, rmax);
Chris@174 1672 updateVerticalPanner();
Chris@174 1673 }
Chris@174 1674 }
Chris@174 1675
Chris@174 1676 void
Chris@174 1677 Pane::dragTopLayer(QMouseEvent *e)
Chris@174 1678 {
Chris@174 1679 // We need to avoid making it too easy to drag both
Chris@174 1680 // horizontally and vertically, in the case where the
Chris@174 1681 // mouse is moved "mostly" in horizontal or vertical axis
Chris@174 1682 // with only a small variation in the other axis. This is
Chris@174 1683 // particularly important during playback (when we want to
Chris@174 1684 // avoid small horizontal motions) or in slow refresh
Chris@174 1685 // layers like spectrogram (when we want to avoid small
Chris@174 1686 // vertical motions).
Chris@174 1687 //
Chris@174 1688 // To this end we have horizontal and vertical thresholds
Chris@174 1689 // and a series of states: unresolved, horizontally or
Chris@174 1690 // vertically constrained, free.
Chris@174 1691 //
Chris@174 1692 // When the mouse first moves, we're unresolved: we
Chris@174 1693 // restrict ourselves to whichever direction seems safest,
Chris@174 1694 // until the mouse has passed a small threshold distance
Chris@174 1695 // from the click point. Then we lock in to one of the
Chris@174 1696 // constrained modes, based on which axis that distance
Chris@174 1697 // was measured in first. Finally, if it turns out we've
Chris@174 1698 // also moved more than a certain larger distance in the
Chris@174 1699 // other direction as well, we may switch into free mode.
Chris@174 1700 //
Chris@174 1701 // If the top layer is incapable of being dragged
Chris@174 1702 // vertically, the logic is short circuited.
Chris@174 1703
Chris@343 1704 m_dragMode = updateDragMode
Chris@343 1705 (m_dragMode,
Chris@343 1706 m_clickPos,
Chris@343 1707 e->pos(),
Chris@343 1708 true, // can move horiz
Chris@343 1709 canTopLayerMoveVertical(), // can move vert
Chris@343 1710 canTopLayerMoveVertical() || (m_manager && m_manager->isPlaying()), // resist horiz
Chris@343 1711 !(m_manager && m_manager->isPlaying())); // resist vert
Chris@174 1712
Chris@343 1713 if (m_dragMode == HorizontalDrag ||
Chris@343 1714 m_dragMode == FreeDrag) {
Chris@174 1715
Chris@174 1716 long frameOff = getFrameForX(e->x()) - getFrameForX(m_clickPos.x());
Chris@174 1717
Chris@174 1718 size_t newCentreFrame = m_dragCentreFrame;
Chris@174 1719
Chris@174 1720 if (frameOff < 0) {
Chris@174 1721 newCentreFrame -= frameOff;
Chris@174 1722 } else if (newCentreFrame >= size_t(frameOff)) {
Chris@174 1723 newCentreFrame -= frameOff;
Chris@174 1724 } else {
Chris@174 1725 newCentreFrame = 0;
Chris@174 1726 }
Chris@363 1727
Chris@363 1728 #ifdef DEBUG_PANE
Chris@339 1729 std::cerr << "Pane::dragTopLayer: newCentreFrame = " << newCentreFrame <<
Chris@339 1730 ", models end frame = " << getModelsEndFrame() << std::endl;
Chris@363 1731 #endif
Chris@339 1732
Chris@174 1733 if (newCentreFrame >= getModelsEndFrame()) {
Chris@174 1734 newCentreFrame = getModelsEndFrame();
Chris@174 1735 if (newCentreFrame > 0) --newCentreFrame;
Chris@174 1736 }
Chris@174 1737
Chris@174 1738 if (getXForFrame(m_centreFrame) != getXForFrame(newCentreFrame)) {
Chris@174 1739 setCentreFrame(newCentreFrame);
Chris@174 1740 }
Chris@174 1741 }
Chris@174 1742
Chris@343 1743 if (m_dragMode == VerticalDrag ||
Chris@343 1744 m_dragMode == FreeDrag) {
Chris@174 1745
Chris@174 1746 float vmin = 0.f, vmax = 0.f;
Chris@174 1747 float dmin = 0.f, dmax = 0.f;
Chris@174 1748
Chris@174 1749 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) {
Chris@174 1750
Chris@248 1751 // std::cerr << "ydiff = " << ydiff << std::endl;
Chris@174 1752
Chris@343 1753 int ydiff = e->y() - m_clickPos.y();
Chris@174 1754 float perpix = (dmax - dmin) / height();
Chris@174 1755 float valdiff = ydiff * perpix;
Chris@248 1756 // std::cerr << "valdiff = " << valdiff << std::endl;
Chris@174 1757
Chris@343 1758 if (m_dragMode == UnresolvedDrag && ydiff != 0) {
Chris@343 1759 m_dragMode = VerticalDrag;
Chris@343 1760 }
Chris@343 1761
Chris@174 1762 float newmin = m_dragStartMinValue + valdiff;
Chris@174 1763 float newmax = m_dragStartMinValue + (dmax - dmin) + valdiff;
Chris@174 1764 if (newmin < vmin) {
Chris@174 1765 newmax += vmin - newmin;
Chris@174 1766 newmin += vmin - newmin;
Chris@174 1767 }
Chris@174 1768 if (newmax > vmax) {
Chris@174 1769 newmin -= newmax - vmax;
Chris@174 1770 newmax -= newmax - vmax;
Chris@174 1771 }
Chris@248 1772 // std::cerr << "(" << dmin << ", " << dmax << ") -> ("
Chris@248 1773 // << newmin << ", " << newmax << ") (drag start " << m_dragStartMinValue << ")" << std::endl;
Chris@174 1774
Chris@174 1775 setTopLayerDisplayExtents(newmin, newmax);
Chris@174 1776 updateVerticalPanner();
Chris@174 1777 }
Chris@174 1778 }
Chris@174 1779 }
Chris@174 1780
Chris@343 1781 Pane::DragMode
Chris@343 1782 Pane::updateDragMode(DragMode dragMode,
Chris@343 1783 QPoint origin,
Chris@343 1784 QPoint point,
Chris@343 1785 bool canMoveHorizontal,
Chris@343 1786 bool canMoveVertical,
Chris@343 1787 bool resistHorizontal,
Chris@343 1788 bool resistVertical)
Chris@343 1789 {
Chris@343 1790 int xdiff = point.x() - origin.x();
Chris@343 1791 int ydiff = point.y() - origin.y();
Chris@343 1792
Chris@343 1793 int smallThreshold = 10, bigThreshold = 80;
Chris@343 1794
Chris@343 1795 // std::cerr << "Pane::updateDragMode: xdiff = " << xdiff << ", ydiff = "
Chris@343 1796 // << ydiff << ", canMoveVertical = " << canMoveVertical << ", drag mode = " << m_dragMode << std::endl;
Chris@343 1797
Chris@343 1798 if (dragMode == UnresolvedDrag) {
Chris@343 1799
Chris@343 1800 if (abs(ydiff) > smallThreshold &&
Chris@343 1801 abs(ydiff) > abs(xdiff) * 2 &&
Chris@343 1802 canMoveVertical) {
Chris@343 1803 // std::cerr << "Pane::updateDragMode: passed vertical threshold" << std::endl;
Chris@343 1804 dragMode = VerticalDrag;
Chris@343 1805 } else if (abs(xdiff) > smallThreshold &&
Chris@343 1806 abs(xdiff) > abs(ydiff) * 2 &&
Chris@343 1807 canMoveHorizontal) {
Chris@343 1808 // std::cerr << "Pane::updateDragMode: passed horizontal threshold" << std::endl;
Chris@343 1809 dragMode = HorizontalDrag;
Chris@343 1810 } else if (abs(xdiff) > smallThreshold &&
Chris@343 1811 abs(ydiff) > smallThreshold &&
Chris@343 1812 canMoveVertical &&
Chris@343 1813 canMoveHorizontal) {
Chris@343 1814 // std::cerr << "Pane::updateDragMode: passed both thresholds" << std::endl;
Chris@343 1815 dragMode = FreeDrag;
Chris@343 1816 }
Chris@343 1817 }
Chris@343 1818
Chris@343 1819 if (dragMode == VerticalDrag && canMoveHorizontal) {
Chris@343 1820 if (abs(xdiff) > bigThreshold) dragMode = FreeDrag;
Chris@343 1821 }
Chris@343 1822
Chris@343 1823 if (dragMode == HorizontalDrag && canMoveVertical) {
Chris@343 1824 if (abs(ydiff) > bigThreshold) dragMode = FreeDrag;
Chris@343 1825 }
Chris@343 1826
Chris@343 1827 if (dragMode == UnresolvedDrag) {
Chris@343 1828 if (!resistHorizontal && xdiff != 0) {
Chris@343 1829 dragMode = HorizontalDrag;
Chris@343 1830 }
Chris@343 1831 if (!resistVertical && ydiff != 0) {
Chris@343 1832 if (dragMode == HorizontalDrag) dragMode = FreeDrag;
Chris@343 1833 else dragMode = VerticalDrag;
Chris@343 1834 }
Chris@343 1835 }
Chris@343 1836
Chris@343 1837 return dragMode;
Chris@343 1838 }
Chris@343 1839
Chris@174 1840 void
Chris@174 1841 Pane::dragExtendSelection(QMouseEvent *e)
Chris@174 1842 {
Chris@174 1843 int mouseFrame = getFrameForX(e->x());
Chris@174 1844 size_t resolution = 1;
Chris@174 1845 int snapFrameLeft = mouseFrame;
Chris@174 1846 int snapFrameRight = mouseFrame;
Chris@174 1847
Chris@174 1848 Layer *layer = getSelectedLayer();
Chris@174 1849 if (layer && !m_shiftPressed) {
Chris@174 1850 layer->snapToFeatureFrame(this, snapFrameLeft,
Chris@174 1851 resolution, Layer::SnapLeft);
Chris@174 1852 layer->snapToFeatureFrame(this, snapFrameRight,
Chris@174 1853 resolution, Layer::SnapRight);
Chris@174 1854 }
Chris@174 1855
Chris@174 1856 // std::cerr << "snap: frame = " << mouseFrame << ", start frame = " << m_selectionStartFrame << ", left = " << snapFrameLeft << ", right = " << snapFrameRight << std::endl;
Chris@174 1857
Chris@174 1858 if (snapFrameLeft < 0) snapFrameLeft = 0;
Chris@174 1859 if (snapFrameRight < 0) snapFrameRight = 0;
Chris@174 1860
Chris@174 1861 size_t min, max;
Chris@174 1862
Chris@248 1863 if (m_selectionStartFrame > size_t(snapFrameLeft)) {
Chris@174 1864 min = snapFrameLeft;
Chris@174 1865 max = m_selectionStartFrame;
Chris@248 1866 } else if (size_t(snapFrameRight) > m_selectionStartFrame) {
Chris@174 1867 min = m_selectionStartFrame;
Chris@174 1868 max = snapFrameRight;
Chris@174 1869 } else {
Chris@174 1870 min = snapFrameLeft;
Chris@174 1871 max = snapFrameRight;
Chris@174 1872 }
Chris@174 1873
Chris@174 1874 if (m_manager) {
Chris@333 1875 m_manager->setInProgressSelection(Selection(alignToReference(min),
Chris@333 1876 alignToReference(max)),
Chris@174 1877 !m_resizing && !m_ctrlPressed);
Chris@174 1878 }
Chris@174 1879
Chris@259 1880 edgeScrollMaybe(e->x());
Chris@259 1881
Chris@259 1882 update();
Chris@259 1883 }
Chris@259 1884
Chris@259 1885 void
Chris@259 1886 Pane::edgeScrollMaybe(int x)
Chris@259 1887 {
Chris@259 1888 int mouseFrame = getFrameForX(x);
Chris@259 1889
Chris@174 1890 bool doScroll = false;
Chris@174 1891 if (!m_manager) doScroll = true;
Chris@174 1892 if (!m_manager->isPlaying()) doScroll = true;
Chris@174 1893 if (m_followPlay != PlaybackScrollContinuous) doScroll = true;
Chris@174 1894
Chris@174 1895 if (doScroll) {
Chris@174 1896 int offset = mouseFrame - getStartFrame();
Chris@174 1897 int available = getEndFrame() - getStartFrame();
Chris@259 1898 int move = 0;
Chris@174 1899 if (offset >= available * 0.95) {
Chris@259 1900 move = int(offset - available * 0.95) + 1;
Chris@259 1901 } else if (offset <= available * 0.10) {
Chris@259 1902 move = int(available * 0.10 - offset) + 1;
Chris@259 1903 move = -move;
Chris@259 1904 }
Chris@259 1905 if (move != 0) {
Chris@174 1906 setCentreFrame(m_centreFrame + move);
Chris@259 1907 update();
Chris@174 1908 }
Chris@174 1909 }
Chris@174 1910 }
Chris@174 1911
Chris@174 1912 void
Chris@127 1913 Pane::mouseDoubleClickEvent(QMouseEvent *e)
Chris@127 1914 {
Chris@127 1915 if (e->buttons() & Qt::RightButton) {
Chris@127 1916 return;
Chris@127 1917 }
Chris@127 1918
Chris@343 1919 // std::cerr << "mouseDoubleClickEvent" << std::endl;
Chris@127 1920
Chris@127 1921 m_clickPos = e->pos();
Chris@127 1922 m_clickedInRange = true;
Chris@127 1923 m_shiftPressed = (e->modifiers() & Qt::ShiftModifier);
Chris@127 1924 m_ctrlPressed = (e->modifiers() & Qt::ControlModifier);
Chris@127 1925
Chris@127 1926 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@127 1927 if (m_manager) mode = m_manager->getToolMode();
Chris@127 1928
Chris@255 1929 bool relocate = (mode == ViewManager::NavigateMode ||
Chris@255 1930 (e->buttons() & Qt::MidButton));
Chris@255 1931
Chris@127 1932 if (mode == ViewManager::NavigateMode ||
Chris@127 1933 mode == ViewManager::EditMode) {
Chris@127 1934
Chris@127 1935 Layer *layer = getSelectedLayer();
Chris@127 1936 if (layer && layer->isLayerEditable()) {
Chris@255 1937 if (layer->editOpen(this, e)) relocate = false;
Chris@127 1938 }
Chris@280 1939
Chris@280 1940 } else if (mode == ViewManager::MeasureMode) {
Chris@280 1941
Chris@280 1942 Layer *layer = getTopLayer();
Chris@280 1943 if (layer) layer->measureDoubleClick(this, e);
Chris@280 1944 update();
Chris@127 1945 }
Chris@255 1946
Chris@255 1947 if (relocate) {
Chris@255 1948
Chris@255 1949 long f = getFrameForX(e->x());
Chris@255 1950
Chris@255 1951 setCentreFrame(f);
Chris@255 1952
Chris@255 1953 m_dragCentreFrame = f;
Chris@255 1954 m_dragStartMinValue = 0;
Chris@255 1955 m_dragMode = UnresolvedDrag;
Chris@255 1956
Chris@255 1957 float vmin, vmax, dmin, dmax;
Chris@255 1958 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) {
Chris@255 1959 m_dragStartMinValue = dmin;
Chris@255 1960 }
Chris@255 1961 }
Chris@127 1962 }
Chris@127 1963
Chris@127 1964 void
Chris@290 1965 Pane::enterEvent(QEvent *)
Chris@290 1966 {
Chris@290 1967 m_mouseInWidget = true;
Chris@290 1968 }
Chris@290 1969
Chris@290 1970 void
Chris@127 1971 Pane::leaveEvent(QEvent *)
Chris@127 1972 {
Chris@290 1973 m_mouseInWidget = false;
Chris@127 1974 bool previouslyIdentifying = m_identifyFeatures;
Chris@127 1975 m_identifyFeatures = false;
Chris@127 1976 if (previouslyIdentifying) update();
Chris@189 1977 emit contextHelpChanged("");
Chris@127 1978 }
Chris@127 1979
Chris@127 1980 void
Chris@133 1981 Pane::resizeEvent(QResizeEvent *)
Chris@133 1982 {
Chris@133 1983 updateHeadsUpDisplay();
Chris@133 1984 }
Chris@133 1985
Chris@133 1986 void
Chris@127 1987 Pane::wheelEvent(QWheelEvent *e)
Chris@127 1988 {
Chris@127 1989 //std::cerr << "wheelEvent, delta " << e->delta() << std::endl;
Chris@127 1990
Chris@127 1991 int count = e->delta();
Chris@127 1992
Chris@127 1993 if (count > 0) {
Chris@127 1994 if (count >= 120) count /= 120;
Chris@127 1995 else count = 1;
Chris@127 1996 }
Chris@127 1997
Chris@127 1998 if (count < 0) {
Chris@127 1999 if (count <= -120) count /= 120;
Chris@127 2000 else count = -1;
Chris@127 2001 }
Chris@127 2002
Chris@127 2003 if (e->modifiers() & Qt::ControlModifier) {
Chris@127 2004
Chris@127 2005 // Scroll left or right, rapidly
Chris@127 2006
Chris@127 2007 if (getStartFrame() < 0 &&
Chris@127 2008 getEndFrame() >= getModelsEndFrame()) return;
Chris@127 2009
Chris@127 2010 long delta = ((width() / 2) * count * m_zoomLevel);
Chris@127 2011
Chris@127 2012 if (int(m_centreFrame) < delta) {
Chris@127 2013 setCentreFrame(0);
Chris@127 2014 } else if (int(m_centreFrame) - delta >= int(getModelsEndFrame())) {
Chris@127 2015 setCentreFrame(getModelsEndFrame());
Chris@127 2016 } else {
Chris@127 2017 setCentreFrame(m_centreFrame - delta);
Chris@127 2018 }
Chris@127 2019
Chris@256 2020 } else if (e->modifiers() & Qt::ShiftModifier) {
Chris@256 2021
Chris@256 2022 // Zoom vertically
Chris@256 2023
Chris@256 2024 if (m_vpan) {
Chris@256 2025 m_vpan->scroll(e->delta() > 0);
Chris@256 2026 }
Chris@256 2027
Chris@256 2028 } else if (e->modifiers() & Qt::AltModifier) {
Chris@256 2029
Chris@256 2030 // Zoom vertically
Chris@256 2031
Chris@256 2032 if (m_vthumb) {
Chris@256 2033 m_vthumb->scroll(e->delta() > 0);
Chris@256 2034 }
Chris@256 2035
Chris@127 2036 } else {
Chris@127 2037
Chris@127 2038 // Zoom in or out
Chris@127 2039
Chris@127 2040 int newZoomLevel = m_zoomLevel;
Chris@127 2041
Chris@127 2042 while (count > 0) {
Chris@127 2043 if (newZoomLevel <= 2) {
Chris@127 2044 newZoomLevel = 1;
Chris@127 2045 break;
Chris@127 2046 }
Chris@127 2047 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel - 1,
Chris@127 2048 ZoomConstraint::RoundDown);
Chris@127 2049 --count;
Chris@127 2050 }
Chris@127 2051
Chris@127 2052 while (count < 0) {
Chris@127 2053 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel + 1,
Chris@127 2054 ZoomConstraint::RoundUp);
Chris@127 2055 ++count;
Chris@127 2056 }
Chris@127 2057
Chris@127 2058 if (newZoomLevel != m_zoomLevel) {
Chris@127 2059 setZoomLevel(newZoomLevel);
Chris@127 2060 }
Chris@127 2061 }
Chris@127 2062
Chris@127 2063 emit paneInteractedWith();
Chris@127 2064 }
Chris@127 2065
Chris@132 2066 void
Chris@132 2067 Pane::horizontalThumbwheelMoved(int value)
Chris@132 2068 {
Chris@137 2069 //!!! dupe with updateHeadsUpDisplay
Chris@137 2070
Chris@132 2071 int count = 0;
Chris@132 2072 int level = 1;
Chris@137 2073
Chris@137 2074
Chris@137 2075 //!!! pull out into function (presumably in View)
Chris@137 2076 bool haveConstraint = false;
Chris@137 2077 for (LayerList::const_iterator i = m_layers.begin(); i != m_layers.end();
Chris@137 2078 ++i) {
Chris@137 2079 if ((*i)->getZoomConstraint() && !(*i)->supportsOtherZoomLevels()) {
Chris@137 2080 haveConstraint = true;
Chris@137 2081 break;
Chris@137 2082 }
Chris@132 2083 }
Chris@132 2084
Chris@137 2085 if (haveConstraint) {
Chris@137 2086 while (true) {
Chris@137 2087 if (m_hthumb->getMaximumValue() - value == count) break;
Chris@137 2088 int newLevel = getZoomConstraintBlockSize(level + 1,
Chris@137 2089 ZoomConstraint::RoundUp);
Chris@137 2090 if (newLevel == level) break;
Chris@137 2091 level = newLevel;
Chris@137 2092 if (++count == 50) break;
Chris@137 2093 }
Chris@137 2094 } else {
Chris@137 2095 while (true) {
Chris@137 2096 if (m_hthumb->getMaximumValue() - value == count) break;
Chris@137 2097 int step = level / 10;
Chris@137 2098 int pwr = 0;
Chris@137 2099 while (step > 0) {
Chris@137 2100 ++pwr;
Chris@137 2101 step /= 2;
Chris@137 2102 }
Chris@137 2103 step = 1;
Chris@137 2104 while (pwr > 0) {
Chris@137 2105 step *= 2;
Chris@137 2106 --pwr;
Chris@137 2107 }
Chris@137 2108 // std::cerr << level << std::endl;
Chris@137 2109 level += step;
Chris@137 2110 if (++count == 100 || level > 262144) break;
Chris@137 2111 }
Chris@137 2112 }
Chris@137 2113
Chris@244 2114 // std::cerr << "new level is " << level << std::endl;
Chris@132 2115 setZoomLevel(level);
Chris@132 2116 }
Chris@132 2117
Chris@132 2118 void
Chris@132 2119 Pane::verticalThumbwheelMoved(int value)
Chris@132 2120 {
Chris@133 2121 Layer *layer = 0;
Chris@133 2122 if (getLayerCount() > 0) layer = getLayer(getLayerCount() - 1);
Chris@133 2123 if (layer) {
Chris@133 2124 int defaultStep = 0;
Chris@133 2125 int max = layer->getVerticalZoomSteps(defaultStep);
Chris@133 2126 if (max == 0) {
Chris@133 2127 updateHeadsUpDisplay();
Chris@133 2128 return;
Chris@133 2129 }
Chris@133 2130 if (value > max) {
Chris@133 2131 value = max;
Chris@133 2132 }
Chris@133 2133 layer->setVerticalZoomStep(value);
Chris@174 2134 updateVerticalPanner();
Chris@133 2135 }
Chris@132 2136 }
Chris@132 2137
Chris@174 2138 void
Chris@174 2139 Pane::verticalPannerMoved(float x0, float y0, float w, float h)
Chris@174 2140 {
Chris@174 2141 float vmin, vmax, dmin, dmax;
Chris@174 2142 if (!getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) return;
Chris@174 2143 float y1 = y0 + h;
Chris@174 2144 float newmax = vmin + ((1.0 - y0) * (vmax - vmin));
Chris@174 2145 float newmin = vmin + ((1.0 - y1) * (vmax - vmin));
Chris@438 2146 // std::cerr << "verticalPannerMoved: (" << x0 << "," << y0 << "," << w
Chris@438 2147 // << "," << h << ") -> (" << newmin << "," << newmax << ")" << std::endl;
Chris@174 2148 setTopLayerDisplayExtents(newmin, newmax);
Chris@174 2149 }
Chris@174 2150
Chris@188 2151 void
Chris@188 2152 Pane::editVerticalPannerExtents()
Chris@188 2153 {
Chris@188 2154 if (!m_vpan || !m_manager || !m_manager->getZoomWheelsEnabled()) return;
Chris@188 2155
Chris@188 2156 float vmin, vmax, dmin, dmax;
Chris@188 2157 QString unit;
Chris@188 2158 if (!getTopLayerDisplayExtents(vmin, vmax, dmin, dmax, &unit)
Chris@188 2159 || vmax == vmin) {
Chris@188 2160 return;
Chris@188 2161 }
Chris@188 2162
Chris@188 2163 RangeInputDialog dialog(tr("Enter new range"),
Chris@188 2164 tr("New vertical display range, from %1 to %2 %4:")
Chris@188 2165 .arg(vmin).arg(vmax).arg(unit),
Chris@188 2166 unit, vmin, vmax, this);
Chris@188 2167 dialog.setRange(dmin, dmax);
Chris@188 2168
Chris@188 2169 if (dialog.exec() == QDialog::Accepted) {
Chris@188 2170 dialog.getRange(dmin, dmax);
Chris@188 2171 setTopLayerDisplayExtents(dmin, dmax);
Chris@188 2172 updateVerticalPanner();
Chris@188 2173 }
Chris@188 2174 }
Chris@188 2175
Chris@312 2176 void
Chris@437 2177 Pane::layerParametersChanged()
Chris@437 2178 {
Chris@437 2179 View::layerParametersChanged();
Chris@437 2180 updateHeadsUpDisplay();
Chris@437 2181 }
Chris@437 2182
Chris@437 2183 void
Chris@312 2184 Pane::dragEnterEvent(QDragEnterEvent *e)
Chris@312 2185 {
Chris@312 2186 QStringList formats(e->mimeData()->formats());
Chris@312 2187 std::cerr << "dragEnterEvent: format: "
Chris@312 2188 << formats.join(",").toStdString()
Chris@312 2189 << ", possibleActions: " << e->possibleActions()
Chris@312 2190 << ", proposedAction: " << e->proposedAction() << std::endl;
Chris@312 2191
Chris@312 2192 if (e->provides("text/uri-list") || e->provides("text/plain")) {
Chris@312 2193
Chris@312 2194 if (e->proposedAction() & Qt::CopyAction) {
Chris@312 2195 e->acceptProposedAction();
Chris@312 2196 } else {
Chris@312 2197 e->setDropAction(Qt::CopyAction);
Chris@312 2198 e->accept();
Chris@312 2199 }
Chris@312 2200 }
Chris@312 2201 }
Chris@312 2202
Chris@312 2203 void
Chris@312 2204 Pane::dropEvent(QDropEvent *e)
Chris@312 2205 {
Chris@312 2206 std::cerr << "dropEvent: text: \"" << e->mimeData()->text().toStdString()
Chris@312 2207 << "\"" << std::endl;
Chris@312 2208
Chris@312 2209 if (e->provides("text/uri-list") || e->provides("text/plain")) {
Chris@312 2210
Chris@312 2211 if (e->proposedAction() & Qt::CopyAction) {
Chris@312 2212 e->acceptProposedAction();
Chris@312 2213 } else {
Chris@312 2214 e->setDropAction(Qt::CopyAction);
Chris@312 2215 e->accept();
Chris@312 2216 }
Chris@312 2217
Chris@312 2218 if (e->provides("text/uri-list")) {
Chris@312 2219
Chris@312 2220 std::cerr << "accepting... data is \"" << e->encodedData("text/uri-list").data() << "\"" << std::endl;
Chris@312 2221 emit dropAccepted(QString::fromLocal8Bit
Chris@312 2222 (e->encodedData("text/uri-list").data())
Chris@312 2223 .split(QRegExp("[\\r\\n]+"),
Chris@312 2224 QString::SkipEmptyParts));
Chris@312 2225 } else {
Chris@312 2226 emit dropAccepted(QString::fromLocal8Bit
Chris@312 2227 (e->encodedData("text/plain").data()));
Chris@312 2228 }
Chris@312 2229 }
Chris@312 2230 }
Chris@312 2231
Chris@127 2232 bool
Chris@127 2233 Pane::editSelectionStart(QMouseEvent *e)
Chris@127 2234 {
Chris@127 2235 if (!m_identifyFeatures ||
Chris@127 2236 !m_manager ||
Chris@127 2237 m_manager->getToolMode() != ViewManager::EditMode) {
Chris@127 2238 return false;
Chris@127 2239 }
Chris@127 2240
Chris@127 2241 bool closeToLeft, closeToRight;
Chris@127 2242 Selection s(getSelectionAt(e->x(), closeToLeft, closeToRight));
Chris@127 2243 if (s.isEmpty()) return false;
Chris@127 2244 m_editingSelection = s;
Chris@127 2245 m_editingSelectionEdge = (closeToLeft ? -1 : closeToRight ? 1 : 0);
Chris@127 2246 m_mousePos = e->pos();
Chris@127 2247 return true;
Chris@127 2248 }
Chris@127 2249
Chris@127 2250 bool
Chris@127 2251 Pane::editSelectionDrag(QMouseEvent *e)
Chris@127 2252 {
Chris@127 2253 if (m_editingSelection.isEmpty()) return false;
Chris@127 2254 m_mousePos = e->pos();
Chris@127 2255 update();
Chris@127 2256 return true;
Chris@127 2257 }
Chris@127 2258
Chris@127 2259 bool
Chris@248 2260 Pane::editSelectionEnd(QMouseEvent *)
Chris@127 2261 {
Chris@127 2262 if (m_editingSelection.isEmpty()) return false;
Chris@127 2263
Chris@127 2264 int offset = m_mousePos.x() - m_clickPos.x();
Chris@127 2265 Layer *layer = getSelectedLayer();
Chris@127 2266
Chris@127 2267 if (offset == 0 || !layer) {
Chris@127 2268 m_editingSelection = Selection();
Chris@127 2269 return true;
Chris@127 2270 }
Chris@127 2271
Chris@127 2272 int p0 = getXForFrame(m_editingSelection.getStartFrame()) + offset;
Chris@127 2273 int p1 = getXForFrame(m_editingSelection.getEndFrame()) + offset;
Chris@127 2274
Chris@127 2275 long f0 = getFrameForX(p0);
Chris@127 2276 long f1 = getFrameForX(p1);
Chris@127 2277
Chris@127 2278 Selection newSelection(f0, f1);
Chris@127 2279
Chris@127 2280 if (m_editingSelectionEdge == 0) {
Chris@127 2281
Chris@127 2282 CommandHistory::getInstance()->startCompoundOperation
Chris@127 2283 (tr("Drag Selection"), true);
Chris@127 2284
Chris@127 2285 layer->moveSelection(m_editingSelection, f0);
Chris@127 2286
Chris@127 2287 } else {
Chris@127 2288
Chris@127 2289 CommandHistory::getInstance()->startCompoundOperation
Chris@127 2290 (tr("Resize Selection"), true);
Chris@127 2291
Chris@127 2292 if (m_editingSelectionEdge < 0) {
Chris@127 2293 f1 = m_editingSelection.getEndFrame();
Chris@127 2294 } else {
Chris@127 2295 f0 = m_editingSelection.getStartFrame();
Chris@127 2296 }
Chris@127 2297
Chris@127 2298 newSelection = Selection(f0, f1);
Chris@127 2299 layer->resizeSelection(m_editingSelection, newSelection);
Chris@127 2300 }
Chris@127 2301
Chris@127 2302 m_manager->removeSelection(m_editingSelection);
Chris@127 2303 m_manager->addSelection(newSelection);
Chris@127 2304
Chris@127 2305 CommandHistory::getInstance()->endCompoundOperation();
Chris@127 2306
Chris@127 2307 m_editingSelection = Selection();
Chris@127 2308 return true;
Chris@127 2309 }
Chris@127 2310
Chris@127 2311 void
Chris@127 2312 Pane::toolModeChanged()
Chris@127 2313 {
Chris@127 2314 ViewManager::ToolMode mode = m_manager->getToolMode();
Chris@127 2315 // std::cerr << "Pane::toolModeChanged(" << mode << ")" << std::endl;
Chris@127 2316
Chris@267 2317 if (mode == ViewManager::MeasureMode && !m_measureCursor1) {
Chris@267 2318 m_measureCursor1 = new QCursor(QBitmap(":/icons/measure1cursor.xbm"),
Chris@267 2319 QBitmap(":/icons/measure1mask.xbm"),
Chris@267 2320 15, 14);
Chris@267 2321 m_measureCursor2 = new QCursor(QBitmap(":/icons/measure2cursor.xbm"),
Chris@267 2322 QBitmap(":/icons/measure2mask.xbm"),
Chris@267 2323 16, 17);
Chris@257 2324 }
Chris@257 2325
Chris@127 2326 switch (mode) {
Chris@127 2327
Chris@127 2328 case ViewManager::NavigateMode:
Chris@127 2329 setCursor(Qt::PointingHandCursor);
Chris@127 2330 break;
Chris@127 2331
Chris@127 2332 case ViewManager::SelectMode:
Chris@127 2333 setCursor(Qt::ArrowCursor);
Chris@127 2334 break;
Chris@127 2335
Chris@127 2336 case ViewManager::EditMode:
Chris@127 2337 setCursor(Qt::UpArrowCursor);
Chris@127 2338 break;
Chris@127 2339
Chris@127 2340 case ViewManager::DrawMode:
Chris@127 2341 setCursor(Qt::CrossCursor);
Chris@127 2342 break;
Chris@335 2343
Chris@335 2344 case ViewManager::EraseMode:
Chris@335 2345 setCursor(Qt::CrossCursor);
Chris@335 2346 break;
Chris@257 2347
Chris@257 2348 case ViewManager::MeasureMode:
Chris@267 2349 if (m_measureCursor1) setCursor(*m_measureCursor1);
Chris@257 2350 break;
Chris@257 2351
Chris@127 2352 /*
Chris@127 2353 case ViewManager::TextMode:
Chris@127 2354 setCursor(Qt::IBeamCursor);
Chris@127 2355 break;
Chris@127 2356 */
Chris@127 2357 }
Chris@127 2358 }
Chris@127 2359
Chris@133 2360 void
Chris@133 2361 Pane::zoomWheelsEnabledChanged()
Chris@133 2362 {
Chris@133 2363 updateHeadsUpDisplay();
Chris@133 2364 update();
Chris@133 2365 }
Chris@133 2366
Chris@133 2367 void
Chris@224 2368 Pane::viewZoomLevelChanged(View *v, unsigned long z, bool locked)
Chris@133 2369 {
Chris@212 2370 // std::cerr << "Pane[" << this << "]::zoomLevelChanged (global now "
Chris@212 2371 // << (m_manager ? m_manager->getGlobalZoom() : 0) << ")" << std::endl;
Chris@192 2372
Chris@224 2373 View::viewZoomLevelChanged(v, z, locked);
Chris@224 2374
Chris@232 2375 if (m_hthumb && !m_hthumb->isVisible()) return;
Chris@224 2376
Chris@222 2377 if (v != this) {
Chris@222 2378 if (!locked || !m_followZoom) return;
Chris@222 2379 }
Chris@222 2380
Chris@133 2381 if (m_manager && m_manager->getZoomWheelsEnabled()) {
Chris@133 2382 updateHeadsUpDisplay();
Chris@133 2383 }
Chris@133 2384 }
Chris@133 2385
Chris@133 2386 void
Chris@133 2387 Pane::propertyContainerSelected(View *v, PropertyContainer *pc)
Chris@133 2388 {
Chris@133 2389 Layer *layer = 0;
Chris@133 2390
Chris@133 2391 if (getLayerCount() > 0) {
Chris@133 2392 layer = getLayer(getLayerCount() - 1);
Chris@133 2393 disconnect(layer, SIGNAL(verticalZoomChanged()),
Chris@133 2394 this, SLOT(verticalZoomChanged()));
Chris@133 2395 }
Chris@133 2396
Chris@133 2397 View::propertyContainerSelected(v, pc);
Chris@133 2398 updateHeadsUpDisplay();
Chris@133 2399
Chris@187 2400 if (m_vthumb) {
Chris@187 2401 RangeMapper *rm = 0;
Chris@187 2402 if (layer) rm = layer->getNewVerticalZoomRangeMapper();
Chris@187 2403 if (rm) m_vthumb->setRangeMapper(rm);
Chris@187 2404 }
Chris@187 2405
Chris@133 2406 if (getLayerCount() > 0) {
Chris@133 2407 layer = getLayer(getLayerCount() - 1);
Chris@133 2408 connect(layer, SIGNAL(verticalZoomChanged()),
Chris@133 2409 this, SLOT(verticalZoomChanged()));
Chris@133 2410 }
Chris@133 2411 }
Chris@133 2412
Chris@133 2413 void
Chris@133 2414 Pane::verticalZoomChanged()
Chris@133 2415 {
Chris@133 2416 Layer *layer = 0;
Chris@133 2417
Chris@133 2418 if (getLayerCount() > 0) {
Chris@133 2419
Chris@133 2420 layer = getLayer(getLayerCount() - 1);
Chris@133 2421
Chris@133 2422 if (m_vthumb && m_vthumb->isVisible()) {
Chris@133 2423 m_vthumb->setValue(layer->getCurrentVerticalZoomStep());
Chris@133 2424 }
Chris@133 2425 }
Chris@133 2426 }
Chris@133 2427
Chris@189 2428 void
Chris@189 2429 Pane::updateContextHelp(const QPoint *pos)
Chris@189 2430 {
Chris@189 2431 QString help = "";
Chris@189 2432
Chris@189 2433 if (m_clickedInRange) {
Chris@189 2434 emit contextHelpChanged("");
Chris@189 2435 return;
Chris@189 2436 }
Chris@189 2437
Chris@189 2438 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@189 2439 if (m_manager) mode = m_manager->getToolMode();
Chris@189 2440
Chris@189 2441 bool editable = false;
Chris@189 2442 Layer *layer = getSelectedLayer();
Chris@189 2443 if (layer && layer->isLayerEditable()) {
Chris@189 2444 editable = true;
Chris@189 2445 }
Chris@189 2446
Chris@189 2447 if (mode == ViewManager::NavigateMode) {
Chris@189 2448
Chris@189 2449 help = tr("Click and drag to navigate");
Chris@189 2450
Chris@189 2451 } else if (mode == ViewManager::SelectMode) {
Chris@189 2452
Chris@217 2453 if (!hasTopLayerTimeXAxis()) return;
Chris@217 2454
Chris@189 2455 bool haveSelection = (m_manager && !m_manager->getSelections().empty());
Chris@189 2456
Chris@189 2457 if (haveSelection) {
Chris@189 2458 if (editable) {
Chris@189 2459 help = tr("Click and drag to select a range; hold Shift to avoid snapping to items; hold Ctrl for multi-select; middle-click and drag to navigate");
Chris@189 2460 } else {
Chris@189 2461 help = tr("Click and drag to select a range; hold Ctrl for multi-select; middle-click and drag to navigate");
Chris@189 2462 }
Chris@189 2463
Chris@189 2464 if (pos) {
Chris@189 2465 bool closeToLeft = false, closeToRight = false;
Chris@189 2466 Selection selection = getSelectionAt(pos->x(), closeToLeft, closeToRight);
Chris@189 2467 if ((closeToLeft || closeToRight) && !(closeToLeft && closeToRight)) {
Chris@189 2468
Chris@189 2469 help = tr("Click and drag to move the selection boundary");
Chris@189 2470 }
Chris@189 2471 }
Chris@189 2472 } else {
Chris@189 2473 if (editable) {
Chris@189 2474 help = tr("Click and drag to select a range; hold Shift to avoid snapping to items; middle-click to navigate");
Chris@189 2475 } else {
Chris@189 2476 help = tr("Click and drag to select a range; middle-click and drag to navigate");
Chris@189 2477 }
Chris@189 2478 }
Chris@189 2479
Chris@189 2480 } else if (mode == ViewManager::DrawMode) {
Chris@189 2481
Chris@189 2482 //!!! could call through to a layer function to find out exact meaning
Chris@189 2483 if (editable) {
Chris@189 2484 help = tr("Click to add a new item in the active layer");
Chris@189 2485 }
Chris@335 2486
Chris@335 2487 } else if (mode == ViewManager::EraseMode) {
Chris@335 2488
Chris@335 2489 //!!! could call through to a layer function to find out exact meaning
Chris@335 2490 if (editable) {
Chris@335 2491 help = tr("Click to erase an item from the active layer");
Chris@335 2492 }
Chris@189 2493
Chris@189 2494 } else if (mode == ViewManager::EditMode) {
Chris@189 2495
Chris@189 2496 //!!! could call through to layer
Chris@189 2497 if (editable) {
Chris@189 2498 help = tr("Click and drag an item in the active layer to move it");
Chris@189 2499 if (pos) {
Chris@189 2500 bool closeToLeft = false, closeToRight = false;
Chris@189 2501 Selection selection = getSelectionAt(pos->x(), closeToLeft, closeToRight);
Chris@189 2502 if (!selection.isEmpty()) {
Chris@189 2503 help = tr("Click and drag to move all items in the selected range");
Chris@189 2504 }
Chris@189 2505 }
Chris@189 2506 }
Chris@189 2507 }
Chris@189 2508
Chris@189 2509 emit contextHelpChanged(help);
Chris@189 2510 }
Chris@189 2511
Chris@189 2512 void
Chris@189 2513 Pane::mouseEnteredWidget()
Chris@189 2514 {
Chris@189 2515 QWidget *w = dynamic_cast<QWidget *>(sender());
Chris@189 2516 if (!w) return;
Chris@189 2517
Chris@189 2518 if (w == m_vpan) {
Chris@189 2519 emit contextHelpChanged(tr("Click and drag to adjust the visible range of the vertical scale"));
Chris@189 2520 } else if (w == m_vthumb) {
Chris@189 2521 emit contextHelpChanged(tr("Click and drag to adjust the vertical zoom level"));
Chris@189 2522 } else if (w == m_hthumb) {
Chris@189 2523 emit contextHelpChanged(tr("Click and drag to adjust the horizontal zoom level"));
Chris@189 2524 } else if (w == m_reset) {
Chris@189 2525 emit contextHelpChanged(tr("Reset horizontal and vertical zoom levels to their defaults"));
Chris@189 2526 }
Chris@189 2527 }
Chris@189 2528
Chris@189 2529 void
Chris@189 2530 Pane::mouseLeftWidget()
Chris@189 2531 {
Chris@189 2532 emit contextHelpChanged("");
Chris@189 2533 }
Chris@189 2534
Chris@316 2535 void
Chris@316 2536 Pane::toXml(QTextStream &stream,
Chris@316 2537 QString indent, QString extraAttributes) const
Chris@127 2538 {
Chris@316 2539 View::toXml
Chris@316 2540 (stream, indent,
Chris@127 2541 QString("type=\"pane\" centreLineVisible=\"%1\" height=\"%2\" %3")
Chris@127 2542 .arg(m_centreLineVisible).arg(height()).arg(extraAttributes));
Chris@127 2543 }
Chris@127 2544
Chris@127 2545