annotate view/Pane.cpp @ 23:7b19f2719f91

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