Mercurial > hg > svgui
comparison view/Pane.cpp @ 373:0895517bb2d1 1.2-stable
* merge from trunk (1.2 ended up being tracked from trunk, but we may want
this branch for fixes later)
author | Chris Cannam |
---|---|
date | Wed, 27 Feb 2008 10:32:45 +0000 |
parents | 2f83b6e3b8ca |
children |
comparison
equal
deleted
inserted
replaced
337:813170c57b13 | 373:0895517bb2d1 |
---|---|
20 #include "base/RealTime.h" | 20 #include "base/RealTime.h" |
21 #include "base/Profiler.h" | 21 #include "base/Profiler.h" |
22 #include "ViewManager.h" | 22 #include "ViewManager.h" |
23 #include "base/CommandHistory.h" | 23 #include "base/CommandHistory.h" |
24 #include "base/TextAbbrev.h" | 24 #include "base/TextAbbrev.h" |
25 #include "base/Preferences.h" | |
25 #include "layer/WaveformLayer.h" | 26 #include "layer/WaveformLayer.h" |
26 | 27 |
27 //!!! ugh | 28 //!!! ugh |
28 #include "data/model/WaveFileModel.h" | 29 #include "data/model/WaveFileModel.h" |
29 | 30 |
47 #include "widgets/RangeInputDialog.h" | 48 #include "widgets/RangeInputDialog.h" |
48 #include "widgets/NotifyingPushButton.h" | 49 #include "widgets/NotifyingPushButton.h" |
49 | 50 |
50 #include "widgets/KeyReference.h" //!!! should probably split KeyReference into a data class in base and another that shows the widget | 51 #include "widgets/KeyReference.h" //!!! should probably split KeyReference into a data class in base and another that shows the widget |
51 | 52 |
53 //#define DEBUG_PANE | |
54 | |
52 using std::cerr; | 55 using std::cerr; |
53 using std::endl; | 56 using std::endl; |
54 | 57 |
55 QCursor *Pane::m_measureCursor1 = 0; | 58 QCursor *Pane::m_measureCursor1 = 0; |
56 QCursor *Pane::m_measureCursor2 = 0; | 59 QCursor *Pane::m_measureCursor2 = 0; |
61 m_clickedInRange(false), | 64 m_clickedInRange(false), |
62 m_shiftPressed(false), | 65 m_shiftPressed(false), |
63 m_ctrlPressed(false), | 66 m_ctrlPressed(false), |
64 m_navigating(false), | 67 m_navigating(false), |
65 m_resizing(false), | 68 m_resizing(false), |
69 m_editing(false), | |
70 m_releasing(false), | |
66 m_centreLineVisible(true), | 71 m_centreLineVisible(true), |
67 m_scaleWidth(0), | 72 m_scaleWidth(0), |
68 m_headsUpDisplay(0), | 73 m_headsUpDisplay(0), |
69 m_vpan(0), | 74 m_vpan(0), |
70 m_hthumb(0), | 75 m_hthumb(0), |
386 if (e) r = e->rect(); | 391 if (e) r = e->rect(); |
387 | 392 |
388 View::paintEvent(e); | 393 View::paintEvent(e); |
389 | 394 |
390 paint.begin(this); | 395 paint.begin(this); |
396 setPaintFont(paint); | |
391 | 397 |
392 if (e) paint.setClipRect(r); | 398 if (e) paint.setClipRect(r); |
393 | 399 |
394 ViewManager::ToolMode toolMode = m_manager->getToolMode(); | 400 ViewManager::ToolMode toolMode = m_manager->getToolMode(); |
395 | 401 |
1207 emit contextHelpChanged(""); | 1213 emit contextHelpChanged(""); |
1208 emit rightButtonMenuRequested(mapToGlobal(e->pos())); | 1214 emit rightButtonMenuRequested(mapToGlobal(e->pos())); |
1209 return; | 1215 return; |
1210 } | 1216 } |
1211 | 1217 |
1218 // std::cerr << "mousePressEvent" << std::endl; | |
1219 | |
1212 m_clickPos = e->pos(); | 1220 m_clickPos = e->pos(); |
1213 m_mousePos = m_clickPos; | 1221 m_mousePos = m_clickPos; |
1214 m_clickedInRange = true; | 1222 m_clickedInRange = true; |
1215 m_editingSelection = Selection(); | 1223 m_editingSelection = Selection(); |
1216 m_editingSelectionEdge = 0; | 1224 m_editingSelectionEdge = 0; |
1220 | 1228 |
1221 ViewManager::ToolMode mode = ViewManager::NavigateMode; | 1229 ViewManager::ToolMode mode = ViewManager::NavigateMode; |
1222 if (m_manager) mode = m_manager->getToolMode(); | 1230 if (m_manager) mode = m_manager->getToolMode(); |
1223 | 1231 |
1224 m_navigating = false; | 1232 m_navigating = false; |
1233 m_resizing = false; | |
1234 m_editing = false; | |
1235 m_releasing = false; | |
1225 | 1236 |
1226 if (mode == ViewManager::NavigateMode || | 1237 if (mode == ViewManager::NavigateMode || |
1227 (e->buttons() & Qt::MidButton) || | 1238 (e->buttons() & Qt::MidButton) || |
1228 (mode == ViewManager::MeasureMode && | 1239 (mode == ViewManager::MeasureMode && |
1229 (e->buttons() & Qt::LeftButton) && m_shiftPressed)) { | 1240 (e->buttons() & Qt::LeftButton) && m_shiftPressed)) { |
1301 layer->eraseStart(this, e); | 1312 layer->eraseStart(this, e); |
1302 } | 1313 } |
1303 | 1314 |
1304 } else if (mode == ViewManager::EditMode) { | 1315 } else if (mode == ViewManager::EditMode) { |
1305 | 1316 |
1306 if (!editSelectionStart(e)) { | 1317 // Do nothing here -- we'll do it in mouseMoveEvent when the |
1307 Layer *layer = getSelectedLayer(); | 1318 // drag threshold has been passed |
1308 if (layer && layer->isLayerEditable()) { | |
1309 layer->editStart(this, e); | |
1310 } | |
1311 } | |
1312 | 1319 |
1313 } else if (mode == ViewManager::MeasureMode) { | 1320 } else if (mode == ViewManager::MeasureMode) { |
1314 | 1321 |
1315 Layer *layer = getTopLayer(); | 1322 Layer *layer = getTopLayer(); |
1316 if (layer) layer->measureStart(this, e); | 1323 if (layer) layer->measureStart(this, e); |
1325 { | 1332 { |
1326 if (e->buttons() & Qt::RightButton) { | 1333 if (e->buttons() & Qt::RightButton) { |
1327 return; | 1334 return; |
1328 } | 1335 } |
1329 | 1336 |
1337 // std::cerr << "mouseReleaseEvent" << std::endl; | |
1338 | |
1330 ViewManager::ToolMode mode = ViewManager::NavigateMode; | 1339 ViewManager::ToolMode mode = ViewManager::NavigateMode; |
1331 if (m_manager) mode = m_manager->getToolMode(); | 1340 if (m_manager) mode = m_manager->getToolMode(); |
1341 | |
1342 m_releasing = true; | |
1332 | 1343 |
1333 if (m_clickedInRange) { | 1344 if (m_clickedInRange) { |
1334 mouseMoveEvent(e); | 1345 mouseMoveEvent(e); |
1335 } | 1346 } |
1336 | 1347 |
1354 zoomToRegion(x0, y0, x1, y1); | 1365 zoomToRegion(x0, y0, x1, y1); |
1355 } | 1366 } |
1356 | 1367 |
1357 } else if (mode == ViewManager::SelectMode) { | 1368 } else if (mode == ViewManager::SelectMode) { |
1358 | 1369 |
1359 if (!hasTopLayerTimeXAxis()) return; | 1370 if (!hasTopLayerTimeXAxis()) { |
1371 m_releasing = false; | |
1372 return; | |
1373 } | |
1360 | 1374 |
1361 if (m_manager && m_manager->haveInProgressSelection()) { | 1375 if (m_manager && m_manager->haveInProgressSelection()) { |
1362 | 1376 |
1363 bool exclusive; | 1377 bool exclusive; |
1364 Selection selection = m_manager->getInProgressSelection(exclusive); | 1378 Selection selection = m_manager->getInProgressSelection(exclusive); |
1394 update(); | 1408 update(); |
1395 } | 1409 } |
1396 | 1410 |
1397 } else if (mode == ViewManager::EditMode) { | 1411 } else if (mode == ViewManager::EditMode) { |
1398 | 1412 |
1399 if (!editSelectionEnd(e)) { | 1413 if (m_editing) { |
1400 Layer *layer = getSelectedLayer(); | 1414 if (!editSelectionEnd(e)) { |
1401 if (layer && layer->isLayerEditable()) { | 1415 Layer *layer = getSelectedLayer(); |
1402 layer->editEnd(this, e); | 1416 if (layer && layer->isLayerEditable()) { |
1403 update(); | 1417 layer->editEnd(this, e); |
1404 } | 1418 update(); |
1405 } | 1419 } |
1420 } | |
1421 } | |
1406 | 1422 |
1407 } else if (mode == ViewManager::MeasureMode) { | 1423 } else if (mode == ViewManager::MeasureMode) { |
1408 | 1424 |
1409 Layer *layer = getTopLayer(); | 1425 Layer *layer = getTopLayer(); |
1410 if (layer) layer->measureEnd(this, e); | 1426 if (layer) layer->measureEnd(this, e); |
1411 if (m_measureCursor1) setCursor(*m_measureCursor1); | 1427 if (m_measureCursor1) setCursor(*m_measureCursor1); |
1412 update(); | 1428 update(); |
1413 } | 1429 } |
1414 | 1430 |
1415 m_clickedInRange = false; | 1431 m_clickedInRange = false; |
1432 m_releasing = false; | |
1416 | 1433 |
1417 emit paneInteractedWith(); | 1434 emit paneInteractedWith(); |
1418 } | 1435 } |
1419 | 1436 |
1420 void | 1437 void |
1422 { | 1439 { |
1423 if (e->buttons() & Qt::RightButton) { | 1440 if (e->buttons() & Qt::RightButton) { |
1424 return; | 1441 return; |
1425 } | 1442 } |
1426 | 1443 |
1444 // std::cerr << "mouseMoveEvent" << std::endl; | |
1445 | |
1427 updateContextHelp(&e->pos()); | 1446 updateContextHelp(&e->pos()); |
1447 | |
1448 if (m_navigating && m_clickedInRange && !m_releasing) { | |
1449 | |
1450 // if no buttons pressed, and not called from | |
1451 // mouseReleaseEvent, we want to reset clicked-ness (to avoid | |
1452 // annoying continual drags when we moved the mouse outside | |
1453 // the window after pressing button first time). | |
1454 | |
1455 if (!(e->buttons() & Qt::LeftButton) && | |
1456 !(e->buttons() & Qt::MidButton)) { | |
1457 m_clickedInRange = false; | |
1458 return; | |
1459 } | |
1460 } | |
1428 | 1461 |
1429 ViewManager::ToolMode mode = ViewManager::NavigateMode; | 1462 ViewManager::ToolMode mode = ViewManager::NavigateMode; |
1430 if (m_manager) mode = m_manager->getToolMode(); | 1463 if (m_manager) mode = m_manager->getToolMode(); |
1431 | 1464 |
1432 QPoint prevPoint = m_identifyPoint; | 1465 QPoint prevPoint = m_identifyPoint; |
1507 layer->eraseDrag(this, e); | 1540 layer->eraseDrag(this, e); |
1508 } | 1541 } |
1509 | 1542 |
1510 } else if (mode == ViewManager::EditMode) { | 1543 } else if (mode == ViewManager::EditMode) { |
1511 | 1544 |
1512 if (!editSelectionDrag(e)) { | 1545 if (m_editing) { |
1513 Layer *layer = getSelectedLayer(); | 1546 if (!editSelectionDrag(e)) { |
1514 if (layer && layer->isLayerEditable()) { | 1547 Layer *layer = getSelectedLayer(); |
1515 layer->editDrag(this, e); | 1548 if (layer && layer->isLayerEditable()) { |
1516 } | 1549 layer->editDrag(this, e); |
1517 } | 1550 } |
1551 } | |
1552 } | |
1553 | |
1554 if (!m_editing) { | |
1555 | |
1556 DragMode newDragMode = updateDragMode | |
1557 (m_dragMode, | |
1558 m_clickPos, | |
1559 e->pos(), | |
1560 true, // can move horiz | |
1561 true, // can move vert | |
1562 true, // resist horiz | |
1563 true); // resist vert | |
1564 | |
1565 if (newDragMode != UnresolvedDrag) { | |
1566 | |
1567 m_editing = true; | |
1568 | |
1569 QMouseEvent clickEvent(QEvent::MouseButtonPress, | |
1570 m_clickPos, | |
1571 Qt::NoButton, | |
1572 e->buttons(), | |
1573 e->modifiers()); | |
1574 | |
1575 if (!editSelectionStart(&clickEvent)) { | |
1576 Layer *layer = getSelectedLayer(); | |
1577 if (layer && layer->isLayerEditable()) { | |
1578 layer->editStart(this, &clickEvent); | |
1579 } | |
1580 } | |
1581 } | |
1582 } | |
1518 | 1583 |
1519 } else if (mode == ViewManager::MeasureMode) { | 1584 } else if (mode == ViewManager::MeasureMode) { |
1520 | 1585 |
1521 if (m_measureCursor2) setCursor(*m_measureCursor2); | 1586 if (m_measureCursor2) setCursor(*m_measureCursor2); |
1522 | 1587 |
1613 // other direction as well, we may switch into free mode. | 1678 // other direction as well, we may switch into free mode. |
1614 // | 1679 // |
1615 // If the top layer is incapable of being dragged | 1680 // If the top layer is incapable of being dragged |
1616 // vertically, the logic is short circuited. | 1681 // vertically, the logic is short circuited. |
1617 | 1682 |
1618 int xdiff = e->x() - m_clickPos.x(); | 1683 m_dragMode = updateDragMode |
1619 int ydiff = e->y() - m_clickPos.y(); | 1684 (m_dragMode, |
1620 int smallThreshold = 10, bigThreshold = 50; | 1685 m_clickPos, |
1621 | 1686 e->pos(), |
1622 bool canMoveVertical = canTopLayerMoveVertical(); | 1687 true, // can move horiz |
1623 bool canMoveHorizontal = true; | 1688 canTopLayerMoveVertical(), // can move vert |
1624 | 1689 canTopLayerMoveVertical() || (m_manager && m_manager->isPlaying()), // resist horiz |
1625 if (!canMoveHorizontal) { | 1690 !(m_manager && m_manager->isPlaying())); // resist vert |
1626 m_dragMode = HorizontalDrag; | 1691 |
1627 } | 1692 if (m_dragMode == HorizontalDrag || |
1628 | 1693 m_dragMode == FreeDrag) { |
1629 if (m_dragMode == UnresolvedDrag) { | |
1630 | |
1631 if (abs(ydiff) > smallThreshold && | |
1632 abs(ydiff) > abs(xdiff) * 2) { | |
1633 m_dragMode = VerticalDrag; | |
1634 } else if (abs(xdiff) > smallThreshold && | |
1635 abs(xdiff) > abs(ydiff) * 2) { | |
1636 m_dragMode = HorizontalDrag; | |
1637 } else if (abs(xdiff) > smallThreshold && | |
1638 abs(ydiff) > smallThreshold) { | |
1639 m_dragMode = FreeDrag; | |
1640 } else { | |
1641 // When playing, we don't want to disturb the play | |
1642 // position too easily; when not playing, we don't | |
1643 // want to move up/down too easily | |
1644 if (m_manager && m_manager->isPlaying()) { | |
1645 canMoveHorizontal = false; | |
1646 } else { | |
1647 canMoveVertical = false; | |
1648 } | |
1649 } | |
1650 } | |
1651 | |
1652 if (m_dragMode == VerticalDrag) { | |
1653 if (abs(xdiff) > bigThreshold) m_dragMode = FreeDrag; | |
1654 else canMoveHorizontal = false; | |
1655 } | |
1656 | |
1657 if (m_dragMode == HorizontalDrag && canMoveVertical) { | |
1658 if (abs(ydiff) > bigThreshold) m_dragMode = FreeDrag; | |
1659 else canMoveVertical = false; | |
1660 } | |
1661 | |
1662 if (canMoveHorizontal) { | |
1663 | 1694 |
1664 long frameOff = getFrameForX(e->x()) - getFrameForX(m_clickPos.x()); | 1695 long frameOff = getFrameForX(e->x()) - getFrameForX(m_clickPos.x()); |
1665 | 1696 |
1666 size_t newCentreFrame = m_dragCentreFrame; | 1697 size_t newCentreFrame = m_dragCentreFrame; |
1667 | 1698 |
1670 } else if (newCentreFrame >= size_t(frameOff)) { | 1701 } else if (newCentreFrame >= size_t(frameOff)) { |
1671 newCentreFrame -= frameOff; | 1702 newCentreFrame -= frameOff; |
1672 } else { | 1703 } else { |
1673 newCentreFrame = 0; | 1704 newCentreFrame = 0; |
1674 } | 1705 } |
1675 | 1706 |
1707 #ifdef DEBUG_PANE | |
1708 std::cerr << "Pane::dragTopLayer: newCentreFrame = " << newCentreFrame << | |
1709 ", models end frame = " << getModelsEndFrame() << std::endl; | |
1710 #endif | |
1711 | |
1676 if (newCentreFrame >= getModelsEndFrame()) { | 1712 if (newCentreFrame >= getModelsEndFrame()) { |
1677 newCentreFrame = getModelsEndFrame(); | 1713 newCentreFrame = getModelsEndFrame(); |
1678 if (newCentreFrame > 0) --newCentreFrame; | 1714 if (newCentreFrame > 0) --newCentreFrame; |
1679 } | 1715 } |
1680 | 1716 |
1681 if (getXForFrame(m_centreFrame) != getXForFrame(newCentreFrame)) { | 1717 if (getXForFrame(m_centreFrame) != getXForFrame(newCentreFrame)) { |
1682 setCentreFrame(newCentreFrame); | 1718 setCentreFrame(newCentreFrame); |
1683 } | 1719 } |
1684 } | 1720 } |
1685 | 1721 |
1686 if (canMoveVertical) { | 1722 if (m_dragMode == VerticalDrag || |
1723 m_dragMode == FreeDrag) { | |
1687 | 1724 |
1688 float vmin = 0.f, vmax = 0.f; | 1725 float vmin = 0.f, vmax = 0.f; |
1689 float dmin = 0.f, dmax = 0.f; | 1726 float dmin = 0.f, dmax = 0.f; |
1690 | 1727 |
1691 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) { | 1728 if (getTopLayerDisplayExtents(vmin, vmax, dmin, dmax)) { |
1692 | 1729 |
1693 // std::cerr << "ydiff = " << ydiff << std::endl; | 1730 // std::cerr << "ydiff = " << ydiff << std::endl; |
1694 | 1731 |
1732 int ydiff = e->y() - m_clickPos.y(); | |
1695 float perpix = (dmax - dmin) / height(); | 1733 float perpix = (dmax - dmin) / height(); |
1696 float valdiff = ydiff * perpix; | 1734 float valdiff = ydiff * perpix; |
1697 // std::cerr << "valdiff = " << valdiff << std::endl; | 1735 // std::cerr << "valdiff = " << valdiff << std::endl; |
1736 | |
1737 if (m_dragMode == UnresolvedDrag && ydiff != 0) { | |
1738 m_dragMode = VerticalDrag; | |
1739 } | |
1698 | 1740 |
1699 float newmin = m_dragStartMinValue + valdiff; | 1741 float newmin = m_dragStartMinValue + valdiff; |
1700 float newmax = m_dragStartMinValue + (dmax - dmin) + valdiff; | 1742 float newmax = m_dragStartMinValue + (dmax - dmin) + valdiff; |
1701 if (newmin < vmin) { | 1743 if (newmin < vmin) { |
1702 newmax += vmin - newmin; | 1744 newmax += vmin - newmin; |
1711 | 1753 |
1712 setTopLayerDisplayExtents(newmin, newmax); | 1754 setTopLayerDisplayExtents(newmin, newmax); |
1713 updateVerticalPanner(); | 1755 updateVerticalPanner(); |
1714 } | 1756 } |
1715 } | 1757 } |
1758 } | |
1759 | |
1760 Pane::DragMode | |
1761 Pane::updateDragMode(DragMode dragMode, | |
1762 QPoint origin, | |
1763 QPoint point, | |
1764 bool canMoveHorizontal, | |
1765 bool canMoveVertical, | |
1766 bool resistHorizontal, | |
1767 bool resistVertical) | |
1768 { | |
1769 int xdiff = point.x() - origin.x(); | |
1770 int ydiff = point.y() - origin.y(); | |
1771 | |
1772 int smallThreshold = 10, bigThreshold = 80; | |
1773 | |
1774 // std::cerr << "Pane::updateDragMode: xdiff = " << xdiff << ", ydiff = " | |
1775 // << ydiff << ", canMoveVertical = " << canMoveVertical << ", drag mode = " << m_dragMode << std::endl; | |
1776 | |
1777 if (dragMode == UnresolvedDrag) { | |
1778 | |
1779 if (abs(ydiff) > smallThreshold && | |
1780 abs(ydiff) > abs(xdiff) * 2 && | |
1781 canMoveVertical) { | |
1782 // std::cerr << "Pane::updateDragMode: passed vertical threshold" << std::endl; | |
1783 dragMode = VerticalDrag; | |
1784 } else if (abs(xdiff) > smallThreshold && | |
1785 abs(xdiff) > abs(ydiff) * 2 && | |
1786 canMoveHorizontal) { | |
1787 // std::cerr << "Pane::updateDragMode: passed horizontal threshold" << std::endl; | |
1788 dragMode = HorizontalDrag; | |
1789 } else if (abs(xdiff) > smallThreshold && | |
1790 abs(ydiff) > smallThreshold && | |
1791 canMoveVertical && | |
1792 canMoveHorizontal) { | |
1793 // std::cerr << "Pane::updateDragMode: passed both thresholds" << std::endl; | |
1794 dragMode = FreeDrag; | |
1795 } | |
1796 } | |
1797 | |
1798 if (dragMode == VerticalDrag && canMoveHorizontal) { | |
1799 if (abs(xdiff) > bigThreshold) dragMode = FreeDrag; | |
1800 } | |
1801 | |
1802 if (dragMode == HorizontalDrag && canMoveVertical) { | |
1803 if (abs(ydiff) > bigThreshold) dragMode = FreeDrag; | |
1804 } | |
1805 | |
1806 if (dragMode == UnresolvedDrag) { | |
1807 if (!resistHorizontal && xdiff != 0) { | |
1808 dragMode = HorizontalDrag; | |
1809 } | |
1810 if (!resistVertical && ydiff != 0) { | |
1811 if (dragMode == HorizontalDrag) dragMode = FreeDrag; | |
1812 else dragMode = VerticalDrag; | |
1813 } | |
1814 } | |
1815 | |
1816 return dragMode; | |
1716 } | 1817 } |
1717 | 1818 |
1718 void | 1819 void |
1719 Pane::dragExtendSelection(QMouseEvent *e) | 1820 Pane::dragExtendSelection(QMouseEvent *e) |
1720 { | 1821 { |