annotate widgets/Pane.cpp @ 37:21d061e66177

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