annotate view/Pane.cpp @ 282:d9319859a4cf tip

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