1 /* This file is part of the KDE project
2  * Copyright (C) 2006-2007 Jan Hambrecht <jaham@gmx.net>
3  * Copyright (C) 2008-2009 Fredy Yanardi <fyanardi@gmail.com>
4  * Copyright (C) 2009 Jean-Nicolas Artaud <jeannicolasartaud@gmail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public License
17  * along with this library; see the file COPYING.LIB.  If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #include "KoPADocumentStructureDocker.h"
23 
24 #include "KoPADocumentModel.h"
25 #include "KoPADocument.h"
26 #include "KoPAPageBase.h"
27 #include "KoPACanvas.h"
28 #include "KoPAViewBase.h"
29 
30 #include <KoShapeManager.h>
31 #include <KoToolManager.h>
32 #include <KoCanvasBase.h>
33 #include <KoCanvasController.h>
34 #include <KoSelection.h>
35 #include <KoShapeOdfSaveHelper.h>
36 #include <KoPAOdfPageSaveHelper.h>
37 #include <KoDrag.h>
38 #include <KoShapeCreateCommand.h>
39 #include <KoShapeDeleteCommand.h>
40 #include <KoShapeReorderCommand.h>
41 #include <KoShapeLayer.h>
42 #include <KoShapePaste.h>
43 #include <KoViewItemContextBar.h>
44 
45 #include <KoIcon.h>
46 
47 #include <KSharedConfig>
48 #include <klocalizedstring.h>
49 #include <kmessagebox.h>
50 #include <kconfiggroup.h>
51 
52 #include <QMimeData>
53 #include <QMenu>
54 #include <QInputDialog>
55 #include <QGridLayout>
56 #include <QToolButton>
57 #include <QButtonGroup>
58 #include <QItemSelection>
59 #include <QApplication>
60 #include <QClipboard>
61 
62 #include <algorithm>
63 
64 enum ButtonIds
65 {
66     Button_Raise,
67     Button_Lower,
68     Button_Delete
69 };
70 
KoPADocumentStructureDockerFactory(KoDocumentSectionView::DisplayMode mode,KoPageApp::PageType pageType)71 KoPADocumentStructureDockerFactory::KoPADocumentStructureDockerFactory(KoDocumentSectionView::DisplayMode mode, KoPageApp::PageType pageType)
72 : m_mode(mode)
73 , m_pageType(pageType)
74 {
75 }
76 
id() const77 QString KoPADocumentStructureDockerFactory::id() const
78 {
79     return QString("document section view");
80 }
81 
createDockWidget()82 QDockWidget* KoPADocumentStructureDockerFactory::createDockWidget()
83 {
84     return new KoPADocumentStructureDocker(m_mode, m_pageType);
85 }
86 
KoPADocumentStructureDocker(KoDocumentSectionView::DisplayMode mode,KoPageApp::PageType pageType,QWidget * parent)87 KoPADocumentStructureDocker::KoPADocumentStructureDocker(KoDocumentSectionView::DisplayMode mode, KoPageApp::PageType pageType, QWidget* parent)
88 : QDockWidget(parent)
89 , KoCanvasObserverBase()
90 , m_doc(0)
91 , m_model(0)
92 {
93     setWindowTitle(i18n("Document"));
94 
95     QWidget *mainWidget = new QWidget(this);
96     QGridLayout* layout = new QGridLayout(mainWidget);
97     layout->addWidget(m_sectionView = new KoDocumentSectionView(mainWidget), 0, 0, 1, -1);
98 
99     QToolButton *button = new QToolButton(mainWidget);
100     button->setIcon(koIcon("list-add"));
101     if (pageType == KoPageApp::Slide) {
102         button->setToolTip(i18n("Add a new slide or layer"));
103     }
104     else {
105         button->setToolTip(i18n("Add a new page or layer"));
106     }
107     layout->addWidget(button, 1, 0);
108 
109     QMenu *menu = new QMenu(button);
110     button->setMenu(menu);
111     button->setPopupMode(QToolButton::InstantPopup);
112     menu->addAction(koIcon("document-new"),
113                     (pageType == KoPageApp::Slide) ? i18n("Slide") : i18n("Page"),
114                     this, SLOT(addPage()));
115     m_addLayerAction = menu->addAction(koIcon("layer-new"), i18n("Layer"), this, SLOT(addLayer()));
116 
117     m_buttonGroup = new QButtonGroup(mainWidget);
118     m_buttonGroup->setExclusive(false);
119 
120     button = new QToolButton(mainWidget);
121     button->setIcon(koIcon("list-remove"));
122     button->setToolTip(i18n("Delete selected objects"));
123     m_buttonGroup->addButton(button, Button_Delete);
124     layout->addWidget(button, 1, 1);
125 
126     button = new QToolButton(mainWidget);
127     button->setIcon(koIcon("arrow-up"));
128     button->setToolTip(i18n("Raise selected objects"));
129     m_buttonGroup->addButton(button, Button_Raise);
130     layout->addWidget(button, 1, 3);
131 
132     button = new QToolButton(mainWidget);
133     button->setIcon(koIcon("arrow-down"));
134     button->setToolTip(i18n("Lower selected objects"));
135     m_buttonGroup->addButton(button, Button_Lower);
136     layout->addWidget(button, 1, 4);
137 
138     button = new QToolButton(mainWidget);
139     menu = new QMenu(this);
140     QActionGroup *group = new QActionGroup(this);
141 
142     m_viewModeActions.insert(KoDocumentSectionView::MinimalMode,
143                               menu->addAction(koIcon("view-list-text"), i18n("Minimal View"), this, SLOT(minimalView())));
144     m_viewModeActions.insert(KoDocumentSectionView::DetailedMode,
145                               menu->addAction(koIcon("view-list-details"), i18n("Detailed View"), this, SLOT(detailedView())));
146     m_viewModeActions.insert(KoDocumentSectionView::ThumbnailMode,
147                               menu->addAction(koIcon("view-preview"), i18n("Thumbnail View"), this, SLOT(thumbnailView())));
148 
149     foreach (QAction* action, m_viewModeActions) {
150         action->setCheckable(true);
151         action->setActionGroup(group);
152     }
153 
154     button->setMenu(menu);
155     button->setPopupMode(QToolButton::InstantPopup);
156     button->setIcon(koIcon("view-choose"));
157     button->setText(i18n("View mode"));
158     layout->addWidget(button, 1, 5);
159 
160     layout->setSpacing(0);
161     layout->setMargin(3);
162     layout->setColumnStretch(2, 10);
163 
164     setWidget(mainWidget);
165 
166     connect(m_buttonGroup, SIGNAL(buttonClicked(int)), this, SLOT(slotButtonClicked(int)));
167 
168     m_model = new KoPADocumentModel(this);
169     m_sectionView->setModel(m_model);
170     m_sectionView->setSelectionBehavior(QAbstractItemView::SelectRows);
171     m_sectionView->setSelectionMode(QAbstractItemView::ExtendedSelection);
172     m_sectionView->setDragDropMode(QAbstractItemView::InternalMove);
173 
174     connect(m_sectionView, SIGNAL(pressed(QModelIndex)), this, SLOT(itemClicked(QModelIndex)));
175     connect(m_sectionView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
176              this, SLOT(itemSelected(QItemSelection,QItemSelection)));
177 
178     connect(m_model, SIGNAL(requestPageSelection(int,int)), this, SLOT(selectPages(int,int)));
179     connect(m_model, SIGNAL(modelReset()), this, SIGNAL(dockerReset()));
180 
181     KConfigGroup configGroup =  KSharedConfig::openConfig()->group("KoPageApp/DocumentStructureDocker");
182     QString viewModeString = configGroup.readEntry("ViewMode", "");
183 
184     if (viewModeString.isEmpty())
185         setViewMode(mode);
186     else
187         setViewMode(viewModeFromString(viewModeString));
188 
189     m_itemsContextBar = new KoViewItemContextBar(m_sectionView);
190 }
191 
~KoPADocumentStructureDocker()192 KoPADocumentStructureDocker::~KoPADocumentStructureDocker()
193 {
194     KConfigGroup configGroup =  KSharedConfig::openConfig()->group("KoPageApp/DocumentStructureDocker");
195     configGroup.writeEntry("ViewMode", viewModeToString(m_sectionView->displayMode()));
196 }
197 
updateView()198 void KoPADocumentStructureDocker::updateView()
199 {
200     m_model->update();
201 }
202 
slotButtonClicked(int buttonId)203 void KoPADocumentStructureDocker::slotButtonClicked(int buttonId)
204 {
205     switch (buttonId)
206     {
207         case Button_Raise:
208             raiseItem();
209             break;
210         case Button_Lower:
211             lowerItem();
212             break;
213         case Button_Delete:
214             deleteItem();
215             break;
216     }
217 }
218 
itemClicked(const QModelIndex & index)219 void KoPADocumentStructureDocker::itemClicked(const QModelIndex &index)
220 {
221     Q_ASSERT(index.internalPointer());
222 
223     if (!index.isValid())
224         return;
225 
226     KoShape *shape = static_cast<KoShape*>(index.internalPointer());
227     if (!shape)
228         return;
229     // check whether the newly selected shape is a page or shape/layer
230     bool isPage = (dynamic_cast<KoPAPageBase *>(shape) != 0);
231     KoCanvasController* canvasController = KoToolManager::instance()->activeCanvasController();
232     KoSelection *selection = canvasController->canvas()->shapeManager()->selection();
233 
234     if (isPage) {
235         // no shape is currently selected
236         if (!m_selectedShapes.isEmpty()) {
237             m_sectionView->clearSelection();
238             selection->deselectAll();
239             m_sectionView->setCurrentIndex(index);
240             m_selectedShapes.clear();
241             emit pageChanged(dynamic_cast<KoPAPageBase *>(shape));
242         }
243         else {
244             // There are more than one page selected
245             if (m_sectionView->selectionModel()->selectedIndexes().size() == 1) {
246                 emit pageChanged(dynamic_cast<KoPAPageBase *>(shape));
247             }
248         }
249     }
250     else {
251         KoPAPageBase *newPageByShape = m_doc->pageByShape(shape);
252         // there is already shape(s) selected
253         if (!m_selectedShapes.isEmpty()) {
254             // if the newly selected shape is not in the same page as previously
255             // selected shape(s), then clear previous selection
256             KoPAPageBase *currentPage = m_doc->pageByShape(m_selectedShapes.first());
257             KoShapeLayer *layer = dynamic_cast<KoShapeLayer *>(shape);
258             if (currentPage != newPageByShape) {
259                 m_sectionView->clearSelection();
260                 selection->deselectAll();
261                 m_sectionView->setCurrentIndex(index);
262                 m_selectedShapes.clear();
263                 emit pageChanged(newPageByShape);
264                 if (layer) {
265                     selection->setActiveLayer(layer);
266                 }
267                 else {
268                     selection->select(shape);
269                     shape->update();
270                 }
271             }
272             else {
273                 QList<KoPAPageBase*> selectedPages;
274                 QList<KoShapeLayer*> selectedLayers;
275                 QList<KoShape*> selectedShapes;
276 
277                 // separate selected layers and selected shapes
278                 extractSelectedLayersAndShapes(selectedPages, selectedLayers, selectedShapes);
279 
280                 // XXX: Do stuff withthe selected pages!
281 
282                 foreach (KoShape* shape, selection->selectedShapes()) {
283                     shape->update();
284                 }
285                 selection->deselectAll();
286                 foreach (KoShape* shape, selectedShapes) {
287                     if (shape) {
288                         selection->select(shape);
289                         shape->update();
290                     }
291                 }
292                 // if we just selected a layer, check whether this layer is already active, if not
293                 // then make it active
294                 if (layer && selection->activeLayer() != layer && selectedLayers.count() <= 1) {
295                     selection->setActiveLayer(layer);
296                 }
297             }
298         }
299         // no shape is selected, meaning only page(s) is selected
300         else {
301             m_sectionView->clearSelection();
302             m_sectionView->setCurrentIndex(index);
303             selection->select(shape);
304             shape->update();
305             emit pageChanged(newPageByShape);
306         }
307         m_selectedShapes.append(shape);
308     }
309 }
310 
addLayer()311 void KoPADocumentStructureDocker::addLayer()
312 {
313     bool ok = true;
314     QString name = QInputDialog::getText(this, i18n("New Layer"), i18n("Enter the name of the new layer:"),
315                                          QLineEdit::Normal, i18n("New layer"), &ok);
316     if (ok) {
317         KoShapeLayer* layer = new KoShapeLayer();
318         KoPACanvas * canvas = dynamic_cast<KoPACanvas *>(KoToolManager::instance()->activeCanvasController()->canvas());
319         if (canvas) {
320             layer->setParent(canvas->koPAView()->activePage());
321             layer->setName(name);
322             QList<KoShape*> layers(canvas->koPAView()->activePage()->shapes());
323             if (!layers.isEmpty()) {
324                 std::sort(layers.begin(), layers.end(), KoShape::compareShapeZIndex);
325                 layer->setZIndex(layers.last()->zIndex() + 1);
326             }
327             KUndo2Command *cmd = new KoShapeCreateCommand(m_doc, layer, 0);
328             cmd->setText(kundo2_i18n("Create Layer"));
329             m_doc->addCommand(cmd);
330             m_model->update();
331         }
332     }
333 }
334 
deleteItem()335 void KoPADocumentStructureDocker::deleteItem()
336 {
337     QList<KoPAPageBase*> selectedPages;
338     QList<KoShapeLayer*> selectedLayers;
339     QList<KoShape*> selectedShapes;
340 
341     // separate selected layers and selected shapes
342     extractSelectedLayersAndShapes(selectedPages, selectedLayers, selectedShapes);
343 
344     KUndo2Command *cmd = 0;
345 
346     if (selectedLayers.count()) {
347         if (m_doc->pages().count() > selectedPages.count()) {
348             QList<KoShape*> deleteShapes;
349             foreach(KoPAPageBase* page, selectedPages) {
350                 deleteShapes += page->shapes();
351                 deleteShapes.append(page);
352             }
353             cmd = new KoShapeDeleteCommand(m_doc, deleteShapes);
354             cmd->setText(kundo2_i18n("Delete Layer"));
355         }
356         else {
357             KMessageBox::error(0, i18n("Could not delete all layers. At least one layer is required."), i18n("Error deleting layers"));
358         }
359     }
360     else if (selectedShapes.count()) {
361         cmd = new KoShapeDeleteCommand(m_doc, selectedShapes);
362     }
363     else if (!selectedPages.isEmpty() && selectedPages.count() < m_doc->pages().count()) {
364         m_doc->removePages(selectedPages);
365     }
366 
367     if (cmd) {
368         m_doc->addCommand(cmd);
369         m_model->update();
370     }
371 }
372 
raiseItem()373 void KoPADocumentStructureDocker::raiseItem()
374 {
375     QList<KoPAPageBase*> selectedPages;
376     QList<KoShapeLayer*> selectedLayers;
377     QList<KoShape*> selectedShapes;
378 
379     // separate selected layers and selected shapes
380     extractSelectedLayersAndShapes(selectedPages, selectedLayers, selectedShapes);
381 
382     KUndo2Command *cmd = 0;
383 
384     if (selectedLayers.count()) {
385 //         // check if all layers could be raised
386 //         foreach(KoShapeLayer* layer, selectedLayers)
387 //             if (! m_document->canRaiseLayer(layer))
388 //                 return;
389 
390 //        cmd = new KoPALayerReorderCommand(m_document, selectedLayers, KoPALayerReorderCommand::RaiseLayer);
391     }
392     else if (selectedShapes.count()) {
393         cmd = KoShapeReorderCommand::createCommand(selectedShapes,
394                 KoToolManager::instance()->activeCanvasController()->canvas()->shapeManager(),
395                 KoShapeReorderCommand::RaiseShape);
396     }
397 
398     if (cmd) {
399         m_doc->addCommand(cmd);
400         m_model->update();
401     }
402 }
403 
lowerItem()404 void KoPADocumentStructureDocker::lowerItem()
405 {
406     QList<KoPAPageBase*> selectedPages;
407     QList<KoShapeLayer*> selectedLayers;
408     QList<KoShape*> selectedShapes;
409 
410     // separate selected layers and selected shapes
411     extractSelectedLayersAndShapes(selectedPages, selectedLayers, selectedShapes);
412 
413     KUndo2Command *cmd = 0;
414 
415     if (selectedLayers.count()) {
416 //         // check if all layers could be raised
417 //         foreach(KoShapeLayer* layer, selectedLayers)
418 //             if (! m_document->canLowerLayer(layer))
419 //                 return;
420 
421 //        cmd = new KoPALayerReorderCommand(m_document, selectedLayers, KoPALayerReorderCommand::LowerLayer);
422     }
423     else if (selectedShapes.count()) {
424         cmd = KoShapeReorderCommand::createCommand(selectedShapes,
425                 KoToolManager::instance()->activeCanvasController()->canvas()->shapeManager(),
426                 KoShapeReorderCommand::LowerShape);
427     }
428 
429     if (cmd) {
430         m_doc->addCommand(cmd);
431         m_model->update();
432     }
433 }
434 
extractSelectedLayersAndShapes(QList<KoPAPageBase * > & pages,QList<KoShapeLayer * > & layers,QList<KoShape * > & shapes)435 void KoPADocumentStructureDocker::extractSelectedLayersAndShapes(QList<KoPAPageBase*> &pages, QList<KoShapeLayer*> &layers, QList<KoShape*> &shapes)
436 {
437     pages.clear();
438     layers.clear();
439     shapes.clear();
440 
441     QModelIndexList selectedItems = m_sectionView->selectionModel()->selectedIndexes();
442     if (selectedItems.count() == 0)
443         return;
444 
445     // TODO tz: I don't know what is best:
446     // 1. only make it possible to select one type of object page, layer, shape
447     // 2. don't add shapes when we already have the page/layer/group in the selection
448     // separate selected layers and selected shapes
449     foreach(const QModelIndex & index, selectedItems) {
450         KoShape *shape = static_cast<KoShape*>(index.internalPointer());
451         KoPAPageBase * page = dynamic_cast<KoPAPageBase*>(shape);
452         if (page) {
453             pages.append(page);
454         }
455         else {
456             KoShapeLayer *layer = dynamic_cast<KoShapeLayer*>(shape);
457             if (layer)
458                 layers.append(layer);
459             else if (! selectedItems.contains(index.parent()))
460                 shapes.append(shape);
461         }
462     }
463 }
464 
setCanvas(KoCanvasBase * canvas)465 void KoPADocumentStructureDocker::setCanvas(KoCanvasBase* canvas)
466 {
467     KoPACanvas * c = dynamic_cast<KoPACanvas*> (canvas);
468     if (c) {
469         m_doc = c->document();
470         m_model->setDocument(m_doc);
471         m_sectionView->setModel(m_model);
472     }
473 }
474 
unsetCanvas()475 void KoPADocumentStructureDocker::unsetCanvas()
476 {
477     m_doc = 0;
478     m_model->setDocument(0);
479     m_sectionView->setModel(0);
480 }
481 
setActivePage(KoPAPageBase * page)482 void KoPADocumentStructureDocker::setActivePage(KoPAPageBase *page)
483 {
484     if (m_doc) {
485         int row = m_doc->pageIndex(page);
486         QModelIndex index = m_model->index(row, 0);
487         if (index != m_sectionView->currentIndex()
488                 && index != getRootIndex(m_sectionView->currentIndex())) {
489             m_sectionView->setCurrentIndex(index);
490         }
491     }
492 }
493 
setMasterMode(bool master)494 void KoPADocumentStructureDocker::setMasterMode(bool master)
495 {
496     m_model->setMasterMode(master);
497 }
498 
minimalView()499 void KoPADocumentStructureDocker::minimalView()
500 {
501     setViewMode(KoDocumentSectionView::MinimalMode);
502     m_itemsContextBar->disableContextBar();
503 }
504 
detailedView()505 void KoPADocumentStructureDocker::detailedView()
506 {
507     setViewMode(KoDocumentSectionView::DetailedMode);
508     m_itemsContextBar->disableContextBar();
509 }
510 
thumbnailView()511 void KoPADocumentStructureDocker::thumbnailView()
512 {
513     setViewMode(KoDocumentSectionView::ThumbnailMode);
514     m_itemsContextBar->enableContextBar();
515 }
516 
setViewMode(KoDocumentSectionView::DisplayMode mode)517 void KoPADocumentStructureDocker::setViewMode(KoDocumentSectionView::DisplayMode mode)
518 {
519     bool expandable = (mode != KoDocumentSectionView::ThumbnailMode);
520 
521     // if we switch to non-expandable mode (ThumbnailMode) and if current index
522     // is not a page, we need to select the corresponding page first, otherwise
523     // none of the page will be selected when we do collapse all
524     if (!expandable) {
525         QModelIndex currentIndex = m_sectionView->currentIndex();
526         QModelIndex rootIndex = getRootIndex(currentIndex);
527         if (currentIndex != rootIndex) {
528             m_sectionView->setCurrentIndex(rootIndex);
529         }
530         m_sectionView->collapseAll();
531     }
532 
533     m_sectionView->setDisplayMode(mode);
534     m_sectionView->setItemsExpandable(expandable);
535     m_sectionView->setRootIsDecorated(expandable);
536     // m_sectionView->setSelectionMode(expandable ? QAbstractItemView::ExtendedSelection : QAbstractItemView::SingleSelection);
537 
538     m_viewModeActions[mode]->setChecked (true);
539 }
540 
getRootIndex(const QModelIndex & index) const541 QModelIndex KoPADocumentStructureDocker::getRootIndex(const QModelIndex &index) const
542 {
543     QModelIndex currentIndex;
544     QModelIndex parentIndex = index.parent();
545     if (!parentIndex.isValid()) {
546         return index;
547     }
548     while (parentIndex.isValid()) {
549         currentIndex = parentIndex;
550         parentIndex = currentIndex.parent();
551     }
552 
553     return currentIndex;
554 }
555 
viewModeFromString(const QString & mode)556 KoDocumentSectionView::DisplayMode KoPADocumentStructureDocker::viewModeFromString(const QString& mode)
557 {
558     if (mode == "Minimal")
559         return KoDocumentSectionView::MinimalMode;
560     else if (mode == "Detailed")
561         return KoDocumentSectionView::DetailedMode;
562     else if (mode == "Thumbnail")
563         return KoDocumentSectionView::ThumbnailMode;
564 
565     return KoDocumentSectionView::DetailedMode;
566 }
567 
viewModeToString(KoDocumentSectionView::DisplayMode mode)568 QString KoPADocumentStructureDocker::viewModeToString(KoDocumentSectionView::DisplayMode mode)
569 {
570     switch (mode)
571     {
572         case KoDocumentSectionView::MinimalMode:
573             return QString("Minimal");
574             break;
575         case KoDocumentSectionView::DetailedMode:
576             return QString("Detailed");
577             break;
578         case KoDocumentSectionView::ThumbnailMode:
579             return QString("Thumbnail");
580             break;
581     }
582 
583     return QString();
584 }
585 
itemSelected(const QItemSelection & selected,const QItemSelection & deselected)586 void KoPADocumentStructureDocker::itemSelected(const QItemSelection& selected, const QItemSelection& deselected)
587 {
588     Q_UNUSED(deselected);
589 
590     if (selected.indexes().isEmpty()) {
591         m_buttonGroup->button(Button_Raise)->setEnabled(false);
592         m_buttonGroup->button(Button_Lower)->setEnabled(false);
593         m_addLayerAction->setEnabled(false);
594     }
595     else {
596         m_buttonGroup->button(Button_Raise)->setEnabled(true);
597         m_buttonGroup->button(Button_Lower)->setEnabled(true);
598         m_addLayerAction->setEnabled(true);
599     }
600 
601     if (!m_sectionView->selectionModel()->selectedIndexes().empty() &&
602             m_sectionView->selectionModel()->selectedIndexes().count() < m_doc->pages().count()) {
603         m_buttonGroup->button(Button_Delete)->setEnabled(true);
604     }
605     else {
606         m_buttonGroup->button(Button_Delete)->setEnabled(false);
607     }
608 }
609 
addPage()610 void KoPADocumentStructureDocker::addPage()
611 {
612     KoPACanvas * canvas = dynamic_cast<KoPACanvas *>(KoToolManager::instance()->activeCanvasController()->canvas());
613     if (canvas) {
614         canvas->koPAView()->insertPage();
615     }
616 }
617 
contextMenuEvent(QContextMenuEvent * event)618 void KoPADocumentStructureDocker::contextMenuEvent(QContextMenuEvent* event)
619 {
620     QMenu menu(this);
621 
622     // Not connected yet
623     if (m_doc->pageType() == KoPageApp::Slide) {
624         menu.addAction(koIcon("document-new"), i18n("Add a new slide"), this, SLOT(addPage()));
625     }
626     else {
627         menu.addAction(koIcon("document-new"), i18n("Add a new page"), this, SLOT(addPage()));
628     }
629     menu.addAction(koIcon("edit-delete"), i18n("Delete selected objects"), this, SLOT(deleteItem()));
630     menu.addSeparator();
631     menu.addAction(koIcon("edit-cut"), i18n("Cut"), this, SLOT(editCut()));
632     menu.addAction(koIcon("edit-copy"), i18n("Copy"), this, SLOT(editCopy()));
633     menu.addAction(koIcon("edit-paste"), i18n("Paste"), this, SLOT(editPaste()));
634 
635     menu.exec(event->globalPos());
636 }
637 
editCut()638 void KoPADocumentStructureDocker::editCut()
639 {
640     editCopy();
641     deleteItem();
642 }
643 
editCopy()644 void KoPADocumentStructureDocker::editCopy()
645 {
646     QList<KoPAPageBase*> pages;
647     QList<KoShapeLayer*> layers;
648     QList<KoShape*> shapes;
649 
650     // separate selected layers and selected shapes
651     extractSelectedLayersAndShapes(pages, layers, shapes);
652 
653     foreach (KoShape* shape, layers) {
654         // Add layers to shapes
655         shapes.append(shape);
656     }
657 
658     if (!shapes.empty()) {
659         // Copy Shapes or Layers
660         KoShapeOdfSaveHelper saveHelper(shapes);
661         KoDrag drag;
662         drag.setOdf(KoOdf::mimeType(KoOdf::Text), saveHelper);
663         drag.addToClipboard();
664         return;
665     }
666 
667     if (!pages.empty()) {
668         // Copy Pages
669         KoPAOdfPageSaveHelper saveHelper(m_doc, pages);
670         KoDrag drag;
671         drag.setOdf(KoOdf::mimeType(m_doc->documentType()), saveHelper);
672         drag.addToClipboard();
673     }
674 }
675 
editPaste()676 void KoPADocumentStructureDocker::editPaste()
677 {
678     const QMimeData * data = QApplication::clipboard()->mimeData();
679 
680     if (data->hasFormat(KoOdf::mimeType(KoOdf::Text))) {
681         // Paste Shapes or Layers
682         KoCanvasBase* canvas = KoToolManager::instance()->activeCanvasController()->canvas();
683         KoShapeManager * shapeManager = canvas->shapeManager();
684         KoShapePaste paste(canvas, shapeManager->selection()->activeLayer());
685         paste.paste(KoOdf::Text, data);
686 
687     }
688     else {
689         // Paste Pages
690         KoPACanvas * canvas = static_cast<KoPACanvas *>(KoToolManager::instance()->activeCanvasController()->canvas());
691         canvas->koPAView()->pagePaste();
692     }
693 }
694 
selectPages(int start,int count)695 void KoPADocumentStructureDocker::selectPages(int start, int count)
696 {
697     if ((start < 0) || (count < 1)) {
698         return;
699     }
700     emit pageChanged(m_doc->pageByIndex(start, false));
701     m_sectionView->clearSelection();
702     for (int i = start; i < (start + count); i++) {
703         QModelIndex index = m_model->index(i, 0, QModelIndex());
704         if (index.isValid()) {
705             m_sectionView->selectionModel()->select(index, QItemSelectionModel::Select);
706         }
707     }
708 }
709 
710 // kate: replace-tabs on; space-indent on; indent-width 4; mixedindent off; indent-mode cstyle;
711