File indexing completed on 2024-05-12 15:56:38
0001 /* This file is part of the KDE project 0002 * 0003 * SPDX-FileCopyrightText: 2006, 2008-2009 Thomas Zander <zander@kde.org> 0004 * SPDX-FileCopyrightText: 2006 Peter Simonsson <peter.simonsson@gmail.com> 0005 * SPDX-FileCopyrightText: 2006, 2009 Thorsten Zachmann <zachmann@kde.org> 0006 * SPDX-FileCopyrightText: 2007-2010 Boudewijn Rempt <boud@valdyas.org> 0007 * SPDX-FileCopyrightText: 2007 C. Boemann <cbo@boemann.dk> 0008 * SPDX-FileCopyrightText: 2006-2008 Jan Hambrecht <jaham@gmx.net> 0009 * 0010 * SPDX-License-Identifier: LGPL-2.0-or-later 0011 */ 0012 0013 #include "KoCanvasControllerWidget.h" 0014 #include "KoCanvasControllerWidget_p.h" 0015 0016 #include "KoCanvasControllerWidgetViewport_p.h" 0017 #include "KoShape.h" 0018 #include "KoViewConverter.h" 0019 #include "KoCanvasBase.h" 0020 #include "KoCanvasObserverBase.h" 0021 #include "KoCanvasSupervisor.h" 0022 #include "KoToolManager_p.h" 0023 0024 #include <FlakeDebug.h> 0025 #include <QMouseEvent> 0026 #include <QPainter> 0027 #include <QScrollBar> 0028 #include <QEvent> 0029 #include <QDockWidget> 0030 #include <QTimer> 0031 #include <QPointer> 0032 0033 #include <QOpenGLWidget> 0034 0035 #include <math.h> 0036 0037 void KoCanvasControllerWidget::Private::setDocumentOffset() 0038 { 0039 // The margins scroll the canvas widget inside the viewport, not 0040 // the document. The documentOffset is meant to be the value that 0041 // the canvas must add to the update rect in its paint event, to 0042 // compensate. 0043 0044 QPoint pt(q->horizontalScrollBar()->value(), q->verticalScrollBar()->value()); 0045 q->proxyObject->emitMoveDocumentOffset(pt); 0046 0047 QWidget *canvasWidget = canvas->canvasWidget(); 0048 0049 if (canvasWidget) { 0050 // If it isn't an OpenGL canvas 0051 if (qobject_cast<QOpenGLWidget*>(canvasWidget) == 0) { 0052 QPoint diff = q->documentOffset() - pt; 0053 canvasWidget->scroll(diff.x(), diff.y(), canvasWidget->rect()); 0054 } 0055 } 0056 0057 q->setDocumentOffset(pt); 0058 } 0059 0060 void KoCanvasControllerWidget::Private::resetScrollBars() 0061 { 0062 // The scrollbar value always points at the top-left corner of the 0063 // bit of image we paint. 0064 0065 int docH = (int)q->documentSize().height() + q->margin(); 0066 int docW = (int)q->documentSize().width() + q->margin(); 0067 int drawH = viewportWidget->height(); 0068 int drawW = viewportWidget->width(); 0069 0070 QScrollBar *hScroll = q->horizontalScrollBar(); 0071 QScrollBar *vScroll = q->verticalScrollBar(); 0072 0073 int horizontalReserve = vastScrollingFactor * drawW; 0074 int verticalReserve = vastScrollingFactor * drawH; 0075 0076 int xMin = -horizontalReserve; 0077 int yMin = -verticalReserve; 0078 0079 int xMax = docW - drawW + horizontalReserve; 0080 int yMax = docH - drawH + verticalReserve; 0081 0082 hScroll->setRange(xMin, xMax); 0083 vScroll->setRange(yMin, yMax); 0084 0085 int fontheight = QFontMetrics(q->font()).height(); 0086 0087 vScroll->setPageStep(drawH); 0088 vScroll->setSingleStep(fontheight); 0089 hScroll->setPageStep(drawW); 0090 hScroll->setSingleStep(fontheight); 0091 0092 } 0093 0094 void KoCanvasControllerWidget::Private::emitPointerPositionChangedSignals(QEvent *event) 0095 { 0096 if (!canvas) return; 0097 if (!canvas->viewConverter()) return; 0098 0099 QPoint pointerPos; 0100 QMouseEvent *mouseEvent = dynamic_cast<QMouseEvent*>(event); 0101 if (mouseEvent) { 0102 pointerPos = mouseEvent->pos(); 0103 } else { 0104 QTabletEvent *tabletEvent = dynamic_cast<QTabletEvent*>(event); 0105 if (tabletEvent) { 0106 pointerPos = tabletEvent->pos(); 0107 } 0108 } 0109 0110 QPoint pixelPos = (pointerPos - canvas->documentOrigin()) + q->documentOffset(); 0111 QPointF documentPos = canvas->viewConverter()->viewToDocument(pixelPos); 0112 0113 q->proxyObject->emitDocumentMousePositionChanged(documentPos); 0114 q->proxyObject->emitCanvasMousePositionChanged(pointerPos); 0115 } 0116 0117 0118 #include <QTime> 0119 0120 void KoCanvasControllerWidget::Private::activate() 0121 { 0122 if (!observerProvider) { 0123 return; 0124 } 0125 KoCanvasBase *canvas = q->canvas(); 0126 Q_FOREACH (KoCanvasObserverBase *docker, observerProvider->canvasObservers()) { 0127 KoCanvasObserverBase *observer = dynamic_cast<KoCanvasObserverBase*>(docker); 0128 if (observer) { 0129 observer->setObservedCanvas(canvas); 0130 } 0131 } 0132 0133 } 0134 0135 void KoCanvasControllerWidget::Private::unsetCanvas() 0136 { 0137 if (!observerProvider) { 0138 return; 0139 } 0140 Q_FOREACH (KoCanvasObserverBase *docker, observerProvider->canvasObservers()) { 0141 KoCanvasObserverBase *observer = dynamic_cast<KoCanvasObserverBase*>(docker); 0142 if (observer) { 0143 if (observer->observedCanvas() == q->canvas()) { 0144 observer->unsetObservedCanvas(); 0145 } 0146 } 0147 } 0148 } 0149 0150 //////////// 0151 KoCanvasControllerWidget::KoCanvasControllerWidget(KisKActionCollection * actionCollection, KoCanvasSupervisor *observerProvider, QWidget *parent) 0152 : QAbstractScrollArea(parent) 0153 , KoCanvasController(actionCollection) 0154 , d(new Private(this, observerProvider)) 0155 { 0156 // We need to set this as QDeclarativeView sets them a bit different from QAbstractScrollArea 0157 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); 0158 0159 // And then our own Viewport 0160 d->viewportWidget = new Viewport(this); 0161 setViewport(d->viewportWidget); 0162 d->viewportWidget->setFocusPolicy(Qt::NoFocus); 0163 setFocusPolicy(Qt::NoFocus); 0164 setFrameStyle(0); 0165 0166 //setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); 0167 setAutoFillBackground(false); 0168 /* 0169 Fixes: apps starting at zero zoom. 0170 Details: Since the document is set on the mainwindow before loading commences the inial show/layout can choose 0171 to set the document to be very small, even to be zero pixels tall. Setting a sane minimum size on the 0172 widget means we no longer get rounding errors in zooming and we no longer end up with zero-zoom. 0173 Note: KoPage apps should probably startup with a sane document size; for Krita that's impossible 0174 */ 0175 setMinimumSize(QSize(50, 50)); 0176 setMouseTracking(true); 0177 0178 connect(horizontalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(updateCanvasOffsetX())); 0179 connect(verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(updateCanvasOffsetY())); 0180 connect(d->viewportWidget, SIGNAL(sizeChanged()), this, SLOT(updateCanvasOffsetX())); 0181 connect(proxyObject, SIGNAL(moveDocumentOffset(QPoint)), d->viewportWidget, SLOT(documentOffsetMoved(QPoint))); 0182 } 0183 0184 KoCanvasControllerWidget::~KoCanvasControllerWidget() 0185 { 0186 delete d; 0187 } 0188 0189 void KoCanvasControllerWidget::activate() 0190 { 0191 d->activate(); 0192 } 0193 0194 void KoCanvasControllerWidget::scrollContentsBy(int dx, int dy) 0195 { 0196 Q_UNUSED(dx); 0197 Q_UNUSED(dy); 0198 d->setDocumentOffset(); 0199 } 0200 0201 QSizeF KoCanvasControllerWidget::viewportSize() const 0202 { 0203 // Calculate viewport size aligned to device pixels to match KisOpenGLCanvas2. 0204 qreal dpr = viewport()->devicePixelRatioF(); 0205 int viewportWidth = static_cast<int>(viewport()->width() * dpr); 0206 int viewportHeight = static_cast<int>(viewport()->height() * dpr); 0207 return QSizeF(viewportWidth / dpr, viewportHeight / dpr); 0208 } 0209 0210 void KoCanvasControllerWidget::resizeEvent(QResizeEvent *resizeEvent) 0211 { 0212 proxyObject->emitSizeChanged(resizeEvent->size()); 0213 0214 // XXX: When resizing, keep the area we're looking at now in the 0215 // center of the resized view. 0216 resetScrollBars(); 0217 d->setDocumentOffset(); 0218 } 0219 0220 void KoCanvasControllerWidget::setCanvas(KoCanvasBase *canvas) 0221 { 0222 if (d->canvas) { 0223 d->unsetCanvas(); 0224 proxyObject->emitCanvasRemoved(this); 0225 d->canvas->setCanvasController(0); 0226 d->canvas->canvasWidget()->removeEventFilter(this); 0227 } 0228 0229 d->canvas = canvas; 0230 0231 if (d->canvas) { 0232 d->canvas->setCanvasController(this); 0233 changeCanvasWidget(d->canvas->canvasWidget()); 0234 0235 proxyObject->emitCanvasSet(this); 0236 QTimer::singleShot(0, this, SLOT(activate())); 0237 0238 setPreferredCenterFractionX(0); 0239 setPreferredCenterFractionY(0); 0240 } 0241 } 0242 0243 KoCanvasBase* KoCanvasControllerWidget::canvas() const 0244 { 0245 if (d->canvas.isNull()) return 0; 0246 return d->canvas; 0247 } 0248 0249 void KoCanvasControllerWidget::changeCanvasWidget(QWidget *widget) 0250 { 0251 if (d->viewportWidget->canvas()) { 0252 widget->setCursor(d->viewportWidget->canvas()->cursor()); 0253 d->viewportWidget->canvas()->removeEventFilter(this); 0254 } 0255 0256 d->viewportWidget->setCanvas(widget); 0257 setFocusProxy(d->canvas->canvasWidget()); 0258 } 0259 0260 int KoCanvasControllerWidget::visibleHeight() const 0261 { 0262 if (d->canvas == 0) 0263 return 0; 0264 QWidget *canvasWidget = canvas()->canvasWidget(); 0265 0266 int height1; 0267 if (canvasWidget == 0) 0268 height1 = viewport()->height(); 0269 else 0270 height1 = qMin(viewport()->height(), canvasWidget->height()); 0271 int height2 = height(); 0272 return qMin(height1, height2); 0273 } 0274 0275 int KoCanvasControllerWidget::visibleWidth() const 0276 { 0277 if (d->canvas == 0) 0278 return 0; 0279 QWidget *canvasWidget = canvas()->canvasWidget(); 0280 0281 int width1; 0282 if (canvasWidget == 0) 0283 width1 = viewport()->width(); 0284 else 0285 width1 = qMin(viewport()->width(), canvasWidget->width()); 0286 int width2 = width(); 0287 return qMin(width1, width2); 0288 } 0289 0290 int KoCanvasControllerWidget::canvasOffsetX() const 0291 { 0292 int offset = -horizontalScrollBar()->value(); 0293 0294 if (d->canvas) { 0295 offset += d->canvas->canvasWidget()->x() + frameWidth(); 0296 } 0297 0298 return offset; 0299 } 0300 0301 int KoCanvasControllerWidget::canvasOffsetY() const 0302 { 0303 int offset = -verticalScrollBar()->value(); 0304 0305 if (d->canvas) { 0306 offset += d->canvas->canvasWidget()->y() + frameWidth(); 0307 } 0308 0309 return offset; 0310 } 0311 0312 void KoCanvasControllerWidget::updateCanvasOffsetX() 0313 { 0314 proxyObject->emitCanvasOffsetXChanged(canvasOffsetX()); 0315 if (d->ignoreScrollSignals) 0316 return; 0317 0318 setPreferredCenterFractionX((horizontalScrollBar()->value() 0319 + viewport()->width() / 2.0) / documentSize().width()); 0320 } 0321 0322 void KoCanvasControllerWidget::updateCanvasOffsetY() 0323 { 0324 proxyObject->emitCanvasOffsetYChanged(canvasOffsetY()); 0325 if (d->ignoreScrollSignals) 0326 return; 0327 0328 setPreferredCenterFractionY((verticalScrollBar()->value() 0329 + verticalScrollBar()->pageStep() / 2.0) / documentSize().height()); 0330 } 0331 0332 void KoCanvasControllerWidget::ensureVisible(KoShape *shape) 0333 { 0334 Q_ASSERT(shape); 0335 ensureVisible(d->canvas->viewConverter()->documentToView(shape->boundingRect())); 0336 } 0337 0338 void KoCanvasControllerWidget::ensureVisible(const QRectF &rect, bool smooth) 0339 { 0340 QRect currentVisible(-canvasOffsetX(), -canvasOffsetY(), visibleWidth(), visibleHeight()); 0341 0342 QRect viewRect = rect.toRect(); 0343 viewRect.translate(d->canvas->documentOrigin()); 0344 if (!viewRect.isValid() || currentVisible.contains(viewRect)) 0345 return; // its visible. Nothing to do. 0346 0347 // if we move, we move a little more so the amount of times we have to move is less. 0348 int jumpWidth = smooth ? 0 : currentVisible.width() / 5; 0349 int jumpHeight = smooth ? 0 : currentVisible.height() / 5; 0350 if (!smooth && viewRect.width() + jumpWidth > currentVisible.width()) 0351 jumpWidth = 0; 0352 if (!smooth && viewRect.height() + jumpHeight > currentVisible.height()) 0353 jumpHeight = 0; 0354 0355 int horizontalMove = 0; 0356 if (currentVisible.width() <= viewRect.width()) // center view 0357 horizontalMove = viewRect.center().x() - currentVisible.center().x(); 0358 else if (currentVisible.x() > viewRect.x()) // move left 0359 horizontalMove = viewRect.x() - currentVisible.x() - jumpWidth; 0360 else if (currentVisible.right() < viewRect.right()) // move right 0361 horizontalMove = viewRect.right() - qMax(0, currentVisible.right() - jumpWidth); 0362 0363 int verticalMove = 0; 0364 if (currentVisible.height() <= viewRect.height()) // center view 0365 verticalMove = viewRect.center().y() - currentVisible.center().y(); 0366 if (currentVisible.y() > viewRect.y()) // move up 0367 verticalMove = viewRect.y() - currentVisible.y() - jumpHeight; 0368 else if (currentVisible.bottom() < viewRect.bottom()) // move down 0369 verticalMove = viewRect.bottom() - qMax(0, currentVisible.bottom() - jumpHeight); 0370 0371 pan(QPoint(horizontalMove, verticalMove)); 0372 } 0373 0374 void KoCanvasControllerWidget::recenterPreferred() 0375 { 0376 const bool oldIgnoreScrollSignals = d->ignoreScrollSignals; 0377 d->ignoreScrollSignals = true; 0378 0379 QPointF center = preferredCenter(); 0380 0381 // convert into a viewport based point 0382 center.rx() += d->canvas->canvasWidget()->x() + frameWidth(); 0383 center.ry() += d->canvas->canvasWidget()->y() + frameWidth(); 0384 0385 // scroll to a new center point 0386 QPointF topLeft = center - 0.5 * QPointF(viewport()->width(), viewport()->height()); 0387 setScrollBarValue(topLeft.toPoint()); 0388 0389 d->ignoreScrollSignals = oldIgnoreScrollSignals; 0390 } 0391 0392 void KoCanvasControllerWidget::zoomIn(const QPoint ¢er) 0393 { 0394 zoomBy(center, sqrt(2.0)); 0395 } 0396 0397 void KoCanvasControllerWidget::zoomOut(const QPoint ¢er) 0398 { 0399 zoomBy(center, sqrt(0.5)); 0400 } 0401 0402 0403 void KoCanvasControllerWidget::zoomBy(const QPoint ¢er, qreal zoom) 0404 { 0405 const QPointF oldCenter = preferredCenter(); 0406 const QPointF newCenter = center + scrollBarValue(); 0407 const QPointF stillPoint = (zoom * newCenter - oldCenter) / (zoom - 1.0); 0408 0409 proxyObject->emitZoomRelative(zoom, stillPoint); 0410 } 0411 0412 void KoCanvasControllerWidget::zoomTo(const QRect &viewRect) 0413 { 0414 qreal scale; 0415 0416 if (1.0 * viewport()->width() / viewRect.width() > 1.0 * viewport()->height() / viewRect.height()) 0417 scale = 1.0 * viewport()->height() / viewRect.height(); 0418 else 0419 scale = 1.0 * viewport()->width() / viewRect.width(); 0420 0421 zoomBy(viewRect.center(), scale); 0422 } 0423 0424 void KoCanvasControllerWidget::updateDocumentSize(const QSizeF &sz, bool recalculateCenter) 0425 { 0426 // Don't update if the document-size didn't changed to prevent infinite loops and unneeded updates. 0427 if (KoCanvasController::documentSize() == sz) 0428 return; 0429 0430 if (!recalculateCenter) { 0431 // assume the distance from the top stays equal and recalculate the center. 0432 setPreferredCenterFractionX(documentSize().width() * preferredCenterFractionX() / sz.width()); 0433 setPreferredCenterFractionY(documentSize().height() * preferredCenterFractionY() / sz.height()); 0434 } 0435 0436 const bool oldIgnoreScrollSignals = d->ignoreScrollSignals; 0437 d->ignoreScrollSignals = true; 0438 KoCanvasController::setDocumentSize(sz); 0439 d->viewportWidget->setDocumentSize(sz); 0440 resetScrollBars(); 0441 0442 // Always emit the new offset. 0443 updateCanvasOffsetX(); 0444 updateCanvasOffsetY(); 0445 0446 d->ignoreScrollSignals = oldIgnoreScrollSignals; 0447 } 0448 0449 void KoCanvasControllerWidget::setZoomWithWheel(bool zoom) 0450 { 0451 d->zoomWithWheel = zoom; 0452 } 0453 0454 void KoCanvasControllerWidget::setVastScrolling(qreal factor) 0455 { 0456 d->vastScrollingFactor = factor; 0457 } 0458 0459 QPointF KoCanvasControllerWidget::currentCursorPosition() const 0460 { 0461 QWidget *canvasWidget = d->canvas->canvasWidget(); 0462 const KoViewConverter *converter = d->canvas->viewConverter(); 0463 return converter->viewToDocument(canvasWidget->mapFromGlobal(QCursor::pos()) + d->canvas->canvasController()->documentOffset() - canvasWidget->pos()); 0464 } 0465 0466 void KoCanvasControllerWidget::pan(const QPoint &distance) 0467 { 0468 QPoint sourcePoint = scrollBarValue(); 0469 setScrollBarValue(sourcePoint + distance); 0470 } 0471 0472 void KoCanvasControllerWidget::panUp() 0473 { 0474 pan(QPoint(0, verticalScrollBar()->singleStep())); 0475 } 0476 0477 void KoCanvasControllerWidget::panDown() 0478 { 0479 pan(QPoint(0, -verticalScrollBar()->singleStep())); 0480 } 0481 0482 void KoCanvasControllerWidget::panLeft() 0483 { 0484 pan(QPoint(horizontalScrollBar()->singleStep(), 0)); 0485 } 0486 0487 void KoCanvasControllerWidget::panRight() 0488 { 0489 pan(QPoint(-horizontalScrollBar()->singleStep(), 0)); 0490 } 0491 0492 void KoCanvasControllerWidget::setPreferredCenter(const QPointF &viewPoint) 0493 { 0494 setPreferredCenterFractionX(viewPoint.x() / documentSize().width()); 0495 setPreferredCenterFractionY(viewPoint.y() / documentSize().height()); 0496 recenterPreferred(); 0497 } 0498 0499 QPointF KoCanvasControllerWidget::preferredCenter() const 0500 { 0501 QPointF center; 0502 center.setX(preferredCenterFractionX() * documentSize().width()); 0503 center.setY(preferredCenterFractionY() * documentSize().height()); 0504 return center; 0505 } 0506 0507 void KoCanvasControllerWidget::paintEvent(QPaintEvent *event) 0508 { 0509 QPainter gc(viewport()); 0510 d->viewportWidget->handlePaintEvent(gc, event); 0511 } 0512 0513 void KoCanvasControllerWidget::dragEnterEvent(QDragEnterEvent *event) 0514 { 0515 d->viewportWidget->handleDragEnterEvent(event); 0516 } 0517 0518 void KoCanvasControllerWidget::dropEvent(QDropEvent *event) 0519 { 0520 d->viewportWidget->handleDropEvent(event); 0521 } 0522 0523 void KoCanvasControllerWidget::dragMoveEvent(QDragMoveEvent *event) 0524 { 0525 d->viewportWidget->handleDragMoveEvent(event); 0526 } 0527 0528 void KoCanvasControllerWidget::dragLeaveEvent(QDragLeaveEvent *event) 0529 { 0530 d->viewportWidget->handleDragLeaveEvent(event); 0531 } 0532 0533 void KoCanvasControllerWidget::wheelEvent(QWheelEvent *event) 0534 { 0535 if (d->zoomWithWheel != ((event->modifiers() & Qt::ControlModifier) == Qt::ControlModifier)) { 0536 const qreal zoomCoeff = event->delta() > 0 ? sqrt(2.0) : sqrt(0.5); 0537 zoomRelativeToPoint(event->pos(), zoomCoeff); 0538 0539 event->accept(); 0540 } else 0541 QAbstractScrollArea::wheelEvent(event); 0542 } 0543 0544 void KoCanvasControllerWidget::zoomRelativeToPoint(const QPoint &widgetPoint, qreal zoomCoeff) 0545 { 0546 const QPoint offset = scrollBarValue(); 0547 const QPoint mousePos(widgetPoint + offset); 0548 0549 const bool oldIgnoreScrollSignals = d->ignoreScrollSignals; 0550 d->ignoreScrollSignals = true; 0551 proxyObject->emitZoomRelative(zoomCoeff, mousePos); 0552 d->ignoreScrollSignals = oldIgnoreScrollSignals; 0553 } 0554 0555 bool KoCanvasControllerWidget::focusNextPrevChild(bool) 0556 { 0557 // we always return false meaning the canvas takes keyboard focus, but never gives it away. 0558 return false; 0559 } 0560 0561 bool KoCanvasControllerWidget::viewportEvent(QEvent *event) { 0562 // Workaround: Don't let QAbstractScrollArea handle Gesture events. Because 0563 // Qt's detection of touch point positions is a bit buggy, it is handled 0564 // with custom algorithms in the KisInputManager. But we must also not let 0565 // the corresponding event propagate to the parent QAbstractScrollArea. 0566 if (event->type() == QEvent::Gesture) { 0567 return false; 0568 } 0569 return QAbstractScrollArea::viewportEvent(event); 0570 } 0571 0572 void KoCanvasControllerWidget::setMargin(int margin) 0573 { 0574 KoCanvasController::setMargin(margin); 0575 Q_ASSERT(d->viewportWidget); 0576 d->viewportWidget->setMargin(margin); 0577 } 0578 0579 QPoint KoCanvasControllerWidget::scrollBarValue() const 0580 { 0581 QScrollBar * hBar = horizontalScrollBar(); 0582 QScrollBar * vBar = verticalScrollBar(); 0583 0584 return QPoint(hBar->value(), vBar->value()); 0585 } 0586 0587 void KoCanvasControllerWidget::setScrollBarValue(const QPoint &value) 0588 { 0589 QScrollBar * hBar = horizontalScrollBar(); 0590 QScrollBar * vBar = verticalScrollBar(); 0591 0592 hBar->setValue(value.x()); 0593 vBar->setValue(value.y()); 0594 } 0595 0596 void KoCanvasControllerWidget::resetScrollBars() 0597 { 0598 d->resetScrollBars(); 0599 } 0600 0601 qreal KoCanvasControllerWidget::vastScrollingFactor() const 0602 { 0603 return d->vastScrollingFactor; 0604 } 0605 0606 KoCanvasControllerWidget::Private *KoCanvasControllerWidget::priv() 0607 { 0608 return d; 0609 } 0610 0611 //have to include this because of Q_PRIVATE_SLOT 0612 #include "moc_KoCanvasControllerWidget.cpp"