1 /* This file is part of the KDE project
2 
3    Copyright (C) 2006-2009 Thorsten Zachmann <zachmann@kde.org>
4    Copyright (C) 2007 Thomas Zander <zander@kde.org>
5    Copyright (C) 2009 Inge Wallin   <inge@lysator.liu.se>
6    Copyright (C) 2010 Boudewijn Rempt <boud@kogmbh.com>
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 #include "KoPAView.h"
25 
26 #include <QGridLayout>
27 #include <QApplication>
28 #include <QClipboard>
29 #include <QLabel>
30 #include <QTabBar>
31 
32 #include <KoIcon.h>
33 #include <KoShapeRegistry.h>
34 #include <KoShapeFactoryBase.h>
35 #include <KoProperties.h>
36 #include <KoCanvasControllerWidget.h>
37 #include <KoCanvasResourceManager.h>
38 #include <KoColorBackground.h>
39 #include <KoFind.h>
40 #include <KoTextDocumentLayout.h>
41 #include <KoToolManager.h>
42 #include <KoToolProxy.h>
43 #include <KoZoomHandler.h>
44 #include <KoStandardAction.h>
45 #include <KoModeBoxFactory.h>
46 #include <KoToolBoxFactory.h>
47 #include <KoShapeController.h>
48 #include <KoShapeManager.h>
49 #include <KoZoomAction.h>
50 #include <KoZoomController.h>
51 #include <KoInlineTextObjectManager.h>
52 #include <KoSelection.h>
53 #include <KoGridData.h>
54 #include <KoGuidesData.h>
55 #include <KoMainWindow.h>
56 #include <KoDockerManager.h>
57 #include <KoShapeLayer.h>
58 #include <KoRuler.h>
59 #include <KoRulerController.h>
60 #include <KoDrag.h>
61 #include <KoCutController.h>
62 #include <KoCopyController.h>
63 #include <KoUnit.h>
64 
65 #include "KoPADocumentStructureDocker.h"
66 #include "KoShapeTraversal.h"
67 #include "KoPACanvas.h"
68 #include "KoPADocument.h"
69 #include "KoPAPage.h"
70 #include "KoPAMasterPage.h"
71 #include "KoPAViewModeNormal.h"
72 #include "KoPAOdfPageSaveHelper.h"
73 #include "KoPAPastePage.h"
74 #include "KoPAPrintJob.h"
75 #include "commands/KoPAPageInsertCommand.h"
76 #include "commands/KoPAChangeMasterPageCommand.h"
77 #include "dialogs/KoPAMasterPageDialog.h"
78 #include "dialogs/KoPAPageLayoutDialog.h"
79 #include "dialogs/KoPAConfigureDialog.h"
80 #include "widgets/KoPageNavigator.h"
81 
82 #include <PageAppDebug.h>
83 #include <klocalizedstring.h>
84 #include <ktoggleaction.h>
85 #include <kactionmenu.h>
86 #include <kactioncollection.h>
87 #include <kmessagebox.h>
88 #include <KoNetAccess.h>
89 
90 #include <QFileDialog>
91 #include <QAction>
92 #include <QStatusBar>
93 #include <QTemporaryFile>
94 #include <QUrl>
95 
96 
97 class Q_DECL_HIDDEN KoPAView::Private
98 {
99 public:
Private(KoPADocument * document)100     Private( KoPADocument *document )
101     : doc( document )
102     , canvas( 0 )
103     , activePage( 0 )
104     {}
105 
~Private()106     ~Private()
107     {}
108 
109     // These were originally private in the .h file
110     KoPADocumentStructureDocker *documentStructureDocker;
111 
112     KoCanvasController *canvasController;
113     KoZoomController *zoomController;
114     KoCopyController *copyController;
115     KoCutController *cutController;
116 
117     QAction *editPaste;
118     QAction *deleteSelectionAction;
119 
120     KToggleAction *actionViewSnapToGrid;
121     KToggleAction *actionViewShowMasterPages;
122 
123     QAction *actionInsertPage;
124     QAction *actionCopyPage;
125     QAction *actionDeletePage;
126 
127     QAction *actionMasterPage;
128     QAction *actionPageLayout;
129 
130     QAction *actionConfigure;
131 
132     KoRuler *horizontalRuler;
133     KoRuler *verticalRuler;
134     KToggleAction *viewRulers;
135 
136     KoZoomAction  *zoomAction;
137 
138     KToggleAction *showPageMargins;
139 
140     KoFind *find;
141 
142     KoPAViewMode *viewModeNormal;
143 
144     // This tab bar hidden by default. It could be used to alternate between view modes
145     QTabBar *tabBar;
146 
147     QGridLayout *tabBarLayout;
148     QWidget *insideWidget;
149 
150     // status bar
151     KoPageNavigator *pageNavigator;
152     QLabel *status;       ///< ordinary status
153     QWidget *zoomActionWidget;
154 
155     // These used to be protected.
156     KoPADocument *doc;
157     KoPACanvas *canvas;
158     KoPAPageBase *activePage;
159 };
160 
161 
162 
KoPAView(KoPart * part,KoPADocument * document,KoPAFlags withModeBox,QWidget * parent)163 KoPAView::KoPAView(KoPart *part, KoPADocument *document, KoPAFlags withModeBox, QWidget *parent)
164 : KoView(part, document, parent)
165 , d( new Private(document))
166 {
167     initGUI(withModeBox);
168     initActions();
169 
170     if ( d->doc->pageCount() > 0 )
171         doUpdateActivePage( d->doc->pageByIndex( 0, false ) );
172 
173     setAcceptDrops(true);
174 }
175 
~KoPAView()176 KoPAView::~KoPAView()
177 {
178     KoToolManager::instance()->removeCanvasController( d->canvasController );
179 
180     removeStatusBarItem(d->status);
181     removeStatusBarItem(d->zoomActionWidget);
182 
183     delete d->canvasController;
184     delete d->zoomController;
185     delete d->viewModeNormal;
186 
187     delete d;
188 }
189 
addImages(const QVector<QImage> & imageList,const QPoint & insertAt)190 void KoPAView::addImages(const QVector<QImage> &imageList, const QPoint &insertAt)
191 {
192     // get position from event and convert to document coordinates
193     QPointF pos = zoomHandler()->viewToDocument(insertAt)
194             + kopaCanvas()->documentOffset() - kopaCanvas()->documentOrigin();
195 
196     // create a factory
197     KoShapeFactoryBase *factory = KoShapeRegistry::instance()->value("PictureShape");
198     if (!factory) {
199         warnPageApp << "No picture shape found, cannot drop images.";
200         return;
201     }
202 
203     foreach(const QImage &image, imageList) {
204 
205         KoProperties params;
206         QVariant v;
207         v.setValue<QImage>(image);
208         params.setProperty("qimage", v);
209 
210         KoShape *shape = factory->createShape(&params, d->doc->resourceManager());
211 
212         if (!shape) {
213             warnPageApp << "Could not create a shape from the image";
214             return;
215         }
216         shape->setPosition(pos);
217         pos += QPointF(25,25); // increase the position for each shape we insert so the
218                                // user can see them all.
219         KUndo2Command *cmd = kopaCanvas()->shapeController()->addShapeDirect(shape);
220         if (cmd) {
221             KoSelection *selection = kopaCanvas()->shapeManager()->selection();
222             selection->deselectAll();
223             selection->select(shape);
224         }
225         kopaCanvas()->addCommand(cmd);
226     }
227 }
228 
229 
initGUI(KoPAFlags flags)230 void KoPAView::initGUI(KoPAFlags flags)
231 {
232     d->tabBarLayout = new QGridLayout(this);
233     d->tabBarLayout->setMargin(0);
234     d->tabBarLayout->setSpacing(0);
235     d->insideWidget = new QWidget();
236     QGridLayout *gridLayout = new QGridLayout(d->insideWidget);
237     gridLayout->setMargin(0);
238     gridLayout->setSpacing(0);
239     setLayout(d->tabBarLayout);
240 
241     d->canvas = new KoPACanvas( this, d->doc, this );
242     KoCanvasControllerWidget *canvasController = new KoCanvasControllerWidget( actionCollection(), this );
243 
244     if (mainWindow()) {
245         // this needs to be done before KoCanvasControllerWidget::setCanvas is called
246         KoPADocumentStructureDockerFactory structureDockerFactory(KoDocumentSectionView::ThumbnailMode, d->doc->pageType());
247         d->documentStructureDocker = qobject_cast<KoPADocumentStructureDocker*>(mainWindow()->createDockWidget(&structureDockerFactory));
248         connect(d->documentStructureDocker, SIGNAL(pageChanged(KoPAPageBase*)), proxyObject, SLOT(updateActivePage(KoPAPageBase*)));
249         connect(d->documentStructureDocker, SIGNAL(dockerReset()), this, SLOT(reinitDocumentDocker()));
250     }
251 
252     d->canvasController = canvasController;
253     d->canvasController->setCanvas( d->canvas );
254     KoToolManager::instance()->addController( d->canvasController );
255     KoToolManager::instance()->registerTools( actionCollection(), d->canvasController );
256 
257     d->zoomController = new KoZoomController( d->canvasController, zoomHandler(), actionCollection());
258     connect( d->zoomController, SIGNAL(zoomChanged(KoZoomMode::Mode,qreal)),
259              this, SLOT(slotZoomChanged(KoZoomMode::Mode,qreal)) );
260 
261     d->zoomAction = d->zoomController->zoomAction();
262 
263     // page/slide navigator
264     d->pageNavigator = new KoPageNavigator(this);
265     addStatusBarItem(d->pageNavigator, 0);
266 
267     // set up status bar message
268     d->status = new QLabel(QString(), this);
269     d->status->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
270     d->status->setMinimumWidth( 300 );
271     addStatusBarItem( d->status, 1 );
272     connect( KoToolManager::instance(), SIGNAL(changedStatusText(QString)),
273              d->status, SLOT(setText(QString)) );
274     d->zoomActionWidget = d->zoomAction->createWidget(  statusBar() );
275     addStatusBarItem( d->zoomActionWidget, 0 );
276 
277     d->zoomController->setZoomMode( KoZoomMode::ZOOM_PAGE );
278 
279     d->viewModeNormal = new KoPAViewModeNormal( this, d->canvas );
280     setViewMode(d->viewModeNormal);
281 
282     // The rulers
283     d->horizontalRuler = new KoRuler(this, Qt::Horizontal, viewConverter( d->canvas ));
284     d->horizontalRuler->setShowMousePosition(true);
285     d->horizontalRuler->setUnit(d->doc->unit());
286     d->verticalRuler = new KoRuler(this, Qt::Vertical, viewConverter( d->canvas ));
287     d->verticalRuler->setUnit(d->doc->unit());
288     d->verticalRuler->setShowMousePosition(true);
289 
290     new KoRulerController(d->horizontalRuler, d->canvas->resourceManager());
291 
292     connect(d->doc, SIGNAL(unitChanged(KoUnit)), this, SLOT(updateUnit(KoUnit)));
293     //Layout a tab bar
294     d->tabBar = new QTabBar();
295     d->tabBarLayout->addWidget(d->insideWidget, 1, 1);
296     setTabBarPosition(Qt::Horizontal);
297 
298     gridLayout->addWidget(d->horizontalRuler->tabChooser(), 0, 0);
299     gridLayout->addWidget(d->horizontalRuler, 0, 1);
300     gridLayout->addWidget(d->verticalRuler, 1, 0);
301     gridLayout->addWidget(canvasController, 1, 1);
302 
303     //tab bar is hidden by default a method is provided to access to the tab bar
304     d->tabBar->hide();
305 
306     connect(d->canvasController->proxyObject, SIGNAL(canvasOffsetXChanged(int)),
307             this, SLOT(pageOffsetChanged()));
308     connect(d->canvasController->proxyObject, SIGNAL(canvasOffsetYChanged(int)),
309             this, SLOT(pageOffsetChanged()));
310     connect(d->canvasController->proxyObject, SIGNAL(sizeChanged(QSize)),
311             this, SLOT(pageOffsetChanged()));
312     connect(d->canvasController->proxyObject, SIGNAL(canvasMousePositionChanged(QPoint)),
313             this, SLOT(updateMousePosition(QPoint)));
314     d->verticalRuler->createGuideToolConnection(d->canvas);
315     d->horizontalRuler->createGuideToolConnection(d->canvas);
316 
317     KoMainWindow *mw = mainWindow();
318     if (flags & KoPAView::ModeBox) {
319         if (mw) {
320             KoModeBoxFactory modeBoxFactory(canvasController, qApp->applicationName(), i18n("Tools"));
321             QDockWidget* modeBox = mw->createDockWidget(&modeBoxFactory);
322             mw->dockerManager()->removeToolOptionsDocker();
323             dynamic_cast<KoCanvasObserverBase*>(modeBox)->setObservedCanvas(d->canvas);
324         }
325     } else {
326         if (mw) {
327             KoToolBoxFactory toolBoxFactory;
328             mw->createDockWidget( &toolBoxFactory );
329             connect(canvasController, SIGNAL(toolOptionWidgetsChanged(QList<QPointer<QWidget>>)),
330             mw->dockerManager(), SLOT(newOptionWidgets(QList<QPointer<QWidget>>)));
331         }
332     }
333 
334     connect(shapeManager(), SIGNAL(selectionChanged()), this, SLOT(selectionChanged()));
335     connect(shapeManager(), SIGNAL(contentChanged()), this, SLOT(updateCanvasSize()));
336     connect(d->doc, SIGNAL(shapeAdded(KoShape*)), this, SLOT(updateCanvasSize()));
337     connect(d->doc, SIGNAL(shapeRemoved(KoShape*)), this, SLOT(updateCanvasSize()));
338     connect(d->doc, SIGNAL(update(KoPAPageBase*)), this, SLOT(pageUpdated(KoPAPageBase*)));
339     connect(d->canvas, SIGNAL(documentSize(QSize)), d->canvasController->proxyObject, SLOT(updateDocumentSize(QSize)));
340     connect(d->canvasController->proxyObject, SIGNAL(moveDocumentOffset(QPoint)), d->canvas, SLOT(slotSetDocumentOffset(QPoint)));
341     connect(d->canvasController->proxyObject, SIGNAL(sizeChanged(QSize)), this, SLOT(updateCanvasSize()));
342 
343     if (mw) {
344         KoToolManager::instance()->requestToolActivation( d->canvasController );
345     }
346 }
347 
initActions()348 void KoPAView::initActions()
349 {
350     QAction *action = actionCollection()->addAction( KStandardAction::Cut, "edit_cut", 0, 0);
351     d->cutController = new KoCutController(kopaCanvas(), action);
352     action = actionCollection()->addAction( KStandardAction::Copy, "edit_copy", 0, 0 );
353     d->copyController = new KoCopyController(kopaCanvas(), action);
354     d->editPaste = actionCollection()->addAction( KStandardAction::Paste, "edit_paste", proxyObject, SLOT(editPaste()) );
355     connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged()));
356     connect(d->canvas->toolProxy(), SIGNAL(toolChanged(QString)), this, SLOT(clipboardDataChanged()));
357     clipboardDataChanged();
358     actionCollection()->addAction(KStandardAction::SelectAll,  "edit_select_all", this, SLOT(editSelectAll()));
359     actionCollection()->addAction(KStandardAction::Deselect,  "edit_deselect_all", this, SLOT(editDeselectAll()));
360 
361     d->deleteSelectionAction = new QAction(koIcon("edit-delete"), i18n("D&elete"), this);
362     actionCollection()->addAction("edit_delete", d->deleteSelectionAction );
363     d->deleteSelectionAction->setShortcut(QKeySequence("Del"));
364     d->deleteSelectionAction->setEnabled(false);
365     connect(d->deleteSelectionAction, SIGNAL(triggered()), this, SLOT(editDeleteSelection()));
366     connect(d->canvas->toolProxy(),    SIGNAL(selectionChanged(bool)),
367             d->deleteSelectionAction, SLOT(setEnabled(bool)));
368 
369     KToggleAction *showGrid= d->doc->gridData().gridToggleAction(d->canvas);
370     actionCollection()->addAction("view_grid", showGrid );
371 
372     d->actionViewSnapToGrid = new KToggleAction(i18n("Snap to Grid"), this);
373     d->actionViewSnapToGrid->setChecked(d->doc->gridData().snapToGrid());
374     actionCollection()->addAction("view_snaptogrid", d->actionViewSnapToGrid);
375     connect( d->actionViewSnapToGrid, SIGNAL(triggered(bool)), this, SLOT(viewSnapToGrid(bool)));
376 
377     KToggleAction *actionViewShowGuides = KoStandardAction::showGuides(this, SLOT(viewGuides(bool)), this);
378     actionViewShowGuides->setChecked( d->doc->guidesData().showGuideLines() );
379     actionCollection()->addAction(KoStandardAction::name(KoStandardAction::ShowGuides),
380             actionViewShowGuides );
381 
382     d->actionViewShowMasterPages = new KToggleAction(i18n( "Show Master Pages" ), this );
383     actionCollection()->addAction( "view_masterpages", d->actionViewShowMasterPages );
384     connect( d->actionViewShowMasterPages, SIGNAL(triggered(bool)), this, SLOT(setMasterMode(bool)) );
385 
386     d->viewRulers  = new KToggleAction(i18n("Show Rulers"), this);
387     actionCollection()->addAction("view_rulers", d->viewRulers );
388     d->viewRulers->setToolTip(i18n("Show/hide the view's rulers"));
389     connect(d->viewRulers, SIGNAL(triggered(bool)), proxyObject, SLOT(setShowRulers(bool)));
390     setShowRulers(d->doc->rulersVisible());
391 
392     d->showPageMargins  = new KToggleAction(i18n("Show Page Margins"), this);
393     actionCollection()->addAction("view_page_margins", d->showPageMargins);
394     d->showPageMargins->setToolTip(i18n("Show/hide the page margins"));
395     connect(d->showPageMargins, SIGNAL(toggled(bool)), SLOT(setShowPageMargins(bool)));
396     setShowPageMargins(d->doc->showPageMargins());
397 
398     d->actionInsertPage = new QAction(koIcon("document-new"), i18n("Insert Page"), this);
399     actionCollection()->addAction( "page_insertpage", d->actionInsertPage );
400     d->actionInsertPage->setToolTip( i18n( "Insert a new page after the current one" ) );
401     d->actionInsertPage->setWhatsThis( i18n( "Insert a new page after the current one" ) );
402     connect( d->actionInsertPage, SIGNAL(triggered()), proxyObject, SLOT(insertPage()) );
403 
404     d->actionCopyPage = new QAction( i18n( "Copy Page" ), this );
405     actionCollection()->addAction( "page_copypage", d->actionCopyPage );
406     d->actionCopyPage->setToolTip( i18n( "Copy the current page" ) );
407     d->actionCopyPage->setWhatsThis( i18n( "Copy the current page" ) );
408     connect( d->actionCopyPage, SIGNAL(triggered()), this, SLOT(copyPage()) );
409 
410     d->actionDeletePage = new QAction( i18n( "Delete Page" ), this );
411     d->actionDeletePage->setEnabled( d->doc->pageCount() > 1 );
412     actionCollection()->addAction( "page_deletepage", d->actionDeletePage );
413     d->actionDeletePage->setToolTip( i18n( "Delete the current page" ) );
414     d->actionDeletePage->setWhatsThis( i18n( "Delete the current page" ) );
415     connect( d->actionDeletePage, SIGNAL(triggered()), this, SLOT(deletePage()) );
416 
417     d->actionMasterPage = new QAction(i18n("Master Page..."), this);
418     actionCollection()->addAction("format_masterpage", d->actionMasterPage);
419     connect(d->actionMasterPage, SIGNAL(triggered()), this, SLOT(formatMasterPage()));
420 
421     d->actionPageLayout = new QAction( i18n( "Page Layout..." ), this );
422     actionCollection()->addAction( "format_pagelayout", d->actionPageLayout );
423     connect( d->actionPageLayout, SIGNAL(triggered()), this, SLOT(formatPageLayout()) );
424 
425     actionCollection()->addAction(KStandardAction::Prior,  "page_previous", this, SLOT(goToPreviousPage()));
426     actionCollection()->addAction(KStandardAction::Next,  "page_next", this, SLOT(goToNextPage()));
427     actionCollection()->addAction(KStandardAction::FirstPage,  "page_first", this, SLOT(goToFirstPage()));
428     actionCollection()->addAction(KStandardAction::LastPage,  "page_last", this, SLOT(goToLastPage()));
429     d->pageNavigator->initActions();
430 
431     KActionMenu *actionMenu = new KActionMenu(i18n("Variable"), this);
432     foreach(QAction *action, d->doc->inlineTextObjectManager()->createInsertVariableActions(d->canvas))
433         actionMenu->addAction(action);
434     actionCollection()->addAction("insert_variable", actionMenu);
435 
436     QAction * am = new QAction(i18n("Import Document..."), this);
437     actionCollection()->addAction("import_document", am);
438     connect(am, SIGNAL(triggered()), this, SLOT(importDocument()));
439 
440     d->actionConfigure = new QAction(koIcon("configure"), i18n("Configure..."), this);
441     actionCollection()->addAction("configure", d->actionConfigure);
442     connect(d->actionConfigure, SIGNAL(triggered()), this, SLOT(configure()));
443     // not sure why this isn't done through KStandardAction, but since it isn't
444     // we ought to set the MenuRole manually so the item ends up in the appropriate
445     // menu on OS X:
446     d->actionConfigure->setMenuRole(QAction::PreferencesRole);
447 
448     d->find = new KoFind( this, d->canvas->resourceManager(), actionCollection() );
449     connect( d->find, SIGNAL(findDocumentSetNext(QTextDocument*)),
450              this,    SLOT(findDocumentSetNext(QTextDocument*)) );
451     connect( d->find, SIGNAL(findDocumentSetPrevious(QTextDocument*)),
452              this,    SLOT(findDocumentSetPrevious(QTextDocument*)) );
453 
454     actionCollection()->action( "object_group" )->setShortcut( QKeySequence( "Ctrl+G" ) );
455     actionCollection()->action( "object_ungroup" )->setShortcut( QKeySequence( "Ctrl+Shift+G" ) );
456 
457     connect(d->doc, &KoPADocument::actionsPossible, this, &KoPAView::setActionEnabled);
458 }
459 
canvasController() const460 KoCanvasController *KoPAView::canvasController() const
461 {
462     return d->canvasController;
463 }
464 
kopaCanvas() const465 KoPACanvasBase * KoPAView::kopaCanvas() const
466 {
467     return d->canvas;
468 }
469 
kopaDocument() const470 KoPADocument * KoPAView::kopaDocument() const
471 {
472     return d->doc;
473 }
474 
activePage() const475 KoPAPageBase* KoPAView::activePage() const
476 {
477     return d->activePage;
478 }
479 
updateReadWrite(bool readwrite)480 void KoPAView::updateReadWrite( bool readwrite )
481 {
482     Q_UNUSED(readwrite);
483 }
484 
horizontalRuler()485 KoRuler* KoPAView::horizontalRuler()
486 {
487     return d->horizontalRuler;
488 }
489 
verticalRuler()490 KoRuler* KoPAView::verticalRuler()
491 {
492     return d->verticalRuler;
493 }
494 
setShowPageMargins(bool state)495 void KoPAView::setShowPageMargins(bool state)
496 {
497     d->showPageMargins->setChecked(state);
498     d->canvas->setShowPageMargins(state);
499     d->doc->setShowPageMargins(state);
500 }
501 
zoomController() const502 KoZoomController* KoPAView::zoomController() const
503 {
504     return d->zoomController;
505 }
506 
copyController() const507 KoCopyController* KoPAView::copyController() const
508 {
509     return d->copyController;
510 }
511 
cutController() const512 KoCutController* KoPAView::cutController() const
513 {
514     return d->cutController;
515 }
516 
deleteSelectionAction() const517 QAction * KoPAView::deleteSelectionAction() const
518 {
519     return d->deleteSelectionAction;
520 }
521 
importDocument()522 void KoPAView::importDocument()
523 {
524     QFileDialog *dialog = new QFileDialog( /* QT5TODO: QUrl("kfiledialog:///OpenDialog"),*/ this );
525     dialog->setObjectName( "file dialog" );
526     dialog->setFileMode( QFileDialog::AnyFile );
527     if ( d->doc->pageType() == KoPageApp::Slide ) {
528         dialog->setWindowTitle(i18n("Import Slideshow"));
529     }
530     else {
531         dialog->setWindowTitle(i18n("Import Document"));
532     }
533 
534     // TODO make it possible to select also other supported types (than the default format) here.
535     // this needs to go via the filters to get the file in the correct format.
536     // For now we only support the native mime types
537     QStringList mimeFilter;
538 
539     mimeFilter << KoOdf::mimeType( d->doc->documentType() ) << KoOdf::templateMimeType( d->doc->documentType() );
540 
541     dialog->setMimeTypeFilters( mimeFilter );
542     if (dialog->exec() == QDialog::Accepted) {
543         QUrl url(dialog->selectedUrls().first());
544         QString tmpFile;
545         if ( KIO::NetAccess::download( url, tmpFile, 0 ) ) {
546             QFile file( tmpFile );
547             file.open( QIODevice::ReadOnly );
548             QByteArray ba;
549             ba = file.readAll();
550 
551             // set the correct mime type as otherwise it does not find the correct tag when loading
552             QMimeData data;
553             data.setData( KoOdf::mimeType( d->doc->documentType() ), ba);
554             KoPAPastePage paste( d->doc,d->activePage );
555             if ( ! paste.paste( d->doc->documentType(), &data ) ) {
556                 KMessageBox::error(0, i18n("Could not import\n%1", url.url(QUrl::PreferLocalFile)));
557             }
558         }
559         else {
560             KMessageBox::error(0, i18n("Could not import\n%1", url.url(QUrl::PreferLocalFile)));
561         }
562     }
563     delete dialog;
564 }
565 
viewSnapToGrid(bool snap)566 void KoPAView::viewSnapToGrid(bool snap)
567 {
568     d->doc->gridData().setSnapToGrid(snap);
569     d->actionViewSnapToGrid->setChecked(snap);
570 }
571 
viewGuides(bool show)572 void KoPAView::viewGuides(bool show)
573 {
574     d->doc->guidesData().setShowGuideLines(show);
575     d->canvas->update();
576 }
577 
editPaste()578 void KoPAView::editPaste()
579 {
580     if ( !d->canvas->toolProxy()->paste() ) {
581         pagePaste();
582     }
583 }
584 
pagePaste()585 void KoPAView::pagePaste()
586 {
587     const QMimeData * data = QApplication::clipboard()->mimeData();
588 
589     KoOdf::DocumentType documentTypes[] = { KoOdf::Graphics, KoOdf::Presentation };
590 
591     for ( unsigned int i = 0; i < sizeof( documentTypes ) / sizeof( KoOdf::DocumentType ); ++i )
592     {
593         if ( data->hasFormat( KoOdf::mimeType( documentTypes[i] ) ) ) {
594             KoPAPastePage paste( d->doc, d->activePage );
595             paste.paste( documentTypes[i], data );
596             break;
597         }
598     }
599 }
600 
editDeleteSelection()601 void KoPAView::editDeleteSelection()
602 {
603     d->canvas->toolProxy()->deleteSelection();
604 }
605 
editSelectAll()606 void KoPAView::editSelectAll()
607 {
608     KoSelection* selection = kopaCanvas()->shapeManager()->selection();
609     if( !selection )
610         return;
611     if (!this->isVisible()) {
612         emit selectAllRequested();
613         return;
614     }
615 
616     QList<KoShape*> shapes = activePage()->shapes();
617 
618     foreach( KoShape *shape, shapes ) {
619         KoShapeLayer *layer = dynamic_cast<KoShapeLayer *>( shape );
620 
621         if ( layer ) {
622             QList<KoShape*> layerShapes( layer->shapes() );
623             foreach( KoShape *layerShape, layerShapes ) {
624                 selection->select( layerShape );
625                 layerShape->update();
626             }
627         }
628     }
629 
630     selectionChanged();
631 }
632 
editDeselectAll()633 void KoPAView::editDeselectAll()
634 {
635     if (!this->isVisible()) {
636         emit deselectAllRequested();
637         return;
638     }
639 
640     KoSelection* selection = kopaCanvas()->shapeManager()->selection();
641     if( selection )
642         selection->deselectAll();
643 
644     selectionChanged();
645     d->canvas->update();
646 }
647 
formatMasterPage()648 void KoPAView::formatMasterPage()
649 {
650     KoPAPage *page = dynamic_cast<KoPAPage *>(d->activePage);
651     Q_ASSERT(page);
652     KoPAMasterPageDialog *dialog = new KoPAMasterPageDialog(d->doc, page->masterPage(), d->canvas);
653 
654     if (dialog->exec() == QDialog::Accepted) {
655         KoPAMasterPage *masterPage = dialog->selectedMasterPage();
656         KoPAPage *page = dynamic_cast<KoPAPage *>(d->activePage);
657         if (page) {
658             KoPAChangeMasterPageCommand * command = new KoPAChangeMasterPageCommand( d->doc, page, masterPage );
659             d->canvas->addCommand( command );
660         }
661     }
662 
663     delete dialog;
664 }
665 
formatPageLayout()666 void KoPAView::formatPageLayout()
667 {
668     const KoPageLayout &pageLayout = viewMode()->activePageLayout();
669 
670     KoPAPageLayoutDialog dialog( d->doc, pageLayout, d->canvas );
671 
672     if ( dialog.exec() == QDialog::Accepted ) {
673         KUndo2Command *command = new KUndo2Command( kundo2_i18n( "Change page layout" ) );
674         viewMode()->changePageLayout( dialog.pageLayout(), dialog.applyToDocument(), command );
675 
676         d->canvas->addCommand( command );
677     }
678 
679 }
680 
slotZoomChanged(KoZoomMode::Mode mode,qreal zoom)681 void KoPAView::slotZoomChanged( KoZoomMode::Mode mode, qreal zoom )
682 {
683     Q_UNUSED(zoom);
684     if (d->activePage) {
685         if (mode == KoZoomMode::ZOOM_PAGE) {
686             const KoPageLayout &layout = viewMode()->activePageLayout();
687             QRectF pageRect( 0, 0, layout.width, layout.height );
688             d->canvasController->ensureVisible(d->canvas->viewConverter()->documentToView(pageRect));
689         } else if (mode == KoZoomMode::ZOOM_WIDTH) {
690             // horizontally center the page
691             const KoPageLayout &layout = viewMode()->activePageLayout();
692             QRectF pageRect( 0, 0, layout.width, layout.height );
693             QRect viewRect = d->canvas->viewConverter()->documentToView(pageRect).toRect();
694             viewRect.translate(d->canvas->documentOrigin());
695             QRect currentVisible(qMax(0, -d->canvasController->canvasOffsetX()), qMax(0, -d->canvasController->canvasOffsetY()), d->canvasController->visibleWidth(), d->canvasController->visibleHeight());
696             int horizontalMove = viewRect.center().x() - currentVisible.center().x();
697             d->canvasController->pan(QPoint(horizontalMove, 0));
698         }
699         updateCanvasSize(true);
700     }
701 }
702 
configure()703 void KoPAView::configure()
704 {
705     openConfiguration();
706     // TODO update canvas
707 }
708 
openConfiguration()709 void KoPAView::openConfiguration()
710 {
711     QPointer<KoPAConfigureDialog> dialog(new KoPAConfigureDialog(this));
712     dialog->exec();
713     delete dialog;
714 }
715 
setMasterMode(bool master)716 void KoPAView::setMasterMode( bool master )
717 {
718     viewMode()->setMasterMode( master );
719     if (mainWindow()) {
720         d->documentStructureDocker->setMasterMode(master);
721     }
722     d->actionMasterPage->setEnabled(!master);
723 
724     QList<KoPAPageBase*> pages = d->doc->pages( master );
725     d->actionDeletePage->setEnabled( pages.size() > 1 );
726 }
727 
shapeManager() const728 KoShapeManager* KoPAView::shapeManager() const
729 {
730     return d->canvas->shapeManager();
731 }
732 
733 
masterShapeManager() const734 KoShapeManager* KoPAView::masterShapeManager() const
735 {
736     return d->canvas->masterShapeManager();
737 }
738 
reinitDocumentDocker()739 void KoPAView::reinitDocumentDocker()
740 {
741     if (mainWindow()) {
742         d->documentStructureDocker->setActivePage( d->activePage );
743     }
744 }
745 
pageUpdated(KoPAPageBase * page)746 void KoPAView::pageUpdated(KoPAPageBase* page)
747 {
748     // if the page was updated its content e.g. master page has been changed. Therefore we need to
749     // set the page again to set the shapes of the new master page and get a repaint. Without this
750     // changing the master page does not update the page.
751     if (d->activePage == page) {
752         doUpdateActivePage(page);
753     }
754 }
755 
updateCanvasSize(bool forceUpdate)756 void KoPAView::updateCanvasSize(bool forceUpdate)
757 {
758     const KoPageLayout &layout = viewMode()->activePageLayout();
759     QPoint scrollValue(d->canvasController->scrollBarValue());
760 
761     QSizeF pageSize(layout.width, layout.height);
762     QSizeF viewportSize = d->canvasController->viewportSize();
763 
764     //calculate size of union page + viewport
765     QSizeF documentMinSize(qMax(zoomHandler()->unzoomItX(viewportSize.width()), layout.width),
766                         qMax(zoomHandler()->unzoomItY(viewportSize.height()), layout.height));
767 
768     // create a rect out of it with origin in tp left of page
769     QRectF documentRect(QPointF((documentMinSize.width() - layout.width) * -0.5,
770                                (documentMinSize.height() - layout.height) * -0.5),
771                        documentMinSize);
772 
773     // Now make a union with the bounding rect of all shapes
774     // Fetch boundingRect like this as a viewmode might have set other shapes than the page
775     foreach (KoShape *layer, d->canvas->shapeManager()->shapes()) {
776         if (! dynamic_cast<KoShapeLayer *>(layer)) {
777             documentRect = documentRect.united(layer->boundingRect());
778         }
779     }
780 
781     QPointF offset = -documentRect.topLeft();
782     QPoint scrollChange = d->canvas->documentOrigin() - zoomHandler()->documentToView(offset).toPoint();
783 
784     if (forceUpdate || scrollChange != QPoint(0, 0)
785                     || d->zoomController->documentSize() != documentRect.size()
786                     || d->zoomController->pageSize() != pageSize) {
787         d->horizontalRuler->setRulerLength(layout.width);
788         d->verticalRuler->setRulerLength(layout.height);
789         d->horizontalRuler->setActiveRange(layout.leftMargin, layout.width - layout.rightMargin);
790         d->verticalRuler->setActiveRange(layout.topMargin, layout.height - layout.bottomMargin);
791         QSizeF documentSize(documentRect.size());
792         d->canvas->setDocumentOrigin(offset);
793         d->zoomController->setDocumentSize(documentSize);
794 
795         d->canvas->resourceManager()->setResource(KoCanvasResourceManager::PageSize, pageSize);
796 
797         d->canvas->update();
798         QSize documentPxSize(zoomHandler()->zoomItX(documentRect.width()), zoomHandler()->zoomItY(documentRect.height()));
799         d->canvasController->proxyObject->updateDocumentSize(documentPxSize);
800         // this can trigger a change of the zoom level in "fit to mode" and therefore this needs to be at the end as it calls this function again
801         d->zoomController->setPageSize(pageSize);
802     }
803 }
804 
doUpdateActivePage(KoPAPageBase * page)805 void KoPAView::doUpdateActivePage( KoPAPageBase * page )
806 {
807     bool pageChanged = page != d->activePage;
808     setActivePage( page );
809 
810     updateCanvasSize(true);
811 
812     updatePageNavigationActions();
813 
814     if ( pageChanged ) {
815         proxyObject->emitActivePageChanged();
816     }
817 
818     pageOffsetChanged();
819 }
820 
setActivePage(KoPAPageBase * page)821 void KoPAView::setActivePage( KoPAPageBase* page )
822 {
823     if ( !page )
824         return;
825 
826     bool pageChanged = page != d->activePage;
827 
828     shapeManager()->removeAdditional( d->activePage );
829     d->activePage = page;
830     shapeManager()->addAdditional( d->activePage );
831     QList<KoShape*> shapes = page->shapes();
832     shapeManager()->setShapes(shapes, KoShapeManager::AddWithoutRepaint);
833     //Make the top most layer active
834     if ( !shapes.isEmpty() ) {
835         KoShapeLayer* layer = dynamic_cast<KoShapeLayer*>( shapes.last() );
836         shapeManager()->selection()->setActiveLayer( layer );
837     }
838 
839     // if the page is not a master page itself set shapes of the master page
840     KoPAPage * paPage = dynamic_cast<KoPAPage *>( page );
841     if ( paPage ) {
842         KoPAMasterPage * masterPage = paPage->masterPage();
843         QList<KoShape*> masterShapes = masterPage->shapes();
844         masterShapeManager()->setShapes(masterShapes, KoShapeManager::AddWithoutRepaint);
845         //Make the top most layer active
846         if ( !masterShapes.isEmpty() ) {
847             KoShapeLayer* layer = dynamic_cast<KoShapeLayer*>( masterShapes.last() );
848             masterShapeManager()->selection()->setActiveLayer( layer );
849         }
850     }
851     else {
852         // if the page is a master page no shapes are in the masterShapeManager
853         masterShapeManager()->setShapes( QList<KoShape*>() );
854     }
855 
856     if ( mainWindow() && pageChanged ) {
857         d->documentStructureDocker->setActivePage(d->activePage);
858         proxyObject->emitActivePageChanged();
859     }
860 
861     // Set the current page number in the canvas resource provider
862     d->canvas->resourceManager()->setResource( KoCanvasResourceManager::CurrentPage, d->doc->pageIndex(d->activePage)+1 );
863 }
864 
navigatePage(KoPageApp::PageNavigation pageNavigation)865 void KoPAView::navigatePage( KoPageApp::PageNavigation pageNavigation )
866 {
867     KoPAPageBase * newPage = d->doc->pageByNavigation( d->activePage, pageNavigation );
868 
869     if ( newPage != d->activePage ) {
870         proxyObject->updateActivePage( newPage );
871     }
872 }
873 
createPrintJob()874 KoPrintJob * KoPAView::createPrintJob()
875 {
876     return new KoPAPrintJob(this);
877 }
878 
pageOffsetChanged()879 void KoPAView::pageOffsetChanged()
880 {
881     QPoint documentOrigin(d->canvas->documentOrigin());
882     d->horizontalRuler->setOffset(d->canvasController->canvasOffsetX() + documentOrigin.x());
883     d->verticalRuler->setOffset(d->canvasController->canvasOffsetY() + documentOrigin.y());
884 }
885 
updateMousePosition(const QPoint & position)886 void KoPAView::updateMousePosition(const QPoint& position)
887 {
888     const QPoint canvasOffset( d->canvasController->canvasOffsetX(), d->canvasController->canvasOffsetY() );
889     const QPoint viewPos = position - d->canvas->documentOrigin() - canvasOffset;
890 
891     d->horizontalRuler->updateMouseCoordinate(viewPos.x());
892     d->verticalRuler->updateMouseCoordinate(viewPos.y());
893 
894     // Update the selection borders in the rulers while moving with the mouse
895     if(d->canvas->shapeManager()->selection() && (d->canvas->shapeManager()->selection()->count() > 0)) {
896         QRectF boundingRect = d->canvas->shapeManager()->selection()->boundingRect();
897         d->horizontalRuler->updateSelectionBorders(boundingRect.x(), boundingRect.right());
898         d->verticalRuler->updateSelectionBorders(boundingRect.y(), boundingRect.bottom());
899     }
900 }
901 
selectionChanged()902 void KoPAView::selectionChanged()
903 {
904     // Show the borders of the selection in the rulers
905     if(d->canvas->shapeManager()->selection() && (d->canvas->shapeManager()->selection()->count() > 0)) {
906         QRectF boundingRect = d->canvas->shapeManager()->selection()->boundingRect();
907         d->horizontalRuler->setShowSelectionBorders(true);
908         d->verticalRuler->setShowSelectionBorders(true);
909         d->horizontalRuler->updateSelectionBorders(boundingRect.x(), boundingRect.right());
910         d->verticalRuler->updateSelectionBorders(boundingRect.y(), boundingRect.bottom());
911     } else {
912         d->horizontalRuler->setShowSelectionBorders(false);
913         d->verticalRuler->setShowSelectionBorders(false);
914     }
915 }
916 
setShowRulers(bool show)917 void KoPAView::setShowRulers(bool show)
918 {
919     d->horizontalRuler->setVisible(show);
920     d->verticalRuler->setVisible(show);
921 
922     d->viewRulers->setChecked(show);
923     d->doc->setRulersVisible(show);
924 }
925 
insertPage()926 void KoPAView::insertPage()
927 {
928     KoPAPageBase * page = 0;
929     if ( viewMode()->masterMode() ) {
930         KoPAMasterPage * masterPage = d->doc->newMasterPage();
931         masterPage->setBackground(QSharedPointer<KoColorBackground>(new KoColorBackground(Qt::white)));
932         // use the layout of the current active page for the new page
933         KoPageLayout & layout = masterPage->pageLayout();
934         KoPAMasterPage * activeMasterPage = dynamic_cast<KoPAMasterPage *>( d->activePage );
935         if ( activeMasterPage ) {
936             layout = activeMasterPage->pageLayout();
937         }
938         page = masterPage;
939     }
940     else {
941         KoPAPage * activePage = static_cast<KoPAPage*>( d->activePage );
942         KoPAMasterPage * masterPage = activePage->masterPage();
943         page = d->doc->newPage( masterPage );
944     }
945 
946     KoPAPageInsertCommand * command = new KoPAPageInsertCommand( d->doc, page, d->activePage );
947     d->canvas->addCommand( command );
948 
949     doUpdateActivePage(page);
950 }
951 
copyPage()952 void KoPAView::copyPage()
953 {
954     QList<KoPAPageBase *> pages;
955     pages.append( d->activePage );
956     KoPAOdfPageSaveHelper saveHelper( d->doc, pages );
957     KoDrag drag;
958     drag.setOdf( KoOdf::mimeType( d->doc->documentType() ), saveHelper );
959     drag.addToClipboard();
960 }
961 
deletePage()962 void KoPAView::deletePage()
963 {
964     if ( !isMasterUsed( d->activePage ) ) {
965         d->doc->removePage( d->activePage );
966     }
967 }
968 
setActionEnabled(int actions,bool enable)969 void KoPAView::setActionEnabled( int actions, bool enable )
970 {
971     if ( actions & ActionInsertPage )
972     {
973         d->actionInsertPage->setEnabled( enable );
974     }
975     if ( actions & ActionCopyPage )
976     {
977         d->actionCopyPage->setEnabled( enable );
978     }
979     if ( actions & ActionDeletePage )
980     {
981         d->actionDeletePage->setEnabled( enable );
982     }
983     if ( actions & ActionViewShowMasterPages )
984     {
985         d->actionViewShowMasterPages->setEnabled( enable );
986     }
987     if ( actions & ActionFormatMasterPage )
988     {
989         d->actionMasterPage->setEnabled( enable );
990     }
991 }
992 
setViewMode(KoPAViewMode * mode)993 void KoPAView::setViewMode(KoPAViewMode* mode)
994 {
995     KoPAViewMode* previousViewMode = viewMode();
996     KoPAViewBase::setViewMode(mode);
997 
998     if (previousViewMode && mode != previousViewMode) {
999         disconnect(d->doc, SIGNAL(shapeAdded(KoShape*)), previousViewMode, SLOT(addShape(KoShape*)));
1000         disconnect(d->doc, SIGNAL(shapeRemoved(KoShape*)), previousViewMode, SLOT(removeShape(KoShape*)));
1001     }
1002     connect(d->doc, SIGNAL(shapeAdded(KoShape*)), mode, SLOT(addShape(KoShape*)));
1003     connect(d->doc, SIGNAL(shapeRemoved(KoShape*)), mode, SLOT(removeShape(KoShape*)));
1004 }
1005 
pageThumbnail(KoPAPageBase * page,const QSize & size)1006 QPixmap KoPAView::pageThumbnail(KoPAPageBase* page, const QSize& size)
1007 {
1008     return d->doc->pageThumbnail(page, size);
1009 }
1010 
exportPageThumbnail(KoPAPageBase * page,const QUrl & url,const QSize & size,const char * format,int quality)1011 bool KoPAView::exportPageThumbnail( KoPAPageBase * page, const QUrl &url, const QSize& size,
1012                                     const char * format, int quality )
1013 {
1014     bool res = false;
1015     QPixmap pix = d->doc->pageThumbnail( page, size );
1016     if ( !pix.isNull() ) {
1017         // Depending on the desired target size due to rounding
1018         // errors during zoom the resulting pixmap *might* be
1019         // 1 pixel or 2 pixels wider/higher than desired: we just
1020         // remove the additional columns/rows.  This can be done
1021         // since Stage is leaving a minimal border below/at
1022         // the right of the image anyway.
1023         if ( size != pix.size() ) {
1024             pix = pix.copy( 0, 0, size.width(), size.height() );
1025         }
1026         // save the pixmap to the desired file
1027         QUrl fileUrl( url );
1028         if ( fileUrl.scheme().isEmpty() ) {
1029             fileUrl.setScheme( "file" );
1030         }
1031         const bool bLocalFile = fileUrl.isLocalFile();
1032         QTemporaryFile* tmpFile = bLocalFile ? 0 : new QTemporaryFile();
1033         if( bLocalFile || tmpFile->open() ) {
1034             QFile file( bLocalFile ? fileUrl.path() : tmpFile->fileName() );
1035             if ( file.open( QIODevice::ReadWrite ) ) {
1036                 res = pix.save( &file, format, quality );
1037                 file.close();
1038             }
1039             if ( !bLocalFile ) {
1040                 if ( res ) {
1041                     res = KIO::NetAccess::upload( tmpFile->fileName(), fileUrl, this );
1042                 }
1043             }
1044         }
1045         if ( !bLocalFile ) {
1046             delete tmpFile;
1047         }
1048    }
1049    return res;
1050 }
1051 
documentStructureDocker() const1052 KoPADocumentStructureDocker* KoPAView::documentStructureDocker() const
1053 {
1054     return d->documentStructureDocker;
1055 }
1056 
clipboardDataChanged()1057 void KoPAView::clipboardDataChanged()
1058 {
1059     const QMimeData* data = QApplication::clipboard()->mimeData();
1060     bool paste = false;
1061 
1062     if (data)
1063     {
1064         // TODO see if we can use the KoPasteController instead of having to add this feature in each calligra app.
1065         QStringList mimeTypes = d->canvas->toolProxy()->supportedPasteMimeTypes();
1066         mimeTypes << KoOdf::mimeType( KoOdf::Graphics );
1067         mimeTypes << KoOdf::mimeType( KoOdf::Presentation );
1068 
1069         foreach(const QString & mimeType, mimeTypes)
1070         {
1071             if ( data->hasFormat( mimeType ) ) {
1072                 paste = true;
1073                 break;
1074             }
1075         }
1076 
1077     }
1078 
1079     d->editPaste->setEnabled(paste);
1080 }
1081 
goToPreviousPage()1082 void KoPAView::goToPreviousPage()
1083 {
1084     navigatePage( KoPageApp::PagePrevious );
1085 }
1086 
goToNextPage()1087 void KoPAView::goToNextPage()
1088 {
1089     navigatePage( KoPageApp::PageNext );
1090 }
1091 
goToFirstPage()1092 void KoPAView::goToFirstPage()
1093 {
1094     navigatePage( KoPageApp::PageFirst );
1095 }
1096 
goToLastPage()1097 void KoPAView::goToLastPage()
1098 {
1099     navigatePage( KoPageApp::PageLast );
1100 }
1101 
findDocumentSetNext(QTextDocument * document)1102 void KoPAView::findDocumentSetNext( QTextDocument * document )
1103 {
1104     KoPAPageBase * page = 0;
1105     KoShape * startShape = 0;
1106     KoTextDocumentLayout *lay = document ? qobject_cast<KoTextDocumentLayout*>(document->documentLayout()) : 0;
1107     if ( lay != 0 ) {
1108         startShape = lay->shapes().value( 0 );
1109         Q_ASSERT( startShape->shapeId() == "TextShapeID" );
1110         page = d->doc->pageByShape( startShape );
1111         if ( d->doc->pageIndex( page ) == -1 ) {
1112             page = 0;
1113         }
1114     }
1115 
1116     if ( page == 0 ) {
1117         page = d->activePage;
1118         startShape = page;
1119     }
1120 
1121     KoShape * shape = startShape;
1122 
1123     do {
1124         // find next text shape
1125         shape = KoShapeTraversal::nextShape( shape, "TextShapeID" );
1126         // get next text shape
1127         if ( shape != 0 ) {
1128             if ( page != d->activePage ) {
1129                 setActivePage( page );
1130                 d->canvas->update();
1131             }
1132             KoSelection* selection = kopaCanvas()->shapeManager()->selection();
1133             selection->deselectAll();
1134             selection->select( shape );
1135             // TODO can this be done nicer? is there a way to get the shape id and the tool id from the shape?
1136             KoToolManager::instance()->switchToolRequested( "TextToolFactory_ID" );
1137             break;
1138         }
1139         else {
1140             //if none is found go to next page and try again
1141             if ( d->doc->pageIndex( page ) < d->doc->pages().size() - 1 ) {
1142                 // TODO use also master slides
1143                 page = d->doc->pageByNavigation( page, KoPageApp::PageNext );
1144             }
1145             else {
1146                 page = d->doc->pageByNavigation( page, KoPageApp::PageFirst );
1147             }
1148             shape = page;
1149         }
1150         // do until you find the same start shape or you are on the same page again only if there was none
1151     } while ( page != startShape );
1152 }
1153 
findDocumentSetPrevious(QTextDocument * document)1154 void KoPAView::findDocumentSetPrevious( QTextDocument * document )
1155 {
1156     KoPAPageBase * page = 0;
1157     KoShape * startShape = 0;
1158     KoTextDocumentLayout *lay = document ? qobject_cast<KoTextDocumentLayout*>(document->documentLayout()) : 0;
1159     if ( lay != 0 ) {
1160         startShape = lay->shapes().value( 0 );
1161         Q_ASSERT( startShape->shapeId() == "TextShapeID" );
1162         page = d->doc->pageByShape( startShape );
1163         if ( d->doc->pageIndex( page ) == -1 ) {
1164             page = 0;
1165         }
1166     }
1167 
1168     bool check = false;
1169     if ( page == 0 ) {
1170         page = d->activePage;
1171         startShape = KoShapeTraversal::last( page );
1172         check = true;
1173     }
1174 
1175     KoShape * shape = startShape;
1176 
1177     do {
1178         if ( !check || shape->shapeId() != "TextShapeID" ) {
1179             shape = KoShapeTraversal::previousShape( shape, "TextShapeID" );
1180         }
1181         // get next text shape
1182         if ( shape != 0 ) {
1183             if ( page != d->activePage ) {
1184                 setActivePage( page );
1185                 d->canvas->update();
1186             }
1187             KoSelection* selection = kopaCanvas()->shapeManager()->selection();
1188             selection->deselectAll();
1189             selection->select( shape );
1190             // TODO can this be done nicer? is there a way to get the shape id and the tool id from the shape?
1191             KoToolManager::instance()->switchToolRequested( "TextToolFactory_ID" );
1192             break;
1193         }
1194         else {
1195             //if none is found go to next page and try again
1196             if ( d->doc->pageIndex( page ) > 0 ) {
1197                 // TODO use also master slides
1198                 page = d->doc->pageByNavigation( page, KoPageApp::PagePrevious );
1199             }
1200             else {
1201                 page = d->doc->pageByNavigation( page, KoPageApp::PageLast );
1202             }
1203             shape = KoShapeTraversal::last( page );
1204             check = true;
1205         }
1206         // do until you find the same start shape or you are on the same page again only if there was none
1207     } while ( shape != startShape );
1208 }
1209 
updatePageNavigationActions()1210 void KoPAView::updatePageNavigationActions()
1211 {
1212     int index = d->doc->pageIndex(activePage());
1213     int pageCount = d->doc->pages(viewMode()->masterMode()).count();
1214 
1215     actionCollection()->action("page_previous")->setEnabled(index > 0);
1216     actionCollection()->action("page_first")->setEnabled(index > 0);
1217     actionCollection()->action("page_next")->setEnabled(index < pageCount - 1);
1218     actionCollection()->action("page_last")->setEnabled(index < pageCount - 1);
1219 }
1220 
isMasterUsed(KoPAPageBase * page)1221 bool KoPAView::isMasterUsed( KoPAPageBase * page )
1222 {
1223     KoPAMasterPage * master = dynamic_cast<KoPAMasterPage *>( page );
1224 
1225     bool used = false;
1226 
1227     if ( master ) {
1228         QList<KoPAPageBase*> pages = d->doc->pages();
1229         foreach( KoPAPageBase * page, pages ) {
1230             KoPAPage * p = dynamic_cast<KoPAPage *>( page );
1231             Q_ASSERT( p );
1232             if ( p && p->masterPage() == master ) {
1233                 used = true;
1234                 break;
1235             }
1236         }
1237     }
1238 
1239     return used;
1240 }
1241 
centerPage()1242 void KoPAView::centerPage()
1243 {
1244     KoPageLayout &layout = d->activePage->pageLayout();
1245     QSizeF pageSize( layout.width, layout.height );
1246 
1247     QPoint documentCenter =
1248         zoomHandler()->documentToView(QPoint(pageSize.width(),
1249                                               pageSize.height())).toPoint();
1250 
1251     d->canvasController->setPreferredCenter(documentCenter);
1252     d->canvasController->recenterPreferred();
1253 
1254 }
1255 
tabBar() const1256 QTabBar *KoPAView::tabBar() const
1257 {
1258     return d->tabBar;
1259 }
1260 
replaceCentralWidget(QWidget * newWidget)1261 void KoPAView::replaceCentralWidget(QWidget *newWidget)
1262 {
1263     // hide standard central widget
1264     d->insideWidget->hide();
1265     // If there is already a custom central widget, it's hided and removed from the layout
1266     hideCustomCentralWidget();
1267     // layout and show new custom widget
1268     d->tabBarLayout->addWidget(newWidget, 2, 1);
1269     newWidget->show();
1270 }
1271 
restoreCentralWidget()1272 void KoPAView::restoreCentralWidget()
1273 {
1274     //hide custom central widget
1275     hideCustomCentralWidget();
1276     //show standard central widget
1277     d->insideWidget->show();
1278 }
1279 
hideCustomCentralWidget()1280 void KoPAView::hideCustomCentralWidget()
1281 {
1282     if (d->tabBarLayout->itemAtPosition(2, 1)) {
1283         if (d->tabBarLayout->itemAtPosition(2, 1)->widget()) {
1284             d->tabBarLayout->itemAtPosition(2, 1)->widget()->hide();
1285         }
1286         d->tabBarLayout->removeItem(d->tabBarLayout->itemAtPosition(2, 1));
1287     }
1288 }
1289 
setTabBarPosition(Qt::Orientation orientation)1290 void KoPAView::setTabBarPosition(Qt::Orientation orientation)
1291 {
1292     switch (orientation) {
1293     case Qt::Horizontal:
1294         d->tabBarLayout->removeWidget(d->tabBar);
1295         d->tabBar->setShape(QTabBar::RoundedNorth);
1296         d->tabBarLayout->addWidget(d->tabBar, 0, 1);
1297         break;
1298     case Qt::Vertical:
1299         d->tabBarLayout->removeWidget(d->tabBar);
1300         d->tabBar->setShape(QTabBar::RoundedWest);
1301         d->tabBarLayout->addWidget(d->tabBar, 1, 0, 2, 1, Qt::AlignTop);
1302         break;
1303     default:
1304         break;
1305     }
1306 }
1307 
updateUnit(const KoUnit & unit)1308 void KoPAView::updateUnit(const KoUnit &unit)
1309 {
1310     d->horizontalRuler->setUnit(unit);
1311     d->verticalRuler->setUnit(unit);
1312     d->canvas->resourceManager()->setResource(KoCanvasResourceManager::Unit, unit);
1313 }
1314