annotate widgets/Pane.cpp @ 41:f2c416cbdaa9

* Add time/Hz description for waveform model to the bottom right of a pane containing a waveform (also tried this in the status bar, wasn't so good) * Further spectrogram fixes
author Chris Cannam
date Fri, 24 Feb 2006 17:26:11 +0000
parents 21d061e66177
children 1bdf285c4eac
rev   line source
Chris@0 1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@0 4 A waveform viewer and audio annotation editor.
Chris@5 5 Chris Cannam, Queen Mary University of London, 2005-2006
Chris@0 6
Chris@0 7 This is experimental software. Not for distribution.
Chris@0 8 */
Chris@0 9
Chris@0 10 #include "widgets/Pane.h"
Chris@0 11 #include "base/Layer.h"
Chris@0 12 #include "base/Model.h"
Chris@0 13 #include "base/ZoomConstraint.h"
Chris@0 14 #include "base/RealTime.h"
Chris@0 15 #include "base/Profiler.h"
Chris@13 16 #include "base/ViewManager.h"
Chris@41 17 #include "layer/WaveformLayer.h"
Chris@0 18
Chris@0 19 #include <QPaintEvent>
Chris@0 20 #include <QPainter>
Chris@0 21 #include <iostream>
Chris@0 22 #include <cmath>
Chris@0 23
Chris@0 24 using std::cerr;
Chris@0 25 using std::endl;
Chris@0 26
Chris@0 27 Pane::Pane(QWidget *w) :
Chris@0 28 View(w, true),
Chris@0 29 m_identifyFeatures(false),
Chris@0 30 m_clickedInRange(false),
Chris@0 31 m_shiftPressed(false),
Chris@13 32 m_ctrlPressed(false),
Chris@17 33 m_navigating(false),
Chris@17 34 m_resizing(false),
Chris@0 35 m_centreLineVisible(true)
Chris@0 36 {
Chris@0 37 setObjectName("Pane");
Chris@0 38 setMouseTracking(true);
Chris@0 39 }
Chris@0 40
Chris@0 41 bool
Chris@0 42 Pane::shouldIlluminateLocalFeatures(const Layer *layer, QPoint &pos)
Chris@0 43 {
Chris@27 44 if (layer == getSelectedLayer()) {
Chris@27 45 pos = m_identifyPoint;
Chris@27 46 return m_identifyFeatures;
Chris@27 47 }
Chris@0 48
Chris@0 49 return false;
Chris@0 50 }
Chris@0 51
Chris@0 52 void
Chris@0 53 Pane::setCentreLineVisible(bool visible)
Chris@0 54 {
Chris@0 55 m_centreLineVisible = visible;
Chris@0 56 update();
Chris@0 57 }
Chris@0 58
Chris@0 59 void
Chris@0 60 Pane::paintEvent(QPaintEvent *e)
Chris@0 61 {
Chris@0 62 QPainter paint;
Chris@0 63
Chris@0 64 QRect r(rect());
Chris@0 65
Chris@0 66 if (e) {
Chris@0 67 r = e->rect();
Chris@0 68 }
Chris@0 69 /*
Chris@0 70 paint.begin(this);
Chris@0 71 paint.setClipRect(r);
Chris@0 72
Chris@0 73 if (hasLightBackground()) {
Chris@0 74 paint.setPen(Qt::white);
Chris@0 75 paint.setBrush(Qt::white);
Chris@0 76 } else {
Chris@0 77 paint.setPen(Qt::black);
Chris@0 78 paint.setBrush(Qt::black);
Chris@0 79 }
Chris@0 80 paint.drawRect(r);
Chris@0 81
Chris@0 82 paint.end();
Chris@0 83 */
Chris@0 84 View::paintEvent(e);
Chris@0 85
Chris@0 86 paint.begin(this);
Chris@0 87
Chris@0 88 if (e) {
Chris@0 89 paint.setClipRect(r);
Chris@0 90 }
Chris@41 91
Chris@41 92 const Model *waveformModel = 0; // just for reporting purposes
Chris@41 93
Chris@0 94 for (LayerList::iterator vi = m_layers.end(); vi != m_layers.begin(); ) {
Chris@0 95 --vi;
Chris@0 96
Chris@41 97 if (dynamic_cast<WaveformLayer *>(*vi)) {
Chris@41 98 waveformModel = (*vi)->getModel();
Chris@41 99 }
Chris@41 100
Chris@0 101 int sw = (*vi)->getVerticalScaleWidth(paint);
Chris@0 102
Chris@0 103 if (sw > 0 && r.left() < sw) {
Chris@0 104
Chris@0 105 // Profiler profiler("Pane::paintEvent - painting vertical scale", true);
Chris@0 106
Chris@0 107 // std::cerr << "Pane::paintEvent: calling paint.save() in vertical scale block" << std::endl;
Chris@0 108 paint.save();
Chris@0 109
Chris@0 110 paint.setPen(Qt::black);
Chris@0 111 paint.setBrush(Qt::white);
Chris@0 112 paint.drawRect(0, 0, sw, height());
Chris@0 113
Chris@0 114 paint.setBrush(Qt::NoBrush);
Chris@0 115 (*vi)->paintVerticalScale(paint, QRect(0, 0, sw, height()));
Chris@0 116
Chris@0 117 paint.restore();
Chris@0 118 }
Chris@41 119
Chris@0 120 if (m_identifyFeatures) {
Chris@25 121
Chris@25 122 QPoint pos = m_identifyPoint;
Chris@25 123 QString desc = (*vi)->getFeatureDescription(pos);
Chris@25 124
Chris@25 125 if (desc != "") {
Chris@25 126
Chris@25 127 paint.save();
Chris@25 128
Chris@25 129 int tabStop =
Chris@25 130 paint.fontMetrics().width(tr("Some lengthy prefix:"));
Chris@25 131
Chris@25 132 QRect boundingRect =
Chris@25 133 paint.fontMetrics().boundingRect
Chris@25 134 (rect(),
Chris@25 135 Qt::AlignRight | Qt::AlignTop | Qt::TextExpandTabs,
Chris@25 136 desc, tabStop);
Chris@25 137
Chris@25 138 if (hasLightBackground()) {
Chris@25 139 paint.setPen(Qt::NoPen);
Chris@25 140 paint.setBrush(QColor(250, 250, 250, 200));
Chris@25 141 } else {
Chris@25 142 paint.setPen(Qt::NoPen);
Chris@25 143 paint.setBrush(QColor(50, 50, 50, 200));
Chris@25 144 }
Chris@25 145
Chris@25 146 int extra = paint.fontMetrics().descent();
Chris@25 147 paint.drawRect(width() - boundingRect.width() - 10 - extra,
Chris@25 148 10 - extra,
Chris@25 149 boundingRect.width() + 2 * extra,
Chris@25 150 boundingRect.height() + extra);
Chris@25 151
Chris@25 152 if (hasLightBackground()) {
Chris@25 153 paint.setPen(QColor(150, 20, 0));
Chris@25 154 } else {
Chris@25 155 paint.setPen(QColor(255, 150, 100));
Chris@25 156 }
Chris@25 157
Chris@25 158 QTextOption option;
Chris@25 159 option.setWrapMode(QTextOption::NoWrap);
Chris@25 160 option.setAlignment(Qt::AlignRight | Qt::AlignTop);
Chris@25 161 option.setTabStop(tabStop);
Chris@25 162 paint.drawText(QRectF(width() - boundingRect.width() - 10, 10,
Chris@25 163 boundingRect.width(),
Chris@25 164 boundingRect.height()),
Chris@25 165 desc,
Chris@25 166 option);
Chris@25 167
Chris@25 168 paint.restore();
Chris@25 169 }
Chris@0 170 }
Chris@0 171
Chris@0 172 break;
Chris@0 173 }
Chris@0 174
Chris@0 175 if (m_centreLineVisible) {
Chris@0 176
Chris@0 177 if (hasLightBackground()) {
Chris@0 178 paint.setPen(QColor(50, 50, 50));
Chris@0 179 } else {
Chris@0 180 paint.setPen(QColor(200, 200, 200));
Chris@0 181 }
Chris@0 182 paint.setBrush(Qt::NoBrush);
Chris@0 183 paint.drawLine(width() / 2, 0, width() / 2, height() - 1);
Chris@0 184
Chris@0 185 // QFont font(paint.font());
Chris@0 186 // font.setBold(true);
Chris@0 187 // paint.setFont(font);
Chris@0 188
Chris@0 189 int sampleRate = getModelsSampleRate();
Chris@0 190 int y = height() - paint.fontMetrics().height()
Chris@0 191 + paint.fontMetrics().ascent() - 6;
Chris@0 192
Chris@0 193 LayerList::iterator vi = m_layers.end();
Chris@0 194
Chris@0 195 if (vi != m_layers.begin()) {
Chris@0 196
Chris@0 197 switch ((*--vi)->getPreferredFrameCountPosition()) {
Chris@0 198
Chris@0 199 case Layer::PositionTop:
Chris@0 200 y = paint.fontMetrics().ascent() + 6;
Chris@0 201 break;
Chris@0 202
Chris@0 203 case Layer::PositionMiddle:
Chris@0 204 y = (height() - paint.fontMetrics().height()) / 2
Chris@0 205 + paint.fontMetrics().ascent();
Chris@0 206 break;
Chris@0 207
Chris@0 208 case Layer::PositionBottom:
Chris@0 209 // y already set correctly
Chris@0 210 break;
Chris@0 211 }
Chris@0 212 }
Chris@0 213
Chris@0 214 if (sampleRate) {
Chris@0 215
Chris@0 216 QString text(QString::fromStdString
Chris@0 217 (RealTime::frame2RealTime
Chris@0 218 (m_centreFrame, sampleRate).toText(true)));
Chris@0 219
Chris@0 220 int tw = paint.fontMetrics().width(text);
Chris@0 221 int x = width()/2 - 4 - tw;
Chris@0 222
Chris@0 223 if (hasLightBackground()) {
Chris@0 224 paint.setPen(palette().background().color());
Chris@0 225 for (int dx = -1; dx <= 1; ++dx) {
Chris@0 226 for (int dy = -1; dy <= 1; ++dy) {
Chris@0 227 if ((dx && dy) || !(dx || dy)) continue;
Chris@0 228 paint.drawText(x + dx, y + dy, text);
Chris@0 229 }
Chris@0 230 }
Chris@0 231 paint.setPen(QColor(50, 50, 50));
Chris@0 232 } else {
Chris@0 233 paint.setPen(QColor(200, 200, 200));
Chris@0 234 }
Chris@0 235
Chris@0 236 paint.drawText(x, y, text);
Chris@0 237 }
Chris@0 238
Chris@0 239 QString text = QString("%1").arg(m_centreFrame);
Chris@0 240
Chris@0 241 int tw = paint.fontMetrics().width(text);
Chris@0 242 int x = width()/2 + 4;
Chris@0 243
Chris@0 244 if (hasLightBackground()) {
Chris@0 245 paint.setPen(palette().background().color());
Chris@0 246 for (int dx = -1; dx <= 1; ++dx) {
Chris@0 247 for (int dy = -1; dy <= 1; ++dy) {
Chris@0 248 if ((dx && dy) || !(dx || dy)) continue;
Chris@0 249 paint.drawText(x + dx, y + dy, text);
Chris@0 250 }
Chris@0 251 }
Chris@0 252 paint.setPen(QColor(50, 50, 50));
Chris@0 253 } else {
Chris@0 254 paint.setPen(QColor(200, 200, 200));
Chris@0 255 }
Chris@0 256 paint.drawText(x, y, text);
Chris@41 257
Chris@41 258 if (waveformModel) {
Chris@41 259
Chris@41 260 QString desc = tr("%1 / %2Hz")
Chris@41 261 .arg(RealTime::frame2RealTime(waveformModel->getEndFrame(),
Chris@41 262 waveformModel->getSampleRate())
Chris@41 263 .toText(false).c_str())
Chris@41 264 .arg(waveformModel->getSampleRate());
Chris@41 265
Chris@41 266 paint.drawText(width() - paint.fontMetrics().width(desc) - 5,
Chris@41 267 height() - paint.fontMetrics().height() +
Chris@41 268 paint.fontMetrics().ascent() - 6,
Chris@41 269 desc);
Chris@41 270 }
Chris@0 271 }
Chris@0 272
Chris@0 273 if (m_clickedInRange && m_shiftPressed) {
Chris@19 274 if (m_manager && (m_manager->getToolMode() == ViewManager::NavigateMode)) {
Chris@19 275 //!!! be nice if this looked a bit more in keeping with the
Chris@19 276 //selection block
Chris@19 277 paint.setPen(Qt::blue);
Chris@19 278 paint.drawRect(m_clickPos.x(), m_clickPos.y(),
Chris@19 279 m_mousePos.x() - m_clickPos.x(),
Chris@19 280 m_mousePos.y() - m_clickPos.y());
Chris@19 281 }
Chris@0 282 }
Chris@0 283
Chris@0 284 paint.end();
Chris@0 285 }
Chris@0 286
Chris@17 287 Selection
Chris@17 288 Pane::getSelectionAt(int x, bool &closeToLeftEdge, bool &closeToRightEdge)
Chris@17 289 {
Chris@17 290 closeToLeftEdge = closeToRightEdge = false;
Chris@17 291
Chris@17 292 if (!m_manager) return Selection();
Chris@17 293
Chris@20 294 long testFrame = getFrameForX(x - 5);
Chris@17 295 if (testFrame < 0) {
Chris@20 296 testFrame = getFrameForX(x);
Chris@17 297 if (testFrame < 0) return Selection();
Chris@17 298 }
Chris@17 299
Chris@17 300 Selection selection = m_manager->getContainingSelection(testFrame, true);
Chris@17 301 if (selection.isEmpty()) return selection;
Chris@17 302
Chris@20 303 int lx = getXForFrame(selection.getStartFrame());
Chris@20 304 int rx = getXForFrame(selection.getEndFrame());
Chris@17 305
Chris@17 306 int fuzz = 2;
Chris@17 307 if (x < lx - fuzz || x > rx + fuzz) return Selection();
Chris@17 308
Chris@17 309 int width = rx - lx;
Chris@17 310 fuzz = 3;
Chris@17 311 if (width < 12) fuzz = width / 4;
Chris@17 312 if (fuzz < 1) fuzz = 1;
Chris@17 313
Chris@17 314 if (x < lx + fuzz) closeToLeftEdge = true;
Chris@17 315 if (x > rx - fuzz) closeToRightEdge = true;
Chris@17 316
Chris@17 317 return selection;
Chris@17 318 }
Chris@17 319
Chris@0 320 void
Chris@0 321 Pane::mousePressEvent(QMouseEvent *e)
Chris@0 322 {
Chris@0 323 m_clickPos = e->pos();
Chris@0 324 m_clickedInRange = true;
Chris@0 325 m_shiftPressed = (e->modifiers() & Qt::ShiftModifier);
Chris@13 326 m_ctrlPressed = (e->modifiers() & Qt::ControlModifier);
Chris@13 327
Chris@13 328 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@13 329 if (m_manager) mode = m_manager->getToolMode();
Chris@13 330
Chris@17 331 m_navigating = false;
Chris@13 332
Chris@17 333 if (mode == ViewManager::NavigateMode || (e->buttons() & Qt::MidButton)) {
Chris@17 334
Chris@17 335 if (mode != ViewManager::NavigateMode) {
Chris@17 336 setCursor(Qt::PointingHandCursor);
Chris@17 337 }
Chris@17 338
Chris@17 339 m_navigating = true;
Chris@13 340 m_dragCentreFrame = m_centreFrame;
Chris@13 341
Chris@13 342 } else if (mode == ViewManager::SelectMode) {
Chris@13 343
Chris@17 344 bool closeToLeft = false, closeToRight = false;
Chris@17 345 Selection selection = getSelectionAt(e->x(), closeToLeft, closeToRight);
Chris@17 346
Chris@17 347 if ((closeToLeft || closeToRight) && !(closeToLeft && closeToRight)) {
Chris@17 348
Chris@17 349 m_manager->removeSelection(selection);
Chris@17 350
Chris@17 351 if (closeToLeft) {
Chris@17 352 m_selectionStartFrame = selection.getEndFrame();
Chris@17 353 } else {
Chris@17 354 m_selectionStartFrame = selection.getStartFrame();
Chris@17 355 }
Chris@17 356
Chris@17 357 m_manager->setInProgressSelection(selection, false);
Chris@17 358 m_resizing = true;
Chris@13 359
Chris@17 360 } else {
Chris@17 361
Chris@20 362 int mouseFrame = getFrameForX(e->x());
Chris@17 363 size_t resolution = 1;
Chris@17 364 int snapFrame = mouseFrame;
Chris@17 365
Chris@17 366 Layer *layer = getSelectedLayer();
Chris@17 367 if (layer) {
Chris@28 368 layer->snapToFeatureFrame(snapFrame, resolution, Layer::SnapLeft);
Chris@17 369 }
Chris@17 370
Chris@17 371 if (snapFrame < 0) snapFrame = 0;
Chris@17 372 m_selectionStartFrame = snapFrame;
Chris@17 373 if (m_manager) {
Chris@17 374 m_manager->setInProgressSelection(Selection(snapFrame,
Chris@17 375 snapFrame + resolution),
Chris@17 376 !m_ctrlPressed);
Chris@17 377 }
Chris@17 378
Chris@17 379 m_resizing = false;
Chris@17 380 }
Chris@17 381
Chris@17 382 update();
Chris@17 383
Chris@17 384 } else if (mode == ViewManager::DrawMode) {
Chris@17 385
Chris@13 386 Layer *layer = getSelectedLayer();
Chris@23 387 if (layer && layer->isLayerEditable()) {
Chris@17 388 layer->drawStart(e);
Chris@13 389 }
Chris@18 390
Chris@18 391 } else if (mode == ViewManager::EditMode) {
Chris@18 392
Chris@18 393 Layer *layer = getSelectedLayer();
Chris@23 394 if (layer && layer->isLayerEditable()) {
Chris@18 395 layer->editStart(e);
Chris@18 396 }
Chris@13 397 }
Chris@0 398
Chris@0 399 emit paneInteractedWith();
Chris@0 400 }
Chris@0 401
Chris@0 402 void
Chris@0 403 Pane::mouseReleaseEvent(QMouseEvent *e)
Chris@0 404 {
Chris@13 405 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@13 406 if (m_manager) mode = m_manager->getToolMode();
Chris@13 407
Chris@0 408 if (m_clickedInRange) {
Chris@0 409 mouseMoveEvent(e);
Chris@0 410 }
Chris@0 411
Chris@17 412 if (m_navigating || mode == ViewManager::NavigateMode) {
Chris@17 413
Chris@17 414 m_navigating = false;
Chris@17 415
Chris@17 416 if (mode != ViewManager::NavigateMode) {
Chris@17 417 // restore cursor
Chris@17 418 toolModeChanged();
Chris@17 419 }
Chris@0 420
Chris@13 421 if (m_shiftPressed) {
Chris@0 422
Chris@13 423 int x0 = std::min(m_clickPos.x(), m_mousePos.x());
Chris@13 424 int x1 = std::max(m_clickPos.x(), m_mousePos.x());
Chris@13 425 int w = x1 - x0;
Chris@13 426
Chris@20 427 long newStartFrame = getFrameForX(x0);
Chris@13 428
Chris@20 429 long visibleFrames = getEndFrame() - getStartFrame();
Chris@20 430 if (newStartFrame <= -visibleFrames) {
Chris@20 431 newStartFrame = -visibleFrames + 1;
Chris@13 432 }
Chris@13 433
Chris@13 434 if (newStartFrame >= long(getModelsEndFrame())) {
Chris@13 435 newStartFrame = getModelsEndFrame() - 1;
Chris@13 436 }
Chris@13 437
Chris@13 438 float ratio = float(w) / float(width());
Chris@13 439 // std::cerr << "ratio: " << ratio << std::endl;
Chris@13 440 size_t newZoomLevel = (size_t)nearbyint(m_zoomLevel * ratio);
Chris@13 441 if (newZoomLevel < 1) newZoomLevel = 1;
Chris@13 442
Chris@13 443 // std::cerr << "start: " << m_startFrame << ", level " << m_zoomLevel << std::endl;
Chris@13 444 setZoomLevel(getZoomConstraintBlockSize(newZoomLevel));
Chris@13 445 setStartFrame(newStartFrame);
Chris@13 446
Chris@13 447 //cerr << "mouseReleaseEvent: start frame now " << m_startFrame << endl;
Chris@13 448 // update();
Chris@0 449 }
Chris@0 450
Chris@13 451 } else if (mode == ViewManager::SelectMode) {
Chris@13 452
Chris@13 453 if (m_manager && m_manager->haveInProgressSelection()) {
Chris@13 454
Chris@13 455 bool exclusive;
Chris@13 456 Selection selection = m_manager->getInProgressSelection(exclusive);
Chris@13 457
Chris@13 458 if (selection.getEndFrame() < selection.getStartFrame() + 2) {
Chris@13 459 selection = Selection();
Chris@13 460 }
Chris@13 461
Chris@13 462 m_manager->clearInProgressSelection();
Chris@13 463
Chris@13 464 if (exclusive) {
Chris@13 465 m_manager->setSelection(selection);
Chris@13 466 } else {
Chris@13 467 m_manager->addSelection(selection);
Chris@13 468 }
Chris@0 469 }
Chris@13 470
Chris@13 471 update();
Chris@17 472
Chris@17 473 } else if (mode == ViewManager::DrawMode) {
Chris@17 474
Chris@17 475 Layer *layer = getSelectedLayer();
Chris@23 476 if (layer && layer->isLayerEditable()) {
Chris@17 477 layer->drawEnd(e);
Chris@17 478 update();
Chris@17 479 }
Chris@18 480
Chris@18 481 } else if (mode == ViewManager::EditMode) {
Chris@18 482
Chris@18 483 Layer *layer = getSelectedLayer();
Chris@23 484 if (layer && layer->isLayerEditable()) {
Chris@18 485 layer->editEnd(e);
Chris@18 486 update();
Chris@18 487 }
Chris@17 488 }
Chris@0 489
Chris@0 490 m_clickedInRange = false;
Chris@0 491
Chris@0 492 emit paneInteractedWith();
Chris@0 493 }
Chris@0 494
Chris@0 495 void
Chris@0 496 Pane::mouseMoveEvent(QMouseEvent *e)
Chris@0 497 {
Chris@13 498 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@13 499 if (m_manager) mode = m_manager->getToolMode();
Chris@13 500
Chris@28 501 QPoint prevPoint = m_identifyPoint;
Chris@28 502 m_identifyPoint = e->pos();
Chris@28 503
Chris@0 504 if (!m_clickedInRange) {
Chris@0 505
Chris@17 506 if (mode == ViewManager::SelectMode) {
Chris@17 507 bool closeToLeft = false, closeToRight = false;
Chris@17 508 getSelectionAt(e->x(), closeToLeft, closeToRight);
Chris@17 509 if ((closeToLeft || closeToRight) && !(closeToLeft && closeToRight)) {
Chris@17 510 setCursor(Qt::SizeHorCursor);
Chris@17 511 } else {
Chris@17 512 setCursor(Qt::ArrowCursor);
Chris@17 513 }
Chris@17 514 }
Chris@0 515
Chris@35 516 //!!! if (mode != ViewManager::DrawMode) {
Chris@0 517
Chris@17 518 bool previouslyIdentifying = m_identifyFeatures;
Chris@17 519 m_identifyFeatures = true;
Chris@17 520
Chris@17 521 if (m_identifyFeatures != previouslyIdentifying ||
Chris@17 522 m_identifyPoint != prevPoint) {
Chris@17 523 update();
Chris@17 524 }
Chris@35 525 // }
Chris@0 526
Chris@13 527 return;
Chris@13 528 }
Chris@0 529
Chris@17 530 if (m_navigating || mode == ViewManager::NavigateMode) {
Chris@0 531
Chris@13 532 if (m_shiftPressed) {
Chris@0 533
Chris@13 534 m_mousePos = e->pos();
Chris@13 535 update();
Chris@0 536
Chris@0 537 } else {
Chris@13 538
Chris@20 539 long frameOff = getFrameForX(e->x()) - getFrameForX(m_clickPos.x());
Chris@20 540
Chris@13 541 size_t newCentreFrame = m_dragCentreFrame;
Chris@13 542
Chris@13 543 if (frameOff < 0) {
Chris@13 544 newCentreFrame -= frameOff;
Chris@13 545 } else if (newCentreFrame >= size_t(frameOff)) {
Chris@13 546 newCentreFrame -= frameOff;
Chris@13 547 } else {
Chris@13 548 newCentreFrame = 0;
Chris@13 549 }
Chris@13 550
Chris@13 551 if (newCentreFrame >= getModelsEndFrame()) {
Chris@13 552 newCentreFrame = getModelsEndFrame();
Chris@13 553 if (newCentreFrame > 0) --newCentreFrame;
Chris@13 554 }
Chris@20 555
Chris@20 556 if (getXForFrame(m_centreFrame) != getXForFrame(newCentreFrame)) {
Chris@13 557 setCentreFrame(newCentreFrame);
Chris@13 558 }
Chris@0 559 }
Chris@0 560
Chris@13 561 } else if (mode == ViewManager::SelectMode) {
Chris@13 562
Chris@20 563 int mouseFrame = getFrameForX(e->x());
Chris@13 564 size_t resolution = 1;
Chris@13 565 int snapFrameLeft = mouseFrame;
Chris@13 566 int snapFrameRight = mouseFrame;
Chris@13 567
Chris@13 568 Layer *layer = getSelectedLayer();
Chris@13 569 if (layer) {
Chris@28 570 layer->snapToFeatureFrame(snapFrameLeft, resolution, Layer::SnapLeft);
Chris@28 571 layer->snapToFeatureFrame(snapFrameRight, resolution, Layer::SnapRight);
Chris@13 572 }
Chris@13 573
Chris@37 574 // std::cerr << "snap: frame = " << mouseFrame << ", start frame = " << m_selectionStartFrame << ", left = " << snapFrameLeft << ", right = " << snapFrameRight << std::endl;
Chris@28 575
Chris@13 576 if (snapFrameLeft < 0) snapFrameLeft = 0;
Chris@13 577 if (snapFrameRight < 0) snapFrameRight = 0;
Chris@13 578
Chris@13 579 size_t min, max;
Chris@13 580
Chris@13 581 if (m_selectionStartFrame > snapFrameLeft) {
Chris@13 582 min = snapFrameLeft;
Chris@13 583 max = m_selectionStartFrame;
Chris@13 584 } else if (snapFrameRight > m_selectionStartFrame) {
Chris@13 585 min = m_selectionStartFrame;
Chris@13 586 max = snapFrameRight;
Chris@13 587 } else {
Chris@13 588 min = snapFrameLeft;
Chris@13 589 max = snapFrameRight;
Chris@0 590 }
Chris@0 591
Chris@13 592 if (m_manager) {
Chris@13 593 m_manager->setInProgressSelection(Selection(min, max),
Chris@17 594 !m_resizing && !m_ctrlPressed);
Chris@0 595 }
Chris@15 596
Chris@15 597 bool doScroll = false;
Chris@15 598 if (!m_manager) doScroll = true;
Chris@15 599 if (!m_manager->isPlaying()) doScroll = true;
Chris@15 600 if (m_followPlay != PlaybackScrollContinuous) doScroll = true;
Chris@15 601
Chris@15 602 if (doScroll) {
Chris@13 603 int offset = mouseFrame - getStartFrame();
Chris@13 604 int available = getEndFrame() - getStartFrame();
Chris@15 605 if (offset >= available * 0.95) {
Chris@15 606 int move = int(offset - available * 0.95) + 1;
Chris@14 607 setCentreFrame(m_centreFrame + move);
Chris@15 608 } else if (offset <= available * 0.10) {
Chris@15 609 int move = int(available * 0.10 - offset) + 1;
Chris@14 610 if (m_centreFrame > move) {
Chris@14 611 setCentreFrame(m_centreFrame - move);
Chris@14 612 } else {
Chris@14 613 setCentreFrame(0);
Chris@14 614 }
Chris@13 615 }
Chris@13 616 }
Chris@13 617
Chris@13 618 update();
Chris@17 619
Chris@17 620 } else if (mode == ViewManager::DrawMode) {
Chris@17 621
Chris@17 622 Layer *layer = getSelectedLayer();
Chris@23 623 if (layer && layer->isLayerEditable()) {
Chris@17 624 layer->drawDrag(e);
Chris@17 625 }
Chris@18 626
Chris@18 627 } else if (mode == ViewManager::EditMode) {
Chris@18 628
Chris@18 629 Layer *layer = getSelectedLayer();
Chris@23 630 if (layer && layer->isLayerEditable()) {
Chris@18 631 layer->editDrag(e);
Chris@18 632 }
Chris@0 633 }
Chris@0 634 }
Chris@0 635
Chris@0 636 void
Chris@0 637 Pane::mouseDoubleClickEvent(QMouseEvent *e)
Chris@0 638 {
Chris@0 639 std::cerr << "mouseDoubleClickEvent" << std::endl;
Chris@36 640
Chris@36 641 m_clickPos = e->pos();
Chris@36 642 m_clickedInRange = true;
Chris@36 643 m_shiftPressed = (e->modifiers() & Qt::ShiftModifier);
Chris@36 644 m_ctrlPressed = (e->modifiers() & Qt::ControlModifier);
Chris@36 645
Chris@36 646 ViewManager::ToolMode mode = ViewManager::NavigateMode;
Chris@36 647 if (m_manager) mode = m_manager->getToolMode();
Chris@36 648
Chris@36 649 if (mode == ViewManager::EditMode) {
Chris@36 650
Chris@36 651 Layer *layer = getSelectedLayer();
Chris@36 652 if (layer && layer->isLayerEditable()) {
Chris@36 653 layer->editOpen(e);
Chris@36 654 }
Chris@36 655 }
Chris@0 656 }
Chris@0 657
Chris@0 658 void
Chris@0 659 Pane::leaveEvent(QEvent *)
Chris@0 660 {
Chris@0 661 bool previouslyIdentifying = m_identifyFeatures;
Chris@0 662 m_identifyFeatures = false;
Chris@0 663 if (previouslyIdentifying) update();
Chris@0 664 }
Chris@0 665
Chris@0 666 void
Chris@0 667 Pane::wheelEvent(QWheelEvent *e)
Chris@0 668 {
Chris@0 669 //std::cerr << "wheelEvent, delta " << e->delta() << std::endl;
Chris@0 670
Chris@0 671 int count = e->delta();
Chris@0 672
Chris@0 673 if (count > 0) {
Chris@0 674 if (count >= 120) count /= 120;
Chris@0 675 else count = 1;
Chris@0 676 }
Chris@0 677
Chris@0 678 if (count < 0) {
Chris@0 679 if (count <= -120) count /= 120;
Chris@0 680 else count = -1;
Chris@0 681 }
Chris@17 682
Chris@17 683 if (e->modifiers() & Qt::ControlModifier) {
Chris@17 684
Chris@20 685 // Scroll left or right, rapidly
Chris@20 686
Chris@17 687 if (getStartFrame() < 0 &&
Chris@17 688 getEndFrame() >= getModelsEndFrame()) return;
Chris@17 689
Chris@17 690 long delta = ((width() / 2) * count * m_zoomLevel);
Chris@17 691
Chris@17 692 if (int(m_centreFrame) < delta) {
Chris@17 693 setCentreFrame(0);
Chris@17 694 } else if (int(m_centreFrame) - delta >= int(getModelsEndFrame())) {
Chris@17 695 setCentreFrame(getModelsEndFrame());
Chris@17 696 } else {
Chris@17 697 setCentreFrame(m_centreFrame - delta);
Chris@17 698 }
Chris@17 699
Chris@17 700 } else {
Chris@17 701
Chris@20 702 // Zoom in or out
Chris@20 703
Chris@17 704 int newZoomLevel = m_zoomLevel;
Chris@0 705
Chris@17 706 while (count > 0) {
Chris@17 707 if (newZoomLevel <= 2) {
Chris@17 708 newZoomLevel = 1;
Chris@17 709 break;
Chris@17 710 }
Chris@17 711 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel - 1,
Chris@17 712 ZoomConstraint::RoundDown);
Chris@17 713 --count;
Chris@0 714 }
Chris@17 715
Chris@17 716 while (count < 0) {
Chris@17 717 newZoomLevel = getZoomConstraintBlockSize(newZoomLevel + 1,
Chris@17 718 ZoomConstraint::RoundUp);
Chris@17 719 ++count;
Chris@17 720 }
Chris@17 721
Chris@17 722 if (newZoomLevel != m_zoomLevel) {
Chris@17 723 setZoomLevel(newZoomLevel);
Chris@17 724 }
Chris@0 725 }
Chris@0 726
Chris@0 727 emit paneInteractedWith();
Chris@0 728 }
Chris@8 729
Chris@13 730 void
Chris@13 731 Pane::toolModeChanged()
Chris@13 732 {
Chris@13 733 ViewManager::ToolMode mode = m_manager->getToolMode();
Chris@13 734 std::cerr << "Pane::toolModeChanged(" << mode << ")" << std::endl;
Chris@13 735
Chris@13 736 switch (mode) {
Chris@13 737
Chris@13 738 case ViewManager::NavigateMode:
Chris@13 739 setCursor(Qt::PointingHandCursor);
Chris@13 740 break;
Chris@13 741
Chris@13 742 case ViewManager::SelectMode:
Chris@13 743 setCursor(Qt::ArrowCursor);
Chris@13 744 break;
Chris@13 745
Chris@13 746 case ViewManager::EditMode:
Chris@19 747 setCursor(Qt::UpArrowCursor);
Chris@13 748 break;
Chris@13 749
Chris@13 750 case ViewManager::DrawMode:
Chris@13 751 setCursor(Qt::CrossCursor);
Chris@13 752 break;
Chris@36 753 /*
Chris@13 754 case ViewManager::TextMode:
Chris@13 755 setCursor(Qt::IBeamCursor);
Chris@13 756 break;
Chris@36 757 */
Chris@13 758 }
Chris@13 759 }
Chris@13 760
Chris@8 761 QString
Chris@8 762 Pane::toXmlString(QString indent, QString extraAttributes) const
Chris@8 763 {
Chris@8 764 return View::toXmlString
Chris@8 765 (indent,
Chris@8 766 QString("type=\"pane\" centreLineVisible=\"%1\" %2")
Chris@8 767 .arg(m_centreLineVisible).arg(extraAttributes));
Chris@8 768 }
Chris@8 769
Chris@0 770
Chris@0 771 #ifdef INCLUDE_MOCFILES
Chris@0 772 #include "Pane.moc.cpp"
Chris@0 773 #endif
Chris@0 774