File indexing completed on 2024-05-05 17:09:09
0001 /* 0002 * This file is part of the KDE project 0003 * 0004 * Copyright (C) 2013 Shantanu Tushar <shantanu@kde.org> 0005 * Copyright (C) 2013 Sujith Haridasan <sujith.h@gmail.com> 0006 * Copyright (C) 2013 Arjen Hiemstra <ahiemstra@heimr.nl> 0007 * 0008 * This library is free software; you can redistribute it and/or 0009 * modify it under the terms of the GNU Library General Public 0010 * License as published by the Free Software Foundation; either 0011 * version 2 of the License, or (at your option) any later version. 0012 * 0013 * This library is distributed in the hope that it will be useful, 0014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0016 * Library General Public License for more details. 0017 * 0018 * You should have received a copy of the GNU Library General Public License 0019 * along with this library; see the file COPYING.LIB. If not, write to 0020 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0021 * Boston, MA 02110-1301, USA. 0022 * 0023 */ 0024 0025 #include "CQTextDocumentCanvas.h" 0026 #include "CQCanvasController.h" 0027 #include "CQTextDocumentModel.h" 0028 #include "CQTextDocumentNotesModel.h" 0029 0030 #include "gemini/ViewModeSwitchEvent.h" 0031 0032 #include <KoPluginLoader.h> 0033 #include <KoDocumentEntry.h> 0034 #include <KoUnit.h> 0035 #include <KoDocument.h> 0036 #include <KoDocumentResourceManager.h> 0037 #include <KoPart.h> 0038 #include <KoFindText.h> 0039 #include <KoCanvasBase.h> 0040 #include <KoToolManager.h> 0041 #include <KoZoomHandler.h> 0042 #include <KoZoomController.h> 0043 #include <KoShape.h> 0044 #include <KoToolManager_p.h> 0045 #include <KoToolBase.h> 0046 #include <KoPointerEvent.h> 0047 #include <KoSelection.h> 0048 #include <KoShapeRegistry.h> 0049 #include <KoShapeAnchor.h> 0050 #include <KoShapeContainer.h> 0051 #include <KoTextEditor.h> 0052 #include <KoProperties.h> 0053 #include <KoColumns.h> 0054 #include <KWDocument.h> 0055 #include <KWPage.h> 0056 #include <KWCanvasItem.h> 0057 #include <commands/KWShapeCreateCommand.h> 0058 0059 #include <KActionCollection> 0060 0061 #include <QPluginLoader> 0062 #include <QMimeDatabase> 0063 #include <QStyleOptionGraphicsItem> 0064 #include <QGraphicsWidget> 0065 #include <QTextDocument> 0066 #include <QTextFrame> 0067 #include <QTextLayout> 0068 #include <QGraphicsSceneMouseEvent> 0069 #include <QTextDocumentFragment> 0070 #include <QSvgRenderer> 0071 #include <QApplication> 0072 #include <QDebug> 0073 0074 class CQTextDocumentCanvas::Private 0075 { 0076 public: 0077 Private() 0078 : canvas(0), 0079 findText(0), 0080 documentModel(0), 0081 document(0), 0082 pageNumber(0), 0083 throttleTimer(new QTimer()), 0084 currentTool(0), 0085 notes(0), 0086 textEditor(0) 0087 { 0088 throttleTimer->setInterval(200); 0089 throttleTimer->setSingleShot(true); 0090 } 0091 0092 KWCanvasItem *canvas; 0093 QString searchTerm; 0094 KoFindText *findText; 0095 CQTextDocumentModel *documentModel; 0096 KWDocument* document; 0097 KoPart* part; 0098 QSize documentSize; 0099 int pageNumber; 0100 QPoint currentPoint; 0101 QObjectList linkTargets; 0102 QTimer* throttleTimer; 0103 KoToolBase* currentTool; 0104 CQTextDocumentNotesModel* notes; 0105 KoTextEditor* textEditor; 0106 0107 void updateLinkTargets() 0108 { 0109 qDeleteAll(linkTargets); 0110 linkTargets.clear(); 0111 0112 if (!canvas) { 0113 return; 0114 } 0115 0116 foreach(const KoShape* shape, canvas->shapeManager()->shapes()) { 0117 if (!shape->hyperLink().isEmpty()) { 0118 QObject * obj = new QObject(documentModel); 0119 obj->setProperty("linkRect", shape->boundingRect()); 0120 obj->setProperty("linkTarget", QUrl(shape->hyperLink())); 0121 linkTargets.append(obj); 0122 } 0123 } 0124 0125 foreach(QTextDocument* text, findText->documents()) { 0126 QTextBlock block = text->rootFrame()->firstCursorPosition().block(); 0127 for (; block.isValid(); block = block.next()) { 0128 block.begin(); 0129 QTextBlock::iterator it; 0130 for (it = block.begin(); !(it.atEnd()); ++it) { 0131 QTextFragment fragment = it.fragment(); 0132 if (fragment.isValid()) { 0133 QTextCharFormat format = fragment.charFormat(); 0134 if (format.isAnchor()) { 0135 // This is an anchor, store target and position... 0136 QObject * obj = new QObject(documentModel); 0137 QRectF rect = getFragmentPosition(block, fragment); 0138 KWPage page = document->pageManager()->page(rect.left()); 0139 rect.translate(page.topMargin(), page.rightMargin()); 0140 rect = canvas->viewMode()->documentToView(rect, canvas->viewConverter()); 0141 rect.translate(page.pageNumber() * (page.topMargin() + page.bottomMargin()) + 20, 0); 0142 obj->setProperty("linkRect", rect); 0143 obj->setProperty("linkTarget", QUrl(format.anchorHref())); 0144 linkTargets.append(obj); 0145 } 0146 } 0147 } 0148 } 0149 } 0150 } 0151 0152 QRectF getFragmentPosition(QTextBlock block, QTextFragment fragment) 0153 { 0154 // TODO this only produces a position for the first part, if the link spans more than one line... 0155 // Need to sort that somehow, unfortunately probably by slapping this code into the above function. 0156 // For now leave it like this, more important things are needed. 0157 QTextLayout* layout = block.layout(); 0158 QTextLine line = layout->lineForTextPosition(fragment.position() - block.position()); 0159 if (!line.isValid()) { 0160 // fragment has no valid position and consequently no line... 0161 return QRectF(); 0162 } 0163 qreal top = line.position().y(); 0164 qreal bottom = line.position().y() + line.height(); 0165 qreal left = line.cursorToX(fragment.position() - block.position()); 0166 qreal right = line.cursorToX((fragment.position() - block.position()) + fragment.length()); 0167 QRectF fragmentPosition(QPointF(top, left), QPointF(bottom, right)); 0168 return fragmentPosition.adjusted(layout->position().x(), layout->position().y(), 0, 0); 0169 } 0170 0171 QList<KoShape*> deepShapeFind(const QList<KoShape*>& shapes) 0172 { 0173 QList<KoShape*> allShapes; 0174 foreach(KoShape* shape, shapes) { 0175 allShapes.append(shape); 0176 KoShapeContainer *container = dynamic_cast<KoShapeContainer*>(shape); 0177 if (container) { 0178 allShapes.append(deepShapeFind(container->shapes())); 0179 } 0180 } 0181 return allShapes; 0182 } 0183 QRectF getCursorPosition(int position) 0184 { 0185 QPointF point; 0186 QTextBlock block = textEditor->document()->findBlock(position); 0187 QTextLayout* layout = block.layout(); 0188 QTextLine line = layout->lineForTextPosition(position - block.position()); 0189 if (!line.isValid()) { 0190 // fragment has no valid position and consequently no line... 0191 return QRectF(); 0192 } 0193 qreal top = line.position().y(); 0194 qreal left = line.cursorToX(position - block.position()); 0195 point = QPointF(left + layout->position().y(), top + layout->position().x()); 0196 0197 KoShape* shape = canvas->shapeManager()->selection()->firstSelectedShape(); 0198 point += shape->position(); 0199 while(KoShapeContainer* parent = shape->parent()) { 0200 point += parent->position(); 0201 } 0202 0203 KWPage page = document->pageManager()->page(point.y()); 0204 // point += QPointF(page.rightMargin(), page.pageNumber() * page.topMargin() 0205 // + (page.pageNumber() - 1) * page.bottomMargin()); 0206 // if (page.pageNumber() > 1) 0207 // point += QPointF(0, 20); 0208 point += QPointF(0, (page.pageNumber() - 1) * (page.topMargin() + 20)); 0209 // point = canvas->viewConverter()->documentToView(point); 0210 0211 return canvas->viewConverter()->documentToView(QRectF(point, QSizeF(0, line.height()))); 0212 } 0213 }; 0214 0215 CQTextDocumentCanvas::CQTextDocumentCanvas(QDeclarativeItem* parent) 0216 : CQCanvasBase(parent), d(new Private) 0217 { 0218 setAcceptedMouseButtons(Qt::LeftButton); 0219 d->findText = new KoFindText(this); 0220 0221 connect (d->findText, SIGNAL(updateCanvas()), SLOT(updateCanvas())); 0222 connect (d->findText, SIGNAL(matchFound(KoFindMatch)), SLOT(findMatchFound(KoFindMatch))); 0223 connect (d->findText, SIGNAL(noMatchFound()), SLOT(findNoMatchFound())); 0224 connect (KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*,int)), SLOT(currentToolChanged(KoCanvasController*,int))); 0225 } 0226 0227 CQTextDocumentCanvas::~CQTextDocumentCanvas() 0228 { 0229 d->part->removeMainWindow(d->part->currentMainwindow()); 0230 KoToolManager::instance()->removeCanvasController(d->canvas->canvasController()); 0231 delete d; 0232 } 0233 0234 void CQTextDocumentCanvas::openFile(const QString& uri) 0235 { 0236 emit loadingBegun(); 0237 0238 KoDocumentEntry entry; 0239 QList<QPluginLoader*> pluginLoaders = KoPluginLoader::pluginLoaders("calligra/parts"); 0240 Q_FOREACH (QPluginLoader *loader, pluginLoaders) { 0241 if (loader->fileName().contains(QLatin1String("wordspart"))) { 0242 entry = KoDocumentEntry(loader); 0243 pluginLoaders.removeOne(loader); 0244 break; 0245 } 0246 } 0247 qDeleteAll(pluginLoaders); 0248 if (entry.isEmpty()) { 0249 qWarning("Unable to load Words plugin, aborting!"); 0250 return; 0251 } 0252 0253 // QT5TODO: ownership of d->part unclear 0254 d->part = entry.createKoPart(); 0255 KoDocument* document = d->part->document(); 0256 document->setAutoSave(0); 0257 document->setCheckAutoSaveFile(false); 0258 0259 QUrl url(uri); 0260 if (url.scheme() == "newfile") { 0261 KWDocument* doc = qobject_cast<KWDocument*>(document); 0262 doc->initEmpty(); 0263 KWPageStyle style = doc->pageManager()->defaultPageStyle(); 0264 Q_ASSERT(style.isValid()); 0265 0266 KoColumns columns; 0267 columns.count = url.queryItemValue("columncount").toInt(); 0268 columns.gapWidth = url.queryItemValue("columngap").toDouble(); 0269 style.setColumns(columns); 0270 0271 KoPageLayout layout = style.pageLayout(); 0272 layout.format = KoPageFormat::formatFromString(url.queryItemValue("pageformat")); 0273 layout.orientation = (KoPageFormat::Orientation)url.queryItemValue("pageorientation").toInt(); 0274 layout.height = MM_TO_POINT(url.queryItemValue("height").toDouble()); 0275 layout.width = MM_TO_POINT(url.queryItemValue("width").toDouble()); 0276 if (url.queryItemValue("facingpages").toInt() == 1) { 0277 layout.bindingSide = MM_TO_POINT(url.queryItemValue("leftmargin").toDouble()); 0278 layout.pageEdge = MM_TO_POINT(url.queryItemValue("rightmargin").toDouble()); 0279 layout.leftMargin = layout.rightMargin = -1; 0280 } 0281 else { 0282 layout.bindingSide = layout.pageEdge = -1; 0283 layout.leftMargin = MM_TO_POINT(url.queryItemValue("leftmargin").toDouble()); 0284 layout.rightMargin = MM_TO_POINT(url.queryItemValue("rightmargin").toDouble()); 0285 } 0286 layout.topMargin = MM_TO_POINT(url.queryItemValue("topmargin").toDouble()); 0287 layout.bottomMargin = MM_TO_POINT(url.queryItemValue("bottommargin").toDouble()); 0288 style.setPageLayout(layout); 0289 0290 doc->setUnit(KoUnit::fromSymbol(url.queryItemValue("unit"))); 0291 doc->relayout(); 0292 } else if (url.scheme() == "template") { 0293 qApp->setOverrideCursor(Qt::BusyCursor); 0294 // Nip away the manually added template:// bit of the uri passed from the caller 0295 bool ok = document->loadNativeFormat(uri.mid(11)); 0296 document->setModified(false); 0297 document->undoStack()->clear(); 0298 0299 if (ok) { 0300 QString mimeType = QMimeDatabase().mimeTypeForUrl(url).name(); 0301 // in case this is a open document template remove the -template from the end 0302 mimeType.remove( QRegExp( "-template$" ) ); 0303 document->setMimeTypeAfterLoading(mimeType); 0304 document->resetURL(); 0305 document->setEmpty(); 0306 } else { 0307 document->showLoadingErrorDialog(); 0308 document->initEmpty(); 0309 } 0310 qApp->restoreOverrideCursor(); 0311 } else { 0312 document->openUrl(url); 0313 } 0314 0315 document->setModified(false); 0316 qApp->processEvents(); 0317 0318 d->canvas = dynamic_cast<KWCanvasItem*> (d->part->canvasItem(d->part->document())); 0319 createAndSetCanvasControllerOn(d->canvas); 0320 createAndSetZoomController(d->canvas); 0321 updateZoomControllerAccordingToDocument(document); 0322 0323 d->canvas->resourceManager()->setResource(KoDocumentResourceManager::HandleRadius, 9); 0324 d->canvas->resourceManager()->setResource(KoDocumentResourceManager::GrabSensitivity, 9); 0325 0326 QGraphicsWidget *graphicsWidget = dynamic_cast<QGraphicsWidget*>(d->canvas); 0327 graphicsWidget->setParentItem(this); 0328 graphicsWidget->installEventFilter(this); 0329 graphicsWidget->setVisible(true); 0330 graphicsWidget->setGeometry(x(), y(), width(), height()); 0331 0332 if (d->pageNumber >= 1) { 0333 gotoPage(d->pageNumber, document); 0334 } 0335 0336 QList<QTextDocument*> texts; 0337 KoFindText::findTextInShapes(d->canvas->shapeManager()->shapes(), texts); 0338 d->findText->setDocuments(texts); 0339 0340 d->document = qobject_cast<KWDocument*>(document); 0341 d->documentModel = new CQTextDocumentModel(this, d->document, d->canvas->shapeManager()); 0342 emit documentModelChanged(); 0343 emit thumbnailSizeChanged(); 0344 connect(d->documentModel, SIGNAL(thumbnailSizeChanged()), SIGNAL(thumbnailSizeChanged())); 0345 0346 d->updateLinkTargets(); 0347 emit linkTargetsChanged(); 0348 0349 connect(d->canvas->shapeManager(), SIGNAL(selectionChanged()), SIGNAL(textEditorChanged())); 0350 connect(d->canvas->shapeManager(), SIGNAL(selectionChanged()), SIGNAL(shapeTransparencyChanged())); 0351 0352 d->notes = new CQTextDocumentNotesModel(this); 0353 emit notesChanged(); 0354 0355 emit textEditorChanged(); 0356 emit loadingFinished(); 0357 } 0358 0359 void CQTextDocumentCanvas::gotoPage(int pageNumber, KoDocument *document) 0360 { 0361 const KWDocument *kwDoc = static_cast<const KWDocument*>(document); 0362 KWPage currentTextDocPage = kwDoc->pageManager()->page(pageNumber); 0363 0364 QRectF rect = d->canvas->viewConverter()->documentToView(currentTextDocPage.rect()); 0365 canvasController()->pan(rect.topLeft().toPoint() - d->canvas->viewConverter()->documentToView(canvasController()->documentOffset()).toPoint()); 0366 alignTopWith(rect.top()); 0367 updateCanvas(); 0368 } 0369 0370 int CQTextDocumentCanvas::cameraY() const 0371 { 0372 return d->currentPoint.y(); 0373 } 0374 0375 qreal CQTextDocumentCanvas::pagePosition(int pageIndex) 0376 { 0377 KWPage page = d->document->pageManager()->page(pageIndex); 0378 // a very silly heuristic for ensuring the page number changes if we change pages. 0379 // this means we don't have to glue the canvas and controlleritem together too close, 0380 // but yes, it does look a bit silly. 0381 QTimer::singleShot(0, d->throttleTimer, SLOT(stop())); 0382 QTimer::singleShot(0, this, SIGNAL(currentPageNumberChanged())); 0383 return d->canvas->viewMode()->documentToView(page.rect().topLeft(), d->canvas->viewConverter()).y(); 0384 } 0385 0386 qreal CQTextDocumentCanvas::shapeTransparency() const 0387 { 0388 if (d->canvas && d->canvas->shapeManager()) { 0389 KoShape* shape = d->canvas->shapeManager()->selection()->firstSelectedShape(); 0390 if (shape) { 0391 return shape->transparency(); 0392 } 0393 } 0394 return CQCanvasBase::shapeTransparency(); 0395 } 0396 0397 void CQTextDocumentCanvas::setShapeTransparency(qreal newTransparency) 0398 { 0399 if (d->canvas && d->canvas->shapeManager()) { 0400 KoShape* shape = d->canvas->shapeManager()->selection()->firstSelectedShape(); 0401 if (shape) { 0402 if (!qFuzzyCompare(1 + shape->transparency(), 1 + newTransparency)) { 0403 shape->setTransparency(newTransparency); 0404 CQCanvasBase::setShapeTransparency(newTransparency); 0405 } 0406 } 0407 } 0408 } 0409 0410 QObject* CQTextDocumentCanvas::textEditor() 0411 { 0412 if (d->canvas) { 0413 if (d->textEditor) { 0414 disconnect(d->textEditor, SIGNAL(cursorPositionChanged()), this, SIGNAL(selectionChanged())); 0415 } 0416 d->textEditor = KoTextEditor::getTextEditorFromCanvas(d->canvas); 0417 if (d->textEditor) { 0418 disconnect(d->textEditor, SIGNAL(cursorPositionChanged()), this, SIGNAL(selectionChanged())); 0419 } 0420 emit selectionChanged(); 0421 return d->textEditor; 0422 } 0423 return 0; 0424 } 0425 0426 bool CQTextDocumentCanvas::hasSelection() const 0427 { 0428 if (d->textEditor) { 0429 return d->textEditor->hasSelection(); 0430 } 0431 return false; 0432 } 0433 0434 QRectF CQTextDocumentCanvas::selectionStartPos() const 0435 { 0436 if (d->textEditor) { 0437 return d->getCursorPosition(d->textEditor->selectionStart()); 0438 } 0439 return QRectF(0,0,0,0); 0440 } 0441 0442 QRectF CQTextDocumentCanvas::selectionEndPos() const 0443 { 0444 if (d->textEditor) { 0445 return d->getCursorPosition(d->textEditor->selectionEnd()); 0446 } 0447 return QRectF(0,0,0,0); 0448 } 0449 0450 QObject* CQTextDocumentCanvas::zoomAction() const 0451 { 0452 if (zoomController() && zoomController()->zoomAction()) { 0453 return zoomController()->zoomAction(); 0454 } 0455 return 0; 0456 } 0457 0458 QSizeF CQTextDocumentCanvas::thumbnailSize() const 0459 { 0460 if (d->documentModel) { 0461 return d->documentModel->thumbnailSize(); 0462 } 0463 return QSizeF(); 0464 } 0465 0466 void CQTextDocumentCanvas::setThumbnailSize(const QSizeF& newSize) 0467 { 0468 if (d->documentModel) { 0469 d->documentModel->setThumbnailSize(newSize.toSize()); 0470 } 0471 emit thumbnailSizeChanged(); 0472 } 0473 0474 void CQTextDocumentCanvas::deselectEverything() 0475 { 0476 KoTextEditor* editor = KoTextEditor::getTextEditorFromCanvas(d->canvas); 0477 if (editor) { 0478 editor->clearSelection(); 0479 } 0480 d->canvas->shapeManager()->selection()->deselectAll(); 0481 updateCanvas(); 0482 } 0483 0484 QObject* CQTextDocumentCanvas::notes() const 0485 { 0486 return d->notes; 0487 } 0488 0489 void CQTextDocumentCanvas::addSticker(const QString& imageUrl) 0490 { 0491 QSvgRenderer renderer(QUrl(imageUrl).toLocalFile()); 0492 // Prepare a QImage with desired characteristics 0493 QImage image(200, 200, QImage::Format_ARGB32); 0494 image.fill(Qt::transparent); 0495 0496 // Get QPainter that paints to the image 0497 QPainter painter(&image); 0498 renderer.render(&painter); 0499 painter.end(); 0500 0501 KoProperties* params = new KoProperties(); 0502 params->setProperty("qimage", image); 0503 KoShapeFactoryBase* factory = KoShapeRegistry::instance()->get("PictureShape"); 0504 if (factory) { 0505 KoShape* shape = factory->createShape(params, d->document->resourceManager()); 0506 0507 QPointF pos = d->canvas->viewToDocument(d->canvas->documentOffset() + QPointF(d->canvas->size().width() / 2, d->canvas->size().height() / 2)); 0508 KoShapeAnchor *anchor = new KoShapeAnchor(shape); 0509 anchor->setAnchorType(KoShapeAnchor::AnchorPage); 0510 anchor->setHorizontalPos(KoShapeAnchor::HFromLeft); 0511 anchor->setVerticalPos(KoShapeAnchor::VFromTop); 0512 anchor->setHorizontalRel(KoShapeAnchor::HPage); 0513 anchor->setVerticalRel(KoShapeAnchor::VPage); 0514 shape->setAnchor(anchor); 0515 shape->setPosition(pos); 0516 shape->scale(0.2, 0.2); 0517 0518 // KWShapeCreateCommand *cmd = new KWShapeCreateCommand(d->document, shape); 0519 KoSelection *selection = d->canvas->shapeManager()->selection(); 0520 selection->deselectAll(); 0521 selection->select(shape); 0522 // d->canvas->addCommand(cmd); 0523 d->canvas->shapeManager()->addShape(shape); 0524 0525 d->notes->addEntry("", imageUrl, "Neutral", shape); 0526 } 0527 } 0528 0529 void CQTextDocumentCanvas::addNote(const QString& text, const QString& color, const QString& imageUrl) 0530 { 0531 QSvgRenderer renderer(QUrl(imageUrl).toLocalFile()); 0532 0533 // Prepare a QImage with desired characteritisc 0534 QImage image(400, 200, QImage::Format_ARGB32); 0535 image.fill(Qt::transparent); 0536 0537 // Get QPainter that paints to the image 0538 QPainter painter(&image); 0539 painter.setRenderHint(QPainter::Antialiasing, true); 0540 painter.setRenderHint(QPainter::SmoothPixmapTransform, true); 0541 painter.setRenderHint(QPainter::TextAntialiasing, true); 0542 0543 renderer.render(&painter, image.rect()); 0544 0545 QFont font; 0546 font.setFamily("Permanent Marker"); 0547 font.setStyle(QFont::StyleNormal); 0548 font.setPixelSize(40); 0549 painter.setPen(QPen(QColor(color), 0)); 0550 painter.setFont(font); 0551 painter.drawText(image.rect().adjusted(10, 10, -20, -20), Qt::AlignCenter | Qt::TextWordWrap, text); 0552 painter.end(); 0553 0554 KoProperties* params = new KoProperties(); 0555 params->setProperty("qimage", image); 0556 KoShapeFactoryBase* factory = KoShapeRegistry::instance()->get("PictureShape"); 0557 if (factory) { 0558 KoShape* shape = factory->createShape(params, d->document->resourceManager()); 0559 0560 QPointF pos = d->canvas->viewToDocument(d->canvas->documentOffset() + QPointF(d->canvas->size().width() / 2, d->canvas->size().height() / 2)); 0561 KoShapeAnchor *anchor = new KoShapeAnchor(shape); 0562 anchor->setAnchorType(KoShapeAnchor::AnchorPage); 0563 anchor->setHorizontalPos(KoShapeAnchor::HFromLeft); 0564 anchor->setVerticalPos(KoShapeAnchor::VFromTop); 0565 anchor->setHorizontalRel(KoShapeAnchor::HPage); 0566 anchor->setVerticalRel(KoShapeAnchor::VPage); 0567 shape->setAnchor(anchor); 0568 shape->setPosition(pos); 0569 shape->rotate(-15); 0570 shape->scale(0.3, 0.3); 0571 0572 // KWShapeCreateCommand *cmd = new KWShapeCreateCommand(d->document, shape); 0573 KoSelection *selection = d->canvas->shapeManager()->selection(); 0574 selection->deselectAll(); 0575 selection->select(shape); 0576 // d->canvas->addCommand(cmd); 0577 d->canvas->shapeManager()->addShape(shape); 0578 0579 d->notes->addEntry(text, "", color, shape); 0580 } 0581 } 0582 0583 void CQTextDocumentCanvas::setCameraY(int cameraY) 0584 { 0585 d->currentPoint.setY (cameraY); 0586 emit cameraYChanged(); 0587 } 0588 0589 void CQTextDocumentCanvas::alignTopWith(int y) 0590 { 0591 d->currentPoint.setY(y); 0592 emit cameraYChanged(); 0593 } 0594 0595 int CQTextDocumentCanvas::currentPageNumber() const 0596 { 0597 if (d->document && !d->throttleTimer->isActive()) { 0598 // Can't use this at the moment, we sort of don't have the right one, because derp :P 0599 //d->canvas->resourceManager()->resource(KoCanvasResourceManager::CurrentPage).toInt(); 0600 d->throttleTimer->start(); 0601 const KWDocument *kwDoc = static_cast<const KWDocument*>(d->document); 0602 d->pageNumber = kwDoc->pageManager()->page(d->canvas->viewMode()->viewToDocument(d->canvas->documentOffset(), d->canvas->viewConverter())).pageNumber(); 0603 } 0604 return d->pageNumber; 0605 } 0606 0607 void CQTextDocumentCanvas::setCurrentPageNumber(const int& currentPageNumber) 0608 { 0609 if (d->pageNumber != currentPageNumber) { 0610 gotoPage(currentPageNumber, d->document); 0611 } 0612 } 0613 0614 void CQTextDocumentCanvas::render(QPainter* painter, const QRectF& target) 0615 { 0616 Q_UNUSED(target) 0617 QStyleOptionGraphicsItem option; 0618 option.exposedRect = QRect(0, 0, width(), height()); 0619 option.rect = option.exposedRect.toAlignedRect(); 0620 d->canvas->canvasItem()->paint(painter, &option); 0621 } 0622 0623 bool CQTextDocumentCanvas::event( QEvent* event ) 0624 { 0625 switch(static_cast<int>(event->type())) { 0626 case ViewModeSwitchEvent::AboutToSwitchViewModeEvent: { 0627 ViewModeSynchronisationObject* syncObject = static_cast<ViewModeSwitchEvent*>(event)->synchronisationObject(); 0628 0629 if (d->canvas) { 0630 syncObject->documentOffset = d->canvas->documentOffset(); 0631 syncObject->zoomLevel = zoomController()->zoomAction()->effectiveZoom(); 0632 syncObject->activeToolId = KoToolManager::instance()->activeToolId(); 0633 syncObject->shapes = d->canvas->shapeManager()->shapes(); 0634 syncObject->initialized = true; 0635 } 0636 0637 return true; 0638 } 0639 case ViewModeSwitchEvent::SwitchedToTouchModeEvent: { 0640 ViewModeSynchronisationObject* syncObject = static_cast<ViewModeSwitchEvent*>(event)->synchronisationObject(); 0641 0642 if (d->canvas && syncObject->initialized) { 0643 d->canvas->shapeManager()->setShapes(syncObject->shapes); 0644 0645 KoToolManager::instance()->switchToolRequested("PageToolFactory_ID"); 0646 qApp->processEvents(); 0647 0648 zoomController()->setZoom(KoZoomMode::ZOOM_CONSTANT, syncObject->zoomLevel); 0649 0650 qApp->processEvents(); 0651 emit positionShouldChange(syncObject->documentOffset); 0652 } 0653 0654 return true; 0655 } 0656 // case KisTabletEvent::TabletPressEx: 0657 // case KisTabletEvent::TabletReleaseEx: 0658 // emit interactionStarted(); 0659 // d->canvas->inputManager()->eventFilter(this, event); 0660 // return true; 0661 // case KisTabletEvent::TabletMoveEx: 0662 // d->tabletEventCount++; //Note that this will wraparound at some point; This is intentional. 0663 // #ifdef Q_OS_X11 0664 // if (d->tabletEventCount % 2 == 0) 0665 // #endif 0666 // d->canvas->inputManager()->eventFilter(this, event); 0667 // return true; 0668 default: 0669 break; 0670 } 0671 return QDeclarativeItem::event( event ); 0672 } 0673 0674 void CQTextDocumentCanvas::currentToolChanged(KoCanvasController* controller, int uniqueToolId) 0675 { 0676 Q_UNUSED(controller) 0677 Q_UNUSED(uniqueToolId) 0678 d->currentTool = qobject_cast<KoToolBase*>(KoToolManager::instance()->toolById(d->canvas, KoToolManager::instance()->activeToolId())); 0679 } 0680 0681 void CQTextDocumentCanvas::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* e) 0682 { 0683 QMouseEvent me(e->type(), e->pos().toPoint(), e->button(), e->buttons(), e->modifiers()); 0684 KoPointerEvent pe(&me, d->canvas->viewToDocument(e->pos() + d->canvas->documentOffset())); 0685 d->currentTool->mouseDoubleClickEvent(&pe); 0686 updateCanvas(); 0687 emit selectionChanged(); 0688 e->setAccepted(me.isAccepted()); 0689 } 0690 0691 void CQTextDocumentCanvas::mouseMoveEvent(QGraphicsSceneMouseEvent* e) 0692 { 0693 QMouseEvent me(e->type(), e->pos().toPoint(), e->button(), e->buttons(), e->modifiers()); 0694 KoPointerEvent pe(&me, d->canvas->viewToDocument(e->pos() + d->canvas->documentOffset())); 0695 d->currentTool->mouseMoveEvent(&pe); 0696 updateCanvas(); 0697 emit selectionChanged(); 0698 e->setAccepted(me.isAccepted()); 0699 } 0700 0701 void CQTextDocumentCanvas::mousePressEvent(QGraphicsSceneMouseEvent* e) 0702 { 0703 QMouseEvent me(e->type(), e->pos().toPoint(), e->button(), e->buttons(), e->modifiers()); 0704 KoPointerEvent pe(&me, d->canvas->viewToDocument(e->pos() + d->canvas->documentOffset())); 0705 d->currentTool->mousePressEvent(&pe); 0706 updateCanvas(); 0707 emit selectionChanged(); 0708 e->setAccepted(me.isAccepted()); 0709 } 0710 0711 void CQTextDocumentCanvas::mouseReleaseEvent(QGraphicsSceneMouseEvent* e) 0712 { 0713 QMouseEvent me(e->type(), e->pos().toPoint(), e->button(), e->buttons(), e->modifiers()); 0714 KoPointerEvent pe(&me, d->canvas->viewToDocument(e->pos() + d->canvas->documentOffset())); 0715 d->currentTool->mouseReleaseEvent(&pe); 0716 updateCanvas(); 0717 emit selectionChanged(); 0718 e->setAccepted(me.isAccepted()); 0719 } 0720 0721 void CQTextDocumentCanvas::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) 0722 { 0723 if (d->canvas) { 0724 QGraphicsWidget *widget = dynamic_cast<QGraphicsWidget*>(d->canvas); 0725 if (widget) { 0726 widget->setGeometry(newGeometry); 0727 } 0728 } 0729 QDeclarativeItem::geometryChanged(newGeometry, oldGeometry); 0730 } 0731 0732 void CQTextDocumentCanvas::createAndSetCanvasControllerOn(KoCanvasBase* canvas) 0733 { 0734 //TODO: pass a proper action collection 0735 CQCanvasController *controller = new CQCanvasController(new KActionCollection(this)); 0736 setCanvasController(controller); 0737 connect (controller, SIGNAL(documentSizeChanged(QSize)), SLOT(updateDocumentSize(QSize))); 0738 controller->setCanvas(canvas); 0739 KoToolManager::instance()->addController (controller); 0740 } 0741 0742 void CQTextDocumentCanvas::createAndSetZoomController(KoCanvasBase* canvas) 0743 { 0744 KoZoomHandler* zoomHandler = static_cast<KoZoomHandler*> (canvas->viewConverter()); 0745 setZoomController(new KoZoomController(canvasController(), zoomHandler, new KActionCollection(this))); 0746 0747 KWCanvasItem *kwCanvasItem = static_cast<KWCanvasItem*>(canvas); 0748 connect (kwCanvasItem, SIGNAL(documentSize(QSizeF)), zoomController(), SLOT(setDocumentSize(QSizeF))); 0749 connect (canvasController()->proxyObject, SIGNAL(moveDocumentOffset(QPoint)), SIGNAL(currentPageNumberChanged())); 0750 connect (canvasController()->proxyObject, SIGNAL(moveDocumentOffset(QPoint)), kwCanvasItem, SLOT(setDocumentOffset(QPoint))); 0751 connect (zoomController(), SIGNAL(zoomChanged(KoZoomMode::Mode,qreal)), SIGNAL(zoomActionChanged())); 0752 kwCanvasItem->updateSize(); 0753 emit zoomActionChanged(); 0754 } 0755 0756 void CQTextDocumentCanvas::updateZoomControllerAccordingToDocument(const KoDocument* document) 0757 { 0758 const KWDocument *kwDoc = static_cast<const KWDocument*>(document); 0759 zoomController()->setPageSize (kwDoc->pageManager()->begin().rect().size()); 0760 } 0761 0762 QString CQTextDocumentCanvas::searchTerm() const 0763 { 0764 return d->searchTerm; 0765 } 0766 0767 void CQTextDocumentCanvas::setSearchTerm(const QString& term) 0768 { 0769 d->searchTerm = term; 0770 if (!term.isEmpty()) { 0771 d->findText->find(term); 0772 } 0773 emit searchTermChanged(); 0774 } 0775 0776 void CQTextDocumentCanvas::findMatchFound(const KoFindMatch &match) 0777 { 0778 QTextCursor cursor = match.location().value<QTextCursor>(); 0779 d->canvas->canvasItem()->update(); 0780 0781 d->canvas->resourceManager()->setResource (KoText::CurrentTextAnchor, cursor.anchor()); 0782 d->canvas->resourceManager()->setResource (KoText::CurrentTextPosition, cursor.position()); 0783 } 0784 0785 void CQTextDocumentCanvas::findNoMatchFound() 0786 { 0787 qDebug() << "Match for " << d->searchTerm << " not found"; 0788 } 0789 0790 void CQTextDocumentCanvas::updateCanvas() 0791 { 0792 KWCanvasItem* kwCanvasItem = dynamic_cast<KWCanvasItem*> (d->canvas); 0793 kwCanvasItem->update(); 0794 } 0795 0796 void CQTextDocumentCanvas::findNext() 0797 { 0798 d->findText->findNext(); 0799 } 0800 0801 void CQTextDocumentCanvas::findPrevious() 0802 { 0803 d->findText->findPrevious(); 0804 } 0805 0806 QObject* CQTextDocumentCanvas::documentModel() const 0807 { 0808 return d->documentModel; 0809 } 0810 0811 KWDocument* CQTextDocumentCanvas::document() const 0812 { 0813 return d->document; 0814 } 0815 0816 QObject* CQTextDocumentCanvas::doc() const 0817 { 0818 return d->document; 0819 } 0820 0821 QObject* CQTextDocumentCanvas::part() const 0822 { 0823 return d->part; 0824 } 0825 0826 QObjectList CQTextDocumentCanvas::linkTargets() const 0827 { 0828 return d->linkTargets; 0829 } 0830 0831 QSize CQTextDocumentCanvas::documentSize() const 0832 { 0833 return d->documentSize; 0834 } 0835 0836 void CQTextDocumentCanvas::updateDocumentSize(const QSize& size) 0837 { 0838 d->documentSize = size; 0839 emit documentSizeChanged(); 0840 }