Warning, file /office/calligra/braindump/src/View.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (c) 2009,2010 Cyrille Berger <cberger@cberger.net> 0003 * 0004 * This library is free software; you can redistribute it and/or 0005 * modify it under the terms of the GNU Lesser General Public 0006 * License as published by the Free Software Foundation; 0007 * either version 2, or (at your option) any later version of the License. 0008 * 0009 * This library is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0012 * Lesser General Public License for more details. 0013 * 0014 * You should have received a copy of the GNU Lesser General Public License 0015 * along with this library; see the file COPYING. If not, write to 0016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0017 * Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "View.h" 0021 0022 #include <QGridLayout> 0023 #include <QString> 0024 #include <QVariant> 0025 #include <QToolBar> 0026 #include <QScrollBar> 0027 #include <QStatusBar> 0028 #include <QTimer> 0029 #include <QApplication> 0030 #include <QClipboard> 0031 #include <QPluginLoader> 0032 #include <QMimeData> 0033 #include <QDebug> 0034 #include <QAction> 0035 0036 #include <kactioncollection.h> 0037 #include <KPluginFactory> 0038 0039 #include <KoCanvasControllerWidget.h> 0040 #include <KoToolManager.h> 0041 #include <KoToolProxy.h> 0042 #include <KoZoomHandler.h> 0043 #include <KoShapeController.h> 0044 #include <KoShapeManager.h> 0045 #include <KoSelection.h> 0046 #include <KoMainWindow.h> 0047 #include <KoDockRegistry.h> 0048 #include <KoShapeLayer.h> 0049 #include <KoDrag.h> 0050 #include <KoCutController.h> 0051 #include <KoCopyController.h> 0052 #include "KoZoomController.h" 0053 #include <KoZoomAction.h> 0054 #include <KoIcon.h> 0055 #include "KoToolBoxFactory.h" 0056 #include <KoPluginLoader.h> 0057 #include "KoOdf.h" 0058 #include "KoShapeGroup.h" 0059 #include "KoShapeDeleteCommand.h" 0060 #include "KoShapeCreateCommand.h" 0061 #include "KoShapeGroupCommand.h" 0062 #include "KoShapeUngroupCommand.h" 0063 0064 #include "Canvas.h" 0065 #include "RootSection.h" 0066 #include "Section.h" 0067 #include "ViewManager.h" 0068 #include "import/DockerManager.h" 0069 #include "MainWindow.h" 0070 #include "SectionContainer.h" 0071 #include "SectionsBoxDock.h" 0072 #include "Layout.h" 0073 #include "SectionPropertiesDock.h" 0074 #include "commands/RememberPositionCommand.h" 0075 0076 View::View(RootSection *document, MainWindow* parent) 0077 : QWidget(parent) 0078 , m_doc(document) 0079 , m_canvas(0) 0080 , m_activeSection(0) 0081 , m_mainWindow(parent) 0082 , m_cutController(0) 0083 , m_copyController(0) 0084 { 0085 setXMLFile("braindumpview.rc"); 0086 0087 m_doc->viewManager()->addView(this); 0088 0089 m_editPaste = actionCollection()->addAction(KStandardAction::Paste, "edit_paste", this, SLOT(editPaste())); 0090 m_editCut = actionCollection()->addAction(KStandardAction::Cut, "edit_cut", 0, 0); 0091 m_editCopy = actionCollection()->addAction(KStandardAction::Copy, "edit_copy", 0, 0); 0092 initGUI(); 0093 initActions(); 0094 loadExtensions(); 0095 0096 if(m_doc->sections().count() > 0) { 0097 setActiveSection(m_doc->sections()[0]); 0098 } else { 0099 setActiveSection(0); 0100 } 0101 0102 m_doc->viewManager()->viewHasFocus(this); 0103 } 0104 0105 View::~View() 0106 { 0107 m_doc->viewManager()->removeView(this); 0108 KoToolManager::instance()->removeCanvasController(m_canvasController); 0109 delete m_zoomController; 0110 } 0111 0112 0113 Section* View::activeSection() const 0114 { 0115 return m_activeSection; 0116 } 0117 0118 void View::initGUI() 0119 { 0120 // add all plugins. 0121 foreach(const QString & docker, KoDockRegistry::instance()->keys()) { 0122 qDebug() << "Creating docker: " << docker; 0123 KoDockFactoryBase *factory = KoDockRegistry::instance()->value(docker); 0124 m_mainWindow->createDockWidget(factory); 0125 } 0126 0127 // Init the widgets 0128 QGridLayout * gridLayout = new QGridLayout(this); 0129 gridLayout->setMargin(0); 0130 gridLayout->setSpacing(0); 0131 setLayout(gridLayout); 0132 0133 0134 m_canvasController = new KoCanvasControllerWidget(actionCollection(), this); 0135 m_canvasController->setCanvasMode(KoCanvasController::Infinite); 0136 0137 createCanvas(0); 0138 0139 KoToolManager::instance()->addController(m_canvasController); 0140 KoToolManager::instance()->registerTools(actionCollection(), m_canvasController); 0141 0142 m_zoomController = new KoZoomController(m_canvasController, &m_zoomHandler, actionCollection()); 0143 connect(m_zoomController, SIGNAL(zoomChanged(KoZoomMode::Mode,qreal)), 0144 this, SLOT(slotZoomChanged(KoZoomMode::Mode,qreal))); 0145 0146 m_zoomAction = m_zoomController->zoomAction(); 0147 m_mainWindow->addStatusBarItem(m_zoomAction->createWidget(m_mainWindow->statusBar()), 0, this); 0148 0149 m_zoomController->setZoomMode(KoZoomMode::ZOOM_WIDTH); 0150 0151 gridLayout->addWidget(m_canvasController, 1, 1); 0152 0153 connect(m_canvasController->proxyObject, SIGNAL(canvasMousePositionChanged(QPoint)), 0154 this, SLOT(updateMousePosition(QPoint))); 0155 0156 KoToolBoxFactory toolBoxFactory; 0157 m_mainWindow->createDockWidget(&toolBoxFactory); 0158 0159 connect(m_canvasController, SIGNAL(toolOptionWidgetsChanged(QList<QPointer<QWidget> >)), m_mainWindow->dockerManager(), SLOT(newOptionWidgets(QList<QPointer<QWidget> >))); 0160 0161 SectionsBoxDockFactory structureDockerFactory; 0162 m_sectionsBoxDock = qobject_cast<SectionsBoxDock*>(m_mainWindow->createDockWidget(&structureDockerFactory)); 0163 Q_ASSERT(m_sectionsBoxDock); 0164 m_sectionsBoxDock->setup(m_doc, this); 0165 0166 SectionPropertiesDockFactory sectionPropertiesDockerFactory; 0167 m_sectionPropertiesDock = qobject_cast<SectionPropertiesDock*>(m_mainWindow->createDockWidget(§ionPropertiesDockerFactory)); 0168 Q_ASSERT(m_sectionPropertiesDock); 0169 m_sectionPropertiesDock->setRootSection(m_doc); 0170 0171 KoToolManager::instance()->requestToolActivation(m_canvasController); 0172 0173 show(); 0174 } 0175 0176 void View::initActions() 0177 { 0178 connect(QApplication::clipboard(), SIGNAL(dataChanged()), this, SLOT(clipboardDataChanged())); 0179 clipboardDataChanged(); 0180 actionCollection()->addAction(KStandardAction::SelectAll, "edit_select_all", this, SLOT(editSelectAll())); 0181 actionCollection()->addAction(KStandardAction::Deselect, "edit_deselect_all", this, SLOT(editDeselectAll())); 0182 0183 m_deleteSelectionAction = new QAction(koIcon("edit-delete"), i18n("D&elete"), this); 0184 actionCollection()->addAction("edit_delete", m_deleteSelectionAction); 0185 actionCollection()->setDefaultShortcut(m_deleteSelectionAction, QKeySequence("Del")); 0186 connect(m_deleteSelectionAction, SIGNAL(triggered()), this, SLOT(editDeleteSelection())); 0187 0188 // Shapes menu 0189 // TODO: get an icon "edit-duplicate" 0190 QAction *actionDuplicate = new QAction(i18nc("Duplicate selection", "&Duplicate"), this); 0191 actionCollection()->addAction("shapes_duplicate", actionDuplicate); 0192 actionCollection()->setDefaultShortcut(actionDuplicate, QKeySequence("Ctrl+D")); 0193 connect(actionDuplicate, SIGNAL(triggered()), this, SLOT(selectionDuplicate())); 0194 0195 m_groupShapes = new QAction(koIcon("object-group"), i18n("Group Shapes"), this); 0196 actionCollection()->addAction("shapes_group", m_groupShapes); 0197 actionCollection()->setDefaultShortcut(m_groupShapes, QKeySequence("Ctrl+G")); 0198 connect(m_groupShapes, SIGNAL(triggered()), this, SLOT(groupSelection())); 0199 0200 m_ungroupShapes = new QAction(koIcon("object-ungroup"), i18n("Ungroup Shapes"), this); 0201 actionCollection()->addAction("shapes_ungroup", m_ungroupShapes); 0202 actionCollection()->setDefaultShortcut(m_ungroupShapes, QKeySequence("Ctrl+Shift+G")); 0203 connect(m_ungroupShapes, SIGNAL(triggered()), this, SLOT(ungroupSelection())); 0204 0205 } 0206 0207 void View::loadExtensions() 0208 { 0209 const QList<KPluginFactory *> pluginFactories = 0210 KoPluginLoader::instantiatePluginFactories(QStringLiteral("braindump/extensions")); 0211 0212 foreach (KPluginFactory* factory, pluginFactories) { 0213 QObject *object = factory->create<QObject>(this, QVariantList()); 0214 KXMLGUIClient *clientPlugin = dynamic_cast<KXMLGUIClient*>(object); 0215 if (clientPlugin) { 0216 insertChildClient(clientPlugin); 0217 } else { 0218 // not our/valid plugin, so delete the created object 0219 object->deleteLater(); 0220 } 0221 } 0222 } 0223 0224 0225 void View::editPaste() 0226 { 0227 m_canvas->toolProxy()->paste(); 0228 } 0229 0230 void View::editDeleteSelection() 0231 { 0232 m_canvas->toolProxy()->deleteSelection(); 0233 } 0234 0235 void View::editSelectAll() 0236 { 0237 KoSelection* selection = canvas()->shapeManager()->selection(); 0238 if(!selection) 0239 return; 0240 0241 KoShapeLayer *layer = activeSection()->sectionContainer()->layer(); 0242 0243 QList<KoShape*> layerShapes(layer->shapes()); 0244 foreach(KoShape * layerShape, layerShapes) { 0245 selection->select(layerShape); 0246 layerShape->update(); 0247 } 0248 } 0249 0250 void View::editDeselectAll() 0251 { 0252 KoSelection* selection = canvas()->shapeManager()->selection(); 0253 if(selection) 0254 selection->deselectAll(); 0255 0256 canvas()->update(); 0257 } 0258 0259 void View::slotZoomChanged(KoZoomMode::Mode mode, qreal zoom) 0260 { 0261 Q_UNUSED(mode); 0262 Q_UNUSED(zoom); 0263 canvas()->updateOriginAndSize(); 0264 canvas()->update(); 0265 } 0266 0267 void View::createCanvas(Section* _currentSection) 0268 { 0269 Canvas* canvas = new Canvas(this, m_doc, _currentSection); 0270 m_canvasController->setCanvas(canvas); 0271 // No need to delete the current canvas, it will be deleted in Viewport::setCanvas (flake/KoCanvasController_p.cpp) 0272 m_canvas = canvas; 0273 0274 delete m_cutController; 0275 m_cutController = new KoCutController(m_canvas, m_editCut); 0276 delete m_copyController; 0277 m_copyController = new KoCopyController(m_canvas, m_editCopy); 0278 0279 connect(m_canvas, SIGNAL(canvasReceivedFocus()), SLOT(canvasReceivedFocus())); 0280 connect(m_canvas, SIGNAL(documentRect(QRectF)), SLOT(documentRectChanged(QRectF))); 0281 connect(m_canvasController->proxyObject, SIGNAL(moveDocumentOffset(QPoint)), 0282 m_canvas, SLOT(setDocumentOffset(QPoint))); 0283 connect(m_canvas->toolProxy(), SIGNAL(toolChanged(QString)), this, SLOT(clipboardDataChanged())); 0284 0285 m_canvas->updateOriginAndSize(); 0286 0287 setEnabled(_currentSection); 0288 } 0289 0290 void View::setActiveSection(Section* page) 0291 { 0292 0293 m_activeSection = page; 0294 0295 m_doc->setCurrentSection(page); 0296 0297 createCanvas(m_activeSection); 0298 0299 if(m_activeSection) { 0300 documentRectChanged(m_activeSection->layout()->boundingBox()); 0301 } 0302 0303 m_sectionsBoxDock->updateGUI(); 0304 m_sectionPropertiesDock->setSection(m_activeSection); 0305 } 0306 0307 void View::updateMousePosition(const QPoint& /*position*/) 0308 { 0309 QPoint canvasOffset(m_canvasController->canvasOffsetX(), m_canvasController->canvasOffsetY()); 0310 // the offset is positive it the canvas is shown fully visible 0311 canvasOffset.setX(canvasOffset.x() < 0 ? canvasOffset.x() : 0); 0312 canvasOffset.setY(canvasOffset.y() < 0 ? canvasOffset.y() : 0); 0313 } 0314 0315 void View::clipboardDataChanged() 0316 { 0317 const QMimeData* data = QApplication::clipboard()->mimeData(); 0318 bool paste = false; 0319 0320 if(data) { 0321 // TODO see if we can use the KoPasteController instead of having to add this feature in each calligra app. 0322 QStringList mimeTypes = m_canvas->toolProxy()->supportedPasteMimeTypes(); 0323 mimeTypes << KoOdf::mimeType(KoOdf::Graphics); 0324 mimeTypes << KoOdf::mimeType(KoOdf::Presentation); 0325 0326 foreach(const QString & mimeType, mimeTypes) { 0327 if(data->hasFormat(mimeType)) { 0328 paste = true; 0329 break; 0330 } 0331 } 0332 0333 } 0334 0335 m_editPaste->setEnabled(paste); 0336 } 0337 0338 void View::focusInEvent(QFocusEvent * event) 0339 { 0340 QWidget::focusInEvent(event); 0341 m_doc->viewManager()->viewHasFocus(this); 0342 } 0343 0344 void View::canvasReceivedFocus() 0345 { 0346 m_doc->viewManager()->viewHasFocus(this); 0347 } 0348 0349 void View::documentRectChanged(const QRectF& bb) 0350 { 0351 QSizeF pageSize(400, 400); 0352 // Make sure we never use an empty size 0353 if(!bb.isNull() && !bb.isEmpty()) { 0354 pageSize = bb.size(); 0355 } 0356 m_zoomController->setPageSize(pageSize); 0357 m_zoomController->setDocumentSize(pageSize); 0358 } 0359 0360 void View::selectionDuplicate() 0361 { 0362 m_canvas->toolProxy()->copy(); 0363 m_canvas->toolProxy()->paste(); 0364 } 0365 0366 void View::groupSelection() 0367 { 0368 KoSelection* selection = m_canvas->shapeManager()->selection(); 0369 if(! selection) 0370 return; 0371 0372 QList<KoShape*> selectedShapes = selection->selectedShapes(KoFlake::TopLevelSelection); 0373 QList<KoShape*> groupedShapes; 0374 0375 // only group shapes with an unselected parent 0376 foreach(KoShape * shape, selectedShapes) { 0377 if(selectedShapes.contains(shape->parent())) 0378 continue; 0379 groupedShapes << shape; 0380 } 0381 KoShapeGroup *group = new KoShapeGroup(); 0382 if(selection->activeLayer()) 0383 selection->activeLayer()->addShape(group); 0384 KUndo2Command *cmd = new KUndo2Command(kundo2_i18n("Group shapes")); 0385 new KoShapeCreateCommand(m_activeSection->sectionContainer(), group, cmd); 0386 new KoShapeGroupCommand(group, groupedShapes, cmd); 0387 m_canvas->addCommand(cmd); 0388 } 0389 0390 void View::ungroupSelection() 0391 { 0392 KoSelection* selection = m_canvas->shapeManager()->selection(); 0393 if(! selection) 0394 return; 0395 0396 QList<KoShape*> selectedShapes = selection->selectedShapes(KoFlake::TopLevelSelection); 0397 QList<KoShape*> containerSet; 0398 0399 // only ungroup shape containers with an unselected parent 0400 foreach(KoShape * shape, selectedShapes) { 0401 if(selectedShapes.contains(shape->parent())) 0402 continue; 0403 containerSet << shape; 0404 } 0405 0406 KUndo2Command *cmd = new KUndo2Command(kundo2_i18n("Ungroup shapes")); 0407 0408 // add a ungroup command for each found shape container to the macro command 0409 foreach(KoShape * shape, containerSet) { 0410 KoShapeContainer *container = dynamic_cast<KoShapeContainer*>(shape); 0411 if(container) { 0412 new KoShapeUngroupCommand(container, container->shapes(), QList<KoShape*>(), cmd); 0413 new KoShapeDeleteCommand(m_activeSection->sectionContainer(), container, cmd); 0414 new RememberPositionCommand(container->shapes(), cmd); 0415 } 0416 } 0417 m_canvas->addCommand(cmd); 0418 }