File indexing completed on 2024-05-19 15:27:50

0001 /* This file is part of KGraphViewer.
0002    Copyright (C) 2005-2007 Gael de Chalendar <kleag@free.fr>
0003 
0004    KGraphViewer is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU General Public
0006    License as published by the Free Software Foundation, version 2.
0007 
0008    This program is distributed in the hope that it will be useful,
0009    but WITHOUT ANY WARRANTY; without even the implied warranty of
0010    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0011    General Public License for more details.
0012 
0013    You should have received a copy of the GNU General Public License
0014    along with this program; if not, write to the Free Software
0015    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0016    02110-1301, USA
0017 */
0018 
0019 #include "kgraphviewer_part.h"
0020 #include "config-kgraphviewer.h"
0021 #include "dotgraph.h"
0022 #include "dotgraphview.h"
0023 #include "kgraphviewerlib_debug.h"
0024 
0025 #include <KDirWatch>
0026 #include <KPluginFactory>
0027 #include <KSharedConfig>
0028 #include <QAction>
0029 #include <QDebug>
0030 #include <QIcon>
0031 #include <QStandardPaths>
0032 #include <iostream>
0033 #include <kactioncollection.h>
0034 #include <klocalizedstring.h>
0035 #include <kselectaction.h>
0036 #include <kstandardaction.h>
0037 #include <ktoggleaction.h>
0038 
0039 #include <graphviz/gvc.h>
0040 
0041 // #include "kgraphviewersettings.h"
0042 #include "kgraphviewer_partsettings.h"
0043 
0044 namespace KGraphViewer
0045 {
0046 K_PLUGIN_FACTORY_WITH_JSON(KGraphViewerPartFactory,
0047                            "kgraphviewer_part.json",
0048                            registerPlugin<KGraphViewerPart>();)
0049 
0050 class KGraphViewerPartPrivate
0051 {
0052 public:
0053     KGraphViewerPartPrivate()
0054         : m_watch(new KDirWatch())
0055         , m_layoutMethod(KGraphViewerInterface::InternalLibrary)
0056     {
0057     }
0058 
0059     ~KGraphViewerPartPrivate()
0060     {
0061         delete m_watch;
0062     }
0063 
0064     DotGraphView *m_widget;
0065     KDirWatch *m_watch;
0066     KGraphViewerPart::LayoutMethod m_layoutMethod;
0067 };
0068 
0069 KGraphViewerPart::KGraphViewerPart(QWidget *parentWidget, QObject *parent, const KPluginMetaData &metaData, const QVariantList &)
0070     : KParts::ReadOnlyPart(parent)
0071     , d(new KGraphViewerPartPrivate())
0072 {
0073     /* set the component name (1st argument) so that the XMLGUI .rc
0074        file is found also when this part is called from applications
0075        different then kgraphviewer (like kgrapheditor and konqueror).
0076      */
0077     setMetaData(metaData);
0078 
0079     // set our XML-UI resource file
0080     setXMLFile(QStringLiteral("kgraphviewer_part.rc"), true);
0081 
0082     // this should be your custom internal widget
0083     d->m_widget = new DotGraphView(actionCollection(), parentWidget);
0084     d->m_widget->initEmpty();
0085     d->m_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
0086     connect(d->m_widget, &DotGraphView::graphLoaded, this, &KGraphViewerPart::graphLoaded);
0087     connect(d->m_widget, &DotGraphView::newEdgeAdded, this, &KGraphViewerPart::newEdgeAdded);
0088     connect(d->m_widget, &DotGraphView::newNodeAdded, this, &KGraphViewerPart::newNodeAdded);
0089     connect(d->m_widget, &DotGraphView::removeEdge, this, &KGraphViewerPart::removeEdge);
0090     connect(d->m_widget, &DotGraphView::removeElement, this, &KGraphViewerPart::removeElement);
0091     connect(d->m_widget, &DotGraphView::selectionIs, this, &KGraphViewerPart::selectionIs);
0092     connect(d->m_widget, static_cast<void (DotGraphView::*)(const QString &, const QPoint &)>(&DotGraphView::contextMenuEvent), this, &KGraphViewerPart::contextMenuEvent);
0093     connect(d->m_widget, &DotGraphView::newEdgeFinished, this, &KGraphViewerPart::newEdgeFinished);
0094     connect(d->m_widget, &DotGraphView::hoverEnter, this, &KGraphViewerPart::hoverEnter);
0095     connect(d->m_widget, &DotGraphView::hoverLeave, this, &KGraphViewerPart::hoverLeave);
0096 
0097     // notify the part that this is our internal widget
0098     setWidget(d->m_widget);
0099 
0100     QAction *printAct = actionCollection()->addAction(KStandardAction::Print, "file_print", d->m_widget, SLOT(print()));
0101     actionCollection()->setDefaultShortcut(printAct, Qt::ControlModifier + Qt::Key_P);
0102     printAct->setWhatsThis(i18n("Print the graph using current page setup settings"));
0103 
0104     QAction *printPreviewAct = actionCollection()->addAction(KStandardAction::PrintPreview, "file_print_preview", d->m_widget, SLOT(printPreview()));
0105     actionCollection()->setDefaultShortcut(printPreviewAct, Qt::ControlModifier + Qt::ShiftModifier + Qt::Key_P);
0106     printPreviewAct->setWhatsThis(i18n("Open the print preview window"));
0107 
0108     //   KAction* pagesetupAct = new KAction(i18n("&Page setup"), this); //actionCollection(), "file_page_setup");
0109     QAction *pagesetupAct = actionCollection()->addAction("file_page_setup", d->m_widget, SLOT(pageSetup()));
0110     pagesetupAct->setText(i18n("Page setup"));
0111     pagesetupAct->setWhatsThis(i18n("Opens the Page Setup dialog to allow graph printing to be setup"));
0112 
0113     QAction *redisplayAct = actionCollection()->addAction(KStandardAction::Redisplay, "view_redisplay", d->m_widget, SLOT(reload()));
0114     redisplayAct->setWhatsThis(i18n("Reload the current graph from file"));
0115     redisplayAct->setShortcut(Qt::Key_F5);
0116 
0117     QAction *zoomInAct = actionCollection()->addAction(KStandardAction::ZoomIn, "view_zoom_in", d->m_widget, SLOT(zoomIn()));
0118     // xgettext: no-c-format
0119     zoomInAct->setWhatsThis(i18n("Zoom in by 10% on the currently viewed graph"));
0120     zoomInAct->setShortcut(Qt::Key_F7);
0121 
0122     QAction *zoomOutAct = actionCollection()->addAction(KStandardAction::ZoomOut, "view_zoom_out", d->m_widget, SLOT(zoomOut()));
0123     // xgettext: no-c-format
0124     zoomOutAct->setWhatsThis(i18n("Zoom out by 10% from the currently viewed graph"));
0125     zoomOutAct->setShortcut(Qt::Key_F8);
0126 }
0127 
0128 QString KGraphViewerPart::componentName() const
0129 {
0130     // also the part ui.rc file is in the program folder
0131     // TODO: change the component name to "kgraphviewerpart" by removing this method and
0132     // adapting the folder where the file is placed.
0133     // Needs a way to also move any potential custom user ui.rc files
0134     // from kgraphviewer/kgraphviewer_part.rc to kgraphviewerpart/kgraphviewer_part.rc
0135     return QStringLiteral("kgraphviewer");
0136 }
0137 
0138 /*DotGraph* KGraphViewerPart::graph()
0139 {
0140   return d->m_widget->graph();
0141 }
0142 
0143 const DotGraph* KGraphViewerPart::graph() const
0144 {
0145   return d->m_widget->graph();
0146 }
0147 */
0148 
0149 void KGraphViewerPart::setBackgroundColor(const QColor &color)
0150 {
0151     d->m_widget->setBackgroundColor(color);
0152 }
0153 
0154 bool KGraphViewerPart::closeUrl()
0155 {
0156     return d->m_widget->initEmpty();
0157 }
0158 
0159 bool KGraphViewerPart::slotLoadLibrary(graph_t *graph)
0160 {
0161     bool res = d->m_widget->slotLoadLibrary(graph);
0162     if (res)
0163         d->m_widget->show();
0164     return res;
0165 }
0166 
0167 KGraphViewerPart::~KGraphViewerPart()
0168 {
0169     delete d;
0170 }
0171 
0172 bool KGraphViewerPart::openFile()
0173 {
0174     qCDebug(KGRAPHVIEWERLIB_LOG) << " " << localFilePath();
0175     //    d->m_widget->loadedDot( localFilePath() );
0176     switch (d->m_layoutMethod) {
0177     case ExternalProgram:
0178         if (!d->m_widget->loadDot(localFilePath()))
0179             return false;
0180         break;
0181     case InternalLibrary:
0182         // kpart expects loading to be done sync in this method
0183         if (!d->m_widget->loadLibrarySync(localFilePath()))
0184             return false;
0185         break;
0186     default:
0187         qCWarning(KGRAPHVIEWERLIB_LOG) << "Unsupported layout method " << d->m_layoutMethod;
0188     }
0189 
0190     // deletes the existing file watcher because we have no way know here the name of the
0191     // previously watched file and thus we cannot use removeFile... :-(
0192     delete d->m_watch;
0193     d->m_watch = new KDirWatch();
0194 
0195     //   qCDebug(KGRAPHVIEWERLIB_LOG) << "Watching file " << localFilePath();
0196     d->m_watch->addFile(localFilePath());
0197     connect(d->m_watch, &KDirWatch::dirty, d->m_widget, &DotGraphView::dirty);
0198     QString label = localFilePath().section('/', -1, -1);
0199 
0200     d->m_widget->show();
0201     return true;
0202 }
0203 
0204 void KGraphViewerPart::slotHide(KParts::Part *part)
0205 {
0206     if (part == this) {
0207         d->m_widget->hideToolsWindows();
0208     }
0209 }
0210 
0211 void KGraphViewerPart::slotUpdate()
0212 {
0213     d->m_widget->slotUpdate();
0214 }
0215 
0216 void KGraphViewerPart::prepareAddNewElement(const QMap<QString, QString> &attribs)
0217 {
0218     d->m_widget->prepareAddNewElement(attribs);
0219 }
0220 
0221 void KGraphViewerPart::slotSetGraphAttributes(const QMap<QString, QString> &attribs)
0222 {
0223     d->m_widget->graph()->setGraphAttributes(attribs);
0224 }
0225 
0226 void KGraphViewerPart::slotAddNewNode(const QMap<QString, QString> &attribs)
0227 {
0228     d->m_widget->graph()->addNewNode(attribs);
0229 }
0230 
0231 void KGraphViewerPart::slotAddNewSubgraph(const QMap<QString, QString> &attribs)
0232 {
0233     d->m_widget->graph()->addNewSubgraph(attribs);
0234 }
0235 
0236 void KGraphViewerPart::slotAddNewNodeToSubgraph(const QMap<QString, QString> &attribs, const QString &subgraph)
0237 {
0238     d->m_widget->graph()->addNewNodeToSubgraph(attribs, subgraph);
0239 }
0240 
0241 void KGraphViewerPart::slotAddExistingNodeToSubgraph(const QMap<QString, QString> &attribs, const QString &subgraph)
0242 {
0243     d->m_widget->graph()->addExistingNodeToSubgraph(attribs, subgraph);
0244 }
0245 
0246 void KGraphViewerPart::slotMoveExistingNodeToMainGraph(const QMap<QString, QString> &attribs)
0247 {
0248     d->m_widget->graph()->moveExistingNodeToMainGraph(attribs);
0249 }
0250 
0251 void KGraphViewerPart::slotAddNewEdge(const QString &src, const QString &tgt, const QMap<QString, QString> &attribs)
0252 {
0253     d->m_widget->graph()->addNewEdge(src, tgt, attribs);
0254 }
0255 
0256 void KGraphViewerPart::prepareAddNewEdge(const QMap<QString, QString> &attribs)
0257 {
0258     d->m_widget->prepareAddNewEdge(attribs);
0259 }
0260 
0261 void KGraphViewerPart::setReadOnly()
0262 {
0263     d->m_widget->setReadOnly();
0264 }
0265 
0266 void KGraphViewerPart::setReadWrite()
0267 {
0268     d->m_widget->setReadWrite();
0269 }
0270 
0271 void KGraphViewerPart::saveTo(const QString &fileName)
0272 {
0273     d->m_widget->graph()->saveTo(fileName);
0274 }
0275 
0276 void KGraphViewerPart::slotRemoveNode(const QString &nodeName)
0277 {
0278     d->m_widget->graph()->removeNodeNamed(nodeName);
0279 }
0280 
0281 void KGraphViewerPart::slotRemoveNodeFromSubgraph(const QString &nodeName, const QString &subgraphName)
0282 {
0283     d->m_widget->graph()->removeNodeFromSubgraph(nodeName, subgraphName);
0284 }
0285 
0286 void KGraphViewerPart::slotRemoveSubgraph(const QString &subgraphName)
0287 {
0288     d->m_widget->graph()->removeSubgraphNamed(subgraphName);
0289 }
0290 
0291 void KGraphViewerPart::slotSelectNode(const QString &nodeName)
0292 {
0293     d->m_widget->slotSelectNode(nodeName);
0294 }
0295 
0296 void KGraphViewerPart::slotAddAttribute(const QString &)
0297 {
0298     qCDebug(KGRAPHVIEWERLIB_LOG) << "NOT IMPLEMENTED";
0299 }
0300 
0301 void KGraphViewerPart::slotSetAttribute(const QString &elementId, const QString &attributeName, const QString &attributeValue)
0302 {
0303     d->m_widget->graph()->setAttribute(elementId, attributeName, attributeValue);
0304 }
0305 
0306 void KGraphViewerPart::slotRemoveAttribute(const QString &nodeName, const QString &attribName)
0307 {
0308     d->m_widget->graph()->removeAttribute(nodeName, attribName);
0309 }
0310 
0311 void KGraphViewerPart::slotRemoveEdge(const QString &id)
0312 {
0313     d->m_widget->graph()->removeEdge(id);
0314 }
0315 
0316 void KGraphViewerPart::slotRemoveElement(const QString &id)
0317 {
0318     d->m_widget->graph()->removeElement(id);
0319 }
0320 
0321 void KGraphViewerPart::slotSetHighlighting(bool highlightingValue)
0322 {
0323     d->m_widget->setHighlighting(highlightingValue);
0324 }
0325 
0326 void KGraphViewerPart::slotPrepareToSelect()
0327 {
0328     d->m_widget->prepareSelectElements();
0329 }
0330 
0331 void KGraphViewerPart::slotSetCursor(const QCursor &cursor)
0332 {
0333     d->m_widget->setCursor(cursor);
0334 }
0335 
0336 void KGraphViewerPart::slotUnsetCursor()
0337 {
0338     d->m_widget->unsetCursor();
0339 }
0340 
0341 void KGraphViewerPart::slotSetLayoutMethod(LayoutMethod method)
0342 {
0343     setLayoutMethod(method);
0344 }
0345 
0346 void KGraphViewerPart::setLayoutMethod(LayoutMethod method)
0347 {
0348     d->m_layoutMethod = method;
0349 }
0350 
0351 void KGraphViewerPart::centerOnNode(const QString &nodeId)
0352 {
0353     d->m_widget->centerOnNode(nodeId);
0354 }
0355 
0356 void KGraphViewerPart::selectNode(const QString &nodeId)
0357 {
0358     slotSelectNode(nodeId);
0359 }
0360 
0361 void KGraphViewerPart::setLayoutCommand(const QString &command)
0362 {
0363     d->m_widget->setLayoutCommand(command);
0364 }
0365 
0366 void KGraphViewerPart::setPannerPosition(KGraphViewerInterface::PannerPosition position)
0367 {
0368     d->m_widget->viewBevActivated(position);
0369 }
0370 
0371 void KGraphViewerPart::setPannerEnabled(bool enabled)
0372 {
0373     d->m_widget->setPannerEnabled(enabled);
0374 }
0375 
0376 void KGraphViewerPart::setZoomFactor(double factor)
0377 {
0378     d->m_widget->setZoomFactor(factor);
0379 }
0380 
0381 void KGraphViewerPart::zoomBy(double factor)
0382 {
0383     d->m_widget->applyZoom(factor);
0384 }
0385 
0386 void KGraphViewerPart::zoomIn()
0387 {
0388     d->m_widget->zoomIn();
0389 }
0390 
0391 void KGraphViewerPart::zoomOut()
0392 {
0393     d->m_widget->zoomOut();
0394 }
0395 
0396 void KGraphViewerPart::slotRenameNode(const QString &oldNodeName, const QString &newNodeName)
0397 {
0398     d->m_widget->graph()->renameNode(oldNodeName, newNodeName);
0399 }
0400 
0401 }
0402 
0403 #include "kgraphviewer_part.moc"
0404 
0405 #include "moc_kgraphviewer_part.cpp"