File indexing completed on 2025-02-23 04:08:58
0001 /* 0002 * SPDX-FileCopyrightText: 2007, 2010 Adrian Page <adrian@pagenet.plus.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_canvas_widget_base.h" 0008 0009 #include <QImage> 0010 #include <QPainter> 0011 #include <QTimer> 0012 #include <QMenu> 0013 0014 #include <KoShapeManager.h> 0015 #include <KoToolManager.h> 0016 #include <KoViewConverter.h> 0017 #include <KoToolProxy.h> 0018 #include <KoCanvasController.h> 0019 #include <KoShape.h> 0020 #include <KoSelection.h> 0021 0022 0023 #include "kis_coordinates_converter.h" 0024 #include "kis_canvas_decoration.h" 0025 #include "kis_config.h" 0026 #include "kis_canvas2.h" 0027 #include "KisViewManager.h" 0028 #include "kis_selection_manager.h" 0029 #include "KisDocument.h" 0030 #include "kis_update_info.h" 0031 #include "KisQPainterStateSaver.h" 0032 0033 0034 struct KisCanvasWidgetBase::Private 0035 { 0036 public: 0037 Private(KisCanvas2 *newCanvas, KisCoordinatesConverter *newCoordinatesConverter) 0038 : canvas(newCanvas) 0039 , coordinatesConverter(newCoordinatesConverter) 0040 , viewConverter(newCanvas->viewConverter()) 0041 , toolProxy(newCanvas->toolProxy()) 0042 , ignorenextMouseEventExceptRightMiddleClick(0) 0043 , borderColor(Qt::gray) 0044 {} 0045 0046 QList<KisCanvasDecorationSP> decorations; 0047 KisCanvas2 * canvas; 0048 KisCoordinatesConverter *coordinatesConverter; 0049 const KoViewConverter * viewConverter; 0050 KoToolProxy * toolProxy; 0051 QTimer blockMouseEvent; 0052 0053 bool ignorenextMouseEventExceptRightMiddleClick; // HACK work around Qt bug not sending tablet right/dblclick https://bugreports.qt.io/browse/QTBUG-8598 0054 QColor borderColor; 0055 }; 0056 0057 KisCanvasWidgetBase::KisCanvasWidgetBase(KisCanvas2 * canvas, KisCoordinatesConverter *coordinatesConverter) 0058 : m_d(new Private(canvas, coordinatesConverter)) 0059 { 0060 m_d->blockMouseEvent.setSingleShot(true); 0061 } 0062 0063 KisCanvasWidgetBase::~KisCanvasWidgetBase() 0064 { 0065 /** 0066 * Clear all the attached decoration. Otherwise they might decide 0067 * to process some events or signals after the canvas has been 0068 * destroyed 0069 */ 0070 //5qDeleteAll(m_d->decorations); 0071 m_d->decorations.clear(); 0072 0073 delete m_d; 0074 } 0075 0076 void KisCanvasWidgetBase::drawDecorations(QPainter & gc, const QRect &updateWidgetRect) const 0077 { 0078 if (!m_d->canvas) { 0079 dbgFile<<"canvas doesn't exist, in canvas widget base!"; 0080 return; 0081 } 0082 gc.save(); 0083 0084 // Setup the painter to take care of the offset; all that the 0085 // classes that do painting need to keep track of is resolution 0086 gc.setRenderHint(QPainter::Antialiasing); 0087 gc.setRenderHint(QPainter::TextAntialiasing); 0088 0089 // This option does not do anything anymore with Qt4.6, so don't re-enable it since it seems to break display 0090 // https://lists.qt-project.org/pipermail/qt-interest-old/2009-December/017078.html 0091 // gc.setRenderHint(QPainter::Antialiasing); 0092 0093 gc.setRenderHint(QPainter::SmoothPixmapTransform); 0094 0095 { 0096 KisQPainterStateSaver paintShapesState(&gc); 0097 gc.setTransform(m_d->coordinatesConverter->documentToWidgetTransform()); 0098 0099 // Paint the shapes (other than the layers) 0100 m_d->canvas->globalShapeManager()->paint(gc); 0101 0102 } 0103 0104 // ask the decorations to paint themselves 0105 // decorations are painted in "widget" coordinate system 0106 Q_FOREACH (KisCanvasDecorationSP deco, m_d->decorations) { 0107 if (deco->visible()) { 0108 deco->paint(gc, m_d->coordinatesConverter->widgetToDocument(updateWidgetRect), m_d->coordinatesConverter,m_d->canvas); 0109 } 0110 } 0111 0112 { 0113 KisQPainterStateSaver paintDecorationsState(&gc); 0114 gc.setTransform(m_d->coordinatesConverter->flakeToWidgetTransform()); 0115 0116 // - some tools do not restore gc, but that is not important here 0117 toolProxy()->paint(gc, *m_d->viewConverter); 0118 } 0119 0120 gc.restore(); 0121 } 0122 0123 void KisCanvasWidgetBase::addDecoration(KisCanvasDecorationSP deco) 0124 { 0125 m_d->decorations.push_back(deco); 0126 std::stable_sort(m_d->decorations.begin(), m_d->decorations.end(), KisCanvasDecoration::comparePriority); 0127 } 0128 0129 void KisCanvasWidgetBase::removeDecoration(const QString &id) 0130 { 0131 for (auto it = m_d->decorations.begin(); it != m_d->decorations.end(); ++it) { 0132 if ((*it)->id() == id) { 0133 it = m_d->decorations.erase(it); 0134 break; 0135 } 0136 } 0137 } 0138 0139 KisCanvasDecorationSP KisCanvasWidgetBase::decoration(const QString& id) const 0140 { 0141 Q_FOREACH (KisCanvasDecorationSP deco, m_d->decorations) { 0142 if (deco->id() == id) { 0143 return deco; 0144 } 0145 } 0146 return 0; 0147 } 0148 0149 void KisCanvasWidgetBase::setDecorations(const QList<KisCanvasDecorationSP > &decorations) 0150 { 0151 m_d->decorations=decorations; 0152 std::stable_sort(m_d->decorations.begin(), m_d->decorations.end(), KisCanvasDecoration::comparePriority); 0153 } 0154 0155 QList<KisCanvasDecorationSP > KisCanvasWidgetBase::decorations() const 0156 { 0157 return m_d->decorations; 0158 } 0159 void KisCanvasWidgetBase::notifyDecorationsWindowMinimized(bool minimized) 0160 { 0161 Q_FOREACH (KisCanvasDecorationSP deco, m_d->decorations) { 0162 deco->notifyWindowMinimized(minimized); 0163 } 0164 } 0165 void KisCanvasWidgetBase::setWrapAroundViewingMode(bool value) 0166 { 0167 Q_UNUSED(value); 0168 } 0169 0170 void KisCanvasWidgetBase::setWrapAroundViewingModeAxis(WrapAroundAxis value) 0171 { 0172 Q_UNUSED(value); 0173 } 0174 0175 QImage KisCanvasWidgetBase::createCheckersImage(qint32 checkSize) 0176 { 0177 KisConfig cfg(true); 0178 0179 if(checkSize < 0) 0180 checkSize = cfg.checkSize(); 0181 0182 QColor checkColor1 = cfg.checkersColor1(); 0183 QColor checkColor2 = cfg.checkersColor2(); 0184 0185 QImage tile(checkSize * 2, checkSize * 2, QImage::Format_RGB32); 0186 QPainter pt(&tile); 0187 pt.fillRect(tile.rect(), checkColor2); 0188 pt.fillRect(0, 0, checkSize, checkSize, checkColor1); 0189 pt.fillRect(checkSize, checkSize, checkSize, checkSize, checkColor1); 0190 pt.end(); 0191 0192 return tile; 0193 } 0194 0195 void KisCanvasWidgetBase::notifyConfigChanged() 0196 { 0197 KisConfig cfg(true); 0198 m_d->borderColor = cfg.canvasBorderColor(); 0199 } 0200 0201 QColor KisCanvasWidgetBase::borderColor() const 0202 { 0203 return m_d->borderColor; 0204 } 0205 0206 KisCanvas2 *KisCanvasWidgetBase::canvas() const 0207 { 0208 return m_d->canvas; 0209 } 0210 0211 KisCoordinatesConverter* KisCanvasWidgetBase::coordinatesConverter() const 0212 { 0213 return m_d->coordinatesConverter; 0214 } 0215 0216 QVector<QRect> KisCanvasWidgetBase::updateCanvasProjection(const QVector<KisUpdateInfoSP> &infoObjects) 0217 { 0218 QVector<QRect> dirtyViewRects; 0219 0220 Q_FOREACH (KisUpdateInfoSP info, infoObjects) { 0221 dirtyViewRects << this->updateCanvasProjection(info); 0222 } 0223 0224 return dirtyViewRects; 0225 } 0226 0227 KoToolProxy *KisCanvasWidgetBase::toolProxy() const 0228 { 0229 return m_d->toolProxy; 0230 } 0231 0232 QVariant KisCanvasWidgetBase::processInputMethodQuery(Qt::InputMethodQuery query) const 0233 { 0234 return m_d->toolProxy->inputMethodQuery(query); 0235 } 0236 0237 void KisCanvasWidgetBase::processInputMethodEvent(QInputMethodEvent *event) 0238 { 0239 m_d->toolProxy->inputMethodEvent(event); 0240 } 0241 0242 void KisCanvasWidgetBase::processFocusInEvent(QFocusEvent *event) 0243 { 0244 m_d->toolProxy->focusInEvent(event); 0245 } 0246 0247 void KisCanvasWidgetBase::processFocusOutEvent(QFocusEvent *event) 0248 { 0249 m_d->toolProxy->focusOutEvent(event); 0250 }