Mercurial > hg > svgui
comparison view/View.cpp @ 1216:dc2af6616c83
Merge from branch 3.0-integration
author | Chris Cannam |
---|---|
date | Fri, 13 Jan 2017 10:29:50 +0000 |
parents | c603aba61702 |
children | a34a2a25907c |
comparison
equal
deleted
inserted
replaced
1048:e8102ff5573b | 1216:dc2af6616c83 |
---|---|
18 #include "data/model/Model.h" | 18 #include "data/model/Model.h" |
19 #include "base/ZoomConstraint.h" | 19 #include "base/ZoomConstraint.h" |
20 #include "base/Profiler.h" | 20 #include "base/Profiler.h" |
21 #include "base/Pitch.h" | 21 #include "base/Pitch.h" |
22 #include "base/Preferences.h" | 22 #include "base/Preferences.h" |
23 #include "ViewProxy.h" | |
23 | 24 |
24 #include "layer/TimeRulerLayer.h" | 25 #include "layer/TimeRulerLayer.h" |
25 #include "layer/SingleColourLayer.h" | 26 #include "layer/SingleColourLayer.h" |
27 #include "layer/PaintAssistant.h" | |
28 | |
26 #include "data/model/PowerOfSqrtTwoZoomConstraint.h" | 29 #include "data/model/PowerOfSqrtTwoZoomConstraint.h" |
27 #include "data/model/RangeSummarisableTimeValueModel.h" | 30 #include "data/model/RangeSummarisableTimeValueModel.h" |
28 | 31 |
29 #include "widgets/IconLoader.h" | 32 #include "widgets/IconLoader.h" |
30 | 33 |
35 #include <QProgressDialog> | 38 #include <QProgressDialog> |
36 #include <QTextStream> | 39 #include <QTextStream> |
37 #include <QFont> | 40 #include <QFont> |
38 #include <QMessageBox> | 41 #include <QMessageBox> |
39 #include <QPushButton> | 42 #include <QPushButton> |
43 #include <QSettings> | |
44 #include <QSvgGenerator> | |
40 | 45 |
41 #include <iostream> | 46 #include <iostream> |
42 #include <cassert> | 47 #include <cassert> |
43 #include <cmath> | 48 #include <cmath> |
44 | 49 |
45 #include <unistd.h> | |
46 | |
47 //#define DEBUG_VIEW 1 | 50 //#define DEBUG_VIEW 1 |
48 //#define DEBUG_VIEW_WIDGET_PAINT 1 | 51 //#define DEBUG_VIEW_WIDGET_PAINT 1 |
49 | 52 |
50 | |
51 View::View(QWidget *w, bool showProgress) : | 53 View::View(QWidget *w, bool showProgress) : |
52 QFrame(w), | 54 QFrame(w), |
55 m_id(getNextId()), | |
53 m_centreFrame(0), | 56 m_centreFrame(0), |
54 m_zoomLevel(1024), | 57 m_zoomLevel(1024), |
55 m_followPan(true), | 58 m_followPan(true), |
56 m_followZoom(true), | 59 m_followZoom(true), |
57 m_followPlay(PlaybackScrollPageWithCentre), | 60 m_followPlay(PlaybackScrollPageWithCentre), |
58 m_followPlayIsDetached(false), | 61 m_followPlayIsDetached(false), |
59 m_playPointerFrame(0), | 62 m_playPointerFrame(0), |
60 m_showProgress(showProgress), | 63 m_showProgress(showProgress), |
61 m_cache(0), | 64 m_cache(0), |
65 m_buffer(0), | |
62 m_cacheCentreFrame(0), | 66 m_cacheCentreFrame(0), |
63 m_cacheZoomLevel(1024), | 67 m_cacheZoomLevel(1024), |
64 m_selectionCached(false), | 68 m_selectionCached(false), |
65 m_deleting(false), | 69 m_deleting(false), |
66 m_haveSelectedLayer(false), | 70 m_haveSelectedLayer(false), |
74 { | 78 { |
75 // cerr << "View::~View(" << this << ")" << endl; | 79 // cerr << "View::~View(" << this << ")" << endl; |
76 | 80 |
77 m_deleting = true; | 81 m_deleting = true; |
78 delete m_propertyContainer; | 82 delete m_propertyContainer; |
83 delete m_cache; | |
84 delete m_buffer; | |
79 } | 85 } |
80 | 86 |
81 PropertyContainer::PropertyList | 87 PropertyContainer::PropertyList |
82 View::getProperties() const | 88 View::getProperties() const |
83 { | 89 { |
360 } | 366 } |
361 | 367 |
362 sv_frame_t | 368 sv_frame_t |
363 View::getFrameForX(int x) const | 369 View::getFrameForX(int x) const |
364 { | 370 { |
365 int z = m_zoomLevel; | 371 sv_frame_t z = m_zoomLevel; // nb not just int, or multiplication may overflow |
366 sv_frame_t frame = m_centreFrame - (width()/2) * z; | 372 sv_frame_t frame = m_centreFrame - (width()/2) * z; |
367 | 373 |
374 frame = (frame / z) * z; // this is start frame | |
375 frame = frame + x * z; | |
376 | |
368 #ifdef DEBUG_VIEW_WIDGET_PAINT | 377 #ifdef DEBUG_VIEW_WIDGET_PAINT |
369 SVDEBUG << "View::getFrameForX(" << x << "): z = " << z << ", m_centreFrame = " << m_centreFrame << ", width() = " << width() << ", frame = " << frame << endl; | 378 cerr << "View::getFrameForX(" << x << "): z = " << z << ", m_centreFrame = " << m_centreFrame << ", width() = " << width() << ", frame = " << frame << endl; |
370 #endif | 379 #endif |
371 | 380 |
372 frame = (frame / z) * z; // this is start frame | 381 return frame; |
373 return frame + x * z; | |
374 } | 382 } |
375 | 383 |
376 double | 384 double |
377 View::getYForFrequency(double frequency, | 385 View::getYForFrequency(double frequency, |
378 double minf, | 386 double minf, |
406 return h - (h * (frequency - minf)) / (maxf - minf); | 414 return h - (h * (frequency - minf)) / (maxf - minf); |
407 } | 415 } |
408 } | 416 } |
409 | 417 |
410 double | 418 double |
411 View::getFrequencyForY(int y, | 419 View::getFrequencyForY(double y, |
412 double minf, | 420 double minf, |
413 double maxf, | 421 double maxf, |
414 bool logarithmic) const | 422 bool logarithmic) const |
415 { | 423 { |
416 int h = height(); | 424 double h = height(); |
417 | 425 |
418 if (logarithmic) { | 426 if (logarithmic) { |
419 | 427 |
420 static double lastminf = 0.0, lastmaxf = 0.0; | 428 static double lastminf = 0.0, lastmaxf = 0.0; |
421 static double logminf = 0.0, logmaxf = 0.0; | 429 static double logminf = 0.0, logmaxf = 0.0; |
446 // cout << "zoom level: " << m_zoomLevel << endl; | 454 // cout << "zoom level: " << m_zoomLevel << endl; |
447 #endif | 455 #endif |
448 return m_zoomLevel; | 456 return m_zoomLevel; |
449 } | 457 } |
450 | 458 |
459 int | |
460 View::effectiveDevicePixelRatio() const | |
461 { | |
462 #ifdef Q_OS_MAC | |
463 int dpratio = devicePixelRatio(); | |
464 if (dpratio > 1) { | |
465 QSettings settings; | |
466 settings.beginGroup("Preferences"); | |
467 if (!settings.value("scaledHiDpi", true).toBool()) { | |
468 dpratio = 1; | |
469 } | |
470 settings.endGroup(); | |
471 } | |
472 return dpratio; | |
473 #else | |
474 return 1; | |
475 #endif | |
476 } | |
477 | |
451 void | 478 void |
452 View::setZoomLevel(int z) | 479 View::setZoomLevel(int z) |
453 { | 480 { |
481 int dpratio = effectiveDevicePixelRatio(); | |
482 if (z < dpratio) return; | |
454 if (z < 1) z = 1; | 483 if (z < 1) z = 1; |
455 if (m_zoomLevel != int(z)) { | 484 if (m_zoomLevel != int(z)) { |
456 m_zoomLevel = z; | 485 m_zoomLevel = z; |
457 emit zoomLevelChanged(z, m_followZoom); | 486 emit zoomLevelChanged(z, m_followZoom); |
458 update(); | 487 update(); |
782 m_followZoom = f; | 811 m_followZoom = f; |
783 emit propertyContainerPropertyChanged(m_propertyContainer); | 812 emit propertyContainerPropertyChanged(m_propertyContainer); |
784 } | 813 } |
785 | 814 |
786 void | 815 void |
787 View::drawVisibleText(QPainter &paint, int x, int y, QString text, TextStyle style) const | |
788 { | |
789 if (style == OutlinedText || style == OutlinedItalicText) { | |
790 | |
791 paint.save(); | |
792 | |
793 if (style == OutlinedItalicText) { | |
794 QFont f(paint.font()); | |
795 f.setItalic(true); | |
796 paint.setFont(f); | |
797 } | |
798 | |
799 QColor penColour, surroundColour, boxColour; | |
800 | |
801 penColour = getForeground(); | |
802 surroundColour = getBackground(); | |
803 boxColour = surroundColour; | |
804 boxColour.setAlpha(127); | |
805 | |
806 paint.setPen(Qt::NoPen); | |
807 paint.setBrush(boxColour); | |
808 | |
809 QRect r = paint.fontMetrics().boundingRect(text); | |
810 r.translate(QPoint(x, y)); | |
811 // cerr << "drawVisibleText: r = " << r.x() << "," <<r.y() << " " << r.width() << "x" << r.height() << endl; | |
812 paint.drawRect(r); | |
813 paint.setBrush(Qt::NoBrush); | |
814 | |
815 paint.setPen(surroundColour); | |
816 | |
817 for (int dx = -1; dx <= 1; ++dx) { | |
818 for (int dy = -1; dy <= 1; ++dy) { | |
819 if (!(dx || dy)) continue; | |
820 paint.drawText(x + dx, y + dy, text); | |
821 } | |
822 } | |
823 | |
824 paint.setPen(penColour); | |
825 | |
826 paint.drawText(x, y, text); | |
827 | |
828 paint.restore(); | |
829 | |
830 } else { | |
831 | |
832 cerr << "ERROR: View::drawVisibleText: Boxed style not yet implemented!" << endl; | |
833 } | |
834 } | |
835 | |
836 void | |
837 View::setPlaybackFollow(PlaybackFollowMode m) | 816 View::setPlaybackFollow(PlaybackFollowMode m) |
838 { | 817 { |
839 m_followPlay = m; | 818 m_followPlay = m; |
840 emit propertyContainerPropertyChanged(m_propertyContainer); | 819 emit propertyContainerPropertyChanged(m_propertyContainer); |
841 } | 820 } |
1025 #endif | 1004 #endif |
1026 | 1005 |
1027 f = getAlignedPlaybackFrame(); | 1006 f = getAlignedPlaybackFrame(); |
1028 | 1007 |
1029 #ifdef DEBUG_VIEW | 1008 #ifdef DEBUG_VIEW |
1030 cerr << " -> aligned frame = " << af << endl; | 1009 cerr << " -> aligned frame = " << f << endl; |
1031 #endif | 1010 #endif |
1032 | 1011 |
1033 movePlayPointer(f); | 1012 movePlayPointer(f); |
1034 } | 1013 } |
1035 | 1014 |
1651 } | 1630 } |
1652 | 1631 |
1653 void | 1632 void |
1654 View::setPaintFont(QPainter &paint) | 1633 View::setPaintFont(QPainter &paint) |
1655 { | 1634 { |
1635 int scaleFactor = 1; | |
1636 int dpratio = effectiveDevicePixelRatio(); | |
1637 if (dpratio > 1) { | |
1638 QPaintDevice *dev = paint.device(); | |
1639 if (dynamic_cast<QPixmap *>(dev) || dynamic_cast<QImage *>(dev)) { | |
1640 scaleFactor = dpratio; | |
1641 } | |
1642 } | |
1643 | |
1656 QFont font(paint.font()); | 1644 QFont font(paint.font()); |
1657 font.setPointSize(Preferences::getInstance()->getViewFontSize()); | 1645 font.setPointSize(Preferences::getInstance()->getViewFontSize() |
1646 * scaleFactor); | |
1658 paint.setFont(font); | 1647 paint.setFont(font); |
1648 } | |
1649 | |
1650 QRect | |
1651 View::getPaintRect() const | |
1652 { | |
1653 return rect(); | |
1659 } | 1654 } |
1660 | 1655 |
1661 void | 1656 void |
1662 View::paintEvent(QPaintEvent *e) | 1657 View::paintEvent(QPaintEvent *e) |
1663 { | 1658 { |
1692 #endif | 1687 #endif |
1693 } | 1688 } |
1694 | 1689 |
1695 QRect nonCacheRect(cacheRect); | 1690 QRect nonCacheRect(cacheRect); |
1696 | 1691 |
1692 int dpratio = effectiveDevicePixelRatio(); | |
1693 | |
1697 // If not all layers are scrollable, but some of the back layers | 1694 // If not all layers are scrollable, but some of the back layers |
1698 // are, we should store only those in the cache. | 1695 // are, we should store only those in the cache. |
1699 | 1696 |
1700 bool layersChanged = false; | 1697 bool layersChanged = false; |
1701 LayerList scrollables = getScrollableBackLayers(true, layersChanged); | 1698 LayerList scrollables = getScrollableBackLayers(true, layersChanged); |
1703 bool selectionCacheable = nonScrollables.empty(); | 1700 bool selectionCacheable = nonScrollables.empty(); |
1704 bool haveSelections = m_manager && !m_manager->getSelections().empty(); | 1701 bool haveSelections = m_manager && !m_manager->getSelections().empty(); |
1705 | 1702 |
1706 // If all the non-scrollable layers are non-opaque, then we draw | 1703 // If all the non-scrollable layers are non-opaque, then we draw |
1707 // the selection rectangle behind them and cache it. If any are | 1704 // the selection rectangle behind them and cache it. If any are |
1708 // opaque, however, we can't cache. | 1705 // opaque, however, or if our device-pixel ratio is not 1 (so we |
1706 // need to paint direct to the widget), then we can't cache. | |
1709 // | 1707 // |
1710 if (!selectionCacheable) { | 1708 if (dpratio == 1) { |
1711 selectionCacheable = true; | 1709 |
1712 for (LayerList::const_iterator i = nonScrollables.begin(); | 1710 if (!selectionCacheable) { |
1713 i != nonScrollables.end(); ++i) { | 1711 selectionCacheable = true; |
1714 if ((*i)->isLayerOpaque()) { | 1712 for (LayerList::const_iterator i = nonScrollables.begin(); |
1715 selectionCacheable = false; | 1713 i != nonScrollables.end(); ++i) { |
1716 break; | 1714 if ((*i)->isLayerOpaque()) { |
1717 } | 1715 selectionCacheable = false; |
1718 } | 1716 break; |
1719 } | 1717 } |
1720 | 1718 } |
1721 if (selectionCacheable) { | 1719 } |
1722 QPoint localPos; | 1720 |
1723 bool closeToLeft, closeToRight; | 1721 if (selectionCacheable) { |
1724 if (shouldIlluminateLocalSelection(localPos, closeToLeft, closeToRight)) { | 1722 QPoint localPos; |
1725 selectionCacheable = false; | 1723 bool closeToLeft, closeToRight; |
1726 } | 1724 if (shouldIlluminateLocalSelection |
1725 (localPos, closeToLeft, closeToRight)) { | |
1726 selectionCacheable = false; | |
1727 } | |
1728 } | |
1729 | |
1730 } else { | |
1731 | |
1732 selectionCacheable = false; | |
1727 } | 1733 } |
1728 | 1734 |
1729 #ifdef DEBUG_VIEW_WIDGET_PAINT | 1735 #ifdef DEBUG_VIEW_WIDGET_PAINT |
1730 cerr << "View(" << this << ")::paintEvent: have " << scrollables.size() | 1736 cerr << "View(" << this << ")::paintEvent: have " << scrollables.size() |
1731 << " scrollable back layers and " << nonScrollables.size() | 1737 << " scrollable back layers and " << nonScrollables.size() |
1739 delete m_cache; | 1745 delete m_cache; |
1740 m_cache = 0; | 1746 m_cache = 0; |
1741 m_selectionCached = false; | 1747 m_selectionCached = false; |
1742 } | 1748 } |
1743 | 1749 |
1750 QSize scaledCacheSize(scaledSize(size(), dpratio)); | |
1751 QRect scaledCacheRect(scaledRect(cacheRect, dpratio)); | |
1752 | |
1753 if (!m_buffer || scaledCacheSize != m_buffer->size()) { | |
1754 delete m_buffer; | |
1755 m_buffer = new QPixmap(scaledCacheSize); | |
1756 } | |
1757 | |
1744 if (!scrollables.empty()) { | 1758 if (!scrollables.empty()) { |
1745 | 1759 |
1746 #ifdef DEBUG_VIEW_WIDGET_PAINT | 1760 #ifdef DEBUG_VIEW_WIDGET_PAINT |
1747 cerr << "View(" << this << "): cache " << m_cache << ", cache zoom " | 1761 cerr << "View(" << this << "): cache " << m_cache << ", cache zoom " |
1748 << m_cacheZoomLevel << ", zoom " << m_zoomLevel << endl; | 1762 << m_cacheZoomLevel << ", zoom " << m_zoomLevel << endl; |
1749 #endif | 1763 #endif |
1750 | 1764 |
1751 if (!m_cache || | 1765 if (!m_cache || |
1752 m_cacheZoomLevel != m_zoomLevel || | 1766 m_cacheZoomLevel != m_zoomLevel || |
1753 width() != m_cache->width() || | 1767 scaledCacheSize != m_cache->size()) { |
1754 height() != m_cache->height()) { | |
1755 | 1768 |
1756 // cache is not valid | 1769 // cache is not valid |
1757 | 1770 |
1758 if (cacheRect.width() < width()/10) { | 1771 if (cacheRect.width() < width()/10) { |
1759 delete m_cache; | 1772 delete m_cache; |
1761 #ifdef DEBUG_VIEW_WIDGET_PAINT | 1774 #ifdef DEBUG_VIEW_WIDGET_PAINT |
1762 cerr << "View(" << this << ")::paintEvent: small repaint, not bothering to recreate cache" << endl; | 1775 cerr << "View(" << this << ")::paintEvent: small repaint, not bothering to recreate cache" << endl; |
1763 #endif | 1776 #endif |
1764 } else { | 1777 } else { |
1765 delete m_cache; | 1778 delete m_cache; |
1766 m_cache = new QPixmap(width(), height()); | 1779 m_cache = new QPixmap(scaledCacheSize); |
1767 #ifdef DEBUG_VIEW_WIDGET_PAINT | 1780 #ifdef DEBUG_VIEW_WIDGET_PAINT |
1768 cerr << "View(" << this << ")::paintEvent: recreated cache" << endl; | 1781 cerr << "View(" << this << ")::paintEvent: recreated cache" << endl; |
1769 #endif | 1782 #endif |
1770 cacheRect = rect(); | 1783 cacheRect = rect(); |
1771 repaintCache = true; | 1784 repaintCache = true; |
1776 int dx = | 1789 int dx = |
1777 getXForFrame(m_cacheCentreFrame) - | 1790 getXForFrame(m_cacheCentreFrame) - |
1778 getXForFrame(m_centreFrame); | 1791 getXForFrame(m_centreFrame); |
1779 | 1792 |
1780 if (dx > -width() && dx < width()) { | 1793 if (dx > -width() && dx < width()) { |
1781 #ifdef PIXMAP_COPY_TO_SELF | |
1782 // This is not normally defined. Copying a pixmap to | |
1783 // itself doesn't work properly on Windows, Mac, or | |
1784 // X11 with the raster backend (it only works when | |
1785 // moving in one direction and then presumably only by | |
1786 // accident). It does actually seem to be fine on X11 | |
1787 // with the native backend, but we prefer not to use | |
1788 // that anyway | |
1789 paint.begin(m_cache); | |
1790 paint.drawPixmap(dx, 0, *m_cache); | |
1791 paint.end(); | |
1792 #else | |
1793 static QPixmap *tmpPixmap = 0; | 1794 static QPixmap *tmpPixmap = 0; |
1794 if (!tmpPixmap || | 1795 if (!tmpPixmap || tmpPixmap->size() != scaledCacheSize) { |
1795 tmpPixmap->width() != width() || | |
1796 tmpPixmap->height() != height()) { | |
1797 delete tmpPixmap; | 1796 delete tmpPixmap; |
1798 tmpPixmap = new QPixmap(width(), height()); | 1797 tmpPixmap = new QPixmap(scaledCacheSize); |
1799 } | 1798 } |
1800 paint.begin(tmpPixmap); | 1799 paint.begin(tmpPixmap); |
1801 paint.drawPixmap(0, 0, *m_cache); | 1800 paint.drawPixmap(0, 0, *m_cache); |
1802 paint.end(); | 1801 paint.end(); |
1803 paint.begin(m_cache); | 1802 paint.begin(m_cache); |
1804 paint.drawPixmap(dx, 0, *tmpPixmap); | 1803 paint.drawPixmap(dx, 0, *tmpPixmap); |
1805 paint.end(); | 1804 paint.end(); |
1806 #endif | |
1807 if (dx < 0) { | 1805 if (dx < 0) { |
1808 cacheRect = QRect(width() + dx, 0, -dx, height()); | 1806 cacheRect = QRect(width() + dx, 0, -dx, height()); |
1809 } else { | 1807 } else { |
1810 cacheRect = QRect(0, 0, dx, height()); | 1808 cacheRect = QRect(0, 0, dx, height()); |
1811 } | 1809 } |
1822 | 1820 |
1823 } else { | 1821 } else { |
1824 #ifdef DEBUG_VIEW_WIDGET_PAINT | 1822 #ifdef DEBUG_VIEW_WIDGET_PAINT |
1825 cerr << "View(" << this << ")::paintEvent: cache is good" << endl; | 1823 cerr << "View(" << this << ")::paintEvent: cache is good" << endl; |
1826 #endif | 1824 #endif |
1827 paint.begin(this); | 1825 paint.begin(m_buffer); |
1828 paint.drawPixmap(cacheRect, *m_cache, cacheRect); | 1826 paint.drawPixmap(scaledCacheRect, *m_cache, scaledCacheRect); |
1829 paint.end(); | 1827 paint.end(); |
1830 QFrame::paintEvent(e); | 1828 QFrame::paintEvent(e); |
1831 paintedCacheRect = true; | 1829 paintedCacheRect = true; |
1832 } | 1830 } |
1833 | 1831 |
1839 // cerr << "View(" << this << ")::paintEvent: cacheRect " << cacheRect << ", nonCacheRect " << (nonCacheRect | cacheRect) << ", repaintCache " << repaintCache << ", paintedCacheRect " << paintedCacheRect << endl; | 1837 // cerr << "View(" << this << ")::paintEvent: cacheRect " << cacheRect << ", nonCacheRect " << (nonCacheRect | cacheRect) << ", repaintCache " << repaintCache << ", paintedCacheRect " << paintedCacheRect << endl; |
1840 #endif | 1838 #endif |
1841 | 1839 |
1842 // Scrollable (cacheable) items first | 1840 // Scrollable (cacheable) items first |
1843 | 1841 |
1842 ViewProxy proxy(this, dpratio); | |
1843 | |
1844 if (!paintedCacheRect) { | 1844 if (!paintedCacheRect) { |
1845 | 1845 |
1846 if (repaintCache) paint.begin(m_cache); | 1846 QRect rectToPaint; |
1847 else paint.begin(this); | 1847 |
1848 if (repaintCache) { | |
1849 paint.begin(m_cache); | |
1850 rectToPaint = scaledCacheRect; | |
1851 } else { | |
1852 paint.begin(m_buffer); | |
1853 rectToPaint = scaledCacheRect; | |
1854 } | |
1855 | |
1848 setPaintFont(paint); | 1856 setPaintFont(paint); |
1849 paint.setClipRect(cacheRect); | 1857 paint.setClipRect(rectToPaint); |
1850 | 1858 |
1851 paint.setPen(getBackground()); | 1859 paint.setPen(getBackground()); |
1852 paint.setBrush(getBackground()); | 1860 paint.setBrush(getBackground()); |
1853 paint.drawRect(cacheRect); | 1861 paint.drawRect(rectToPaint); |
1854 | 1862 |
1855 paint.setPen(getForeground()); | 1863 paint.setPen(getForeground()); |
1856 paint.setBrush(Qt::NoBrush); | 1864 paint.setBrush(Qt::NoBrush); |
1857 | 1865 |
1858 for (LayerList::iterator i = scrollables.begin(); i != scrollables.end(); ++i) { | 1866 for (LayerList::iterator i = scrollables.begin(); i != scrollables.end(); ++i) { |
1859 paint.setRenderHint(QPainter::Antialiasing, false); | 1867 paint.setRenderHint(QPainter::Antialiasing, false); |
1860 paint.save(); | 1868 paint.save(); |
1861 (*i)->paint(this, paint, cacheRect); | 1869 #ifdef DEBUG_VIEW_WIDGET_PAINT |
1870 cerr << "Painting scrollable layer " << *i << " using proxy with repaintCache = " << repaintCache << ", dpratio = " << dpratio << ", rectToPaint = " << rectToPaint.x() << "," << rectToPaint.y() << " " << rectToPaint.width() << "x" << rectToPaint.height() << endl; | |
1871 #endif | |
1872 (*i)->paint(&proxy, paint, rectToPaint); | |
1862 paint.restore(); | 1873 paint.restore(); |
1863 } | 1874 } |
1864 | 1875 |
1865 if (haveSelections && selectionCacheable) { | 1876 if (haveSelections && selectionCacheable) { |
1866 drawSelections(paint); | 1877 drawSelections(paint); |
1869 | 1880 |
1870 paint.end(); | 1881 paint.end(); |
1871 | 1882 |
1872 if (repaintCache) { | 1883 if (repaintCache) { |
1873 cacheRect |= (e ? e->rect() : rect()); | 1884 cacheRect |= (e ? e->rect() : rect()); |
1874 paint.begin(this); | 1885 scaledCacheRect = scaledRect(cacheRect, dpratio); |
1875 paint.drawPixmap(cacheRect, *m_cache, cacheRect); | 1886 paint.begin(m_buffer); |
1887 paint.drawPixmap(scaledCacheRect, *m_cache, scaledCacheRect); | |
1876 paint.end(); | 1888 paint.end(); |
1877 } | 1889 } |
1878 } | 1890 } |
1879 | 1891 |
1880 // Now non-cacheable items. We always need to redraw the | 1892 // Now non-cacheable items. We always need to redraw the |
1881 // non-cacheable items across at least the area we drew of the | 1893 // non-cacheable items across at least the area we drew of the |
1882 // cacheable items. | 1894 // cacheable items. |
1883 | 1895 |
1884 nonCacheRect |= cacheRect; | 1896 nonCacheRect |= cacheRect; |
1885 | 1897 |
1886 paint.begin(this); | 1898 QRect scaledNonCacheRect = scaledRect(nonCacheRect, dpratio); |
1887 paint.setClipRect(nonCacheRect); | 1899 |
1900 paint.begin(m_buffer); | |
1901 paint.setClipRect(scaledNonCacheRect); | |
1888 setPaintFont(paint); | 1902 setPaintFont(paint); |
1889 if (scrollables.empty()) { | 1903 if (scrollables.empty()) { |
1890 paint.setPen(getBackground()); | 1904 paint.setPen(getBackground()); |
1891 paint.setBrush(getBackground()); | 1905 paint.setBrush(getBackground()); |
1892 paint.drawRect(nonCacheRect); | 1906 paint.drawRect(scaledNonCacheRect); |
1893 } | 1907 } |
1894 | 1908 |
1895 paint.setPen(getForeground()); | 1909 paint.setPen(getForeground()); |
1896 paint.setBrush(Qt::NoBrush); | 1910 paint.setBrush(Qt::NoBrush); |
1897 | 1911 |
1898 for (LayerList::iterator i = nonScrollables.begin(); i != nonScrollables.end(); ++i) { | 1912 for (LayerList::iterator i = nonScrollables.begin(); i != nonScrollables.end(); ++i) { |
1899 // Profiler profiler2("View::paintEvent non-cacheable"); | 1913 // Profiler profiler2("View::paintEvent non-cacheable"); |
1900 (*i)->paint(this, paint, nonCacheRect); | 1914 #ifdef DEBUG_VIEW_WIDGET_PAINT |
1915 cerr << "Painting non-scrollable layer " << *i << " without proxy with repaintCache = " << repaintCache << ", dpratio = " << dpratio << ", rectToPaint = " << nonCacheRect.x() << "," << nonCacheRect.y() << " " << nonCacheRect.width() << "x" << nonCacheRect.height() << endl; | |
1916 #endif | |
1917 (*i)->paint(&proxy, paint, scaledNonCacheRect); | |
1901 } | 1918 } |
1902 | 1919 |
1920 paint.end(); | |
1921 | |
1922 paint.begin(this); | |
1923 QRect finalPaintRect = e ? e->rect() : rect(); | |
1924 paint.drawPixmap(finalPaintRect, *m_buffer, scaledRect(finalPaintRect, dpratio)); | |
1903 paint.end(); | 1925 paint.end(); |
1904 | 1926 |
1905 paint.begin(this); | 1927 paint.begin(this); |
1906 setPaintFont(paint); | 1928 setPaintFont(paint); |
1907 if (e) paint.setClipRect(e->rect()); | 1929 if (e) paint.setClipRect(e->rect()); |
1923 // Don't show the play pointer when it is redundant with | 1945 // Don't show the play pointer when it is redundant with |
1924 // the centre line | 1946 // the centre line |
1925 showPlayPointer = false; | 1947 showPlayPointer = false; |
1926 } | 1948 } |
1927 } | 1949 } |
1928 | 1950 |
1929 if (showPlayPointer) { | 1951 if (showPlayPointer) { |
1930 | 1952 |
1931 paint.begin(this); | 1953 paint.begin(this); |
1932 | 1954 |
1933 int playx = getXForFrame(m_playPointerFrame); | 1955 int playx = getXForFrame(m_playPointerFrame); |
2079 | 2101 |
2080 if (dw < (p1 - p0)) { | 2102 if (dw < (p1 - p0)) { |
2081 dx = p1 - 2 - dw; | 2103 dx = p1 - 2 - dw; |
2082 } | 2104 } |
2083 | 2105 |
2084 paint.drawText(sx, sy, startText); | 2106 PaintAssistant::drawVisibleText(this, paint, sx, sy, startText, |
2085 paint.drawText(ex, ey, endText); | 2107 PaintAssistant::OutlinedText); |
2086 paint.drawText(dx, dy, durationText); | 2108 PaintAssistant::drawVisibleText(this, paint, ex, ey, endText, |
2109 PaintAssistant::OutlinedText); | |
2110 PaintAssistant::drawVisibleText(this, paint, dx, dy, durationText, | |
2111 PaintAssistant::OutlinedText); | |
2087 if (durationBothEnds) { | 2112 if (durationBothEnds) { |
2088 paint.drawText(sx, dy, durationText); | 2113 PaintAssistant::drawVisibleText(this, paint, sx, dy, durationText, |
2114 PaintAssistant::OutlinedText); | |
2089 } | 2115 } |
2090 } | 2116 } |
2091 } | 2117 } |
2092 | 2118 |
2093 paint.restore(); | 2119 paint.restore(); |
2298 | 2324 |
2299 dxy = r.y() + r.height() + fontAscent + 2; | 2325 dxy = r.y() + r.height() + fontAscent + 2; |
2300 } | 2326 } |
2301 | 2327 |
2302 if (axs != "") { | 2328 if (axs != "") { |
2303 drawVisibleText(paint, axx, axy, axs, OutlinedText); | 2329 PaintAssistant::drawVisibleText(this, paint, axx, axy, axs, PaintAssistant::OutlinedText); |
2304 axy += fontHeight; | 2330 axy += fontHeight; |
2305 } | 2331 } |
2306 | 2332 |
2307 if (ays != "") { | 2333 if (ays != "") { |
2308 drawVisibleText(paint, axx, axy, ays, OutlinedText); | 2334 PaintAssistant::drawVisibleText(this, paint, axx, axy, ays, PaintAssistant::OutlinedText); |
2309 axy += fontHeight; | 2335 axy += fontHeight; |
2310 } | 2336 } |
2311 | 2337 |
2312 if (bxs != "") { | 2338 if (bxs != "") { |
2313 drawVisibleText(paint, bxx, bxy, bxs, OutlinedText); | 2339 PaintAssistant::drawVisibleText(this, paint, bxx, bxy, bxs, PaintAssistant::OutlinedText); |
2314 bxy += fontHeight; | 2340 bxy += fontHeight; |
2315 } | 2341 } |
2316 | 2342 |
2317 if (bys != "") { | 2343 if (bys != "") { |
2318 drawVisibleText(paint, bxx, bxy, bys, OutlinedText); | 2344 PaintAssistant::drawVisibleText(this, paint, bxx, bxy, bys, PaintAssistant::OutlinedText); |
2319 bxy += fontHeight; | 2345 bxy += fontHeight; |
2320 } | 2346 } |
2321 | 2347 |
2322 if (dxs != "") { | 2348 if (dxs != "") { |
2323 drawVisibleText(paint, dxx, dxy, dxs, OutlinedText); | 2349 PaintAssistant::drawVisibleText(this, paint, dxx, dxy, dxs, PaintAssistant::OutlinedText); |
2324 dxy += fontHeight; | 2350 dxy += fontHeight; |
2325 } | 2351 } |
2326 | 2352 |
2327 if (dys != "") { | 2353 if (dys != "") { |
2328 drawVisibleText(paint, dxx, dxy, dys, OutlinedText); | 2354 PaintAssistant::drawVisibleText(this, paint, dxx, dxy, dys, PaintAssistant::OutlinedText); |
2329 dxy += fontHeight; | 2355 dxy += fontHeight; |
2330 } | 2356 } |
2331 | 2357 |
2332 paint.restore(); | 2358 paint.restore(); |
2333 } | 2359 } |
2410 paint.setPen(getForeground()); | 2436 paint.setPen(getForeground()); |
2411 paint.setBrush(Qt::NoBrush); | 2437 paint.setBrush(Qt::NoBrush); |
2412 | 2438 |
2413 for (LayerList::iterator i = m_layerStack.begin(); | 2439 for (LayerList::iterator i = m_layerStack.begin(); |
2414 i != m_layerStack.end(); ++i) { | 2440 i != m_layerStack.end(); ++i) { |
2415 if(!((*i)->isLayerDormant(this))){ | 2441 if (!((*i)->isLayerDormant(this))){ |
2416 | 2442 |
2417 paint.setRenderHint(QPainter::Antialiasing, false); | 2443 paint.setRenderHint(QPainter::Antialiasing, false); |
2418 | 2444 |
2419 paint.save(); | 2445 paint.save(); |
2420 paint.translate(xorigin + x, 0); | 2446 paint.translate(xorigin + x, 0); |
2421 | 2447 |
2422 cerr << "Centre frame now: " << m_centreFrame << " drawing to " << chunk.x() + x + xorigin << ", " << chunk.width() << endl; | 2448 cerr << "Centre frame now: " << m_centreFrame << " drawing to " << chunk.x() + x + xorigin << ", " << chunk.width() << endl; |
2423 | 2449 |
2424 (*i)->setSynchronousPainting(true); | 2450 (*i)->setSynchronousPainting(true); |
2425 | 2451 |
2426 (*i)->paint(this, paint, chunk); | 2452 (*i)->paint(this, paint, chunk); |
2427 | 2453 |
2428 (*i)->setSynchronousPainting(false); | 2454 (*i)->setSynchronousPainting(false); |
2429 | 2455 |
2430 paint.restore(); | 2456 paint.restore(); |
2431 } | 2457 } |
2432 } | 2458 } |
2433 } | 2459 } |
2434 | 2460 |
2435 m_centreFrame = origCentreFrame; | 2461 m_centreFrame = origCentreFrame; |
2436 update(); | 2462 update(); |
2437 return true; | 2463 return true; |
2438 } | 2464 } |
2439 | 2465 |
2440 QImage * | 2466 QImage * |
2441 View::toNewImage() | 2467 View::renderToNewImage() |
2442 { | 2468 { |
2443 sv_frame_t f0 = getModelsStartFrame(); | 2469 sv_frame_t f0 = getModelsStartFrame(); |
2444 sv_frame_t f1 = getModelsEndFrame(); | 2470 sv_frame_t f1 = getModelsEndFrame(); |
2445 | 2471 |
2446 return toNewImage(f0, f1); | 2472 return renderPartToNewImage(f0, f1); |
2447 } | 2473 } |
2448 | 2474 |
2449 QImage * | 2475 QImage * |
2450 View::toNewImage(sv_frame_t f0, sv_frame_t f1) | 2476 View::renderPartToNewImage(sv_frame_t f0, sv_frame_t f1) |
2451 { | 2477 { |
2452 int x0 = int(f0 / getZoomLevel()); | 2478 int x0 = int(f0 / getZoomLevel()); |
2453 int x1 = int(f1 / getZoomLevel()); | 2479 int x1 = int(f1 / getZoomLevel()); |
2454 | 2480 |
2455 QImage *image = new QImage(x1 - x0, height(), QImage::Format_RGB32); | 2481 QImage *image = new QImage(x1 - x0, height(), QImage::Format_RGB32); |
2464 return image; | 2490 return image; |
2465 } | 2491 } |
2466 } | 2492 } |
2467 | 2493 |
2468 QSize | 2494 QSize |
2469 View::getImageSize() | 2495 View::getRenderedImageSize() |
2470 { | 2496 { |
2471 sv_frame_t f0 = getModelsStartFrame(); | 2497 sv_frame_t f0 = getModelsStartFrame(); |
2472 sv_frame_t f1 = getModelsEndFrame(); | 2498 sv_frame_t f1 = getModelsEndFrame(); |
2473 | 2499 |
2474 return getImageSize(f0, f1); | 2500 return getRenderedPartImageSize(f0, f1); |
2475 } | 2501 } |
2476 | 2502 |
2477 QSize | 2503 QSize |
2478 View::getImageSize(sv_frame_t f0, sv_frame_t f1) | 2504 View::getRenderedPartImageSize(sv_frame_t f0, sv_frame_t f1) |
2479 { | 2505 { |
2480 int x0 = int(f0 / getZoomLevel()); | 2506 int x0 = int(f0 / getZoomLevel()); |
2481 int x1 = int(f1 / getZoomLevel()); | 2507 int x1 = int(f1 / getZoomLevel()); |
2482 | 2508 |
2483 return QSize(x1 - x0, height()); | 2509 return QSize(x1 - x0, height()); |
2510 } | |
2511 | |
2512 bool | |
2513 View::renderToSvgFile(QString filename) | |
2514 { | |
2515 sv_frame_t f0 = getModelsStartFrame(); | |
2516 sv_frame_t f1 = getModelsEndFrame(); | |
2517 | |
2518 return renderPartToSvgFile(filename, f0, f1); | |
2519 } | |
2520 | |
2521 bool | |
2522 View::renderPartToSvgFile(QString filename, sv_frame_t f0, sv_frame_t f1) | |
2523 { | |
2524 int x0 = int(f0 / getZoomLevel()); | |
2525 int x1 = int(f1 / getZoomLevel()); | |
2526 | |
2527 QSvgGenerator generator; | |
2528 generator.setFileName(filename); | |
2529 generator.setSize(QSize(x1 - x0, height())); | |
2530 generator.setViewBox(QRect(0, 0, x1 - x0, height())); | |
2531 generator.setTitle(tr("Exported image from %1") | |
2532 .arg(QApplication::applicationName())); | |
2533 | |
2534 QPainter paint; | |
2535 paint.begin(&generator); | |
2536 bool result = render(paint, 0, f0, f1); | |
2537 paint.end(); | |
2538 return result; | |
2484 } | 2539 } |
2485 | 2540 |
2486 void | 2541 void |
2487 View::toXml(QTextStream &stream, | 2542 View::toXml(QTextStream &stream, |
2488 QString indent, QString extraAttributes) const | 2543 QString indent, QString extraAttributes) const |