Warning, file /office/calligra/braindump/src/Canvas.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002  *  Copyright (c) 2006,2007 Thorsten Zachmann <zachmann@kde.org>
0003  *  Copyright (c) 2009,2010 Cyrille Berger <cberger@cberger.net>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Lesser General Public
0007  * License as published by the Free Software Foundation;
0008  * either version 2, or (at your option) any later version of the License.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Lesser General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Lesser General Public License
0016  * along with this library; see the file COPYING.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  */
0020 
0021 #include "Canvas.h"
0022 
0023 #include <QMenu>
0024 #include <QMouseEvent>
0025 #include <QPainter>
0026 
0027 #include <kxmlguifactory.h>
0028 #include <kundo2command.h>
0029 
0030 #include <KoCanvasController.h>
0031 #include <KoSelection.h>
0032 #include <KoShapeManager.h>
0033 #include <KoShapeLayer.h>
0034 #include <KoToolProxy.h>
0035 #include <KoUnit.h>
0036 
0037 #include "RootSection.h"
0038 #include "View.h"
0039 #include "ViewManager.h"
0040 #include "Section.h"
0041 #include "Layout.h"
0042 #include "SectionContainer.h"
0043 
0044 Canvas::Canvas(View* view, RootSection* doc, Section* currentSection)
0045     : QWidget(view)
0046     , KoCanvasBase(currentSection ? currentSection->sectionContainer() : 0)
0047     , m_origin(0, 0)
0048     , m_view(view)
0049     , m_doc(doc)
0050 {
0051     m_shapeManager = new KoShapeManager(this);
0052     connect(m_shapeManager, SIGNAL(selectionChanged()), SLOT(updateOriginAndSize()));
0053     m_toolProxy = new KoToolProxy(this);
0054     setFocusPolicy(Qt::StrongFocus);
0055     // this is much faster than painting it in the paintevent
0056     QPalette pal = palette();
0057     pal.setColor(QPalette::Base, Qt::white);
0058     pal.setColor(QPalette::Text, Qt::black);
0059     setPalette(pal);
0060     setBackgroundRole(QPalette::Base);
0061     setAutoFillBackground(true);
0062     setAttribute(Qt::WA_InputMethodEnabled, true);
0063 
0064     if(currentSection) {
0065 
0066         QList<KoShape*> shapes;
0067         shapes.push_back(currentSection->sectionContainer()->layer());
0068         shapeManager()->setShapes(shapes, KoShapeManager::AddWithoutRepaint);
0069 
0070         KoShapeLayer* layer = currentSection->sectionContainer()->layer();
0071         shapeManager()->selection()->setActiveLayer(layer);
0072 
0073         // Make sure the canvas is enabled
0074         setEnabled(true);
0075 
0076         update();
0077     } else {
0078         setEnabled(false);
0079     }
0080 }
0081 
0082 Canvas::~Canvas()
0083 {
0084     delete m_toolProxy;
0085     delete m_shapeManager;
0086 }
0087 
0088 void Canvas::setDocumentOffset(const QPoint &offset)
0089 {
0090     m_originalOffset = offset;
0091     updateOffset();
0092 }
0093 
0094 void Canvas::addCommand(KUndo2Command *command)
0095 {
0096     m_doc->addCommand(m_view->activeSection(), command);
0097     updateOriginAndSize();
0098 }
0099 
0100 KoShapeManager * Canvas::shapeManager() const
0101 {
0102     return m_shapeManager;
0103 }
0104 
0105 void Canvas::updateCanvas(const QRectF& rc)
0106 {
0107     QRect clipRect(viewToWidget(viewConverter()->documentToView(rc).toRect()));
0108     clipRect.adjust(-2, -2, 2, 2);   // Resize to fit anti-aliasing
0109     clipRect.moveTopLeft(clipRect.topLeft() - m_documentOffset);
0110     update(clipRect);
0111 
0112     emit canvasUpdated();
0113 }
0114 
0115 KoViewConverter * Canvas::viewConverter() const
0116 {
0117     return m_view->zoomHandler();
0118 }
0119 
0120 KoUnit Canvas::unit() const
0121 {
0122     return KoUnit(KoUnit::Centimeter);
0123 }
0124 
0125 const QPoint & Canvas::documentOffset() const
0126 {
0127     return m_documentOffset;
0128 }
0129 
0130 QPoint Canvas::documentOrigin() const
0131 {
0132     return m_origin;
0133 }
0134 
0135 void Canvas::paintEvent(QPaintEvent *event)
0136 {
0137     QPainter painter(this);
0138 
0139     painter.translate(-documentOffset());
0140     painter.setRenderHint(QPainter::Antialiasing);
0141     QRectF clipRect = event->rect().translated(documentOffset());
0142     painter.setClipRect(clipRect);
0143 
0144     painter.translate(m_origin.x(), m_origin.y());
0145 
0146     const KoViewConverter* converter = viewConverter();
0147     shapeManager()->paint(painter, *converter, false);
0148     painter.setRenderHint(QPainter::Antialiasing, false);
0149 
0150     painter.setRenderHint(QPainter::Antialiasing);
0151     m_toolProxy->paint(painter, *converter);
0152 }
0153 
0154 void Canvas::tabletEvent(QTabletEvent *event)
0155 {
0156     m_toolProxy->tabletEvent(event, viewConverter()->viewToDocument(widgetToView(event->pos() + m_documentOffset)));
0157 }
0158 
0159 void Canvas::mousePressEvent(QMouseEvent *event)
0160 {
0161     m_toolProxy->mousePressEvent(event, viewConverter()->viewToDocument(widgetToView(event->pos() + m_documentOffset)));
0162 
0163     if(!event->isAccepted() && event->button() == Qt::RightButton) {
0164         showContextMenu(event->globalPos(), toolProxy()->popupActionList());
0165     }
0166 
0167     event->setAccepted(true);
0168 }
0169 
0170 void Canvas::mouseDoubleClickEvent(QMouseEvent *event)
0171 {
0172     m_toolProxy->mouseDoubleClickEvent(event, viewConverter()->viewToDocument(widgetToView(event->pos() + m_documentOffset)));
0173 }
0174 
0175 void Canvas::mouseMoveEvent(QMouseEvent *event)
0176 {
0177     m_toolProxy->mouseMoveEvent(event, viewConverter()->viewToDocument(widgetToView(event->pos() + m_documentOffset)));
0178 }
0179 
0180 void Canvas::mouseReleaseEvent(QMouseEvent *event)
0181 {
0182     m_toolProxy->mouseReleaseEvent(event, viewConverter()->viewToDocument(widgetToView(event->pos() + m_documentOffset)));
0183 }
0184 
0185 void Canvas::keyPressEvent(QKeyEvent *event)
0186 {
0187     m_toolProxy->keyPressEvent(event);
0188 #if 0
0189 
0190     if(! event->isAccepted()) {
0191         event->accept();
0192         switch(event->key()) {
0193         case Qt::Key_Home:
0194             m_view->navigatePage(KoPageApp::PageFirst);
0195             break;
0196         case Qt::Key_PageUp:
0197             m_view->navigatePage(KoPageApp::PagePrevious);
0198             break;
0199         case Qt::Key_PageDown:
0200             m_view->navigatePage(KoPageApp::PageNext);
0201             break;
0202         case Qt::Key_End:
0203             m_view->navigatePage(KoPageApp::PageLast);
0204             break;
0205         default:
0206             event->ignore();
0207             break;
0208         }
0209     }
0210     if(! event->isAccepted()) {
0211         if(event->key() == Qt::Key_Backtab
0212                 or(event->key() == Qt::Key_Tab && (event->modifiers() & Qt::ShiftModifier))) {
0213             focusNextPrevChild(false);
0214         } else if(event->key() == Qt::Key_Tab) {
0215             focusNextPrevChild(true);
0216         }
0217     }
0218 #endif
0219 }
0220 
0221 void Canvas::keyReleaseEvent(QKeyEvent *event)
0222 {
0223     m_toolProxy->keyReleaseEvent(event);
0224 }
0225 
0226 void Canvas::wheelEvent(QWheelEvent * event)
0227 {
0228     m_toolProxy->wheelEvent(event, viewConverter()->viewToDocument(widgetToView(event->pos() + m_documentOffset)));
0229 }
0230 
0231 void Canvas::closeEvent(QCloseEvent * event)
0232 {
0233     event->ignore();
0234 }
0235 
0236 void Canvas::updateInputMethodInfo()
0237 {
0238     updateMicroFocus();
0239 }
0240 
0241 QVariant Canvas::inputMethodQuery(Qt::InputMethodQuery query) const
0242 {
0243     if (query == Qt::ImMicroFocus) {
0244         QRectF rect = (m_toolProxy->inputMethodQuery(query, *(viewConverter())).toRectF()).toRect();
0245         QPointF scroll(canvasController()->scrollBarValue());
0246         rect.translate(documentOrigin() - scroll);
0247         return rect.toRect();
0248     }
0249     return m_toolProxy->inputMethodQuery(query, *(viewConverter()));
0250 }
0251 
0252 void Canvas::inputMethodEvent(QInputMethodEvent *event)
0253 {
0254     m_toolProxy->inputMethodEvent(event);
0255 }
0256 
0257 void Canvas::resizeEvent(QResizeEvent * event)
0258 {
0259     emit sizeChanged(event->size());
0260     updateOriginAndSize();
0261 }
0262 
0263 void Canvas::showContextMenu(const QPoint& globalPos, const QList<QAction*>& actionList)
0264 {
0265     m_view->unplugActionList("toolproxy_action_list");
0266     m_view->plugActionList("toolproxy_action_list", actionList);
0267     QMenu *menu = dynamic_cast<QMenu*>(m_view->factory()->container("default_canvas_popup", m_view));
0268 
0269     if(menu)
0270         menu->exec(globalPos);
0271 }
0272 
0273 void Canvas::setBackgroundColor(const QColor &color)
0274 {
0275     QPalette pal = palette();
0276     pal.setColor(QPalette::Normal, backgroundRole(), color);
0277     pal.setColor(QPalette::Inactive, backgroundRole(), color);
0278     setPalette(pal);
0279 }
0280 
0281 void Canvas::updateOriginAndSize()
0282 {
0283     if(m_view->activeSection()) {
0284         QRectF rect = m_view->activeSection()->layout()->boundingBox();
0285         if(rect != m_oldDocumentRect) {
0286             m_oldDocumentRect = rect;
0287             emit(documentRect(rect));
0288             update();
0289         }
0290         QRect viewRect = viewConverter()->documentToView(rect).toRect();
0291         if(m_oldViewDocumentRect != viewRect) {
0292             m_oldViewDocumentRect = viewRect;
0293             m_origin = -viewRect.topLeft();
0294             KoCanvasController* controller = canvasController();
0295             if(controller) {
0296                 // tell canvas controller the new document size in pixel
0297                 controller->updateDocumentSize(viewRect.size(), true);
0298                 // make sure the actual selection is visible
0299                 KoSelection * selection = m_shapeManager->selection();
0300                 if(selection->count())
0301                     controller->ensureVisible(viewConverter()->documentToView(selection->boundingRect()));
0302                 updateOffset();
0303             }
0304         }
0305     }
0306 }
0307 
0308 void Canvas::updateOffset()
0309 {
0310     qreal dx = qMax(0, (size().width() - m_oldViewDocumentRect.size().width()) / 2);
0311     qreal dy = qMax(0, (size().height() - m_oldViewDocumentRect.size().height()) / 2);
0312     m_documentOffset = m_originalOffset - QPoint(dx, dy);
0313 }
0314 
0315 void Canvas::gridSize(qreal *horizontal, qreal *vertical) const
0316 {
0317     *horizontal = 1;
0318     *vertical = 1;
0319 }
0320 
0321 bool Canvas::snapToGrid() const
0322 {
0323     return false;
0324 }
0325 
0326 void Canvas::setCursor(const QCursor &cursor)
0327 {
0328     QWidget::setCursor(cursor);
0329 }
0330 
0331 void Canvas::focusInEvent(QFocusEvent * event)
0332 {
0333     QWidget::focusInEvent(event);
0334     emit(canvasReceivedFocus());
0335 }
0336 
0337 QPoint Canvas::widgetToView(const QPoint& p) const
0338 {
0339     return p - m_origin;
0340 }
0341 
0342 QRect Canvas::widgetToView(const QRect& r) const
0343 {
0344     return r.translated(- m_origin);
0345 }
0346 
0347 QPoint Canvas::viewToWidget(const QPoint& p) const
0348 {
0349     return p + m_origin;
0350 }
0351 
0352 QRect Canvas::viewToWidget(const QRect& r) const
0353 {
0354     return r.translated(m_origin);
0355 }