File indexing completed on 2024-05-12 16:30:49
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2001-2002 Lennart Kudling <kudling@kde.org> 0003 * Copyright (C) 2001-2005,2007 Rob Buis <buis@kde.org> 0004 * Copyright (C) 2002-2003,2005 Tomislav Lukman <tomislav.lukman@ck.t-com.hr> 0005 * Copyright (C) 2002-2003,2006 Laurent Montel <montel@kde.org> 0006 * Copyright (C) 2002-2006 Stephan Binner <binner@kde.org> 0007 * Copyright (C) 2002,2005 David Faure <faure@kde.org> 0008 * Copyright (C) 2002 Benoit Vautrin <benoit.vautrin@free.fr> 0009 * Copyright (C) 2002,2005-2007 Thomas Zander <zander@kde.org> 0010 * Copyright (C) 2003 Dirk Mueller <mueller@kde.org> 0011 * Copyright (C) 2003,2006 Stephan Kulow <coolo@kde.org> 0012 * Copyright (C) 2004 Brad Hards <bradh@frogmouth.net> 0013 * Copyright (C) 2005-2006 Tim Beaulen <tbscope@gmail.com> 0014 * Copyright (C) 2005 Yann Bodson <yann.bodson@online.fr> 0015 * Copyright (C) 2005-2010 Boudewijn Rempt <boud@valdyas.org> 0016 * Copyright (C) 2005-2009,2011 Jan Hambrecht <jaham@gmx.net> 0017 * Copyright (C) 2005-2006 Peter Simonsson <psn@linux.se> 0018 * Copyright (C) 2005-2006 Sven Langkamp <sven.langkamp@gmail.com> 0019 * Copyright (C) 2005-2006 Inge Wallin <inge@lysator.liu.se> 0020 * Copyright (C) 2005-2006 C. Boemann <cbo@boemann.dk> 0021 * Copyright (C) 2006 Martin Ellis <martin.ellis@kdemail.net> 0022 * Copyright (C) 2006 Adriaan de Groot <groot@kde.org> 0023 * Copyright (C) 2006 Sebastian Sauer <mail@dipe.org> 0024 * Copyright (C) 2006-2007 Thorsten Zachmann <t.zachmann@zagge.de> 0025 * Copyright (C) 2006 Andreas Hartmetz <ahartmetz@gmail.com> 0026 * Copyright (C) 2006 Stefan Nikolaus <stefan.nikolaus@kdemail.net> 0027 * Copyright (C) 2006-2007 Aaron J. Seigo <aseigo@kde.org> 0028 * Copyright (C) 2007 Matthias Kretz <kretz@kde.org> 0029 * 0030 * This library is free software; you can redistribute it and/or 0031 * modify it under the terms of the GNU Library General Public 0032 * License as published by the Free Software Foundation; either 0033 * version 2 of the License, or (at your option) any later version. 0034 * 0035 * This library is distributed in the hope that it will be useful, 0036 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0037 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0038 * Library General Public License for more details. 0039 * 0040 * You should have received a copy of the GNU Library General Public License 0041 * along with this library; see the file COPYING.LIB. If not, write to 0042 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0043 * Boston, MA 02110-1301, USA. 0044 */ 0045 0046 #include "KarbonView.h" 0047 0048 // Dialogs. 0049 #include "KarbonConfigureDialog.h" 0050 0051 // The rest. 0052 #include "Karbon.h" 0053 #include "KarbonFactory.h" 0054 #include "KarbonPart.h" 0055 #include "KarbonDocument.h" 0056 #include "KarbonSmallStylePreview.h" 0057 #include "KarbonDocumentMergeCommand.h" 0058 #include "KarbonPaletteBarWidget.h" 0059 #include "KarbonUiDebug.h" 0060 #include "KarbonOutlinePaintingStrategy.h" 0061 0062 #include <KoPACanvas.h> 0063 #include <KoCanvasResourceManager.h> 0064 #include <KoPAPageBase.h> 0065 0066 #include <KoMainWindow.h> 0067 #include <KoShapeStroke.h> 0068 #include <KoCanvasControllerWidget.h> 0069 #include <KoDocumentResourceManager.h> 0070 #include <KoCanvasResourceManager.h> 0071 #include <KoFilterManager.h> 0072 #include <KoRuler.h> 0073 #include <KoToolManager.h> 0074 #include <KoStandardAction.h> 0075 #include <KoToolProxy.h> 0076 #include <KoShapeManager.h> 0077 #include <KoShapeController.h> 0078 #include <KoShapeContainer.h> 0079 #include <KoShapeGroup.h> 0080 #include <KoShapeCreateCommand.h> 0081 #include <KoShapeDeleteCommand.h> 0082 #include <KoShapeReorderCommand.h> 0083 #include <KoShapeStrokeCommand.h> 0084 #include <KoShapeBackgroundCommand.h> 0085 #include <KoParameterToPathCommand.h> 0086 #include <KoShapeClipCommand.h> 0087 #include <KoShapeUnclipCommand.h> 0088 #include <KoSelection.h> 0089 #include <KoZoomAction.h> 0090 #include <KoZoomHandler.h> 0091 #include <KoPathShape.h> 0092 #include <KoPathPoint.h> 0093 #include <KoPathPointData.h> 0094 #include <KoPathCombineCommand.h> 0095 #include <KoPathReverseCommand.h> 0096 #include <KoPathPointMoveCommand.h> 0097 #include <KoShapeTransformCommand.h> 0098 #include <KoShapeGroupCommand.h> 0099 #include <KoToolBoxFactory.h> 0100 #include <KoParameterShape.h> 0101 #include <KoRulerController.h> 0102 #include <KoDockRegistry.h> 0103 #include <KoDockerManager.h> 0104 #include <KoGridData.h> 0105 #include <KoGuidesData.h> 0106 #include <KoShapeLayer.h> 0107 #include <KoColorBackground.h> 0108 #include <KoCutController.h> 0109 #include <KoCopyController.h> 0110 #include <KoPasteController.h> 0111 #include <KoSnapGuide.h> 0112 #include <KoShapeFactoryBase.h> 0113 #include <KoShapeRegistry.h> 0114 #include <KoImageCollection.h> 0115 #include <KoImageData.h> 0116 #include <KoProperties.h> 0117 #include <KoZoomController.h> 0118 #include <KoIcon.h> 0119 #include <KoFileDialog.h> 0120 #include <KoUnit.h> 0121 #include <KoPluginLoader.h> 0122 #include <KoComponentData.h> 0123 0124 // KF5 header 0125 #include <kcolormimedata.h> 0126 #include <klocalizedstring.h> 0127 #include <kmessagebox.h> 0128 #include <kactioncollection.h> 0129 #include <kstandardaction.h> 0130 #include <ktoggleaction.h> 0131 #include <KPluginFactory> 0132 #include <KXMLGUIFactory> 0133 0134 // qt header 0135 #include <QMimeDatabase> 0136 #include <QAction> 0137 #include <QResizeEvent> 0138 #include <QDropEvent> 0139 #include <QGridLayout> 0140 #include <QStatusBar> 0141 #include <QLabel> 0142 #include <QImageReader> 0143 #include <QPluginLoader> 0144 #include <QLocale> 0145 0146 #include <unistd.h> 0147 #include <KConfigGroup> 0148 0149 class Q_DECL_HIDDEN KarbonView::Private 0150 { 0151 public: 0152 Private(KarbonPart *part, KarbonDocument * doc) 0153 : karbonPart(part), part(doc) 0154 , colorBar(0), closePath(0), combinePath(0) 0155 , separatePath(0), reversePath(0), intersectPath(0) 0156 , subtractPath(0), unitePath(0), excludePath(0) 0157 , pathSnapToGrid(0), configureAction(0), clipObjects(0) 0158 , unclipObjects(0), flipVertical(0), flipHorizontal(0) 0159 , viewAction(0), snapGridAction(0), showPageMargins(0) 0160 , showGuidesAction(0), showPaletteAction(0) 0161 , status(0), cursorCoords(0), smallPreview(0) 0162 {} 0163 0164 KarbonPart * karbonPart; 0165 KarbonDocument * part; 0166 KarbonPaletteBarWidget *colorBar; 0167 0168 // actions: 0169 QAction * closePath; 0170 QAction * combinePath; 0171 QAction * separatePath; 0172 QAction * reversePath; 0173 QAction * intersectPath; 0174 QAction * subtractPath; 0175 QAction * unitePath; 0176 QAction * excludePath; 0177 QAction * pathSnapToGrid; 0178 QAction * configureAction; 0179 QAction * clipObjects; 0180 QAction * unclipObjects; 0181 QAction * flipVertical; 0182 QAction * flipHorizontal; 0183 0184 KToggleAction * viewAction; 0185 0186 KToggleAction * snapGridAction; 0187 KToggleAction * showPageMargins; 0188 KToggleAction * showGuidesAction; 0189 0190 KToggleAction * showPaletteAction; 0191 0192 //Status Bar 0193 QLabel * status; ///< ordinary status 0194 QLabel * cursorCoords; ///< cursor coordinates 0195 KarbonSmallStylePreview * smallPreview; ///< small style preview 0196 }; 0197 0198 KarbonView::KarbonView(KarbonPart *karbonPart, KarbonDocument* doc, QWidget* parent) 0199 : KoPAView(karbonPart, doc, KoPAView::NormalMode, parent) 0200 , d(new Private(karbonPart, doc)) 0201 { 0202 setAcceptDrops(true); 0203 0204 setXMLFile(QString::fromLatin1("karbon.rc")); 0205 0206 d->cursorCoords = new QLabel(QString(), this); 0207 d->cursorCoords->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); 0208 d->cursorCoords->setMinimumWidth(50); 0209 addStatusBarItem(d->cursorCoords, 0); 0210 connect(canvasController()->proxyObject, SIGNAL(canvasMousePositionChanged(QPoint)), this, SLOT(mousePositionChanged(QPoint))); 0211 0212 d->smallPreview = new KarbonSmallStylePreview(this); 0213 connect(d->smallPreview, SIGNAL(fillApplied()), this, SLOT(applyFillToSelection())); 0214 connect(d->smallPreview, SIGNAL(strokeApplied()), this, SLOT(applyStrokeToSelection())); 0215 addStatusBarItem(d->smallPreview, 0); 0216 // FIXME: This was not neccessary before refactoring to pageapp, why now? 0217 // Also, changing colors of a shape does not update preview 0218 connect(shapeManager(), SIGNAL(selectionChanged()), d->smallPreview, SLOT(selectionChanged())); 0219 0220 initActions(); 0221 0222 // Load all plugins 0223 const QList<KPluginFactory *> pluginFactories = 0224 KoPluginLoader::instantiatePluginFactories(QStringLiteral("karbon/extensions")); 0225 foreach (KPluginFactory* factory, pluginFactories) { 0226 QObject *object = factory->create<QObject>(this, QVariantList()); 0227 KXMLGUIClient *clientPlugin = dynamic_cast<KXMLGUIClient*>(object); 0228 if (clientPlugin) { 0229 insertChildClient(clientPlugin); 0230 } else { 0231 // not our/valid plugin, so delete the created object 0232 object->deleteLater(); 0233 } 0234 } 0235 0236 unsigned int max = static_cast<KarbonDocument*>(kopaDocument())->maxRecentFiles(); 0237 setNumberOfRecentFiles(max); 0238 0239 d->colorBar = new KarbonPaletteBarWidget(Qt::Horizontal, this); 0240 connect(d->colorBar, SIGNAL(colorSelected(KoColor)), this, SLOT(applyPaletteColor(KoColor))); 0241 connect(shapeManager(), SIGNAL(selectionContentChanged()), d->colorBar, SLOT(updateDocumentColors())); 0242 connect(kopaDocument(), SIGNAL(shapeAdded(KoShape*)), d->colorBar, SLOT(updateDocumentColors())); 0243 connect(kopaDocument(), SIGNAL(shapeRemoved(KoShape*)), d->colorBar, SLOT(updateDocumentColors())); 0244 0245 if (mainWindow()) { 0246 KSharedConfigPtr config = KSharedConfig::openConfig(); 0247 if (config->hasGroup("Interface")) { 0248 KConfigGroup interfaceGroup = config->group( "Interface" ); 0249 if (!interfaceGroup.readEntry<bool>("ShowPalette", true)) { 0250 d->colorBar->setVisible(false); 0251 d->showPaletteAction->setChecked(false); 0252 } 0253 } 0254 } 0255 0256 reorganizeGUI(); 0257 0258 setFocusPolicy(Qt::NoFocus); 0259 } 0260 0261 KarbonView::~KarbonView() 0262 { 0263 removeStatusBarItem(d->cursorCoords); 0264 removeStatusBarItem(d->smallPreview); 0265 0266 if (factory()) { 0267 factory()->removeClient(this); 0268 } 0269 delete d; 0270 } 0271 0272 KarbonPaletteBarWidget *KarbonView::colorBar() const 0273 { 0274 return d->colorBar; 0275 } 0276 0277 KarbonDocument * KarbonView::part() const 0278 { 0279 return static_cast<KarbonDocument*>(kopaDocument()); 0280 } 0281 0282 KoCanvasResourceManager *KarbonView::resourceManager() const 0283 { 0284 return kopaCanvas()->resourceManager(); 0285 } 0286 0287 KoPACanvas *KarbonView::canvasWidget() const 0288 { 0289 return dynamic_cast<KoPACanvas*>(kopaCanvas()); 0290 } 0291 0292 void KarbonView::resizeEvent(QResizeEvent* /*event*/) 0293 { 0294 if (!kopaCanvas()) 0295 return; 0296 0297 reorganizeGUI(); 0298 } 0299 0300 void KarbonView::dragEnterEvent(QDragEnterEvent * event) 0301 { 0302 QColor color = KColorMimeData::fromMimeData(event->mimeData()); 0303 if (color.isValid()) { 0304 event->accept(); 0305 } 0306 KoView::dragEnterEvent(event); 0307 } 0308 0309 void KarbonView::dropEvent(QDropEvent *e) 0310 { 0311 0312 //Accepts QColor - from Color Manager's KColorPatch 0313 QColor color = KColorMimeData::fromMimeData(e->mimeData()); 0314 if (color.isValid()) { 0315 KoSelection * selection = shapeManager()->selection(); 0316 if (! selection) 0317 return; 0318 0319 if (! kopaDocument()) 0320 return; 0321 0322 if (resourceManager()->intResource(KoCanvasResourceManager::ActiveStyleType) == KoFlake::Foreground) { 0323 QList<KoShapeStrokeModel*> strokes; 0324 QList<KoShape*> selectedShapes = selection->selectedShapes(); 0325 foreach(KoShape * shape, selectedShapes) { 0326 KoShapeStroke * stroke = dynamic_cast<KoShapeStroke*>(shape->stroke()); 0327 KoShapeStroke * newStroke = 0; 0328 if (stroke) { 0329 newStroke = new KoShapeStroke(*stroke); 0330 newStroke->setColor(color); 0331 } else { 0332 newStroke = new KoShapeStroke(1.0, color); 0333 } 0334 strokes.append(newStroke); 0335 } 0336 kopaCanvas()->addCommand(new KoShapeStrokeCommand(selectedShapes, strokes, 0)); 0337 } else { 0338 QSharedPointer<KoShapeBackground> fill(new KoColorBackground(color)); 0339 kopaCanvas()->addCommand(new KoShapeBackgroundCommand(selection->selectedShapes(), fill, 0)); 0340 } 0341 } 0342 0343 KoPAView::dropEvent(e); 0344 } 0345 0346 void KarbonView::fileImportGraphic() 0347 { 0348 QByteArray nativeMimeType = kopaDocument()->nativeFormatMimeType(); 0349 QStringList filter = KoFilterManager::mimeFilter(nativeMimeType, KoFilterManager::Import); 0350 0351 QStringList imageFilter; 0352 // add filters for all formats supported by QImage 0353 foreach(const QByteArray &mimeType, QImageReader::supportedMimeTypes()) { 0354 imageFilter << QLatin1String(mimeType); 0355 } 0356 filter.append(imageFilter); 0357 0358 KoFileDialog dialog(0, KoFileDialog::OpenFile, "OpenDocument"); 0359 dialog.setCaption(i18n("Choose Graphic to Add")); 0360 dialog.setMimeTypeFilters(imageFilter); 0361 QString fname = dialog.filename(); 0362 0363 if (fname.isEmpty()) return; 0364 0365 KarbonPart importPart(0); 0366 KarbonDocument importDocument(&importPart); 0367 importPart.setDocument(&importDocument); 0368 0369 bool success = true; 0370 0371 // check if we have an empty mime type (probably because the "All supported files" 0372 // filter was active) 0373 QString currentMimeFilter; 0374 // get mime type from file 0375 QMimeType mimeType = QMimeDatabase().mimeTypeForFile(fname); 0376 if (mimeType.isValid()) { 0377 const QString mime = mimeType.name(); 0378 if (mime == nativeMimeType) { 0379 currentMimeFilter = nativeMimeType; 0380 } else { 0381 foreach(const QString &filter, imageFilter) { 0382 if (mime == filter) { 0383 currentMimeFilter = filter; 0384 break; 0385 } 0386 } 0387 } 0388 } 0389 0390 // check if we are loading an image format 0391 if (imageFilter.contains(currentMimeFilter)) { 0392 QImage image; 0393 if (!image.load(fname)) { 0394 KMessageBox::error(0, i18n("Could not load image."), i18n("Import graphic"), 0); 0395 return; 0396 } 0397 KoShapeFactoryBase * factory = KoShapeRegistry::instance()->get("PictureShape"); 0398 if (!factory) { 0399 KMessageBox::error(0, i18n("Could not create image shape."), i18n("Import graphic"), 0); 0400 return; 0401 } 0402 0403 KoShape *picture = factory->createDefaultShape(kopaDocument()->resourceManager()); 0404 KoImageCollection *imageCollection = kopaDocument()->resourceManager()->imageCollection(); 0405 if (!picture || !imageCollection) { 0406 KMessageBox::error(0, i18n("Could not create image shape."), i18n("Import graphic"), 0); 0407 return; 0408 } 0409 0410 // calculate shape size in point from image resolution 0411 qreal pxWidth = static_cast<qreal>(image.width()); 0412 qreal pxHeight = static_cast<qreal>(image.height()); 0413 qreal width = DM_TO_POINT(pxWidth / static_cast<qreal>(image.dotsPerMeterX()) * 10.0); 0414 qreal height = DM_TO_POINT(pxHeight / static_cast<qreal>(image.dotsPerMeterY()) * 10.0); 0415 0416 // set shape data 0417 picture->setUserData(imageCollection->createImageData(image)); 0418 picture->setSize(QSizeF(width, height)); 0419 picture->setPosition(QPointF()); 0420 picture->setKeepAspectRatio(true); 0421 0422 KUndo2Command * cmd = kopaCanvas()->shapeController()->addShapeDirect(picture); 0423 cmd->setText(kundo2_i18n("Insert graphics")); 0424 kopaCanvas()->addCommand(cmd); 0425 shapeManager()->selection()->select(picture); 0426 return; 0427 } 0428 // TODO: It is not obvious how this is best implemented when importing multipage docs 0429 // Append pages? 0430 // Append layers to existing pages? 0431 // Add shapes to active page? 0432 // etc? 0433 // check if we are loading our native format 0434 if (nativeMimeType == currentMimeFilter) { 0435 // directly load the native format 0436 success = importDocument.loadNativeFormat(fname); 0437 if (!success) { 0438 importDocument.showLoadingErrorDialog(); 0439 } 0440 } else { 0441 // use import filters to load the file 0442 KoFilterManager man(&importDocument); 0443 KoFilter::ConversionStatus status = KoFilter::OK; 0444 QString importedFile = man.importDocument(fname, QString(), status); 0445 if (status != KoFilter::OK) { 0446 importDocument.showLoadingErrorDialog(); 0447 success = false; 0448 } else if (!importedFile.isEmpty()) { 0449 success = importDocument.loadNativeFormat(importedFile); 0450 if (!success) { 0451 importDocument.showLoadingErrorDialog(); 0452 } 0453 // remove the temporary file created during format conversion 0454 unlink(QFile::encodeName(importedFile)); 0455 } 0456 } 0457 0458 if (success) { 0459 KarbonDocumentMergeCommand * cmd = new KarbonDocumentMergeCommand(dynamic_cast<KarbonDocument*>(kopaDocument()), importDocument); 0460 kopaCanvas()->addCommand(cmd); 0461 /* 0462 foreach(KoShape * shape, importedShapes) { 0463 d->canvas->shapeManager()->selection()->select(shape, false); 0464 }*/ 0465 } 0466 } 0467 0468 void KarbonView::selectionDuplicate() 0469 { 0470 kopaCanvas()->toolProxy()->copy(); 0471 kopaCanvas()->toolProxy()->paste(); 0472 } 0473 0474 void KarbonView::selectionDistributeHorizontalCenter() 0475 { 0476 selectionDistribute(KoShapeDistributeCommand::HorizontalCenterDistribution); 0477 } 0478 0479 void KarbonView::selectionDistributeHorizontalGap() 0480 { 0481 selectionDistribute(KoShapeDistributeCommand::HorizontalGapsDistribution); 0482 } 0483 0484 void KarbonView::selectionDistributeHorizontalLeft() 0485 { 0486 selectionDistribute(KoShapeDistributeCommand::HorizontalLeftDistribution); 0487 } 0488 0489 void KarbonView::selectionDistributeHorizontalRight() 0490 { 0491 selectionDistribute(KoShapeDistributeCommand::HorizontalRightDistribution); 0492 } 0493 0494 void KarbonView::selectionDistributeVerticalCenter() 0495 { 0496 selectionDistribute(KoShapeDistributeCommand::VerticalCenterDistribution); 0497 } 0498 0499 void KarbonView::selectionDistributeVerticalGap() 0500 { 0501 selectionDistribute(KoShapeDistributeCommand::VerticalGapsDistribution); 0502 } 0503 0504 void KarbonView::selectionDistributeVerticalBottom() 0505 { 0506 selectionDistribute(KoShapeDistributeCommand::VerticalBottomDistribution); 0507 } 0508 0509 void KarbonView::selectionDistributeVerticalTop() 0510 { 0511 selectionDistribute(KoShapeDistributeCommand::VerticalTopDistribution); 0512 } 0513 0514 void KarbonView::selectionDistribute(KoShapeDistributeCommand::Distribute distribute) 0515 { 0516 KoSelection* selection = shapeManager()->selection(); 0517 if (! selection) 0518 return; 0519 0520 QList<KoShape*> selectedShapes = selection->selectedShapes(KoFlake::TopLevelSelection); 0521 if (selectedShapes.count() < 2) return; 0522 0523 KoShapeDistributeCommand *cmd = new KoShapeDistributeCommand(selectedShapes, distribute, selection->boundingRect()); 0524 0525 kopaCanvas()->addCommand(cmd); 0526 } 0527 0528 void KarbonView::clipObjects() 0529 { 0530 KoSelection* selection = shapeManager()->selection(); 0531 if( ! selection ) 0532 return; 0533 0534 QList<KoShape*> selectedShapes = selection->selectedShapes( KoFlake::TopLevelSelection ); 0535 if( ! selectedShapes.count() ) 0536 return; 0537 0538 KoShape * shapeToClip = selectedShapes.first(); 0539 selectedShapes.removeOne( shapeToClip ); 0540 0541 QList<KoPathShape*> clipPaths; 0542 foreach( KoShape * shape, selectedShapes ) 0543 { 0544 KoPathShape * path = dynamic_cast<KoPathShape*>( shape ); 0545 if( path ) 0546 clipPaths.append( path ); 0547 } 0548 0549 if( ! clipPaths.count() ) 0550 return; 0551 0552 KUndo2Command * cmd = new KoShapeClipCommand( kopaDocument(), shapeToClip, clipPaths ); 0553 kopaCanvas()->addCommand( cmd ); 0554 } 0555 0556 void KarbonView::unclipObjects() 0557 { 0558 KoSelection* selection = shapeManager()->selection(); 0559 if( ! selection ) 0560 return; 0561 0562 QList<KoShape*> selectedShapes = selection->selectedShapes( KoFlake::TopLevelSelection ); 0563 if( ! selectedShapes.count() ) 0564 return; 0565 0566 QList<KoShape*> shapesToUnclip; 0567 foreach(KoShape *shape, selectedShapes) { 0568 if (shape->clipPath()) 0569 shapesToUnclip.append(shape); 0570 } 0571 if (!shapesToUnclip.count()) 0572 return; 0573 0574 kopaCanvas()->addCommand(new KoShapeUnclipCommand(kopaDocument(), shapesToUnclip)); 0575 } 0576 0577 void KarbonView::flipVertical() 0578 { 0579 selectionFlip(false, true); 0580 } 0581 0582 void KarbonView::flipHorizontal() 0583 { 0584 selectionFlip(true, false); 0585 } 0586 0587 void KarbonView::selectionFlip(bool horizontally, bool vertically) 0588 { 0589 if (!horizontally && !vertically) 0590 return; 0591 0592 KoSelection* selection = shapeManager()->selection(); 0593 if( ! selection ) 0594 return; 0595 0596 QList<KoShape*> selectedShapes = selection->selectedShapes( KoFlake::StrippedSelection ); 0597 const int selectedShapesCount = selectedShapes.count(); 0598 if( selectedShapesCount < 1 ) 0599 return; 0600 0601 // mirror about center point 0602 QPointF mirrorCenter = selection->absolutePosition(KoFlake::CenteredPosition); 0603 0604 QTransform mirrorMatrix; 0605 mirrorMatrix.translate(mirrorCenter.x(), mirrorCenter.y()); 0606 mirrorMatrix.scale( horizontally ? -1.0 : 1.0, vertically ? -1.0 : 1.0); 0607 mirrorMatrix.translate(-mirrorCenter.x(), -mirrorCenter.y()); 0608 0609 QVector<QTransform> oldState; 0610 QVector<QTransform> newState; 0611 oldState.reserve(selectedShapesCount); 0612 newState.reserve(selectedShapesCount); 0613 0614 foreach( KoShape* shape, selectedShapes ) { 0615 shape->update(); 0616 oldState << shape->transformation(); 0617 // apply the mirror transformation 0618 shape->applyAbsoluteTransformation(mirrorMatrix); 0619 newState << shape->transformation(); 0620 } 0621 selection->applyAbsoluteTransformation(mirrorMatrix); 0622 0623 KUndo2Command *cmd = new KoShapeTransformCommand(selectedShapes, oldState, newState); 0624 if (horizontally && !vertically) 0625 cmd->setText(kundo2_i18n("Mirror Horizontally")); 0626 else if (!horizontally && vertically) 0627 cmd->setText(kundo2_i18n("Mirror Vertically")); 0628 else 0629 cmd->setText(kundo2_i18n("Mirror Horizontally and Vertically")); 0630 kopaCanvas()->addCommand(cmd); 0631 } 0632 0633 void KarbonView::closePath() 0634 { 0635 // TODO add the new close path command here 0636 } 0637 0638 void KarbonView::combinePath() 0639 { 0640 KoSelection* selection = shapeManager()->selection(); 0641 if (! selection) 0642 return; 0643 0644 QList<KoShape*> selectedShapes = selection->selectedShapes(); 0645 QList<KoPathShape*> paths; 0646 0647 foreach(KoShape* shape, selectedShapes) { 0648 KoPathShape *path = dynamic_cast<KoPathShape*>(shape); 0649 if (path) { 0650 KoParameterShape * paramShape = dynamic_cast<KoParameterShape*>(path); 0651 if (paramShape && paramShape->isParametricShape()) 0652 continue; 0653 paths << path; 0654 selection->deselect(shape); 0655 } 0656 } 0657 0658 if (paths.size()) 0659 kopaCanvas()->addCommand(new KoPathCombineCommand(kopaDocument(), paths)); 0660 } 0661 0662 void KarbonView::separatePath() 0663 { 0664 KoSelection* selection = shapeManager()->selection(); 0665 if (! selection) 0666 return; 0667 0668 QList<KoShape*> selectedShapes = selection->selectedShapes(); 0669 QList<KoPathShape*> paths; 0670 0671 foreach(KoShape* shape, selectedShapes) { 0672 KoPathShape *path = dynamic_cast<KoPathShape*>(shape); 0673 if (path) { 0674 paths << path; 0675 selection->deselect(shape); 0676 } 0677 } 0678 0679 if (!paths.size()) { 0680 return; 0681 } 0682 0683 KUndo2Command *cmd = new KUndo2Command; 0684 cmd->setText(kundo2_i18n("Separate paths")); 0685 0686 foreach(KoPathShape* p, paths) { 0687 QList<KoPathShape*> separatedPaths; 0688 QList<KoShape*> newShapes; 0689 if (p->separate(separatedPaths)) { 0690 foreach(KoPathShape *subPath, separatedPaths) { 0691 new KoShapeCreateCommand(kopaDocument(), subPath, cmd); 0692 newShapes << subPath; 0693 } 0694 // make sure we put the new subpaths into the parent 0695 // of the original path 0696 KoShapeGroup *parentGroup = dynamic_cast<KoShapeGroup*>(p->parent()); 0697 if (parentGroup) { 0698 new KoShapeGroupCommand(parentGroup, newShapes, cmd); 0699 } 0700 new KoShapeDeleteCommand(kopaDocument(), p, cmd); 0701 } 0702 } 0703 kopaCanvas()->addCommand(cmd); 0704 } 0705 0706 void KarbonView::reversePath() 0707 { 0708 QList<KoPathShape*> paths = selectedPathShapes(); 0709 if (paths.size()) 0710 kopaCanvas()->addCommand(new KoPathReverseCommand(paths)); 0711 } 0712 0713 void KarbonView::intersectPaths() 0714 { 0715 booleanOperation(KarbonBooleanCommand::Intersection); 0716 } 0717 0718 void KarbonView::subtractPaths() 0719 { 0720 booleanOperation(KarbonBooleanCommand::Subtraction); 0721 } 0722 0723 void KarbonView::unitePaths() 0724 { 0725 booleanOperation(KarbonBooleanCommand::Union); 0726 } 0727 0728 void KarbonView::excludePaths() 0729 { 0730 booleanOperation(KarbonBooleanCommand::Exclusion); 0731 } 0732 0733 void KarbonView::booleanOperation(KarbonBooleanCommand::BooleanOperation operation) 0734 { 0735 KoSelection* selection = shapeManager()->selection(); 0736 if (! selection) 0737 return; 0738 0739 QList<KoShape*> selectedShapes = selection->selectedShapes(); 0740 QList<KoPathShape*> paths; 0741 0742 foreach(KoShape* shape, selectedShapes) { 0743 KoPathShape *path = dynamic_cast<KoPathShape*>(shape); 0744 if (path) { 0745 paths << path; 0746 selection->deselect(shape); 0747 } 0748 } 0749 0750 if (paths.size() == 2) { 0751 KUndo2Command * macro = new KUndo2Command(kundo2_i18n("Boolean Operation")); 0752 KoParameterShape * paramShape = dynamic_cast<KoParameterShape*>(paths[0]); 0753 if (paramShape && paramShape->isParametricShape()) 0754 new KoParameterToPathCommand(paramShape, macro); 0755 paramShape = dynamic_cast<KoParameterShape*>(paths[1]); 0756 if (paramShape && paramShape->isParametricShape()) 0757 new KoParameterToPathCommand(paramShape, macro); 0758 new KarbonBooleanCommand(kopaDocument(), paths[0], paths[1], operation, macro); 0759 new KoShapeDeleteCommand(kopaDocument(), paths[0], macro); 0760 new KoShapeDeleteCommand(kopaDocument(), paths[1], macro); 0761 kopaCanvas()->addCommand(macro); 0762 } 0763 } 0764 0765 void KarbonView::pathSnapToGrid() 0766 { 0767 KoSelection* selection = shapeManager()->selection(); 0768 if (! selection) 0769 return; 0770 0771 QList<KoShape*> selectedShapes = selection->selectedShapes(); 0772 QList<KoPathPointData> points; 0773 QVector<QPointF> offsets; 0774 0775 // store current grid snap state 0776 bool oldSnapToGrid = kopaDocument()->gridData().snapToGrid(); 0777 // enable grid snapping 0778 kopaDocument()->gridData().setSnapToGrid(true); 0779 0780 KoSnapGuide snapGuide(kopaCanvas()); 0781 snapGuide.enableSnapStrategies(KoSnapGuide::GridSnapping); 0782 snapGuide.setSnapDistance(INT_MAX); 0783 0784 foreach(KoShape* shape, selectedShapes) { 0785 KoParameterShape * paramShape = dynamic_cast<KoParameterShape*>(shape); 0786 if (paramShape && paramShape->isParametricShape()) 0787 continue; 0788 0789 KoPathShape *path = dynamic_cast<KoPathShape*>(shape); 0790 if (! path) 0791 continue; 0792 0793 uint subpathCount = path->subpathCount(); 0794 for (uint i = 0; i < subpathCount; ++i) { 0795 uint pointCount = path->subpathPointCount(i); 0796 for (uint j = 0; j < pointCount; ++j) { 0797 KoPathPointIndex index(i, j); 0798 KoPathPoint * p = path->pointByIndex(index); 0799 if (!p) 0800 continue; 0801 0802 QPointF docPoint = path->shapeToDocument(p->point()); 0803 QPointF offset = snapGuide.snap(docPoint, 0) - docPoint; 0804 points.append(KoPathPointData(path, index)); 0805 offsets.append(offset); 0806 } 0807 } 0808 } 0809 0810 // reset grid snapping state to old value 0811 kopaDocument()->gridData().setSnapToGrid(oldSnapToGrid); 0812 0813 kopaCanvas()->addCommand(new KoPathPointMoveCommand(points, offsets)); 0814 } 0815 0816 void KarbonView::viewModeChanged(bool outlineMode) 0817 { 0818 if (outlineMode) { 0819 new KarbonOutlinePaintingStrategy(shapeManager()); 0820 } else { 0821 shapeManager()->setPaintingStrategy(new KoShapeManagerPaintingStrategy(shapeManager())); 0822 } 0823 } 0824 0825 void KarbonView::zoomSelection() 0826 { 0827 KoSelection* selection = shapeManager()->selection(); 0828 if (! selection) 0829 return; 0830 0831 if (! selection->count()) 0832 return; 0833 0834 const KoZoomHandler * zoomHandler = dynamic_cast<const KoZoomHandler*>(viewConverter()); 0835 if (! zoomHandler) 0836 return; 0837 0838 QRectF bbox = selection->boundingRect(); 0839 QRect viewRect = zoomHandler->documentToView(bbox).toRect(); 0840 0841 kopaCanvas()->canvasController()->zoomTo(viewRect.translated(kopaCanvas()->documentOrigin())); 0842 // QPointF newCenter = kopaCanvas()->documentOrigin() + zoomHandler->documentToView(bbox.center()); 0843 // kopaCanvas()->setPreferredCenter(newCenter.toPoint()); 0844 } 0845 0846 void KarbonView::zoomDrawing() 0847 { 0848 const KoZoomHandler * zoomHandler = dynamic_cast<const KoZoomHandler*>(kopaCanvas()->viewConverter()); 0849 if (! zoomHandler) 0850 return; 0851 0852 QRectF bbox = activePage()->contentRect(); 0853 if (bbox.isNull()) 0854 return; 0855 0856 QRect viewRect = zoomHandler->documentToView(bbox).toRect(); 0857 kopaCanvas()->canvasController()->zoomTo(viewRect.translated(kopaCanvas()->documentOrigin())); 0858 // QPointF newCenter = kopaCanvas()->documentOrigin() + zoomHandler->documentToView(bbox.center()); 0859 // kopaCanvas()->setPreferredCenter(newCenter.toPoint()); 0860 } 0861 0862 void KarbonView::initActions() 0863 { 0864 // view -----> 0865 d->viewAction = new KToggleAction(i18n("Outline &Mode"), this); 0866 actionCollection()->addAction("view_mode", d->viewAction); 0867 connect(d->viewAction, SIGNAL(toggled(bool)), this, SLOT(viewModeChanged(bool))); 0868 0869 // No need for the other actions in read-only (embedded) mode 0870 if (!mainWindow()) 0871 return; 0872 0873 QAction *actionImportGraphic = new QAction(i18n("&Import Graphic..."), this); 0874 actionCollection()->addAction("file_import", actionImportGraphic); 0875 connect(actionImportGraphic, SIGNAL(triggered()), this, SLOT(fileImportGraphic())); 0876 0877 QAction *actionEditGuides = new QAction(koIcon("edit-guides"), i18n("Edit Guides"), this); 0878 actionCollection()->addAction("edit_guides", actionEditGuides); 0879 connect(actionEditGuides, SIGNAL(triggered()), this, SLOT(editGuides())); 0880 // edit <----- 0881 0882 // object -----> 0883 QAction *actionDuplicate = new QAction(i18nc("Duplicate selection", "&Duplicate"), this); 0884 actionCollection()->addAction("object_duplicate", actionDuplicate); 0885 actionDuplicate->setShortcut(QKeySequence("Ctrl+D")); 0886 connect(actionDuplicate, SIGNAL(triggered()), this, SLOT(selectionDuplicate())); 0887 0888 QAction *actionDistributeHorizontalCenter = new QAction(koIcon("distribute-horizontal-center"), i18n("Distribute Center (Horizontal)"), this); 0889 actionCollection()->addAction("object_distribute_horizontal_center", actionDistributeHorizontalCenter); 0890 connect(actionDistributeHorizontalCenter, SIGNAL(triggered()), this, SLOT(selectionDistributeHorizontalCenter())); 0891 0892 QAction *actionDistributeHorizontalGap = new QAction(koIcon("distribute-horizontal-equal"), i18n("Distribute Gaps (Horizontal)"), this); 0893 actionCollection()->addAction("object_distribute_horizontal_gap", actionDistributeHorizontalGap); 0894 connect(actionDistributeHorizontalGap, SIGNAL(triggered()), this, SLOT(selectionDistributeHorizontalGap())); 0895 0896 QAction *actionDistributeLeft = new QAction(koIcon("distribute-horizontal-left"), i18n("Distribute Left Borders"), this); 0897 actionCollection()->addAction("object_distribute_horizontal_left", actionDistributeLeft); 0898 connect(actionDistributeLeft, SIGNAL(triggered()), this, SLOT(selectionDistributeHorizontalLeft())); 0899 0900 QAction *actionDistributeRight = new QAction(koIcon("distribute-horizontal-right"), i18n("Distribute Right Borders"), this); 0901 actionCollection()->addAction("object_distribute_horizontal_right", actionDistributeRight); 0902 connect(actionDistributeRight, SIGNAL(triggered()), this, SLOT(selectionDistributeHorizontalRight())); 0903 0904 QAction *actionDistributeVerticalCenter = new QAction(koIcon("distribute-vertical-center"), i18n("Distribute Center (Vertical)"), this); 0905 actionCollection()->addAction("object_distribute_vertical_center", actionDistributeVerticalCenter); 0906 connect(actionDistributeVerticalCenter, SIGNAL(triggered()), this, SLOT(selectionDistributeVerticalCenter())); 0907 0908 QAction *actionDistributeVerticalGap = new QAction(koIcon("distribute-vertical-equal"), i18n("Distribute Gaps (Vertical)"), this); 0909 actionCollection()->addAction("object_distribute_vertical_gap", actionDistributeVerticalGap); 0910 connect(actionDistributeVerticalGap, SIGNAL(triggered()), this, SLOT(selectionDistributeVerticalGap())); 0911 0912 QAction *actionDistributeBottom = new QAction(koIcon("distribute-vertical-bottom"), i18n("Distribute Bottom Borders"), this); 0913 actionCollection()->addAction("object_distribute_vertical_bottom", actionDistributeBottom); 0914 connect(actionDistributeBottom, SIGNAL(triggered()), this, SLOT(selectionDistributeVerticalBottom())); 0915 0916 QAction *actionDistributeTop = new QAction(koIcon("distribute-vertical-top"), i18n("Distribute Top Borders"), this); 0917 actionCollection()->addAction("object_distribute_vertical_top", actionDistributeTop); 0918 connect(actionDistributeTop, SIGNAL(triggered()), this, SLOT(selectionDistributeVerticalTop())); 0919 0920 d->showPaletteAction = new KToggleAction(i18n("Show Color Palette"), this); 0921 actionCollection()->addAction("view_show_palette", d->showPaletteAction); 0922 d->showPaletteAction->setToolTip(i18n("Show or hide color palette")); 0923 d->showPaletteAction->setChecked(true); 0924 connect(d->showPaletteAction, SIGNAL(triggered()), this, SLOT(showPalette())); 0925 0926 d->clipObjects = new QAction(i18n("&Clip Object"), this); 0927 actionCollection()->addAction("object_clip", d->clipObjects ); 0928 connect(d->clipObjects, SIGNAL(triggered()), this, SLOT(clipObjects())); 0929 0930 d->unclipObjects = new QAction(i18n("&Unclip Objects"), this); 0931 actionCollection()->addAction("object_unclip", d->unclipObjects ); 0932 connect(d->unclipObjects, SIGNAL(triggered()), this, SLOT(unclipObjects())); 0933 0934 d->flipVertical = new QAction(koIcon("object-flip-vertical"), i18n("Mirror Vertically"), this); 0935 actionCollection()->addAction("object_flip_vertical", d->flipVertical); 0936 connect(d->flipVertical, SIGNAL(triggered()), this, SLOT(flipVertical())); 0937 0938 d->flipHorizontal = new QAction(koIcon("object-flip-horizontal"), i18n("Mirror Horizontally"), this); 0939 actionCollection()->addAction("object_flip_horizontal", d->flipHorizontal); 0940 connect(d->flipHorizontal, SIGNAL(triggered()), this, SLOT(flipHorizontal())); 0941 0942 // object <----- 0943 0944 // path -------> 0945 d->closePath = new QAction(i18n("&Close Path"), this); 0946 actionCollection()->addAction("close_path", d->closePath); 0947 d->closePath->setShortcut(QKeySequence("Ctrl+U")); 0948 d->closePath->setEnabled(false); 0949 connect(d->closePath, SIGNAL(triggered()), this, SLOT(closePath())); 0950 0951 d->combinePath = new QAction(i18n("Com&bine Path"), this); 0952 actionCollection()->addAction("combine_path", d->combinePath); 0953 d->combinePath->setShortcut(QKeySequence("Ctrl+K")); 0954 d->combinePath->setEnabled(false); 0955 connect(d->combinePath, SIGNAL(triggered()), this, SLOT(combinePath())); 0956 0957 d->separatePath = new QAction(i18n("Se¶te Path"), this); 0958 actionCollection()->addAction("separate_path", d->separatePath); 0959 d->separatePath->setShortcut(QKeySequence("Shift+Ctrl+K")); 0960 d->separatePath->setEnabled(false); 0961 connect(d->separatePath, SIGNAL(triggered()), this, SLOT(separatePath())); 0962 0963 d->reversePath = new QAction(i18n("Re&verse Path"), this); 0964 actionCollection()->addAction("reverse_path", d->reversePath); 0965 d->reversePath->setShortcut(QKeySequence("Ctrl+R")); 0966 d->reversePath->setEnabled(false); 0967 connect(d->reversePath, SIGNAL(triggered()), this, SLOT(reversePath())); 0968 0969 d->intersectPath = new QAction(i18n("Intersect Paths"), this); 0970 actionCollection()->addAction("intersect_path", d->intersectPath); 0971 //d->intersectPath->setShortcut(QKeySequence("Shift+Ctrl+K")); 0972 d->intersectPath->setEnabled(false); 0973 connect(d->intersectPath, SIGNAL(triggered()), this, SLOT(intersectPaths())); 0974 0975 d->subtractPath = new QAction(i18n("Subtract Paths"), this); 0976 actionCollection()->addAction("subtract_path", d->subtractPath); 0977 //d->subtractPath->setShortcut(QKeySequence("Shift+Ctrl+K")); 0978 d->subtractPath->setEnabled(false); 0979 connect(d->subtractPath, SIGNAL(triggered()), this, SLOT(subtractPaths())); 0980 0981 d->unitePath = new QAction(i18n("Unite Paths"), this); 0982 actionCollection()->addAction("unite_path", d->unitePath); 0983 //d->unitePath->setShortcut(QKeySequence("Shift+Ctrl+K")); 0984 d->unitePath->setEnabled(false); 0985 connect(d->unitePath, SIGNAL(triggered()), this, SLOT(unitePaths())); 0986 0987 d->excludePath = new QAction(i18n("Exclude Paths"), this); 0988 actionCollection()->addAction("exclude_path", d->excludePath); 0989 //d->excludePath->setShortcut(QKeySequence("Shift+Ctrl+K")); 0990 d->excludePath->setEnabled(false); 0991 connect(d->excludePath, SIGNAL(triggered()), this, SLOT(excludePaths())); 0992 0993 d->pathSnapToGrid = new QAction(i18n("Snap Path to Grid"), this); 0994 actionCollection()->addAction("path_snap_to_grid", d->pathSnapToGrid); 0995 d->pathSnapToGrid->setEnabled(false); 0996 connect(d->pathSnapToGrid, SIGNAL(triggered()), this, SLOT(pathSnapToGrid())); 0997 0998 // path <----- 0999 1000 // view ----> 1001 QAction * zoomSelection = new QAction(koIcon("zoom-select"), i18n("Zoom to Selection"), this); 1002 actionCollection()->addAction("view_zoom_selection", zoomSelection); 1003 connect(zoomSelection, SIGNAL(triggered()), this, SLOT(zoomSelection())); 1004 1005 QAction * zoomDrawing = new QAction(koIcon("zoom-draw"), i18n("Zoom to Drawing"), this); 1006 actionCollection()->addAction("view_zoom_drawing", zoomDrawing); 1007 connect(zoomDrawing, SIGNAL(triggered()), this, SLOT(zoomDrawing())); 1008 // view <----- 1009 } 1010 1011 void KarbonView::mousePositionChanged(const QPoint &position) 1012 { 1013 const QPoint canvasOffset(canvasController()->canvasOffsetX(), canvasController()->canvasOffsetY() ); 1014 const QPoint viewPos = position - kopaCanvas()->documentOrigin() - canvasOffset; 1015 1016 QPointF documentPos = kopaCanvas()->viewConverter()->viewToDocument(viewPos); 1017 qreal x = kopaDocument()->unit().toUserValue(documentPos.x()); 1018 qreal y = kopaDocument()->unit().toUserValue(documentPos.y()); 1019 1020 if (statusBar() && statusBar()->isVisible()) { 1021 QLocale locale; 1022 d->cursorCoords->setText(QString::fromLatin1("%1, %2").arg(locale.toString(x, 'f', 2), locale.toString(y, 'f', 2))); 1023 } 1024 } 1025 1026 void KarbonView::reorganizeGUI() 1027 { 1028 // TODO: Find a better solution, maybe move to KoPAView? 1029 if (statusBar()) { 1030 bool show = true; 1031 if (mainWindow()) { 1032 KSharedConfigPtr config = KSharedConfig::openConfig(); 1033 if (config->hasGroup("Interface")) { 1034 KConfigGroup interfaceGroup = config->group( "Interface" ); 1035 if (!interfaceGroup.readEntry<bool>("ShowStatusBar", true)) { 1036 show = false; 1037 } 1038 } 1039 } 1040 statusBar()->setVisible(show); 1041 } 1042 } 1043 1044 void KarbonView::setNumberOfRecentFiles(unsigned int number) 1045 { 1046 if (mainWindow()) { // 0L when embedded into konq ! 1047 mainWindow()->setMaxRecentItems(number); 1048 } 1049 } 1050 1051 void KarbonView::editGuides() 1052 { 1053 KoToolManager::instance()->switchToolRequested("GuidesTool_ID"); 1054 } 1055 1056 void KarbonView::showPalette() 1057 { 1058 if(!mainWindow()) 1059 return; 1060 1061 const bool showPalette = d->showPaletteAction->isChecked(); 1062 d->colorBar->setVisible(showPalette); 1063 1064 // this will make the last setting of the ruler visibility persistent 1065 KConfigGroup interfaceGroup = KarbonFactory::global().config()->group("Interface"); 1066 if (showPalette && !interfaceGroup.hasDefault("ShowPalette")) 1067 interfaceGroup.revertToDefault("ShowPalette"); 1068 else 1069 interfaceGroup.writeEntry("ShowPalette", showPalette); 1070 } 1071 1072 void KarbonView::openConfiguration() 1073 { 1074 QPointer<KarbonConfigureDialog> dialog = new KarbonConfigureDialog(this); 1075 dialog->exec(); 1076 delete dialog; 1077 reorganizeGUI(); 1078 } 1079 1080 void KarbonView::selectionChanged() 1081 { 1082 if (!mainWindow()) 1083 return; 1084 KoSelection *selection = kopaCanvas()->shapeManager()->selection(); 1085 QList<KoShape*> selectedShapes = selection->selectedShapes(KoFlake::FullSelection); 1086 const int count = selectedShapes.count(); 1087 1088 d->closePath->setEnabled(false); 1089 d->combinePath->setEnabled(false); 1090 d->excludePath->setEnabled(false); 1091 d->intersectPath->setEnabled(false); 1092 d->subtractPath->setEnabled(false); 1093 d->unitePath->setEnabled(false); 1094 d->pathSnapToGrid->setEnabled(false); 1095 d->clipObjects->setEnabled(false); 1096 d->unclipObjects->setEnabled(false); 1097 d->flipHorizontal->setEnabled(count > 0); 1098 d->flipVertical->setEnabled(count > 0); 1099 1100 debugKarbonUi << count << " shapes selected"; 1101 1102 if (count > 0) { 1103 uint selectedPaths = 0; 1104 uint selectedParametrics = 0; 1105 // check for different shape types for enabling specific actions 1106 foreach(KoShape* shape, selectedShapes) { 1107 if (dynamic_cast<KoPathShape*>(shape)) { 1108 KoParameterShape * ps = dynamic_cast<KoParameterShape*>(shape); 1109 if (ps && ps->isParametricShape()) 1110 selectedParametrics++; 1111 else 1112 selectedPaths++; 1113 } 1114 } 1115 debugKarbonUi << selectedPaths << " path shapes selected"; 1116 debugKarbonUi << selectedParametrics << " parameter shapes selected"; 1117 //TODO enable action when the ClosePath command is ported 1118 //d->closePath->setEnabled( selectedPaths > 0 ); 1119 d->combinePath->setEnabled(selectedPaths > 1); 1120 d->separatePath->setEnabled(selectedPaths > 0); 1121 d->reversePath->setEnabled(selectedPaths > 0); 1122 d->excludePath->setEnabled(selectedPaths + selectedParametrics == 2); 1123 d->intersectPath->setEnabled(selectedPaths + selectedParametrics == 2); 1124 d->subtractPath->setEnabled(selectedPaths + selectedParametrics == 2); 1125 d->unitePath->setEnabled(selectedPaths + selectedParametrics == 2); 1126 d->pathSnapToGrid->setEnabled(selectedPaths > 0); 1127 d->clipObjects->setEnabled(selectedPaths > 0 && count > 1); 1128 d->unclipObjects->setEnabled(selectedShapes.first()->clipPath() != 0); 1129 // if only one shape selected, set its parent layer as the active layer 1130 if (count == 1) { 1131 KoShapeContainer * parent = selection->selectedShapes().first()->parent(); 1132 while (parent) { 1133 if (parent->parent()) 1134 parent = parent->parent(); 1135 else 1136 break; 1137 } 1138 KoShapeLayer * layer = dynamic_cast<KoShapeLayer*>(parent); 1139 if (layer) 1140 selection->setActiveLayer(layer); 1141 } 1142 } 1143 } 1144 1145 void KarbonView::setCursor(const QCursor &c) 1146 { 1147 kopaCanvas()->setCursor(c); 1148 } 1149 1150 void KarbonView::updateReadWrite(bool readwrite) 1151 { 1152 Q_UNUSED(readwrite); 1153 } 1154 1155 QList<KoPathShape*> KarbonView::selectedPathShapes() 1156 { 1157 KoSelection* selection = shapeManager()->selection(); 1158 if (! selection) 1159 return QList<KoPathShape*>(); 1160 1161 QList<KoShape*> selectedShapes = selection->selectedShapes(); 1162 QList<KoPathShape*> paths; 1163 1164 foreach(KoShape* shape, selectedShapes) { 1165 KoPathShape *path = dynamic_cast<KoPathShape*>(shape); 1166 if (path) { 1167 paths << path; 1168 selection->deselect(shape); 1169 } 1170 } 1171 1172 return paths; 1173 } 1174 1175 void KarbonView::applyFillToSelection() 1176 { 1177 KoSelection *selection = shapeManager()->selection(); 1178 if (! selection->count()) 1179 return; 1180 1181 KoShape * shape = selection->firstSelectedShape(); 1182 kopaCanvas()->addCommand(new KoShapeBackgroundCommand(selection->selectedShapes(), shape->background())); 1183 } 1184 1185 void KarbonView::applyStrokeToSelection() 1186 { 1187 KoSelection *selection = shapeManager()->selection(); 1188 if (! selection->count()) 1189 return; 1190 1191 KoShape * shape = selection->firstSelectedShape(); 1192 kopaCanvas()->addCommand(new KoShapeStrokeCommand(selection->selectedShapes(), shape->stroke())); 1193 } 1194 1195 void KarbonView::applyPaletteColor(const KoColor &color) 1196 { 1197 KoSelection *selection = shapeManager()->selection(); 1198 if (! selection->count()) 1199 return; 1200 1201 int style = resourceManager()->intResource(KoCanvasResourceManager::ActiveStyleType); 1202 if (style == KoFlake::Foreground) { 1203 QList<KoShapeStrokeModel*> newStrokes; 1204 foreach(KoShape *shape, selection->selectedShapes()) { 1205 KoShapeStroke *stroke = dynamic_cast<KoShapeStroke*>(shape->stroke()); 1206 if (stroke) { 1207 // preserve stroke properties 1208 KoShapeStroke *newStroke = new KoShapeStroke(*stroke); 1209 newStroke->setColor(color.toQColor()); 1210 newStrokes << newStroke; 1211 } else { 1212 newStrokes << new KoShapeStroke(1.0, color.toQColor()); 1213 } 1214 } 1215 kopaCanvas()->addCommand(new KoShapeStrokeCommand(selection->selectedShapes(), newStrokes)); 1216 resourceManager()->setForegroundColor(color); 1217 } else { 1218 QSharedPointer<KoShapeBackground> fill(new KoColorBackground(color.toQColor())); 1219 kopaCanvas()->addCommand(new KoShapeBackgroundCommand(selection->selectedShapes(), fill)); 1220 resourceManager()->setBackgroundColor(color); 1221 } 1222 } 1223 1224 void KarbonView::replaceActivePage(KoPAPageBase *page, KoPAPageBase *newActivePage) 1225 { 1226 if (page == activePage() ) { 1227 viewMode()->updateActivePage(newActivePage); 1228 } 1229 } 1230