1 /* This file is part of the KDE project
2  * Copyright (C) 2001-2002 Lennart Kudling <kudling@kde.org>
3  * Copyright (C) 2001-2005,2007 Rob Buis <buis@kde.org>
4  * Copyright (C) 2002-2003,2005 Tomislav Lukman <tomislav.lukman@ck.t-com.hr>
5  * Copyright (C) 2002-2003,2006 Laurent Montel <montel@kde.org>
6  * Copyright (C) 2002-2006 Stephan Binner <binner@kde.org>
7  * Copyright (C) 2002,2005 David Faure <faure@kde.org>
8  * Copyright (C) 2002 Benoit Vautrin <benoit.vautrin@free.fr>
9  * Copyright (C) 2002,2005-2007 Thomas Zander <zander@kde.org>
10  * Copyright (C) 2003 Dirk Mueller <mueller@kde.org>
11  * Copyright (C) 2003,2006 Stephan Kulow <coolo@kde.org>
12  * Copyright (C) 2004 Brad Hards <bradh@frogmouth.net>
13  * Copyright (C) 2005-2006 Tim Beaulen <tbscope@gmail.com>
14  * Copyright (C) 2005 Yann Bodson <yann.bodson@online.fr>
15  * Copyright (C) 2005-2010 Boudewijn Rempt <boud@valdyas.org>
16  * Copyright (C) 2005-2009,2011 Jan Hambrecht <jaham@gmx.net>
17  * Copyright (C) 2005-2006 Peter Simonsson <psn@linux.se>
18  * Copyright (C) 2005-2006 Sven Langkamp <sven.langkamp@gmail.com>
19  * Copyright (C) 2005-2006 Inge Wallin <inge@lysator.liu.se>
20  * Copyright (C) 2005-2006 C. Boemann <cbo@boemann.dk>
21  * Copyright (C) 2006 Martin Ellis <martin.ellis@kdemail.net>
22  * Copyright (C) 2006 Adriaan de Groot <groot@kde.org>
23  * Copyright (C) 2006 Sebastian Sauer <mail@dipe.org>
24  * Copyright (C) 2006-2007 Thorsten Zachmann <t.zachmann@zagge.de>
25  * Copyright (C) 2006 Andreas Hartmetz <ahartmetz@gmail.com>
26  * Copyright (C) 2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net>
27  * Copyright (C) 2006-2007 Aaron J. Seigo <aseigo@kde.org>
28  * Copyright (C) 2007 Matthias Kretz <kretz@kde.org>
29  *
30  * This library is free software; you can redistribute it and/or
31  * modify it under the terms of the GNU Library General Public
32  * License as published by the Free Software Foundation; either
33  * version 2 of the License, or (at your option) any later version.
34  *
35  * This library is distributed in the hope that it will be useful,
36  * but WITHOUT ANY WARRANTY; without even the implied warranty of
37  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
38  * Library General Public License for more details.
39  *
40  * You should have received a copy of the GNU Library General Public License
41  * along with this library; see the file COPYING.LIB.  If not, write to
42  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
43  * Boston, MA 02110-1301, USA.
44  */
45 
46 #include "KarbonView.h"
47 
48 // Dialogs.
49 #include "KarbonConfigureDialog.h"
50 
51 // The rest.
52 #include "Karbon.h"
53 #include "KarbonFactory.h"
54 #include "KarbonPart.h"
55 #include "KarbonDocument.h"
56 #include "KarbonSmallStylePreview.h"
57 #include "KarbonDocumentMergeCommand.h"
58 #include "KarbonPaletteBarWidget.h"
59 #include "KarbonUiDebug.h"
60 #include "KarbonOutlinePaintingStrategy.h"
61 
62 #include <KoPACanvas.h>
63 #include <KoCanvasResourceManager.h>
64 #include <KoPAPageBase.h>
65 
66 #include <KoMainWindow.h>
67 #include <KoShapeStroke.h>
68 #include <KoCanvasControllerWidget.h>
69 #include <KoDocumentResourceManager.h>
70 #include <KoCanvasResourceManager.h>
71 #include <KoFilterManager.h>
72 #include <KoRuler.h>
73 #include <KoToolManager.h>
74 #include <KoStandardAction.h>
75 #include <KoToolProxy.h>
76 #include <KoShapeManager.h>
77 #include <KoShapeController.h>
78 #include <KoShapeContainer.h>
79 #include <KoShapeGroup.h>
80 #include <KoShapeCreateCommand.h>
81 #include <KoShapeDeleteCommand.h>
82 #include <KoShapeReorderCommand.h>
83 #include <KoShapeStrokeCommand.h>
84 #include <KoShapeBackgroundCommand.h>
85 #include <KoParameterToPathCommand.h>
86 #include <KoShapeClipCommand.h>
87 #include <KoShapeUnclipCommand.h>
88 #include <KoSelection.h>
89 #include <KoZoomAction.h>
90 #include <KoZoomHandler.h>
91 #include <KoPathShape.h>
92 #include <KoPathPoint.h>
93 #include <KoPathPointData.h>
94 #include <KoPathCombineCommand.h>
95 #include <KoPathReverseCommand.h>
96 #include <KoPathPointMoveCommand.h>
97 #include <KoShapeTransformCommand.h>
98 #include <KoShapeGroupCommand.h>
99 #include <KoToolBoxFactory.h>
100 #include <KoParameterShape.h>
101 #include <KoRulerController.h>
102 #include <KoDockRegistry.h>
103 #include <KoDockerManager.h>
104 #include <KoGridData.h>
105 #include <KoGuidesData.h>
106 #include <KoShapeLayer.h>
107 #include <KoColorBackground.h>
108 #include <KoCutController.h>
109 #include <KoCopyController.h>
110 #include <KoPasteController.h>
111 #include <KoSnapGuide.h>
112 #include <KoShapeFactoryBase.h>
113 #include <KoShapeRegistry.h>
114 #include <KoImageCollection.h>
115 #include <KoImageData.h>
116 #include <KoProperties.h>
117 #include <KoZoomController.h>
118 #include <KoIcon.h>
119 #include <KoFileDialog.h>
120 #include <KoUnit.h>
121 #include <KoPluginLoader.h>
122 #include <KoComponentData.h>
123 
124 // KF5 header
125 #include <kcolormimedata.h>
126 #include <klocalizedstring.h>
127 #include <kmessagebox.h>
128 #include <kactioncollection.h>
129 #include <kstandardaction.h>
130 #include <ktoggleaction.h>
131 #include <KPluginFactory>
132 #include <KXMLGUIFactory>
133 
134 // qt header
135 #include <QMimeDatabase>
136 #include <QAction>
137 #include <QResizeEvent>
138 #include <QDropEvent>
139 #include <QGridLayout>
140 #include <QStatusBar>
141 #include <QLabel>
142 #include <QImageReader>
143 #include <QPluginLoader>
144 #include <QLocale>
145 
146 #include <unistd.h>
147 #include <KConfigGroup>
148 
149 class Q_DECL_HIDDEN KarbonView::Private
150 {
151 public:
Private(KarbonPart * part,KarbonDocument * doc)152     Private(KarbonPart *part, KarbonDocument * doc)
153             : karbonPart(part), part(doc)
154             , colorBar(0), closePath(0), combinePath(0)
155             , separatePath(0), reversePath(0), intersectPath(0), subtractPath(0)
156             , unitePath(0), excludePath(0), pathSnapToGrid(0), configureAction(0)
157             , deleteSelectionAction(0), clipObjects(0), unclipObjects(0)
158             , flipVertical(0), flipHorizontal(0), viewAction(0)
159             , snapGridAction(0), showPageMargins(0), showGuidesAction(0)
160             , showPaletteAction(0)
161             , status(0), cursorCoords(0), smallPreview(0)
162     {}
163 
164     KarbonPart * karbonPart;
165     KarbonDocument * part;
166     KarbonPaletteBarWidget *colorBar;
167 
168     // actions:
169     QAction * closePath;
170     QAction * combinePath;
171     QAction * separatePath;
172     QAction * reversePath;
173     QAction * intersectPath;
174     QAction * subtractPath;
175     QAction * unitePath;
176     QAction * excludePath;
177     QAction * pathSnapToGrid;
178     QAction * configureAction;
179     QAction * deleteSelectionAction;
180     QAction * clipObjects;
181     QAction * unclipObjects;
182     QAction * flipVertical;
183     QAction * flipHorizontal;
184 
185     KToggleAction * viewAction;
186 
187     KToggleAction * snapGridAction;
188     KToggleAction * showPageMargins;
189     KToggleAction * showGuidesAction;
190 
191     KToggleAction * showPaletteAction;
192 
193     //Status Bar
194     QLabel * status;       ///< ordinary status
195     QLabel * cursorCoords; ///< cursor coordinates
196     KarbonSmallStylePreview * smallPreview; ///< small style preview
197 };
198 
KarbonView(KarbonPart * karbonPart,KarbonDocument * doc,QWidget * parent)199 KarbonView::KarbonView(KarbonPart *karbonPart, KarbonDocument* doc, QWidget* parent)
200     : KoPAView(karbonPart, doc, KoPAView::NormalMode, parent)
201     , d(new Private(karbonPart, doc))
202 {
203     setAcceptDrops(true);
204 
205     setXMLFile(QString::fromLatin1("karbon.rc"));
206 
207     d->cursorCoords = new QLabel(QString(), this);
208     d->cursorCoords->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
209     d->cursorCoords->setMinimumWidth(50);
210     addStatusBarItem(d->cursorCoords, 0);
211     connect(canvasController()->proxyObject, SIGNAL(canvasMousePositionChanged(QPoint)), this, SLOT(mousePositionChanged(QPoint)));
212 
213     d->smallPreview = new KarbonSmallStylePreview(this);
214     connect(d->smallPreview, SIGNAL(fillApplied()), this, SLOT(applyFillToSelection()));
215     connect(d->smallPreview, SIGNAL(strokeApplied()), this, SLOT(applyStrokeToSelection()));
216     addStatusBarItem(d->smallPreview, 0);
217     // FIXME: This was not neccessary before refactoring to pageapp, why now?
218     // Also, changing colors of a shape does not update preview
219     connect(shapeManager(), SIGNAL(selectionChanged()), d->smallPreview, SLOT(selectionChanged()));
220 
221     initActions();
222 
223     // Load all plugins
224     const QList<KPluginFactory *> pluginFactories =
225         KoPluginLoader::instantiatePluginFactories(QStringLiteral("karbon/extensions"));
226     foreach (KPluginFactory* factory, pluginFactories) {
227         QObject *object = factory->create<QObject>(this, QVariantList());
228         KXMLGUIClient *clientPlugin = dynamic_cast<KXMLGUIClient*>(object);
229         if (clientPlugin) {
230             insertChildClient(clientPlugin);
231         } else {
232             // not our/valid plugin, so delete the created object
233             object->deleteLater();
234         }
235     }
236 
237     unsigned int max = static_cast<KarbonDocument*>(kopaDocument())->maxRecentFiles();
238     setNumberOfRecentFiles(max);
239 
240     d->colorBar = new KarbonPaletteBarWidget(Qt::Horizontal, this);
241     connect(d->colorBar, SIGNAL(colorSelected(KoColor)), this, SLOT(applyPaletteColor(KoColor)));
242     connect(shapeManager(), SIGNAL(selectionContentChanged()), d->colorBar, SLOT(updateDocumentColors()));
243     connect(kopaDocument(), SIGNAL(shapeAdded(KoShape*)), d->colorBar, SLOT(updateDocumentColors()));
244     connect(kopaDocument(), SIGNAL(shapeRemoved(KoShape*)), d->colorBar, SLOT(updateDocumentColors()));
245 
246     if (mainWindow()) {
247         KSharedConfigPtr config = KSharedConfig::openConfig();
248         if (config->hasGroup("Interface")) {
249             KConfigGroup interfaceGroup = config->group( "Interface" );
250             if (!interfaceGroup.readEntry<bool>("ShowPalette", true)) {
251                 d->colorBar->setVisible(false);
252                 d->showPaletteAction->setChecked(false);
253             }
254         }
255     }
256 
257     reorganizeGUI();
258 
259     setFocusPolicy(Qt::NoFocus);
260 }
261 
~KarbonView()262 KarbonView::~KarbonView()
263 {
264     removeStatusBarItem(d->cursorCoords);
265     removeStatusBarItem(d->smallPreview);
266 
267     if (factory()) {
268         factory()->removeClient(this);
269     }
270     delete d;
271 }
272 
colorBar() const273 KarbonPaletteBarWidget *KarbonView::colorBar() const
274 {
275     return d->colorBar;
276 }
277 
part() const278 KarbonDocument * KarbonView::part() const
279 {
280     return static_cast<KarbonDocument*>(kopaDocument());
281 }
282 
resourceManager() const283 KoCanvasResourceManager *KarbonView::resourceManager() const
284 {
285     return kopaCanvas()->resourceManager();
286 }
287 
canvasWidget() const288 KoPACanvas *KarbonView::canvasWidget() const
289 {
290     return dynamic_cast<KoPACanvas*>(kopaCanvas());
291 }
292 
resizeEvent(QResizeEvent *)293 void KarbonView::resizeEvent(QResizeEvent* /*event*/)
294 {
295     if (!kopaCanvas())
296         return;
297 
298     reorganizeGUI();
299 }
300 
dragEnterEvent(QDragEnterEvent * event)301 void KarbonView::dragEnterEvent(QDragEnterEvent * event)
302 {
303     QColor color = KColorMimeData::fromMimeData(event->mimeData());
304     if (color.isValid()) {
305         event->accept();
306     }
307     KoView::dragEnterEvent(event);
308 }
309 
dropEvent(QDropEvent * e)310 void KarbonView::dropEvent(QDropEvent *e)
311 {
312 
313     //Accepts QColor - from Color Manager's KColorPatch
314     QColor color = KColorMimeData::fromMimeData(e->mimeData());
315     if (color.isValid()) {
316         KoSelection * selection = shapeManager()->selection();
317         if (! selection)
318             return;
319 
320         if (! kopaDocument())
321             return;
322 
323         if (resourceManager()->intResource(KoCanvasResourceManager::ActiveStyleType) == KoFlake::Foreground) {
324             QList<KoShapeStrokeModel*> strokes;
325             QList<KoShape*> selectedShapes = selection->selectedShapes();
326             foreach(KoShape * shape, selectedShapes) {
327                 KoShapeStroke * stroke = dynamic_cast<KoShapeStroke*>(shape->stroke());
328                 KoShapeStroke * newStroke = 0;
329                 if (stroke) {
330                     newStroke = new KoShapeStroke(*stroke);
331                     newStroke->setColor(color);
332                 } else {
333                     newStroke = new KoShapeStroke(1.0, color);
334                 }
335                 strokes.append(newStroke);
336             }
337             kopaCanvas()->addCommand(new KoShapeStrokeCommand(selectedShapes, strokes, 0));
338         } else {
339             QSharedPointer<KoShapeBackground> fill(new KoColorBackground(color));
340             kopaCanvas()->addCommand(new KoShapeBackgroundCommand(selection->selectedShapes(), fill, 0));
341         }
342     }
343 
344     KoPAView::dropEvent(e);
345 }
346 
fileImportGraphic()347 void KarbonView::fileImportGraphic()
348 {
349     QByteArray nativeMimeType = kopaDocument()->nativeFormatMimeType();
350     QStringList filter = KoFilterManager::mimeFilter(nativeMimeType, KoFilterManager::Import);
351 
352     QStringList imageFilter;
353     // add filters for all formats supported by QImage
354     foreach(const QByteArray &mimeType, QImageReader::supportedMimeTypes()) {
355         imageFilter << QLatin1String(mimeType);
356     }
357     filter.append(imageFilter);
358 
359     KoFileDialog dialog(0, KoFileDialog::OpenFile, "OpenDocument");
360     dialog.setCaption(i18n("Choose Graphic to Add"));
361     dialog.setMimeTypeFilters(imageFilter);
362     QString fname = dialog.filename();
363 
364     if (fname.isEmpty()) return;
365 
366     KarbonPart importPart(0);
367     KarbonDocument importDocument(&importPart);
368     importPart.setDocument(&importDocument);
369 
370     bool success = true;
371 
372     // check if we have an empty mime type (probably because the "All supported files"
373     // filter was active)
374     QString currentMimeFilter;
375     // get mime type from file
376     QMimeType mimeType = QMimeDatabase().mimeTypeForFile(fname);
377     if (mimeType.isValid()) {
378         const QString mime = mimeType.name();
379         if (mime == nativeMimeType) {
380             currentMimeFilter = nativeMimeType;
381         } else {
382             foreach(const QString &filter, imageFilter) {
383                 if (mime == filter) {
384                     currentMimeFilter = filter;
385                     break;
386                 }
387             }
388         }
389     }
390 
391     // check if we are loading an image format
392     if (imageFilter.contains(currentMimeFilter)) {
393         QImage image;
394         if (!image.load(fname)) {
395             KMessageBox::error(0, i18n("Could not load image."), i18n("Import graphic"), 0);
396             return;
397         }
398         KoShapeFactoryBase * factory = KoShapeRegistry::instance()->get("PictureShape");
399         if (!factory) {
400             KMessageBox::error(0, i18n("Could not create image shape."), i18n("Import graphic"), 0);
401             return;
402         }
403 
404         KoShape *picture = factory->createDefaultShape(kopaDocument()->resourceManager());
405         KoImageCollection *imageCollection = kopaDocument()->resourceManager()->imageCollection();
406         if (!picture || !imageCollection) {
407             KMessageBox::error(0, i18n("Could not create image shape."), i18n("Import graphic"), 0);
408             return;
409         }
410 
411         // calculate shape size in point from image resolution
412         qreal pxWidth = static_cast<qreal>(image.width());
413         qreal pxHeight = static_cast<qreal>(image.height());
414         qreal width = DM_TO_POINT(pxWidth / static_cast<qreal>(image.dotsPerMeterX()) * 10.0);
415         qreal height = DM_TO_POINT(pxHeight / static_cast<qreal>(image.dotsPerMeterY()) * 10.0);
416 
417         // set shape data
418         picture->setUserData(imageCollection->createImageData(image));
419         picture->setSize(QSizeF(width, height));
420         picture->setPosition(QPointF());
421         picture->setKeepAspectRatio(true);
422 
423         KUndo2Command * cmd = kopaCanvas()->shapeController()->addShapeDirect(picture);
424         cmd->setText(kundo2_i18n("Insert graphics"));
425         kopaCanvas()->addCommand(cmd);
426         shapeManager()->selection()->select(picture);
427         return;
428     }
429     // TODO: It is not obvious how this is best implemented when importing multipage docs
430     // Append pages?
431     // Append layers to existing pages?
432     // Add shapes to active page?
433     // etc?
434     // check if we are loading our native format
435     if (nativeMimeType == currentMimeFilter) {
436         // directly load the native format
437         success = importDocument.loadNativeFormat(fname);
438         if (!success) {
439             importDocument.showLoadingErrorDialog();
440         }
441     } else {
442         // use import filters to load the file
443         KoFilterManager man(&importDocument);
444         KoFilter::ConversionStatus status = KoFilter::OK;
445         QString importedFile = man.importDocument(fname, QString(), status);
446         if (status != KoFilter::OK) {
447             importDocument.showLoadingErrorDialog();
448             success = false;
449         } else if (!importedFile.isEmpty()) {
450             success = importDocument.loadNativeFormat(importedFile);
451             if (!success) {
452                 importDocument.showLoadingErrorDialog();
453             }
454             // remove the temporary file created during format conversion
455             unlink(QFile::encodeName(importedFile));
456         }
457     }
458 
459     if (success) {
460         KarbonDocumentMergeCommand * cmd = new KarbonDocumentMergeCommand(dynamic_cast<KarbonDocument*>(kopaDocument()), importDocument);
461         kopaCanvas()->addCommand(cmd);
462 /*
463         foreach(KoShape * shape, importedShapes) {
464             d->canvas->shapeManager()->selection()->select(shape, false);
465         }*/
466     }
467 }
468 
selectionDuplicate()469 void KarbonView::selectionDuplicate()
470 {
471     kopaCanvas()->toolProxy()->copy();
472     kopaCanvas()->toolProxy()->paste();
473 }
474 
editSelectAll()475 void KarbonView::editSelectAll()
476 {
477     KoSelection* selection = shapeManager()->selection();
478     if (! selection) {
479         return;
480     }
481     QList<KoShape*> shapes;
482     for (int i = 0; i < kopaDocument()->pages().count(); ++i) {
483         KoShapeLayer *l = dynamic_cast<KoShapeLayer*>(kopaDocument()->pages().at(i));
484         shapes += l->shapes();
485     }
486     debugKarbonUi << "shapes.size() =" << shapes.size();
487 
488     foreach(KoShape* shape, shapes) {
489         selection->select(shape);
490         shape->update();
491     }
492 
493     selectionChanged();
494 }
495 
editDeselectAll()496 void KarbonView::editDeselectAll()
497 {
498     KoSelection* selection = shapeManager()->selection();
499     if (selection)
500         selection->deselectAll();
501 
502     selectionChanged();
503 }
504 
editDeleteSelection()505 void KarbonView::editDeleteSelection()
506 {
507     kopaCanvas()->toolProxy()->deleteSelection();
508 }
509 
selectionDistributeHorizontalCenter()510 void KarbonView::selectionDistributeHorizontalCenter()
511 {
512     selectionDistribute(KoShapeDistributeCommand::HorizontalCenterDistribution);
513 }
514 
selectionDistributeHorizontalGap()515 void KarbonView::selectionDistributeHorizontalGap()
516 {
517     selectionDistribute(KoShapeDistributeCommand::HorizontalGapsDistribution);
518 }
519 
selectionDistributeHorizontalLeft()520 void KarbonView::selectionDistributeHorizontalLeft()
521 {
522     selectionDistribute(KoShapeDistributeCommand::HorizontalLeftDistribution);
523 }
524 
selectionDistributeHorizontalRight()525 void KarbonView::selectionDistributeHorizontalRight()
526 {
527     selectionDistribute(KoShapeDistributeCommand::HorizontalRightDistribution);
528 }
529 
selectionDistributeVerticalCenter()530 void KarbonView::selectionDistributeVerticalCenter()
531 {
532     selectionDistribute(KoShapeDistributeCommand::VerticalCenterDistribution);
533 }
534 
selectionDistributeVerticalGap()535 void KarbonView::selectionDistributeVerticalGap()
536 {
537     selectionDistribute(KoShapeDistributeCommand::VerticalGapsDistribution);
538 }
539 
selectionDistributeVerticalBottom()540 void KarbonView::selectionDistributeVerticalBottom()
541 {
542     selectionDistribute(KoShapeDistributeCommand::VerticalBottomDistribution);
543 }
544 
selectionDistributeVerticalTop()545 void KarbonView::selectionDistributeVerticalTop()
546 {
547     selectionDistribute(KoShapeDistributeCommand::VerticalTopDistribution);
548 }
549 
selectionDistribute(KoShapeDistributeCommand::Distribute distribute)550 void KarbonView::selectionDistribute(KoShapeDistributeCommand::Distribute distribute)
551 {
552     KoSelection* selection = shapeManager()->selection();
553     if (! selection)
554         return;
555 
556     QList<KoShape*> selectedShapes = selection->selectedShapes(KoFlake::TopLevelSelection);
557     if (selectedShapes.count() < 2) return;
558 
559     KoShapeDistributeCommand *cmd = new KoShapeDistributeCommand(selectedShapes, distribute, selection->boundingRect());
560 
561     kopaCanvas()->addCommand(cmd);
562 }
563 
clipObjects()564 void KarbonView::clipObjects()
565 {
566     KoSelection* selection = shapeManager()->selection();
567     if( ! selection )
568         return;
569 
570     QList<KoShape*> selectedShapes = selection->selectedShapes( KoFlake::TopLevelSelection );
571     if( ! selectedShapes.count() )
572         return;
573 
574     KoShape * shapeToClip = selectedShapes.first();
575     selectedShapes.removeOne( shapeToClip );
576 
577     QList<KoPathShape*> clipPaths;
578     foreach( KoShape * shape, selectedShapes )
579     {
580         KoPathShape * path = dynamic_cast<KoPathShape*>( shape );
581         if( path )
582             clipPaths.append( path );
583     }
584 
585     if( ! clipPaths.count() )
586         return;
587 
588     KUndo2Command * cmd = new KoShapeClipCommand( kopaDocument(), shapeToClip, clipPaths );
589     kopaCanvas()->addCommand( cmd );
590 }
591 
unclipObjects()592 void KarbonView::unclipObjects()
593 {
594     KoSelection* selection = shapeManager()->selection();
595     if( ! selection )
596         return;
597 
598     QList<KoShape*> selectedShapes = selection->selectedShapes( KoFlake::TopLevelSelection );
599     if( ! selectedShapes.count() )
600         return;
601 
602     QList<KoShape*> shapesToUnclip;
603     foreach(KoShape *shape, selectedShapes) {
604         if (shape->clipPath())
605             shapesToUnclip.append(shape);
606     }
607     if (!shapesToUnclip.count())
608         return;
609 
610     kopaCanvas()->addCommand(new KoShapeUnclipCommand(kopaDocument(), shapesToUnclip));
611 }
612 
flipVertical()613 void KarbonView::flipVertical()
614 {
615     selectionFlip(false, true);
616 }
617 
flipHorizontal()618 void KarbonView::flipHorizontal()
619 {
620     selectionFlip(true, false);
621 }
622 
selectionFlip(bool horizontally,bool vertically)623 void KarbonView::selectionFlip(bool horizontally, bool vertically)
624 {
625     if (!horizontally && !vertically)
626         return;
627 
628     KoSelection* selection = shapeManager()->selection();
629     if( ! selection )
630         return;
631 
632     QList<KoShape*> selectedShapes = selection->selectedShapes( KoFlake::StrippedSelection );
633     const int selectedShapesCount = selectedShapes.count();
634     if( selectedShapesCount < 1 )
635         return;
636 
637     // mirror about center point
638     QPointF mirrorCenter = selection->absolutePosition(KoFlake::CenteredPosition);
639 
640     QTransform mirrorMatrix;
641     mirrorMatrix.translate(mirrorCenter.x(), mirrorCenter.y());
642     mirrorMatrix.scale( horizontally ? -1.0 : 1.0, vertically ? -1.0 : 1.0);
643     mirrorMatrix.translate(-mirrorCenter.x(), -mirrorCenter.y());
644 
645     QVector<QTransform> oldState;
646     QVector<QTransform> newState;
647     oldState.reserve(selectedShapesCount);
648     newState.reserve(selectedShapesCount);
649 
650     foreach( KoShape* shape, selectedShapes ) {
651         shape->update();
652         oldState << shape->transformation();
653         // apply the mirror transformation
654         shape->applyAbsoluteTransformation(mirrorMatrix);
655         newState << shape->transformation();
656     }
657     selection->applyAbsoluteTransformation(mirrorMatrix);
658 
659     KUndo2Command *cmd = new KoShapeTransformCommand(selectedShapes, oldState, newState);
660     if (horizontally && !vertically)
661         cmd->setText(kundo2_i18n("Mirror Horizontally"));
662     else if (!horizontally && vertically)
663         cmd->setText(kundo2_i18n("Mirror Vertically"));
664     else
665         cmd->setText(kundo2_i18n("Mirror Horizontally and Vertically"));
666     kopaCanvas()->addCommand(cmd);
667 }
668 
closePath()669 void KarbonView::closePath()
670 {
671     // TODO add the new close path command here
672 }
673 
combinePath()674 void KarbonView::combinePath()
675 {
676     KoSelection* selection = shapeManager()->selection();
677     if (! selection)
678         return;
679 
680     QList<KoShape*> selectedShapes = selection->selectedShapes();
681     QList<KoPathShape*> paths;
682 
683     foreach(KoShape* shape, selectedShapes) {
684         KoPathShape *path = dynamic_cast<KoPathShape*>(shape);
685         if (path) {
686             KoParameterShape * paramShape = dynamic_cast<KoParameterShape*>(path);
687             if (paramShape && paramShape->isParametricShape())
688                 continue;
689             paths << path;
690             selection->deselect(shape);
691         }
692     }
693 
694     if (paths.size())
695         kopaCanvas()->addCommand(new KoPathCombineCommand(kopaDocument(), paths));
696 }
697 
separatePath()698 void KarbonView::separatePath()
699 {
700     KoSelection* selection = shapeManager()->selection();
701     if (! selection)
702         return;
703 
704     QList<KoShape*> selectedShapes = selection->selectedShapes();
705     QList<KoPathShape*> paths;
706 
707     foreach(KoShape* shape, selectedShapes) {
708         KoPathShape *path = dynamic_cast<KoPathShape*>(shape);
709         if (path) {
710             paths << path;
711             selection->deselect(shape);
712         }
713     }
714 
715     if (!paths.size()) {
716         return;
717     }
718 
719     KUndo2Command *cmd = new KUndo2Command;
720     cmd->setText(kundo2_i18n("Separate paths"));
721 
722     foreach(KoPathShape* p, paths) {
723         QList<KoPathShape*> separatedPaths;
724         QList<KoShape*> newShapes;
725         if (p->separate(separatedPaths)) {
726             foreach(KoPathShape *subPath, separatedPaths) {
727                 new KoShapeCreateCommand(kopaDocument(), subPath, cmd);
728                 newShapes << subPath;
729             }
730             // make sure we put the new subpaths into the parent
731             // of the original path
732             KoShapeGroup *parentGroup = dynamic_cast<KoShapeGroup*>(p->parent());
733             if (parentGroup) {
734                 new KoShapeGroupCommand(parentGroup, newShapes, cmd);
735             }
736             new KoShapeDeleteCommand(kopaDocument(), p, cmd);
737         }
738     }
739     kopaCanvas()->addCommand(cmd);
740 }
741 
reversePath()742 void KarbonView::reversePath()
743 {
744     QList<KoPathShape*> paths = selectedPathShapes();
745     if (paths.size())
746         kopaCanvas()->addCommand(new KoPathReverseCommand(paths));
747 }
748 
intersectPaths()749 void KarbonView::intersectPaths()
750 {
751     booleanOperation(KarbonBooleanCommand::Intersection);
752 }
753 
subtractPaths()754 void KarbonView::subtractPaths()
755 {
756     booleanOperation(KarbonBooleanCommand::Subtraction);
757 }
758 
unitePaths()759 void KarbonView::unitePaths()
760 {
761     booleanOperation(KarbonBooleanCommand::Union);
762 }
763 
excludePaths()764 void KarbonView::excludePaths()
765 {
766     booleanOperation(KarbonBooleanCommand::Exclusion);
767 }
768 
booleanOperation(KarbonBooleanCommand::BooleanOperation operation)769 void KarbonView::booleanOperation(KarbonBooleanCommand::BooleanOperation operation)
770 {
771     KoSelection* selection = shapeManager()->selection();
772     if (! selection)
773         return;
774 
775     QList<KoShape*> selectedShapes = selection->selectedShapes();
776     QList<KoPathShape*> paths;
777 
778     foreach(KoShape* shape, selectedShapes) {
779         KoPathShape *path = dynamic_cast<KoPathShape*>(shape);
780         if (path) {
781             paths << path;
782             selection->deselect(shape);
783         }
784     }
785 
786     if (paths.size() == 2) {
787         KUndo2Command * macro = new KUndo2Command(kundo2_i18n("Boolean Operation"));
788         KoParameterShape * paramShape = dynamic_cast<KoParameterShape*>(paths[0]);
789         if (paramShape && paramShape->isParametricShape())
790             new KoParameterToPathCommand(paramShape, macro);
791         paramShape = dynamic_cast<KoParameterShape*>(paths[1]);
792         if (paramShape && paramShape->isParametricShape())
793             new KoParameterToPathCommand(paramShape, macro);
794         new KarbonBooleanCommand(kopaDocument(), paths[0], paths[1], operation, macro);
795         new KoShapeDeleteCommand(kopaDocument(), paths[0], macro);
796         new KoShapeDeleteCommand(kopaDocument(), paths[1], macro);
797         kopaCanvas()->addCommand(macro);
798     }
799 }
800 
pathSnapToGrid()801 void KarbonView::pathSnapToGrid()
802 {
803     KoSelection* selection = shapeManager()->selection();
804     if (! selection)
805         return;
806 
807     QList<KoShape*> selectedShapes = selection->selectedShapes();
808     QList<KoPathPointData> points;
809     QVector<QPointF> offsets;
810 
811     // store current grid snap state
812     bool oldSnapToGrid = kopaDocument()->gridData().snapToGrid();
813     // enable grid snapping
814     kopaDocument()->gridData().setSnapToGrid(true);
815 
816     KoSnapGuide snapGuide(kopaCanvas());
817     snapGuide.enableSnapStrategies(KoSnapGuide::GridSnapping);
818     snapGuide.setSnapDistance(INT_MAX);
819 
820     foreach(KoShape* shape, selectedShapes) {
821         KoParameterShape * paramShape = dynamic_cast<KoParameterShape*>(shape);
822         if (paramShape && paramShape->isParametricShape())
823             continue;
824 
825         KoPathShape *path = dynamic_cast<KoPathShape*>(shape);
826         if (! path)
827             continue;
828 
829         uint subpathCount = path->subpathCount();
830         for (uint i = 0; i < subpathCount; ++i) {
831             uint pointCount = path->subpathPointCount(i);
832             for (uint j = 0; j < pointCount; ++j) {
833                 KoPathPointIndex index(i, j);
834                 KoPathPoint * p = path->pointByIndex(index);
835                 if (!p)
836                     continue;
837 
838                 QPointF docPoint = path->shapeToDocument(p->point());
839                 QPointF offset = snapGuide.snap(docPoint, 0) - docPoint;
840                 points.append(KoPathPointData(path, index));
841                 offsets.append(offset);
842             }
843         }
844     }
845 
846     // reset grid snapping state to old value
847     kopaDocument()->gridData().setSnapToGrid(oldSnapToGrid);
848 
849     kopaCanvas()->addCommand(new KoPathPointMoveCommand(points, offsets));
850 }
851 
viewModeChanged(bool outlineMode)852 void KarbonView::viewModeChanged(bool outlineMode)
853 {
854     if (outlineMode) {
855         new KarbonOutlinePaintingStrategy(shapeManager());
856     } else {
857         shapeManager()->setPaintingStrategy(new KoShapeManagerPaintingStrategy(shapeManager()));
858     }
859 }
860 
zoomSelection()861 void KarbonView::zoomSelection()
862 {
863     KoSelection* selection = shapeManager()->selection();
864     if (! selection)
865         return;
866 
867     if (! selection->count())
868         return;
869 
870     const KoZoomHandler * zoomHandler = dynamic_cast<const KoZoomHandler*>(viewConverter());
871     if (! zoomHandler)
872         return;
873 
874     QRectF bbox = selection->boundingRect();
875     QRect viewRect = zoomHandler->documentToView(bbox).toRect();
876 
877     kopaCanvas()->canvasController()->zoomTo(viewRect.translated(kopaCanvas()->documentOrigin()));
878 //     QPointF newCenter = kopaCanvas()->documentOrigin() + zoomHandler->documentToView(bbox.center());
879 //     kopaCanvas()->setPreferredCenter(newCenter.toPoint());
880 }
881 
zoomDrawing()882 void KarbonView::zoomDrawing()
883 {
884     const KoZoomHandler * zoomHandler = dynamic_cast<const KoZoomHandler*>(kopaCanvas()->viewConverter());
885     if (! zoomHandler)
886         return;
887 
888     QRectF bbox = activePage()->contentRect();
889     if (bbox.isNull())
890         return;
891 
892     QRect viewRect = zoomHandler->documentToView(bbox).toRect();
893     kopaCanvas()->canvasController()->zoomTo(viewRect.translated(kopaCanvas()->documentOrigin()));
894 //     QPointF newCenter = kopaCanvas()->documentOrigin() + zoomHandler->documentToView(bbox.center());
895 //     kopaCanvas()->setPreferredCenter(newCenter.toPoint());
896 }
897 
initActions()898 void KarbonView::initActions()
899 {
900     // view ----->
901     d->viewAction  = new KToggleAction(i18n("Outline &Mode"), this);
902     actionCollection()->addAction("view_mode", d->viewAction);
903     connect(d->viewAction, SIGNAL(toggled(bool)), this, SLOT(viewModeChanged(bool)));
904 
905     // No need for the other actions in read-only (embedded) mode
906     if (!mainWindow())
907         return;
908 
909     // edit ----->
910     QAction *action = actionCollection()->addAction(KStandardAction::Cut,  "edit_cut", 0, 0);
911     new KoCutController(kopaCanvas(), action);
912     action = actionCollection()->addAction(KStandardAction::Copy,  "edit_copy", 0, 0);
913     new KoCopyController(kopaCanvas(), action);
914     action = actionCollection()->addAction(KStandardAction::Paste,  "edit_paste", 0, 0);
915     new KoPasteController(kopaCanvas(), action);
916     actionCollection()->addAction(KStandardAction::SelectAll,  "edit_select_all", this, SLOT(editSelectAll()));
917     actionCollection()->addAction(KStandardAction::Deselect,  "edit_deselect_all", this, SLOT(editDeselectAll()));
918 
919     QAction *actionImportGraphic  = new QAction(i18n("&Import Graphic..."), this);
920     actionCollection()->addAction("file_import", actionImportGraphic);
921     connect(actionImportGraphic, SIGNAL(triggered()), this, SLOT(fileImportGraphic()));
922 
923     d->deleteSelectionAction  = new QAction(koIcon("edit-delete"), i18n("D&elete"), this);
924     actionCollection()->addAction("edit_delete", d->deleteSelectionAction);
925     d->deleteSelectionAction->setShortcut(QKeySequence("Del"));
926     connect(d->deleteSelectionAction, SIGNAL(triggered()), this, SLOT(editDeleteSelection()));
927     connect(kopaCanvas()->toolProxy(), SIGNAL(selectionChanged(bool)), d->deleteSelectionAction, SLOT(setEnabled(bool)));
928 
929     QAction *actionEditGuides = new QAction(koIcon("edit-guides"), i18n("Edit Guides"), this);
930     actionCollection()->addAction("edit_guides", actionEditGuides);
931     connect(actionEditGuides, SIGNAL(triggered()), this, SLOT(editGuides()));
932     // edit <-----
933 
934     // object ----->
935     QAction *actionDuplicate  = new QAction(i18nc("Duplicate selection", "&Duplicate"), this);
936     actionCollection()->addAction("object_duplicate", actionDuplicate);
937     actionDuplicate->setShortcut(QKeySequence("Ctrl+D"));
938     connect(actionDuplicate, SIGNAL(triggered()), this, SLOT(selectionDuplicate()));
939 
940     QAction *actionDistributeHorizontalCenter  = new QAction(koIcon("distribute-horizontal-center"), i18n("Distribute Center (Horizontal)"), this);
941     actionCollection()->addAction("object_distribute_horizontal_center", actionDistributeHorizontalCenter);
942     connect(actionDistributeHorizontalCenter, SIGNAL(triggered()), this, SLOT(selectionDistributeHorizontalCenter()));
943 
944     QAction *actionDistributeHorizontalGap  = new QAction(koIcon("distribute-horizontal-equal"), i18n("Distribute Gaps (Horizontal)"), this);
945     actionCollection()->addAction("object_distribute_horizontal_gap", actionDistributeHorizontalGap);
946     connect(actionDistributeHorizontalGap, SIGNAL(triggered()), this, SLOT(selectionDistributeHorizontalGap()));
947 
948     QAction *actionDistributeLeft  = new QAction(koIcon("distribute-horizontal-left"), i18n("Distribute Left Borders"), this);
949     actionCollection()->addAction("object_distribute_horizontal_left", actionDistributeLeft);
950     connect(actionDistributeLeft, SIGNAL(triggered()), this, SLOT(selectionDistributeHorizontalLeft()));
951 
952     QAction *actionDistributeRight  = new QAction(koIcon("distribute-horizontal-right"), i18n("Distribute Right Borders"), this);
953     actionCollection()->addAction("object_distribute_horizontal_right", actionDistributeRight);
954     connect(actionDistributeRight, SIGNAL(triggered()), this, SLOT(selectionDistributeHorizontalRight()));
955 
956     QAction *actionDistributeVerticalCenter  = new QAction(koIcon("distribute-vertical-center"), i18n("Distribute Center (Vertical)"), this);
957     actionCollection()->addAction("object_distribute_vertical_center", actionDistributeVerticalCenter);
958     connect(actionDistributeVerticalCenter, SIGNAL(triggered()), this, SLOT(selectionDistributeVerticalCenter()));
959 
960     QAction *actionDistributeVerticalGap  = new QAction(koIcon("distribute-vertical-equal"), i18n("Distribute Gaps (Vertical)"), this);
961     actionCollection()->addAction("object_distribute_vertical_gap", actionDistributeVerticalGap);
962     connect(actionDistributeVerticalGap, SIGNAL(triggered()), this, SLOT(selectionDistributeVerticalGap()));
963 
964     QAction *actionDistributeBottom  = new QAction(koIcon("distribute-vertical-bottom"), i18n("Distribute Bottom Borders"), this);
965     actionCollection()->addAction("object_distribute_vertical_bottom", actionDistributeBottom);
966     connect(actionDistributeBottom, SIGNAL(triggered()), this, SLOT(selectionDistributeVerticalBottom()));
967 
968     QAction *actionDistributeTop  = new QAction(koIcon("distribute-vertical-top"), i18n("Distribute Top Borders"), this);
969     actionCollection()->addAction("object_distribute_vertical_top", actionDistributeTop);
970     connect(actionDistributeTop, SIGNAL(triggered()), this, SLOT(selectionDistributeVerticalTop()));
971 
972     d->showPaletteAction = new KToggleAction(i18n("Show Color Palette"), this);
973     actionCollection()->addAction("view_show_palette", d->showPaletteAction);
974     d->showPaletteAction->setToolTip(i18n("Show or hide color palette"));
975     d->showPaletteAction->setChecked(true);
976     connect(d->showPaletteAction, SIGNAL(triggered()), this, SLOT(showPalette()));
977 
978     action = actionCollection()->action("object_group");
979     if (action) {
980         action->setShortcut(QKeySequence("Ctrl+G"));
981     }
982     action = actionCollection()->action("object_ungroup");
983     if (action) {
984         action->setShortcut(QKeySequence("Ctrl+Shift+G"));
985     }
986 
987     d->clipObjects  = new QAction(i18n("&Clip Object"), this);
988     actionCollection()->addAction("object_clip", d->clipObjects );
989     connect(d->clipObjects, SIGNAL(triggered()), this, SLOT(clipObjects()));
990 
991     d->unclipObjects  = new QAction(i18n("&Unclip Objects"), this);
992     actionCollection()->addAction("object_unclip", d->unclipObjects );
993     connect(d->unclipObjects, SIGNAL(triggered()), this, SLOT(unclipObjects()));
994 
995     d->flipVertical = new QAction(koIcon("object-flip-vertical"), i18n("Mirror Vertically"), this);
996     actionCollection()->addAction("object_flip_vertical", d->flipVertical);
997     connect(d->flipVertical, SIGNAL(triggered()), this, SLOT(flipVertical()));
998 
999     d->flipHorizontal = new QAction(koIcon("object-flip-horizontal"), i18n("Mirror Horizontally"), this);
1000     actionCollection()->addAction("object_flip_horizontal", d->flipHorizontal);
1001     connect(d->flipHorizontal, SIGNAL(triggered()), this, SLOT(flipHorizontal()));
1002 
1003     // object <-----
1004 
1005     // path ------->
1006     d->closePath  = new QAction(i18n("&Close Path"), this);
1007     actionCollection()->addAction("close_path", d->closePath);
1008     d->closePath->setShortcut(QKeySequence("Ctrl+U"));
1009     d->closePath->setEnabled(false);
1010     connect(d->closePath, SIGNAL(triggered()), this, SLOT(closePath()));
1011 
1012     d->combinePath  = new QAction(i18n("Com&bine Path"), this);
1013     actionCollection()->addAction("combine_path", d->combinePath);
1014     d->combinePath->setShortcut(QKeySequence("Ctrl+K"));
1015     d->combinePath->setEnabled(false);
1016     connect(d->combinePath, SIGNAL(triggered()), this, SLOT(combinePath()));
1017 
1018     d->separatePath  = new QAction(i18n("Se&parate Path"), this);
1019     actionCollection()->addAction("separate_path", d->separatePath);
1020     d->separatePath->setShortcut(QKeySequence("Shift+Ctrl+K"));
1021     d->separatePath->setEnabled(false);
1022     connect(d->separatePath, SIGNAL(triggered()), this, SLOT(separatePath()));
1023 
1024     d->reversePath  = new QAction(i18n("Re&verse Path"), this);
1025     actionCollection()->addAction("reverse_path", d->reversePath);
1026     d->reversePath->setShortcut(QKeySequence("Ctrl+R"));
1027     d->reversePath->setEnabled(false);
1028     connect(d->reversePath, SIGNAL(triggered()), this, SLOT(reversePath()));
1029 
1030     d->intersectPath = new QAction(i18n("Intersect Paths"), this);
1031     actionCollection()->addAction("intersect_path", d->intersectPath);
1032     //d->intersectPath->setShortcut(QKeySequence("Shift+Ctrl+K"));
1033     d->intersectPath->setEnabled(false);
1034     connect(d->intersectPath, SIGNAL(triggered()), this, SLOT(intersectPaths()));
1035 
1036     d->subtractPath = new QAction(i18n("Subtract Paths"), this);
1037     actionCollection()->addAction("subtract_path", d->subtractPath);
1038     //d->subtractPath->setShortcut(QKeySequence("Shift+Ctrl+K"));
1039     d->subtractPath->setEnabled(false);
1040     connect(d->subtractPath, SIGNAL(triggered()), this, SLOT(subtractPaths()));
1041 
1042     d->unitePath = new QAction(i18n("Unite Paths"), this);
1043     actionCollection()->addAction("unite_path", d->unitePath);
1044     //d->unitePath->setShortcut(QKeySequence("Shift+Ctrl+K"));
1045     d->unitePath->setEnabled(false);
1046     connect(d->unitePath, SIGNAL(triggered()), this, SLOT(unitePaths()));
1047 
1048     d->excludePath = new QAction(i18n("Exclude Paths"), this);
1049     actionCollection()->addAction("exclude_path", d->excludePath);
1050     //d->excludePath->setShortcut(QKeySequence("Shift+Ctrl+K"));
1051     d->excludePath->setEnabled(false);
1052     connect(d->excludePath, SIGNAL(triggered()), this, SLOT(excludePaths()));
1053 
1054     d->pathSnapToGrid = new QAction(i18n("Snap Path to Grid"), this);
1055     actionCollection()->addAction("path_snap_to_grid", d->pathSnapToGrid);
1056     d->pathSnapToGrid->setEnabled(false);
1057     connect(d->pathSnapToGrid, SIGNAL(triggered()), this, SLOT(pathSnapToGrid()));
1058 
1059     // path <-----
1060 
1061     // view ---->
1062     QAction * zoomSelection = new QAction(koIcon("zoom-select"), i18n("Zoom to Selection"), this);
1063     actionCollection()->addAction("view_zoom_selection", zoomSelection);
1064     connect(zoomSelection, SIGNAL(triggered()), this, SLOT(zoomSelection()));
1065 
1066     QAction * zoomDrawing = new QAction(koIcon("zoom-draw"), i18n("Zoom to Drawing"), this);
1067     actionCollection()->addAction("view_zoom_drawing", zoomDrawing);
1068     connect(zoomDrawing, SIGNAL(triggered()), this, SLOT(zoomDrawing()));
1069     // view <-----
1070 }
1071 
mousePositionChanged(const QPoint & position)1072 void KarbonView::mousePositionChanged(const QPoint &position)
1073 {
1074     const QPoint canvasOffset(canvasController()->canvasOffsetX(), canvasController()->canvasOffsetY() );
1075     const QPoint viewPos = position - kopaCanvas()->documentOrigin() - canvasOffset;
1076 
1077     QPointF documentPos = kopaCanvas()->viewConverter()->viewToDocument(viewPos);
1078     qreal x = kopaDocument()->unit().toUserValue(documentPos.x());
1079     qreal y = kopaDocument()->unit().toUserValue(documentPos.y());
1080 
1081     if (statusBar() && statusBar()->isVisible()) {
1082         QLocale locale;
1083         d->cursorCoords->setText(QString::fromLatin1("%1, %2").arg(locale.toString(x, 'f', 2), locale.toString(y, 'f', 2)));
1084     }
1085 }
1086 
reorganizeGUI()1087 void KarbonView::reorganizeGUI()
1088 {
1089     // TODO: Find a better solution, maybe move to KoPAView?
1090     if (statusBar()) {
1091         bool show = true;
1092         if (mainWindow()) {
1093             KSharedConfigPtr config = KSharedConfig::openConfig();
1094             if (config->hasGroup("Interface")) {
1095                 KConfigGroup interfaceGroup = config->group( "Interface" );
1096                 if (!interfaceGroup.readEntry<bool>("ShowStatusBar", true)) {
1097                     show = false;
1098                 }
1099             }
1100         }
1101         statusBar()->setVisible(show);
1102     }
1103 }
1104 
setNumberOfRecentFiles(unsigned int number)1105 void KarbonView::setNumberOfRecentFiles(unsigned int number)
1106 {
1107     if (mainWindow()) {    // 0L when embedded into konq !
1108         mainWindow()->setMaxRecentItems(number);
1109     }
1110 }
1111 
editGuides()1112 void KarbonView::editGuides()
1113 {
1114     KoToolManager::instance()->switchToolRequested("GuidesTool_ID");
1115 }
1116 
showPalette()1117 void KarbonView::showPalette()
1118 {
1119     if(!mainWindow())
1120         return;
1121 
1122     const bool showPalette = d->showPaletteAction->isChecked();
1123     d->colorBar->setVisible(showPalette);
1124 
1125     // this will make the last setting of the ruler visibility persistent
1126     KConfigGroup interfaceGroup = KarbonFactory::global().config()->group("Interface");
1127     if (showPalette && !interfaceGroup.hasDefault("ShowPalette"))
1128         interfaceGroup.revertToDefault("ShowPalette");
1129     else
1130         interfaceGroup.writeEntry("ShowPalette", showPalette);
1131 }
1132 
openConfiguration()1133 void KarbonView::openConfiguration()
1134 {
1135     QPointer<KarbonConfigureDialog> dialog = new KarbonConfigureDialog(this);
1136     dialog->exec();
1137     delete dialog;
1138     reorganizeGUI();
1139 }
1140 
selectionChanged()1141 void KarbonView::selectionChanged()
1142 {
1143     if (!mainWindow())
1144         return;
1145     KoSelection *selection = kopaCanvas()->shapeManager()->selection();
1146     QList<KoShape*> selectedShapes = selection->selectedShapes(KoFlake::FullSelection);
1147     const int count = selectedShapes.count();
1148 
1149     d->closePath->setEnabled(false);
1150     d->combinePath->setEnabled(false);
1151     d->excludePath->setEnabled(false);
1152     d->intersectPath->setEnabled(false);
1153     d->subtractPath->setEnabled(false);
1154     d->unitePath->setEnabled(false);
1155     d->pathSnapToGrid->setEnabled(false);
1156     d->clipObjects->setEnabled(false);
1157     d->unclipObjects->setEnabled(false);
1158     d->flipHorizontal->setEnabled(count > 0);
1159     d->flipVertical->setEnabled(count > 0);
1160 
1161     debugKarbonUi << count << " shapes selected";
1162 
1163     if (count > 0) {
1164         uint selectedPaths = 0;
1165         uint selectedParametrics = 0;
1166         // check for different shape types for enabling specific actions
1167         foreach(KoShape* shape, selectedShapes) {
1168             if (dynamic_cast<KoPathShape*>(shape)) {
1169                 KoParameterShape * ps = dynamic_cast<KoParameterShape*>(shape);
1170                 if (ps && ps->isParametricShape())
1171                     selectedParametrics++;
1172                 else
1173                     selectedPaths++;
1174             }
1175         }
1176         debugKarbonUi << selectedPaths << " path shapes selected";
1177         debugKarbonUi << selectedParametrics << " parameter shapes selected";
1178         //TODO enable action when the ClosePath command is ported
1179         //d->closePath->setEnabled( selectedPaths > 0 );
1180         d->combinePath->setEnabled(selectedPaths > 1);
1181         d->separatePath->setEnabled(selectedPaths > 0);
1182         d->reversePath->setEnabled(selectedPaths > 0);
1183         d->excludePath->setEnabled(selectedPaths + selectedParametrics == 2);
1184         d->intersectPath->setEnabled(selectedPaths + selectedParametrics == 2);
1185         d->subtractPath->setEnabled(selectedPaths + selectedParametrics == 2);
1186         d->unitePath->setEnabled(selectedPaths + selectedParametrics == 2);
1187         d->pathSnapToGrid->setEnabled(selectedPaths > 0);
1188         d->clipObjects->setEnabled(selectedPaths > 0 && count > 1);
1189         d->unclipObjects->setEnabled(selectedShapes.first()->clipPath() != 0);
1190         // if only one shape selected, set its parent layer as the active layer
1191         if (count == 1) {
1192             KoShapeContainer * parent = selection->selectedShapes().first()->parent();
1193             while (parent) {
1194                 if (parent->parent())
1195                     parent = parent->parent();
1196                 else
1197                     break;
1198             }
1199             KoShapeLayer * layer = dynamic_cast<KoShapeLayer*>(parent);
1200             if (layer)
1201                 selection->setActiveLayer(layer);
1202         }
1203     }
1204 }
1205 
setCursor(const QCursor & c)1206 void KarbonView::setCursor(const QCursor &c)
1207 {
1208     kopaCanvas()->setCursor(c);
1209 }
1210 
updateReadWrite(bool readwrite)1211 void KarbonView::updateReadWrite(bool readwrite)
1212 {
1213     Q_UNUSED(readwrite);
1214 }
1215 
selectedPathShapes()1216 QList<KoPathShape*> KarbonView::selectedPathShapes()
1217 {
1218     KoSelection* selection = shapeManager()->selection();
1219     if (! selection)
1220         return QList<KoPathShape*>();
1221 
1222     QList<KoShape*> selectedShapes = selection->selectedShapes();
1223     QList<KoPathShape*> paths;
1224 
1225     foreach(KoShape* shape, selectedShapes) {
1226         KoPathShape *path = dynamic_cast<KoPathShape*>(shape);
1227         if (path) {
1228             paths << path;
1229             selection->deselect(shape);
1230         }
1231     }
1232 
1233     return paths;
1234 }
1235 
applyFillToSelection()1236 void KarbonView::applyFillToSelection()
1237 {
1238     KoSelection *selection = shapeManager()->selection();
1239     if (! selection->count())
1240         return;
1241 
1242     KoShape * shape = selection->firstSelectedShape();
1243     kopaCanvas()->addCommand(new KoShapeBackgroundCommand(selection->selectedShapes(), shape->background()));
1244 }
1245 
applyStrokeToSelection()1246 void KarbonView::applyStrokeToSelection()
1247 {
1248     KoSelection *selection = shapeManager()->selection();
1249     if (! selection->count())
1250         return;
1251 
1252     KoShape * shape = selection->firstSelectedShape();
1253     kopaCanvas()->addCommand(new KoShapeStrokeCommand(selection->selectedShapes(), shape->stroke()));
1254 }
1255 
applyPaletteColor(const KoColor & color)1256 void KarbonView::applyPaletteColor(const KoColor &color)
1257 {
1258     KoSelection *selection = shapeManager()->selection();
1259     if (! selection->count())
1260         return;
1261 
1262     int style = resourceManager()->intResource(KoCanvasResourceManager::ActiveStyleType);
1263     if (style == KoFlake::Foreground) {
1264         QList<KoShapeStrokeModel*> newStrokes;
1265         foreach(KoShape *shape, selection->selectedShapes()) {
1266             KoShapeStroke *stroke = dynamic_cast<KoShapeStroke*>(shape->stroke());
1267             if (stroke) {
1268                 // preserve stroke properties
1269                 KoShapeStroke *newStroke = new KoShapeStroke(*stroke);
1270                 newStroke->setColor(color.toQColor());
1271                 newStrokes << newStroke;
1272             } else {
1273                 newStrokes << new KoShapeStroke(1.0, color.toQColor());
1274             }
1275         }
1276         kopaCanvas()->addCommand(new KoShapeStrokeCommand(selection->selectedShapes(), newStrokes));
1277         resourceManager()->setForegroundColor(color);
1278     } else {
1279         QSharedPointer<KoShapeBackground> fill(new KoColorBackground(color.toQColor()));
1280         kopaCanvas()->addCommand(new KoShapeBackgroundCommand(selection->selectedShapes(), fill));
1281         resourceManager()->setBackgroundColor(color);
1282     }
1283 }
1284 
replaceActivePage(KoPAPageBase * page,KoPAPageBase * newActivePage)1285 void KarbonView::replaceActivePage(KoPAPageBase *page, KoPAPageBase *newActivePage)
1286 {
1287     if (page == activePage() ) {
1288         viewMode()->updateActivePage(newActivePage);
1289     }
1290 }
1291 
1292