00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "KoToolManager.h"
00022 #include "KoToolManager_p.h"
00023
00024 #include <QWidget>
00025 #include <QEvent>
00026 #include <QWheelEvent>
00027 #include <QMouseEvent>
00028 #include <QPaintEvent>
00029 #include <QTabletEvent>
00030 #include <QKeyEvent>
00031
00032 #include "KoToolRegistry.h"
00033 #include <KoTool.h>
00034 #include <KoToolBox.h>
00035 #include <KoCreateShapesToolFactory.h>
00036 #include <KoCreateShapesTool.h>
00037 #include <KoInteractionToolFactory.h>
00038 #include <KoPointerEvent.h>
00039 #include <KoShapeControllerBase.h>
00040 #include <KoCanvasController.h>
00041 #include <KoShapeRegistry.h>
00042 #include <KoShapeManager.h>
00043 #include <KoInputDevice.h>
00044 #include <kactioncollection.h>
00045 #include <kdebug.h>
00046 #include <kstaticdeleter.h>
00047
00048 #include <QStringList>
00049 #include <QAbstractButton>
00050 #include <QApplication>
00051
00052 namespace {
00053
00054
00055
00056
00057 static const int MOUSE_CHANGE_EVENT_DELAY = 100;
00058
00059
00060
00061
00062 class TabletProximityFilter {
00063 public:
00064
00065 TabletProximityFilter( KoToolManager * manager )
00066 : m_manager( manager )
00067 {
00068 }
00069
00070 virtual ~TabletProximityFilter();
00071
00072 bool eventFilter( QObject * object, QEvent * event ) {
00073
00074 if ( object == qApp ) {
00075 switch( event->type() ) {
00076 case QEvent::TabletEnterProximity:
00077 break;
00078 case QEvent::TabletLeaveProximity:
00079 break;
00080 default:
00081 break;
00082 }
00083 }
00084 return false;
00085 }
00086
00087 private:
00088
00089 KoToolManager * m_manager;
00090 };
00091
00092 }
00093
00094
00095 class DummyTool : public KoTool {
00096
00097 public:
00098
00099 DummyTool() : KoTool(0) {}
00100 ~DummyTool() {}
00101 void paint( QPainter &, KoViewConverter &) {}
00102 void mousePressEvent( KoPointerEvent *) {}
00103 void mouseMoveEvent( KoPointerEvent *) {}
00104 void mouseReleaseEvent( KoPointerEvent *) {}
00105
00106 };
00107
00108
00109
00110
00111 KoToolManager::KoToolManager()
00112 : QObject()
00113 , m_activeCanvas(0)
00114 , m_activeTool(0)
00115 {
00116 m_dummyTool = new DummyTool();
00117 connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*,QWidget*)),
00118 this, SLOT(movedFocus(QWidget*,QWidget*)));
00119 }
00120
00121 KoToolManager::~KoToolManager() {
00122 delete m_dummyTool;
00123 }
00124
00125 void KoToolManager::paint( QPainter &painter, KoViewConverter &converter )
00126 {
00127 if (m_activeTool) m_activeTool->paint(painter, converter);
00128 }
00129
00130 void KoToolManager::repaintDecorations()
00131 {
00132 if (m_activeTool) m_activeTool->repaintDecorations();
00133 }
00134
00135 void KoToolManager::tabletEvent( QTabletEvent *event, const QPointF &pnt )
00136 {
00137 KoPointerEvent ev( event, pnt );
00138 switch( event->type() ) {
00139 case ( QEvent::TabletPress ):
00140 if (m_activeTool) m_activeTool->mousePressEvent( &ev );
00141 break;
00142 case ( QEvent::TabletRelease ):
00143 if (m_activeTool) m_activeTool->mouseReleaseEvent( &ev );
00144 break;
00145 case ( QEvent::TabletMove ):
00146 default:
00147 if (m_activeTool) m_activeTool->mouseMoveEvent( &ev );
00148 }
00149 }
00150
00151 void KoToolManager::mousePressEvent( QMouseEvent *event, const QPointF &pnt )
00152 {
00153 KoPointerEvent ev( event, pnt );
00154 if (m_activeTool) m_activeTool->mousePressEvent( &ev );
00155 }
00156
00157 void KoToolManager::mouseDoubleClickEvent( QMouseEvent *event, const QPointF &pnt )
00158 {
00159 KoPointerEvent ev( event, pnt );
00160 if (m_activeTool) m_activeTool->mouseDoubleClickEvent( &ev );
00161 }
00162
00163 void KoToolManager::mouseMoveEvent( QMouseEvent *event, const QPointF &pnt )
00164 {
00165 KoPointerEvent ev( event, pnt );
00166 if (m_activeTool) m_activeTool->mouseMoveEvent( &ev );
00167 }
00168
00169 void KoToolManager::mouseReleaseEvent( QMouseEvent *event, const QPointF &pnt )
00170 {
00171 KoPointerEvent ev( event, pnt );
00172 if (m_activeTool) m_activeTool->mouseReleaseEvent( &ev );
00173 }
00174
00175 void KoToolManager::keyPressEvent(QKeyEvent *event)
00176 {
00177 if (m_activeTool) m_activeTool->keyPressEvent( event );
00178 }
00179
00180 void KoToolManager::keyReleaseEvent(QKeyEvent *event)
00181 {
00182 if (m_activeTool) m_activeTool->keyReleaseEvent( event );
00183 }
00184
00185 void KoToolManager::wheelEvent ( QWheelEvent * event, const QPointF &pnt )
00186 {
00187 KoPointerEvent ev( event, pnt );
00188 if (m_activeTool) m_activeTool->wheelEvent( &ev );
00189 }
00190
00191
00192 void KoToolManager::setup() {
00193 if (m_tools.size() > 0)
00194 return;
00195
00196
00197
00198
00199 m_tools.append( new ToolHelper(new KoCreateShapesToolFactory(this, QStringList())) );
00200 m_defaultTool = new ToolHelper(new KoInteractionToolFactory(this, QStringList()));
00201 m_tools.append(m_defaultTool);
00202
00203 KoShapeRegistry::instance();
00204 KoToolRegistry *registry = KoToolRegistry::instance();
00205 foreach(QString id, registry->keys()) {
00206 ToolHelper *t = new ToolHelper(registry->get(id));
00207 connect(t, SIGNAL(toolActivated(ToolHelper*)), this, SLOT(toolActivated(ToolHelper*)));
00208 m_tools.append(t);
00209 }
00210
00211
00212 foreach(ToolHelper *tool, m_tools)
00213 connect(tool, SIGNAL(toolActivated(ToolHelper*)), this, SLOT(toolActivated(ToolHelper*)));
00214 }
00215
00216 KoToolBox *KoToolManager::toolBox(const QString &applicationName) {
00217 setup();
00218 KoToolBox *toolBox = new KoToolBox();
00219 foreach(ToolHelper *tool, m_tools) {
00220 QAbstractButton *but = tool->createButton();
00221 toolBox->addButton(but, tool->toolType(), tool->priority(), tool->uniqueId());
00222 if (tool->toolType() == KoToolFactory::dynamicToolType())
00223 toolBox->setVisibilityCode(but, tool->activationShapeId());
00224 }
00225
00226 toolBox->setup();
00227 toolBox->setWindowTitle(applicationName);
00228 toolBox->setObjectName("ToolBox_"+ applicationName);
00229 connect(this, SIGNAL(changedTool(int)), toolBox, SLOT(setActiveTool(int)));
00230 connect(this, SIGNAL(toolCodesSelected(QList<QString>)),
00231 toolBox, SLOT(setButtonsVisible(QList<QString>)));
00232 QList<QString> empty;
00233 toolBox->setButtonsVisible(empty);
00234 toolBox->setActiveTool(m_defaultTool->uniqueId());
00235 return toolBox;
00236 }
00237
00238 void KoToolManager::registerTools(KActionCollection *ac) {
00239 Q_UNUSED(ac);
00240 setup();
00241
00242 }
00243
00244 void KoToolManager::addControllers(KoCanvasController *controller, KoShapeControllerBase *sc) {
00245 if (m_canvases.contains(controller))
00246 return;
00247 setup();
00248 m_canvases.append(controller);
00249 m_shapeControllers.insert(controller, sc);
00250 if (m_activeCanvas == 0)
00251 m_activeCanvas = controller;
00252 if (controller->canvas())
00253 attachCanvas(controller);
00254 connect(controller, SIGNAL(canvasRemoved(KoCanvasController*)), this, SLOT(detachCanvas(KoCanvasController*)));
00255 connect(controller, SIGNAL(canvasSet(KoCanvasController*)), this, SLOT(attachCanvas(KoCanvasController*)));
00256 }
00257
00258 void KoToolManager::removeCanvasController(KoCanvasController *controller) {
00259 m_canvases.removeAll(controller);
00260 m_shapeControllers.remove(controller);
00261 QMap<QString, KoTool*> toolsMap = m_allTools.value(controller);
00262 foreach(KoTool *tool, toolsMap.values()) {
00263 m_uniqueToolIds.remove(tool);
00264 delete tool;
00265 }
00266 m_allTools.remove(controller);
00267 if (controller->canvas())
00268 detachCanvas(controller);
00269 disconnect(controller, SIGNAL(canvasRemoved(KoCanvasController*)), this, SLOT(detachCanvas(KoCanvasController*)));
00270 disconnect(controller, SIGNAL(canvasSet(KoCanvasController*)), this, SLOT(attachCanvas(KoCanvasController*)));
00271 }
00272
00273 void KoToolManager::toolActivated(ToolHelper *tool) {
00274
00275 QMap<QString, KoTool*> toolsMap = m_allTools.value(m_activeCanvas);
00276 KoTool *t = toolsMap.value(tool->id());
00277
00278 m_activeToolId = tool->id();
00279
00280
00281 if ( m_activeToolId != KoInteractionTool_ID ) {
00282 m_lastSelectedShapes.clear();
00283 KoSelection *selection = m_activeCanvas->canvas()->shapeManager()->selection();
00284 foreach( KoShape *shape, selection->selectedShapes() ) {
00285 if ( tool->activationShapeId().isNull() || tool->activationShapeId() == shape->shapeId() )
00286 m_lastSelectedShapes.append( shape );
00287 }
00288 }
00289
00290 switchTool(t);
00291 }
00292
00293 void KoToolManager::switchTool(const QString &id, bool temporary) {
00294
00295 if (!m_activeCanvas) kDebug() << kBacktrace();
00296 Q_ASSERT(m_activeCanvas);
00297 if (m_activeTool && temporary)
00298 m_stack.push(m_activeToolId);
00299 m_activeToolId = id;
00300 QMap<QString, KoTool*> toolsMap = m_allTools.value(m_activeCanvas);
00301 KoTool *tool = toolsMap.value(id);
00302 if (! tool) {
00303 kWarning(30004) << "Tool requested " << (temporary?"temporary":"") << "switch to unknown tool: '" << id << "'\n";
00304 return;
00305 }
00306 switchTool(tool);
00307 }
00308
00309 void KoToolManager::switchTool(KoTool *tool) {
00310
00311 if (!tool) kDebug() << kBacktrace();
00312 Q_ASSERT(tool);
00313 if (m_activeCanvas == 0) {
00314 return;
00315 }
00316 if (m_activeTool) {
00317 m_activeTool->deactivate();
00318 disconnect(m_activeTool, SIGNAL(sigCursorChanged(QCursor)),
00319 this, SLOT(updateCursor(QCursor)));
00320 disconnect(m_activeTool, SIGNAL(sigActivateTool(const QString &)),
00321 this, SLOT(switchToolRequested(const QString &)));
00322 disconnect(m_activeTool, SIGNAL(sigActivateTemporary(const QString &)),
00323 this, SLOT(switchToolTemporaryRequested(const QString &)));
00324 disconnect(m_activeTool, SIGNAL(sigDone()), this, SLOT(switchBackRequested()));
00325 }
00326 m_activeTool = tool;
00327 connect(m_activeTool, SIGNAL(sigCursorChanged(QCursor)),
00328 this, SLOT(updateCursor(QCursor)));
00329 connect(m_activeTool, SIGNAL(sigActivateTool(const QString &)),
00330 this, SLOT(switchToolRequested(const QString &)));
00331 connect(m_activeTool, SIGNAL(sigActivateTemporary(const QString &)),
00332 this, SLOT(switchToolTemporaryRequested(const QString &)));
00333 connect(m_activeTool, SIGNAL(sigDone()), this, SLOT(switchBackRequested()));
00334
00335
00336 foreach(KoCanvasController *controller, m_canvases) {
00337 if (!controller->canvas())
00338 continue;
00339
00340
00341
00342 controller->canvas()->canvasWidget()->setCursor(Qt::ForbiddenCursor);
00343 }
00344 m_activeTool->activate();
00345 emit changedTool(m_uniqueToolIds.value(m_activeTool));
00346 }
00347
00348 void KoToolManager::attachCanvas(KoCanvasController *controller) {
00349 QMap<QString, KoTool*> toolsMap;
00350 foreach(ToolHelper *tool, m_tools) {
00351 kDebug() << "Creating tool " << tool->id() << ", " << tool->activationShapeId() << endl;
00352 KoTool *tl = tool->createTool(controller->canvas());
00353 m_uniqueToolIds.insert(tl, tool->uniqueId());
00354 toolsMap.insert(tool->id(), tl);
00355 }
00356 KoCreateShapesTool *createTool = dynamic_cast<KoCreateShapesTool*>(toolsMap.value(KoCreateShapesTool_ID));
00357 Q_ASSERT(createTool);
00358 createTool->setShapeController(m_shapeControllers[controller]);
00359 QString id = KoShapeRegistry::instance()->keys()[0];
00360 createTool->setShapeId(id);
00361
00362 m_allTools.remove(controller);
00363 m_allTools.insert(controller, toolsMap);
00364
00365 if (m_activeTool == 0)
00366 toolActivated(m_defaultTool);
00367 else {
00368
00369
00370 controller->canvas()->canvasWidget()->setCursor(Qt::ForbiddenCursor);
00371 }
00372
00373 Connector *connector = new Connector(controller->canvas()->shapeManager());
00374 connect(connector, SIGNAL(selectionChanged(QList<KoShape*>)), this,
00375 SLOT(selectionChanged(QList<KoShape*>)));
00376 }
00377
00378 void KoToolManager::movedFocus(QWidget *from, QWidget *to) {
00379 Q_UNUSED(from);
00380 if (to == 0 || to == m_activeCanvas)
00381 return;
00382
00383 KoCanvasController *newCanvas = 0;
00384
00385 foreach(KoCanvasController* canvas, m_canvases) {
00386 if (canvas == to || canvas->canvas()->canvasWidget() == to) {
00387 newCanvas = canvas;
00388 break;
00389 }
00390 }
00391
00392 if (newCanvas == 0)
00393 return;
00394 if (newCanvas == m_activeCanvas)
00395 return;
00396 if (m_activeCanvas) {
00397
00398
00399 m_activeCanvas->canvas()->canvasWidget()->setCursor(Qt::ForbiddenCursor);
00400 }
00401 m_activeCanvas = newCanvas;
00402
00403 switchTool(m_activeToolId, false);
00404 selectionChanged(m_activeCanvas->canvas()->shapeManager()->selection()->selectedShapes().toList());
00405 }
00406
00407 void KoToolManager::detachCanvas(KoCanvasController *controller) {
00408 if (m_activeCanvas == controller)
00409 m_activeCanvas = 0;
00410 m_activeTool = 0;
00411 QMap<QString, KoTool*> toolsMap = m_allTools.value(controller);
00412 foreach(KoTool *tool, toolsMap.values())
00413 delete tool;
00414 toolsMap.clear();
00415
00416
00417 }
00418
00419 void KoToolManager::updateCursor(QCursor cursor) {
00420 Q_ASSERT(m_activeCanvas);
00421 Q_ASSERT(m_activeCanvas->canvas());
00422 m_activeCanvas->canvas()->canvasWidget()->setCursor(cursor);
00423 }
00424
00425 void KoToolManager::switchToolRequested(const QString & id) {
00426 while (!m_stack.isEmpty())
00427 m_stack.pop();
00428 switchTool(id, false);
00429 }
00430
00431 void KoToolManager::switchToolTemporaryRequested(const QString &id) {
00432 switchTool(id, true);
00433 }
00434
00435 void KoToolManager::switchBackRequested() {
00436 if (m_stack.isEmpty()) {
00437
00438 switchTool(KoInteractionTool_ID, false);
00439 return;
00440 }
00441 switchTool(m_stack.pop(), false);
00442 }
00443
00444 KoShapeController *KoToolManager::shapeCreatorTool(KoCanvasBase *canvas) const {
00445 return shapeController(canvas);
00446 }
00447
00448 KoShapeController *KoToolManager::shapeController(KoCanvasBase *canvas) const {
00449 foreach(KoCanvasController *controller, m_canvases) {
00450 if (controller->canvas() == canvas) {
00451 QMap<QString, KoTool*> tools = m_allTools.value(controller);
00452 KoShapeController *sc =
00453 dynamic_cast<KoShapeController*>(tools.value(KoCreateShapesTool_ID));
00454 Q_ASSERT(sc );
00455 return sc;
00456 }
00457 }
00458 kWarning(30004) << "KoToolManager: can't find the canvas, did you register it?" << endl;
00459 return 0;
00460 }
00461
00462 KoInputDevice KoToolManager::currentInputDevice() const
00463 {
00464 return KoInputDevice::mouse();
00465 }
00466
00467 void KoToolManager::selectionChanged(QList<KoShape*> shapes) {
00468
00469
00470
00471 QList<QString> types;
00472 foreach(KoShape *shape, shapes) {
00473 if (! types.contains(shape->shapeId())) {
00474 types.append(shape->shapeId());
00475 }
00476 }
00477
00478
00479
00480 if ( m_activeToolId != KoInteractionTool_ID ) {
00481 foreach( KoShape* shape, m_lastSelectedShapes ) {
00482 if ( ! shapes.contains( shape ) ) {
00483 switchTool(KoInteractionTool_ID, false);
00484 break;
00485 }
00486 }
00487 }
00488 m_lastSelectedShapes = shapes;
00489
00490 emit toolCodesSelected(types);
00491 }
00492
00493 KoCanvasController *KoToolManager::activeCanvasController() const {
00494 return m_activeCanvas;
00495 }
00496
00497
00498 KoToolManager* KoToolManager::s_instance = 0;
00499 static KStaticDeleter<KoToolManager> staticToolManagerDeleter;
00500
00501 KoToolManager* KoToolManager::instance() {
00502 if (s_instance == 0)
00503 staticToolManagerDeleter.setObject(s_instance, new KoToolManager());
00504 return s_instance;
00505 }
00506
00507 #include "KoToolManager.moc"