1 /*
2 * This file is part of the KDE project
3 *
4 * Copyright (C) 2013 Shantanu Tushar <shantanu@kde.org>
5 * Copyright (C) 2013 Sujith Haridasan <sujith.h@gmail.com>
6 * Copyright (C) 2013 Arjen Hiemstra <ahiemstra@heimr.nl>
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25 #include "CQTextDocumentCanvas.h"
26 #include "CQCanvasController.h"
27 #include "CQTextDocumentModel.h"
28 #include "CQTextDocumentNotesModel.h"
29
30 #include "gemini/ViewModeSwitchEvent.h"
31
32 #include <KoPluginLoader.h>
33 #include <KoDocumentEntry.h>
34 #include <KoUnit.h>
35 #include <KoDocument.h>
36 #include <KoDocumentResourceManager.h>
37 #include <KoPart.h>
38 #include <KoFindText.h>
39 #include <KoCanvasBase.h>
40 #include <KoToolManager.h>
41 #include <KoZoomHandler.h>
42 #include <KoZoomController.h>
43 #include <KoShape.h>
44 #include <KoToolManager_p.h>
45 #include <KoToolBase.h>
46 #include <KoPointerEvent.h>
47 #include <KoSelection.h>
48 #include <KoShapeRegistry.h>
49 #include <KoShapeAnchor.h>
50 #include <KoShapeContainer.h>
51 #include <KoTextEditor.h>
52 #include <KoProperties.h>
53 #include <KoColumns.h>
54 #include <KWDocument.h>
55 #include <KWPage.h>
56 #include <KWCanvasItem.h>
57 #include <commands/KWShapeCreateCommand.h>
58
59 #include <KActionCollection>
60
61 #include <QPluginLoader>
62 #include <QMimeDatabase>
63 #include <QStyleOptionGraphicsItem>
64 #include <QGraphicsWidget>
65 #include <QTextDocument>
66 #include <QTextFrame>
67 #include <QTextLayout>
68 #include <QGraphicsSceneMouseEvent>
69 #include <QTextDocumentFragment>
70 #include <QSvgRenderer>
71 #include <QApplication>
72 #include <QDebug>
73
74 class CQTextDocumentCanvas::Private
75 {
76 public:
Private()77 Private()
78 : canvas(0),
79 findText(0),
80 documentModel(0),
81 document(0),
82 pageNumber(0),
83 throttleTimer(new QTimer()),
84 currentTool(0),
85 notes(0),
86 textEditor(0)
87 {
88 throttleTimer->setInterval(200);
89 throttleTimer->setSingleShot(true);
90 }
91
92 KWCanvasItem *canvas;
93 QString searchTerm;
94 KoFindText *findText;
95 CQTextDocumentModel *documentModel;
96 KWDocument* document;
97 KoPart* part;
98 QSize documentSize;
99 int pageNumber;
100 QPoint currentPoint;
101 QObjectList linkTargets;
102 QTimer* throttleTimer;
103 KoToolBase* currentTool;
104 CQTextDocumentNotesModel* notes;
105 KoTextEditor* textEditor;
106
updateLinkTargets()107 void updateLinkTargets()
108 {
109 qDeleteAll(linkTargets);
110 linkTargets.clear();
111
112 if (!canvas) {
113 return;
114 }
115
116 foreach(const KoShape* shape, canvas->shapeManager()->shapes()) {
117 if (!shape->hyperLink().isEmpty()) {
118 QObject * obj = new QObject(documentModel);
119 obj->setProperty("linkRect", shape->boundingRect());
120 obj->setProperty("linkTarget", QUrl(shape->hyperLink()));
121 linkTargets.append(obj);
122 }
123 }
124
125 foreach(QTextDocument* text, findText->documents()) {
126 QTextBlock block = text->rootFrame()->firstCursorPosition().block();
127 for (; block.isValid(); block = block.next()) {
128 block.begin();
129 QTextBlock::iterator it;
130 for (it = block.begin(); !(it.atEnd()); ++it) {
131 QTextFragment fragment = it.fragment();
132 if (fragment.isValid()) {
133 QTextCharFormat format = fragment.charFormat();
134 if (format.isAnchor()) {
135 // This is an anchor, store target and position...
136 QObject * obj = new QObject(documentModel);
137 QRectF rect = getFragmentPosition(block, fragment);
138 KWPage page = document->pageManager()->page(rect.left());
139 rect.translate(page.topMargin(), page.rightMargin());
140 rect = canvas->viewMode()->documentToView(rect, canvas->viewConverter());
141 rect.translate(page.pageNumber() * (page.topMargin() + page.bottomMargin()) + 20, 0);
142 obj->setProperty("linkRect", rect);
143 obj->setProperty("linkTarget", QUrl(format.anchorHref()));
144 linkTargets.append(obj);
145 }
146 }
147 }
148 }
149 }
150 }
151
getFragmentPosition(QTextBlock block,QTextFragment fragment)152 QRectF getFragmentPosition(QTextBlock block, QTextFragment fragment)
153 {
154 // TODO this only produces a position for the first part, if the link spans more than one line...
155 // Need to sort that somehow, unfortunately probably by slapping this code into the above function.
156 // For now leave it like this, more important things are needed.
157 QTextLayout* layout = block.layout();
158 QTextLine line = layout->lineForTextPosition(fragment.position() - block.position());
159 if (!line.isValid()) {
160 // fragment has no valid position and consequently no line...
161 return QRectF();
162 }
163 qreal top = line.position().y();
164 qreal bottom = line.position().y() + line.height();
165 qreal left = line.cursorToX(fragment.position() - block.position());
166 qreal right = line.cursorToX((fragment.position() - block.position()) + fragment.length());
167 QRectF fragmentPosition(QPointF(top, left), QPointF(bottom, right));
168 return fragmentPosition.adjusted(layout->position().x(), layout->position().y(), 0, 0);
169 }
170
deepShapeFind(const QList<KoShape * > & shapes)171 QList<KoShape*> deepShapeFind(const QList<KoShape*>& shapes)
172 {
173 QList<KoShape*> allShapes;
174 foreach(KoShape* shape, shapes) {
175 allShapes.append(shape);
176 KoShapeContainer *container = dynamic_cast<KoShapeContainer*>(shape);
177 if (container) {
178 allShapes.append(deepShapeFind(container->shapes()));
179 }
180 }
181 return allShapes;
182 }
getCursorPosition(int position)183 QRectF getCursorPosition(int position)
184 {
185 QPointF point;
186 QTextBlock block = textEditor->document()->findBlock(position);
187 QTextLayout* layout = block.layout();
188 QTextLine line = layout->lineForTextPosition(position - block.position());
189 if (!line.isValid()) {
190 // fragment has no valid position and consequently no line...
191 return QRectF();
192 }
193 qreal top = line.position().y();
194 qreal left = line.cursorToX(position - block.position());
195 point = QPointF(left + layout->position().y(), top + layout->position().x());
196
197 KoShape* shape = canvas->shapeManager()->selection()->firstSelectedShape();
198 point += shape->position();
199 while(KoShapeContainer* parent = shape->parent()) {
200 point += parent->position();
201 }
202
203 KWPage page = document->pageManager()->page(point.y());
204 // point += QPointF(page.rightMargin(), page.pageNumber() * page.topMargin()
205 // + (page.pageNumber() - 1) * page.bottomMargin());
206 // if (page.pageNumber() > 1)
207 // point += QPointF(0, 20);
208 point += QPointF(0, (page.pageNumber() - 1) * (page.topMargin() + 20));
209 // point = canvas->viewConverter()->documentToView(point);
210
211 return canvas->viewConverter()->documentToView(QRectF(point, QSizeF(0, line.height())));
212 }
213 };
214
CQTextDocumentCanvas(QDeclarativeItem * parent)215 CQTextDocumentCanvas::CQTextDocumentCanvas(QDeclarativeItem* parent)
216 : CQCanvasBase(parent), d(new Private)
217 {
218 setAcceptedMouseButtons(Qt::LeftButton);
219 d->findText = new KoFindText(this);
220
221 connect (d->findText, SIGNAL(updateCanvas()), SLOT(updateCanvas()));
222 connect (d->findText, SIGNAL(matchFound(KoFindMatch)), SLOT(findMatchFound(KoFindMatch)));
223 connect (d->findText, SIGNAL(noMatchFound()), SLOT(findNoMatchFound()));
224 connect (KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*,int)), SLOT(currentToolChanged(KoCanvasController*,int)));
225 }
226
~CQTextDocumentCanvas()227 CQTextDocumentCanvas::~CQTextDocumentCanvas()
228 {
229 d->part->removeMainWindow(d->part->currentMainwindow());
230 KoToolManager::instance()->removeCanvasController(d->canvas->canvasController());
231 delete d;
232 }
233
openFile(const QString & uri)234 void CQTextDocumentCanvas::openFile(const QString& uri)
235 {
236 emit loadingBegun();
237
238 KoDocumentEntry entry;
239 QList<QPluginLoader*> pluginLoaders = KoPluginLoader::pluginLoaders("calligra/parts");
240 Q_FOREACH (QPluginLoader *loader, pluginLoaders) {
241 if (loader->fileName().contains(QLatin1String("wordspart"))) {
242 entry = KoDocumentEntry(loader);
243 pluginLoaders.removeOne(loader);
244 break;
245 }
246 }
247 qDeleteAll(pluginLoaders);
248 if (entry.isEmpty()) {
249 qWarning("Unable to load Words plugin, aborting!");
250 return;
251 }
252
253 // QT5TODO: ownership of d->part unclear
254 d->part = entry.createKoPart();
255 KoDocument* document = d->part->document();
256 document->setAutoSave(0);
257 document->setCheckAutoSaveFile(false);
258
259 QUrl url(uri);
260 if (url.scheme() == "newfile") {
261 KWDocument* doc = qobject_cast<KWDocument*>(document);
262 doc->initEmpty();
263 KWPageStyle style = doc->pageManager()->defaultPageStyle();
264 Q_ASSERT(style.isValid());
265
266 KoColumns columns;
267 columns.count = url.queryItemValue("columncount").toInt();
268 columns.gapWidth = url.queryItemValue("columngap").toDouble();
269 style.setColumns(columns);
270
271 KoPageLayout layout = style.pageLayout();
272 layout.format = KoPageFormat::formatFromString(url.queryItemValue("pageformat"));
273 layout.orientation = (KoPageFormat::Orientation)url.queryItemValue("pageorientation").toInt();
274 layout.height = MM_TO_POINT(url.queryItemValue("height").toDouble());
275 layout.width = MM_TO_POINT(url.queryItemValue("width").toDouble());
276 if (url.queryItemValue("facingpages").toInt() == 1) {
277 layout.bindingSide = MM_TO_POINT(url.queryItemValue("leftmargin").toDouble());
278 layout.pageEdge = MM_TO_POINT(url.queryItemValue("rightmargin").toDouble());
279 layout.leftMargin = layout.rightMargin = -1;
280 }
281 else {
282 layout.bindingSide = layout.pageEdge = -1;
283 layout.leftMargin = MM_TO_POINT(url.queryItemValue("leftmargin").toDouble());
284 layout.rightMargin = MM_TO_POINT(url.queryItemValue("rightmargin").toDouble());
285 }
286 layout.topMargin = MM_TO_POINT(url.queryItemValue("topmargin").toDouble());
287 layout.bottomMargin = MM_TO_POINT(url.queryItemValue("bottommargin").toDouble());
288 style.setPageLayout(layout);
289
290 doc->setUnit(KoUnit::fromSymbol(url.queryItemValue("unit")));
291 doc->relayout();
292 } else if (url.scheme() == "template") {
293 qApp->setOverrideCursor(Qt::BusyCursor);
294 // Nip away the manually added template:// bit of the uri passed from the caller
295 bool ok = document->loadNativeFormat(uri.mid(11));
296 document->setModified(false);
297 document->undoStack()->clear();
298
299 if (ok) {
300 QString mimeType = QMimeDatabase().mimeTypeForUrl(url).name();
301 // in case this is a open document template remove the -template from the end
302 mimeType.remove( QRegExp( "-template$" ) );
303 document->setMimeTypeAfterLoading(mimeType);
304 document->resetURL();
305 document->setEmpty();
306 } else {
307 document->showLoadingErrorDialog();
308 document->initEmpty();
309 }
310 qApp->restoreOverrideCursor();
311 } else {
312 document->openUrl(url);
313 }
314
315 document->setModified(false);
316 qApp->processEvents();
317
318 d->canvas = dynamic_cast<KWCanvasItem*> (d->part->canvasItem(d->part->document()));
319 createAndSetCanvasControllerOn(d->canvas);
320 createAndSetZoomController(d->canvas);
321 updateZoomControllerAccordingToDocument(document);
322
323 d->canvas->resourceManager()->setResource(KoDocumentResourceManager::HandleRadius, 9);
324 d->canvas->resourceManager()->setResource(KoDocumentResourceManager::GrabSensitivity, 9);
325
326 QGraphicsWidget *graphicsWidget = dynamic_cast<QGraphicsWidget*>(d->canvas);
327 graphicsWidget->setParentItem(this);
328 graphicsWidget->installEventFilter(this);
329 graphicsWidget->setVisible(true);
330 graphicsWidget->setGeometry(x(), y(), width(), height());
331
332 if (d->pageNumber >= 1) {
333 gotoPage(d->pageNumber, document);
334 }
335
336 QList<QTextDocument*> texts;
337 KoFindText::findTextInShapes(d->canvas->shapeManager()->shapes(), texts);
338 d->findText->setDocuments(texts);
339
340 d->document = qobject_cast<KWDocument*>(document);
341 d->documentModel = new CQTextDocumentModel(this, d->document, d->canvas->shapeManager());
342 emit documentModelChanged();
343 emit thumbnailSizeChanged();
344 connect(d->documentModel, SIGNAL(thumbnailSizeChanged()), SIGNAL(thumbnailSizeChanged()));
345
346 d->updateLinkTargets();
347 emit linkTargetsChanged();
348
349 connect(d->canvas->shapeManager(), SIGNAL(selectionChanged()), SIGNAL(textEditorChanged()));
350 connect(d->canvas->shapeManager(), SIGNAL(selectionChanged()), SIGNAL(shapeTransparencyChanged()));
351
352 d->notes = new CQTextDocumentNotesModel(this);
353 emit notesChanged();
354
355 emit textEditorChanged();
356 emit loadingFinished();
357 }
358
gotoPage(int pageNumber,KoDocument * document)359 void CQTextDocumentCanvas::gotoPage(int pageNumber, KoDocument *document)
360 {
361 const KWDocument *kwDoc = static_cast<const KWDocument*>(document);
362 KWPage currentTextDocPage = kwDoc->pageManager()->page(pageNumber);
363
364 QRectF rect = d->canvas->viewConverter()->documentToView(currentTextDocPage.rect());
365 canvasController()->pan(rect.topLeft().toPoint() - d->canvas->viewConverter()->documentToView(canvasController()->documentOffset()).toPoint());
366 alignTopWith(rect.top());
367 updateCanvas();
368 }
369
cameraY() const370 int CQTextDocumentCanvas::cameraY() const
371 {
372 return d->currentPoint.y();
373 }
374
pagePosition(int pageIndex)375 qreal CQTextDocumentCanvas::pagePosition(int pageIndex)
376 {
377 KWPage page = d->document->pageManager()->page(pageIndex);
378 // a very silly heuristic for ensuring the page number changes if we change pages.
379 // this means we don't have to glue the canvas and controlleritem together too close,
380 // but yes, it does look a bit silly.
381 QTimer::singleShot(0, d->throttleTimer, SLOT(stop()));
382 QTimer::singleShot(0, this, SIGNAL(currentPageNumberChanged()));
383 return d->canvas->viewMode()->documentToView(page.rect().topLeft(), d->canvas->viewConverter()).y();
384 }
385
shapeTransparency() const386 qreal CQTextDocumentCanvas::shapeTransparency() const
387 {
388 if (d->canvas && d->canvas->shapeManager()) {
389 KoShape* shape = d->canvas->shapeManager()->selection()->firstSelectedShape();
390 if (shape) {
391 return shape->transparency();
392 }
393 }
394 return CQCanvasBase::shapeTransparency();
395 }
396
setShapeTransparency(qreal newTransparency)397 void CQTextDocumentCanvas::setShapeTransparency(qreal newTransparency)
398 {
399 if (d->canvas && d->canvas->shapeManager()) {
400 KoShape* shape = d->canvas->shapeManager()->selection()->firstSelectedShape();
401 if (shape) {
402 if (!qFuzzyCompare(1 + shape->transparency(), 1 + newTransparency)) {
403 shape->setTransparency(newTransparency);
404 CQCanvasBase::setShapeTransparency(newTransparency);
405 }
406 }
407 }
408 }
409
textEditor()410 QObject* CQTextDocumentCanvas::textEditor()
411 {
412 if (d->canvas) {
413 if (d->textEditor) {
414 disconnect(d->textEditor, SIGNAL(cursorPositionChanged()), this, SIGNAL(selectionChanged()));
415 }
416 d->textEditor = KoTextEditor::getTextEditorFromCanvas(d->canvas);
417 if (d->textEditor) {
418 disconnect(d->textEditor, SIGNAL(cursorPositionChanged()), this, SIGNAL(selectionChanged()));
419 }
420 emit selectionChanged();
421 return d->textEditor;
422 }
423 return 0;
424 }
425
hasSelection() const426 bool CQTextDocumentCanvas::hasSelection() const
427 {
428 if (d->textEditor) {
429 return d->textEditor->hasSelection();
430 }
431 return false;
432 }
433
selectionStartPos() const434 QRectF CQTextDocumentCanvas::selectionStartPos() const
435 {
436 if (d->textEditor) {
437 return d->getCursorPosition(d->textEditor->selectionStart());
438 }
439 return QRectF(0,0,0,0);
440 }
441
selectionEndPos() const442 QRectF CQTextDocumentCanvas::selectionEndPos() const
443 {
444 if (d->textEditor) {
445 return d->getCursorPosition(d->textEditor->selectionEnd());
446 }
447 return QRectF(0,0,0,0);
448 }
449
zoomAction() const450 QObject* CQTextDocumentCanvas::zoomAction() const
451 {
452 if (zoomController() && zoomController()->zoomAction()) {
453 return zoomController()->zoomAction();
454 }
455 return 0;
456 }
457
thumbnailSize() const458 QSizeF CQTextDocumentCanvas::thumbnailSize() const
459 {
460 if (d->documentModel) {
461 return d->documentModel->thumbnailSize();
462 }
463 return QSizeF();
464 }
465
setThumbnailSize(const QSizeF & newSize)466 void CQTextDocumentCanvas::setThumbnailSize(const QSizeF& newSize)
467 {
468 if (d->documentModel) {
469 d->documentModel->setThumbnailSize(newSize.toSize());
470 }
471 emit thumbnailSizeChanged();
472 }
473
deselectEverything()474 void CQTextDocumentCanvas::deselectEverything()
475 {
476 KoTextEditor* editor = KoTextEditor::getTextEditorFromCanvas(d->canvas);
477 if (editor) {
478 editor->clearSelection();
479 }
480 d->canvas->shapeManager()->selection()->deselectAll();
481 updateCanvas();
482 }
483
notes() const484 QObject* CQTextDocumentCanvas::notes() const
485 {
486 return d->notes;
487 }
488
addSticker(const QString & imageUrl)489 void CQTextDocumentCanvas::addSticker(const QString& imageUrl)
490 {
491 QSvgRenderer renderer(QUrl(imageUrl).toLocalFile());
492 // Prepare a QImage with desired characteristics
493 QImage image(200, 200, QImage::Format_ARGB32);
494 image.fill(Qt::transparent);
495
496 // Get QPainter that paints to the image
497 QPainter painter(&image);
498 renderer.render(&painter);
499 painter.end();
500
501 KoProperties* params = new KoProperties();
502 params->setProperty("qimage", image);
503 KoShapeFactoryBase* factory = KoShapeRegistry::instance()->get("PictureShape");
504 if (factory) {
505 KoShape* shape = factory->createShape(params, d->document->resourceManager());
506
507 QPointF pos = d->canvas->viewToDocument(d->canvas->documentOffset() + QPointF(d->canvas->size().width() / 2, d->canvas->size().height() / 2));
508 KoShapeAnchor *anchor = new KoShapeAnchor(shape);
509 anchor->setAnchorType(KoShapeAnchor::AnchorPage);
510 anchor->setHorizontalPos(KoShapeAnchor::HFromLeft);
511 anchor->setVerticalPos(KoShapeAnchor::VFromTop);
512 anchor->setHorizontalRel(KoShapeAnchor::HPage);
513 anchor->setVerticalRel(KoShapeAnchor::VPage);
514 shape->setAnchor(anchor);
515 shape->setPosition(pos);
516 shape->scale(0.2, 0.2);
517
518 // KWShapeCreateCommand *cmd = new KWShapeCreateCommand(d->document, shape);
519 KoSelection *selection = d->canvas->shapeManager()->selection();
520 selection->deselectAll();
521 selection->select(shape);
522 // d->canvas->addCommand(cmd);
523 d->canvas->shapeManager()->addShape(shape);
524
525 d->notes->addEntry("", imageUrl, "Neutral", shape);
526 }
527 }
528
addNote(const QString & text,const QString & color,const QString & imageUrl)529 void CQTextDocumentCanvas::addNote(const QString& text, const QString& color, const QString& imageUrl)
530 {
531 QSvgRenderer renderer(QUrl(imageUrl).toLocalFile());
532
533 // Prepare a QImage with desired characteritisc
534 QImage image(400, 200, QImage::Format_ARGB32);
535 image.fill(Qt::transparent);
536
537 // Get QPainter that paints to the image
538 QPainter painter(&image);
539 painter.setRenderHint(QPainter::Antialiasing, true);
540 painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
541 painter.setRenderHint(QPainter::TextAntialiasing, true);
542
543 renderer.render(&painter, image.rect());
544
545 QFont font;
546 font.setFamily("Permanent Marker");
547 font.setStyle(QFont::StyleNormal);
548 font.setPixelSize(40);
549 painter.setPen(QPen(QColor(color), 0));
550 painter.setFont(font);
551 painter.drawText(image.rect().adjusted(10, 10, -20, -20), Qt::AlignCenter | Qt::TextWordWrap, text);
552 painter.end();
553
554 KoProperties* params = new KoProperties();
555 params->setProperty("qimage", image);
556 KoShapeFactoryBase* factory = KoShapeRegistry::instance()->get("PictureShape");
557 if (factory) {
558 KoShape* shape = factory->createShape(params, d->document->resourceManager());
559
560 QPointF pos = d->canvas->viewToDocument(d->canvas->documentOffset() + QPointF(d->canvas->size().width() / 2, d->canvas->size().height() / 2));
561 KoShapeAnchor *anchor = new KoShapeAnchor(shape);
562 anchor->setAnchorType(KoShapeAnchor::AnchorPage);
563 anchor->setHorizontalPos(KoShapeAnchor::HFromLeft);
564 anchor->setVerticalPos(KoShapeAnchor::VFromTop);
565 anchor->setHorizontalRel(KoShapeAnchor::HPage);
566 anchor->setVerticalRel(KoShapeAnchor::VPage);
567 shape->setAnchor(anchor);
568 shape->setPosition(pos);
569 shape->rotate(-15);
570 shape->scale(0.3, 0.3);
571
572 // KWShapeCreateCommand *cmd = new KWShapeCreateCommand(d->document, shape);
573 KoSelection *selection = d->canvas->shapeManager()->selection();
574 selection->deselectAll();
575 selection->select(shape);
576 // d->canvas->addCommand(cmd);
577 d->canvas->shapeManager()->addShape(shape);
578
579 d->notes->addEntry(text, "", color, shape);
580 }
581 }
582
setCameraY(int cameraY)583 void CQTextDocumentCanvas::setCameraY(int cameraY)
584 {
585 d->currentPoint.setY (cameraY);
586 emit cameraYChanged();
587 }
588
alignTopWith(int y)589 void CQTextDocumentCanvas::alignTopWith(int y)
590 {
591 d->currentPoint.setY(y);
592 emit cameraYChanged();
593 }
594
currentPageNumber() const595 int CQTextDocumentCanvas::currentPageNumber() const
596 {
597 if (d->document && !d->throttleTimer->isActive()) {
598 // Can't use this at the moment, we sort of don't have the right one, because derp :P
599 //d->canvas->resourceManager()->resource(KoCanvasResourceManager::CurrentPage).toInt();
600 d->throttleTimer->start();
601 const KWDocument *kwDoc = static_cast<const KWDocument*>(d->document);
602 d->pageNumber = kwDoc->pageManager()->page(d->canvas->viewMode()->viewToDocument(d->canvas->documentOffset(), d->canvas->viewConverter())).pageNumber();
603 }
604 return d->pageNumber;
605 }
606
setCurrentPageNumber(const int & currentPageNumber)607 void CQTextDocumentCanvas::setCurrentPageNumber(const int& currentPageNumber)
608 {
609 if (d->pageNumber != currentPageNumber) {
610 gotoPage(currentPageNumber, d->document);
611 }
612 }
613
render(QPainter * painter,const QRectF & target)614 void CQTextDocumentCanvas::render(QPainter* painter, const QRectF& target)
615 {
616 Q_UNUSED(target)
617 QStyleOptionGraphicsItem option;
618 option.exposedRect = QRect(0, 0, width(), height());
619 option.rect = option.exposedRect.toAlignedRect();
620 d->canvas->canvasItem()->paint(painter, &option);
621 }
622
event(QEvent * event)623 bool CQTextDocumentCanvas::event( QEvent* event )
624 {
625 switch(static_cast<int>(event->type())) {
626 case ViewModeSwitchEvent::AboutToSwitchViewModeEvent: {
627 ViewModeSynchronisationObject* syncObject = static_cast<ViewModeSwitchEvent*>(event)->synchronisationObject();
628
629 if (d->canvas) {
630 syncObject->documentOffset = d->canvas->documentOffset();
631 syncObject->zoomLevel = zoomController()->zoomAction()->effectiveZoom();
632 syncObject->activeToolId = KoToolManager::instance()->activeToolId();
633 syncObject->shapes = d->canvas->shapeManager()->shapes();
634 syncObject->initialized = true;
635 }
636
637 return true;
638 }
639 case ViewModeSwitchEvent::SwitchedToTouchModeEvent: {
640 ViewModeSynchronisationObject* syncObject = static_cast<ViewModeSwitchEvent*>(event)->synchronisationObject();
641
642 if (d->canvas && syncObject->initialized) {
643 d->canvas->shapeManager()->setShapes(syncObject->shapes);
644
645 KoToolManager::instance()->switchToolRequested("PageToolFactory_ID");
646 qApp->processEvents();
647
648 zoomController()->setZoom(KoZoomMode::ZOOM_CONSTANT, syncObject->zoomLevel);
649
650 qApp->processEvents();
651 emit positionShouldChange(syncObject->documentOffset);
652 }
653
654 return true;
655 }
656 // case KisTabletEvent::TabletPressEx:
657 // case KisTabletEvent::TabletReleaseEx:
658 // emit interactionStarted();
659 // d->canvas->inputManager()->eventFilter(this, event);
660 // return true;
661 // case KisTabletEvent::TabletMoveEx:
662 // d->tabletEventCount++; //Note that this will wraparound at some point; This is intentional.
663 // #ifdef Q_OS_X11
664 // if (d->tabletEventCount % 2 == 0)
665 // #endif
666 // d->canvas->inputManager()->eventFilter(this, event);
667 // return true;
668 default:
669 break;
670 }
671 return QDeclarativeItem::event( event );
672 }
673
currentToolChanged(KoCanvasController * controller,int uniqueToolId)674 void CQTextDocumentCanvas::currentToolChanged(KoCanvasController* controller, int uniqueToolId)
675 {
676 Q_UNUSED(controller)
677 Q_UNUSED(uniqueToolId)
678 d->currentTool = qobject_cast<KoToolBase*>(KoToolManager::instance()->toolById(d->canvas, KoToolManager::instance()->activeToolId()));
679 }
680
mouseDoubleClickEvent(QGraphicsSceneMouseEvent * e)681 void CQTextDocumentCanvas::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* e)
682 {
683 QMouseEvent me(e->type(), e->pos().toPoint(), e->button(), e->buttons(), e->modifiers());
684 KoPointerEvent pe(&me, d->canvas->viewToDocument(e->pos() + d->canvas->documentOffset()));
685 d->currentTool->mouseDoubleClickEvent(&pe);
686 updateCanvas();
687 emit selectionChanged();
688 e->setAccepted(me.isAccepted());
689 }
690
mouseMoveEvent(QGraphicsSceneMouseEvent * e)691 void CQTextDocumentCanvas::mouseMoveEvent(QGraphicsSceneMouseEvent* e)
692 {
693 QMouseEvent me(e->type(), e->pos().toPoint(), e->button(), e->buttons(), e->modifiers());
694 KoPointerEvent pe(&me, d->canvas->viewToDocument(e->pos() + d->canvas->documentOffset()));
695 d->currentTool->mouseMoveEvent(&pe);
696 updateCanvas();
697 emit selectionChanged();
698 e->setAccepted(me.isAccepted());
699 }
700
mousePressEvent(QGraphicsSceneMouseEvent * e)701 void CQTextDocumentCanvas::mousePressEvent(QGraphicsSceneMouseEvent* e)
702 {
703 QMouseEvent me(e->type(), e->pos().toPoint(), e->button(), e->buttons(), e->modifiers());
704 KoPointerEvent pe(&me, d->canvas->viewToDocument(e->pos() + d->canvas->documentOffset()));
705 d->currentTool->mousePressEvent(&pe);
706 updateCanvas();
707 emit selectionChanged();
708 e->setAccepted(me.isAccepted());
709 }
710
mouseReleaseEvent(QGraphicsSceneMouseEvent * e)711 void CQTextDocumentCanvas::mouseReleaseEvent(QGraphicsSceneMouseEvent* e)
712 {
713 QMouseEvent me(e->type(), e->pos().toPoint(), e->button(), e->buttons(), e->modifiers());
714 KoPointerEvent pe(&me, d->canvas->viewToDocument(e->pos() + d->canvas->documentOffset()));
715 d->currentTool->mouseReleaseEvent(&pe);
716 updateCanvas();
717 emit selectionChanged();
718 e->setAccepted(me.isAccepted());
719 }
720
geometryChanged(const QRectF & newGeometry,const QRectF & oldGeometry)721 void CQTextDocumentCanvas::geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry)
722 {
723 if (d->canvas) {
724 QGraphicsWidget *widget = dynamic_cast<QGraphicsWidget*>(d->canvas);
725 if (widget) {
726 widget->setGeometry(newGeometry);
727 }
728 }
729 QDeclarativeItem::geometryChanged(newGeometry, oldGeometry);
730 }
731
createAndSetCanvasControllerOn(KoCanvasBase * canvas)732 void CQTextDocumentCanvas::createAndSetCanvasControllerOn(KoCanvasBase* canvas)
733 {
734 //TODO: pass a proper action collection
735 CQCanvasController *controller = new CQCanvasController(new KActionCollection(this));
736 setCanvasController(controller);
737 connect (controller, SIGNAL(documentSizeChanged(QSize)), SLOT(updateDocumentSize(QSize)));
738 controller->setCanvas(canvas);
739 KoToolManager::instance()->addController (controller);
740 }
741
createAndSetZoomController(KoCanvasBase * canvas)742 void CQTextDocumentCanvas::createAndSetZoomController(KoCanvasBase* canvas)
743 {
744 KoZoomHandler* zoomHandler = static_cast<KoZoomHandler*> (canvas->viewConverter());
745 setZoomController(new KoZoomController(canvasController(), zoomHandler, new KActionCollection(this)));
746
747 KWCanvasItem *kwCanvasItem = static_cast<KWCanvasItem*>(canvas);
748 connect (kwCanvasItem, SIGNAL(documentSize(QSizeF)), zoomController(), SLOT(setDocumentSize(QSizeF)));
749 connect (canvasController()->proxyObject, SIGNAL(moveDocumentOffset(QPoint)), SIGNAL(currentPageNumberChanged()));
750 connect (canvasController()->proxyObject, SIGNAL(moveDocumentOffset(QPoint)), kwCanvasItem, SLOT(setDocumentOffset(QPoint)));
751 connect (zoomController(), SIGNAL(zoomChanged(KoZoomMode::Mode,qreal)), SIGNAL(zoomActionChanged()));
752 kwCanvasItem->updateSize();
753 emit zoomActionChanged();
754 }
755
updateZoomControllerAccordingToDocument(const KoDocument * document)756 void CQTextDocumentCanvas::updateZoomControllerAccordingToDocument(const KoDocument* document)
757 {
758 const KWDocument *kwDoc = static_cast<const KWDocument*>(document);
759 zoomController()->setPageSize (kwDoc->pageManager()->begin().rect().size());
760 }
761
searchTerm() const762 QString CQTextDocumentCanvas::searchTerm() const
763 {
764 return d->searchTerm;
765 }
766
setSearchTerm(const QString & term)767 void CQTextDocumentCanvas::setSearchTerm(const QString& term)
768 {
769 d->searchTerm = term;
770 if (!term.isEmpty()) {
771 d->findText->find(term);
772 }
773 emit searchTermChanged();
774 }
775
findMatchFound(const KoFindMatch & match)776 void CQTextDocumentCanvas::findMatchFound(const KoFindMatch &match)
777 {
778 QTextCursor cursor = match.location().value<QTextCursor>();
779 d->canvas->canvasItem()->update();
780
781 d->canvas->resourceManager()->setResource (KoText::CurrentTextAnchor, cursor.anchor());
782 d->canvas->resourceManager()->setResource (KoText::CurrentTextPosition, cursor.position());
783 }
784
findNoMatchFound()785 void CQTextDocumentCanvas::findNoMatchFound()
786 {
787 qDebug() << "Match for " << d->searchTerm << " not found";
788 }
789
updateCanvas()790 void CQTextDocumentCanvas::updateCanvas()
791 {
792 KWCanvasItem* kwCanvasItem = dynamic_cast<KWCanvasItem*> (d->canvas);
793 kwCanvasItem->update();
794 }
795
findNext()796 void CQTextDocumentCanvas::findNext()
797 {
798 d->findText->findNext();
799 }
800
findPrevious()801 void CQTextDocumentCanvas::findPrevious()
802 {
803 d->findText->findPrevious();
804 }
805
documentModel() const806 QObject* CQTextDocumentCanvas::documentModel() const
807 {
808 return d->documentModel;
809 }
810
document() const811 KWDocument* CQTextDocumentCanvas::document() const
812 {
813 return d->document;
814 }
815
doc() const816 QObject* CQTextDocumentCanvas::doc() const
817 {
818 return d->document;
819 }
820
part() const821 QObject* CQTextDocumentCanvas::part() const
822 {
823 return d->part;
824 }
825
linkTargets() const826 QObjectList CQTextDocumentCanvas::linkTargets() const
827 {
828 return d->linkTargets;
829 }
830
documentSize() const831 QSize CQTextDocumentCanvas::documentSize() const
832 {
833 return d->documentSize;
834 }
835
updateDocumentSize(const QSize & size)836 void CQTextDocumentCanvas::updateDocumentSize(const QSize& size)
837 {
838 d->documentSize = size;
839 emit documentSizeChanged();
840 }
841