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