1 /* This file is part of KGraphViewer.
2 Copyright (C) 2005-2007 Gael de Chalendar <kleag@free.fr>
3
4 KGraphViewer is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public
6 License as published by the Free Software Foundation, version 2.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 02110-1301, USA
17 */
18
19
20 #include "kgrapheditor.h"
21 #include "kgrapheditorConfigDialog.h"
22 #include "kgrapheditorsettings.h"
23 #include "kgrapheditor_debug.h"
24 #include "KGraphEditorNodesTreeWidget.h"
25 #include "KGraphEditorElementTreeWidget.h"
26 #include "ui_preferencesReload.h"
27 #include "ui_preferencesParsing.h"
28 #include "ui_preferencesOpenInExistingWindow.h"
29 #include "ui_preferencesReopenPreviouslyOpenedFiles.h"
30 #include "part/kgraphviewer_part.h"
31
32 #include <kshortcutsdialog.h>
33 #include <QFileDialog>
34 #include <kconfig.h>
35 #include <QUrl>
36 #include <QTabWidget>
37 #include <kparts/partmanager.h>
38 #include <kedittoolbar.h>
39 #include <QDebug>
40 #include <QStandardPaths>
41 #include <kstandardaction.h>
42 #include <ktoggleaction.h>
43 #include <KPluginLoader>
44 #include <KService>
45 #include <QMessageBox>
46 #include <QStatusBar>
47 #include <kconfigdialog.h>
48 #include <QDebug>
49 #include <krecentfilesaction.h>
50 #include <ktoolbar.h>
51 #include <KActionCollection>
52 #include <klocalizedstring.h>
53 #include <QtDBus/QtDBus>
54 #include <QDockWidget>
55 #include <QTreeWidget>
56
57 #include <iostream>
58
59 using namespace KGraphViewer;
60
KGraphEditor()61 KGraphEditor::KGraphEditor() :
62 KParts::MainWindow(),
63 m_rfa(nullptr),
64 m_currentPart(nullptr)
65 {
66 // set the shell's ui resource file
67 setXMLFile("kgrapheditorui.rc");
68
69 m_widget = new QTabWidget(this);
70 m_widget->setTabsClosable(true);
71 connect(m_widget, SIGNAL(tabCloseRequested(int)), this, SLOT(close(int)));
72 connect(m_widget, SIGNAL(currentChanged(int)), this, SLOT(newTabSelectedSlot(int)));
73
74 setCentralWidget(m_widget);
75
76 QDockWidget* topLeftDockWidget = new QDockWidget(this);
77 topLeftDockWidget->setObjectName(QStringLiteral("TopLeftDockWidget"));
78 m_treeWidget = new KGraphEditorNodesTreeWidget(topLeftDockWidget);
79 connect(m_treeWidget,SIGNAL(itemChanged(QTreeWidgetItem*,int)),
80 this,SLOT(slotItemChanged(QTreeWidgetItem*,int)));
81 connect(m_treeWidget,SIGNAL(itemClicked(QTreeWidgetItem*,int)),
82 this,SLOT(slotItemClicked(QTreeWidgetItem*,int)));
83 connect(m_treeWidget, SIGNAL(removeNode(QString)),
84 this, SLOT(slotRemoveNode(QString)));
85 connect(m_treeWidget, SIGNAL(addAttribute(QString)),
86 this, SLOT(slotAddAttribute(QString)));
87 connect(m_treeWidget, SIGNAL(removeAttribute(QString,QString)),
88 this, SLOT(slotRemoveAttribute(QString,QString)));
89
90 // m_treeWidget->setItemDelegate(new VariantDelegate(m_treeWidget));
91 m_treeWidget->setColumnCount(2);
92 topLeftDockWidget->setWidget(m_treeWidget);
93 addDockWidget ( Qt::LeftDockWidgetArea, topLeftDockWidget );
94
95 QDockWidget* bottomLeftDockWidget = new QDockWidget(this);
96 bottomLeftDockWidget->setObjectName(QStringLiteral("BottomLeftDockWidget"));
97 m_newElementAttributesWidget = new KGraphEditorElementTreeWidget(bottomLeftDockWidget);
98 connect(m_newElementAttributesWidget,SIGNAL(itemChanged(QTreeWidgetItem*,int)),
99 this,SLOT(slotNewElementItemChanged(QTreeWidgetItem*,int)));
100 connect(m_newElementAttributesWidget, SIGNAL(addAttribute(QString)),
101 this, SLOT(slotAddNewElementAttribute(QString)));
102 connect(m_newElementAttributesWidget, SIGNAL(removeAttribute(QString)),
103 this, SLOT(slotRemoveNewElementAttribute(QString)));
104 m_newElementAttributesWidget->setColumnCount(2);
105 bottomLeftDockWidget->setWidget(m_newElementAttributesWidget);
106 addDockWidget ( Qt::LeftDockWidgetArea, bottomLeftDockWidget );
107
108
109 if (QDBusConnection::sessionBus().registerService( "org.kde.kgrapheditor" ))
110 {
111 qCDebug(KGRAPHEDITOR_LOG) << "Service Registered successfully";
112 QDBusConnection::sessionBus().registerObject("/", this, QDBusConnection::ExportAllSlots);
113
114 }
115 else
116 {
117 qCDebug(KGRAPHEDITOR_LOG) << "Failed to register service...";
118 }
119
120 // Create a KParts part manager, to handle part activation/deactivation
121 m_manager = new KParts::PartManager( this );
122
123 // When the manager says the active part changes, the window updates (recreates) the GUI
124 connect( m_manager, SIGNAL(activePartChanged(KParts::Part*)),
125 this, SLOT(createGUI(KParts::Part*)) );
126
127 setupGUI(ToolBar | Keys | StatusBar | Save);
128
129 // then, setup our actions
130 setupActions();
131
132 // this routine will find and load our Part. it finds the Part by
133 // name which is a bad idea usually.. but it's alright in this
134 // case since our Part is made for this Shell
135
136 // Creates the GUI with a null part to make appear the main app menus and tools
137 createGUI(0);
138 }
139
~KGraphEditor()140 KGraphEditor::~KGraphEditor()
141 {
142 }
143
reloadPreviousFiles()144 void KGraphEditor::reloadPreviousFiles()
145 {
146 QStringList previouslyOpenedFiles = KGraphEditorSettings::previouslyOpenedFiles();
147 if ( (previouslyOpenedFiles.empty() == false)
148 && (QMessageBox::question(this,
149 i18n("Session Restore"),
150 i18n("Do you want to reload files from previous session?")) == QMessageBox::Yes) )
151 {
152 QStringList::const_iterator it, it_end;
153 it = previouslyOpenedFiles.constBegin(); it_end = previouslyOpenedFiles.constEnd();
154 for (; it != it_end; it++)
155 {
156 openUrl(*it);
157 }
158 }
159 }
160
slotNewGraph()161 KParts::ReadOnlyPart *KGraphEditor::slotNewGraph()
162 {
163 KPluginFactory *factory = KPluginLoader("kgraphviewerpart").factory();
164 if (!factory)
165 {
166 // if we couldn't find our Part, we exit since the Shell by
167 // itself can't do anything useful
168 QMessageBox::critical(this, i18n("Unable to start"), i18n("Could not find the KGraphViewer part."));
169 qApp->quit();
170 // we return here, cause kapp->quit() only means "exit the
171 // next time we enter the event loop...
172 return nullptr;
173 }
174 KParts::ReadOnlyPart* part = factory->create<KParts::ReadOnlyPart>(this);
175 KGraphViewerInterface *view = qobject_cast<KGraphViewerInterface *>(part);
176 if (!view)
177 {
178 // This should not happen
179 qCWarning(KGRAPHEDITOR_LOG) << "Failed to get KPart" << endl;
180 return nullptr;
181 }
182 view->setReadWrite();
183
184 QWidget *w = part->widget();
185
186 m_tabsPartsMap[w] = part;
187 m_tabsFilesMap[w] = "";
188 connect(this,SIGNAL(hide(KParts::Part*)),part,SLOT(slotHide(KParts::Part*)));
189
190 m_manager->addPart(part, true);
191
192 m_widget->addTab(w, QIcon::fromTheme("kgraphviewer"), "");
193 m_widget->setCurrentWidget(w);
194 m_closeAction->setEnabled(true);
195 return part;
196 }
197
openUrl(const QUrl & url)198 void KGraphEditor::openUrl(const QUrl& url)
199 {
200 qCDebug(KGRAPHEDITOR_LOG) << url;
201 KParts::ReadOnlyPart *part = slotNewGraph();
202
203 // (KGraphEditorSettings::parsingMode() == "external")
204 // ?kgv->setLayoutMethod(KGraphViewerInterface::ExternalProgram)
205 // :kgv->setLayoutMethod(KGraphViewerInterface::InternalLibrary);
206
207 QString label = url.path().section('/',-1,-1);
208 // @TODO set label
209 m_widget->setTabText(m_widget->currentIndex(), label);
210 m_tabsFilesMap[m_widget->currentWidget()] = url.path();
211 part->openUrl(url);
212
213 if (m_rfa) {
214 m_rfa->addUrl(url);
215 }
216
217 m_openedFiles.push_back(url.path());
218 }
219
fileOpen()220 void KGraphEditor::fileOpen()
221 {
222 // this slot is called whenever the File->Open menu is selected,
223 // the Open shortcut is pressed (usually CTRL+O) or the Open toolbar
224 // button is clicked
225 QFileDialog fileDialog(this);
226 fileDialog.setMimeTypeFilters(QStringList(QStringLiteral("text/vnd.graphviz")));
227 fileDialog.setAcceptMode(QFileDialog::AcceptOpen);
228 fileDialog.setFileMode(QFileDialog::ExistingFiles);
229 if (fileDialog.exec() != QFileDialog::Accepted) {
230 return;
231 }
232
233 foreach (const QUrl& url, fileDialog.selectedUrls()) {
234 openUrl(url);
235 }
236 }
237
238
setupActions()239 void KGraphEditor::setupActions()
240 {
241 // create our actions
242
243 actionCollection()->addAction( KStandardAction::New, "file_new", this, SLOT(fileNew()) );
244 actionCollection()->addAction( KStandardAction::Open, "file_open", this, SLOT(fileOpen()) );
245 m_rfa = (KRecentFilesAction*) actionCollection()->addAction(KStandardAction::OpenRecent, "file_open_recent", this, SLOT(slotURLSelected(QUrl)) );
246 m_rfa->loadEntries(KConfigGroup(KSharedConfig::openConfig(), "kgrapheditor"));
247 actionCollection()->addAction( KStandardAction::Save, "file_save", this, SLOT(fileSave()) );
248 actionCollection()->addAction( KStandardAction::SaveAs, "file_save_as", this, SLOT(fileSaveAs()) );
249
250 m_closeAction = actionCollection()->addAction( KStandardAction::Close, "file_close", this, SLOT(close()) );
251 m_closeAction->setWhatsThis(i18n("Closes the current file"));
252 m_closeAction->setEnabled(false);
253
254 actionCollection()->addAction( KStandardAction::Quit, "file_quit", qApp, SLOT(quit()) );
255
256 m_statusbarAction = KStandardAction::showStatusbar(this, SLOT(optionsShowStatusbar()), this);
257
258 actionCollection()->addAction( KStandardAction::KeyBindings, "options_configure_keybinding", this, SLOT(optionsConfigureKeys()) );
259 // KStandardAction::keyBindings(this, SLOT(optionsConfigureKeys()), this);
260 actionCollection()->addAction( KStandardAction::ConfigureToolbars, "options_configure_toolbars", this, SLOT(optionsConfigureToolbars()) );
261 actionCollection()->addAction( KStandardAction::Preferences, "options_configure", this, SLOT(optionsConfigure()) );
262
263 QAction* edit_new_vertex = actionCollection()->addAction( "edit_new_vertex" );
264 edit_new_vertex->setText(i18n("Create a New Vertex"));
265 edit_new_vertex->setIcon(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kgraphviewerpart/pics/kgraphviewer-newnode.png")));
266 connect( edit_new_vertex, SIGNAL(triggered(bool)), this, SLOT(slotEditNewVertex()) );
267
268 QAction* edit_new_edge = actionCollection()->addAction( "edit_new_edge" );
269 edit_new_edge->setText(i18n("Create a New Edge"));
270 edit_new_edge->setIcon(QPixmap(QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kgraphviewerpart/pics/kgraphviewer-newedge.png")));
271 connect( edit_new_edge, SIGNAL(triggered(bool)), this, SLOT(slotEditNewEdge()) );
272 }
273
closeEvent(QCloseEvent * event)274 void KGraphEditor::closeEvent(QCloseEvent *event)
275 {
276 KGraphEditorSettings::setPreviouslyOpenedFiles(m_openedFiles);
277 m_rfa->saveEntries(KConfigGroup(KSharedConfig::openConfig(), "kgrapheditor"));
278
279 KGraphEditorSettings::self()->save();
280 KXmlGuiWindow::closeEvent(event);
281 }
282
fileNew()283 void KGraphEditor::fileNew()
284 {
285 // this slot is called whenever the File->New menu is selected,
286 // the New shortcut is pressed (usually CTRL+N) or the New toolbar
287 // button is clicked
288
289 slotNewGraph();
290 }
291
292
optionsShowToolbar()293 void KGraphEditor::optionsShowToolbar()
294 {
295 // this is all very cut and paste code for showing/hiding the
296 // toolbar
297 if (m_toolbarAction->isChecked())
298 toolBar()->show();
299 else
300 toolBar()->hide();
301 }
302
optionsShowStatusbar()303 void KGraphEditor::optionsShowStatusbar()
304 {
305 // this is all very cut and paste code for showing/hiding the
306 // statusbar
307 if (m_statusbarAction->isChecked())
308 statusBar()->show();
309 else
310 statusBar()->hide();
311 }
312
optionsConfigureKeys()313 void KGraphEditor::optionsConfigureKeys()
314 {
315 KShortcutsDialog::configure(actionCollection());
316 }
317
optionsConfigureToolbars()318 void KGraphEditor::optionsConfigureToolbars()
319 {
320 KConfigGroup conf(KConfigGroup(KSharedConfig::openConfig(), "kgrapheditor"));
321 saveMainWindowSettings(conf);
322
323 // use the standard toolbar editor
324 KEditToolBar dlg(factory());
325 connect(&dlg, SIGNAL(newToolbarConfig()),
326 this, SLOT(applyNewToolbarConfig()));
327 dlg.exec();
328 }
329
optionsConfigure()330 void KGraphEditor::optionsConfigure()
331 {
332 //An instance of your dialog could be already created and could be cached,
333 //in which case you want to display the cached dialog instead of creating
334 //another one
335 if ( KgeConfigurationDialog::showDialog( "settings" ) )
336 return;
337
338 //KConfigDialog didn't find an instance of this dialog, so lets create it :
339 KgeConfigurationDialog* dialog = new KgeConfigurationDialog(this, "settings", KGraphEditorSettings::self());
340
341 Ui::KGraphViewerPreferencesParsingWidget* parsingWidget = dialog->m_parsingWidget;
342 qCDebug(KGRAPHEDITOR_LOG) << KGraphEditorSettings::parsingMode();
343 if (KGraphEditorSettings::parsingMode() == "external")
344 {
345 parsingWidget->external->setChecked(true);
346 }
347 else if (KGraphEditorSettings::parsingMode() == "internal")
348 {
349 parsingWidget->internal->setChecked(true);
350 }
351 connect((QObject*)parsingWidget->external, SIGNAL(toggled(bool)), this, SLOT(slotParsingModeExternalToggled(bool)) );
352 connect((QObject*)parsingWidget->internal, SIGNAL(toggled(bool)), this, SLOT(slotParsingModeInternalToggled(bool)) );
353
354
355 /* KGraphViewerPreferencesReloadWidget* reloadWidget =
356 new KGraphViewerPreferencesReloadWidget( 0, "KGraphViewer Settings" );
357 if (KGraphEditorSettings::reloadOnChangeMode() == "yes")
358 {
359 reloadWidget->reloadOnChangeMode->setButton(0);
360 }
361 else if (KGraphEditorSettings::reloadOnChangeMode() == "no")
362 {
363 reloadWidget->reloadOnChangeMode->setButton(1);
364 }
365 else if (KGraphEditorSettings::reloadOnChangeMode() == "ask")
366 {
367 reloadWidget->reloadOnChangeMode->setButton(2);
368 }
369
370 connect((QObject*)reloadWidget->reloadOnChangeMode, SIGNAL(clicked(int)), this, SLOT(reloadOnChangeMode_pressed(int)) );
371
372 dialog->addPage( reloadWidget, i18n("Reloading"), "kgraphreloadoptions", i18n("Reloading"), true);
373
374 KGraphViewerPreferencesOpenInExistingWindowWidget* openingWidget =
375 new KGraphViewerPreferencesOpenInExistingWindowWidget( 0, "KGraphViewer Settings" );
376 if (KGraphEditorSettings::openInExistingWindowMode() == "yes")
377 {
378 openingWidget->openInExistingWindowMode->setButton(0);
379 }
380 else if (KGraphEditorSettings::openInExistingWindowMode() == "no")
381 {
382 openingWidget->openInExistingWindowMode->setButton(1);
383 }
384 else if (KGraphEditorSettings::openInExistingWindowMode() == "ask")
385 {
386 openingWidget->openInExistingWindowMode->setButton(2);
387 }
388
389 connect((QObject*)openingWidget->openInExistingWindowMode, SIGNAL(clicked(int)), this, SLOT(openInExistingWindowMode_pressed(int)) );
390
391 dialog->addPage( openingWidget, i18n("Opening"), "kgraphopeningoptions", i18n("Opening"), true);
392
393 KGraphViewerPreferencesReopenPreviouslyOpenedFilesWidget* reopeningWidget =
394 new KGraphViewerPreferencesReopenPreviouslyOpenedFilesWidget( 0, "KGraphViewer Settings" );
395 if (KGraphEditorSettings::reopenPreviouslyOpenedFilesMode() == "yes")
396 {
397 reopeningWidget->reopenPreviouslyOpenedFilesMode->setButton(0);
398 }
399 else if (KGraphEditorSettings::reopenPreviouslyOpenedFilesMode() == "no")
400 {
401 reopeningWidget->reopenPreviouslyOpenedFilesMode->setButton(1);
402 }
403 else if (KGraphEditorSettings::reopenPreviouslyOpenedFilesMode() == "ask")
404 {
405 reopeningWidget->reopenPreviouslyOpenedFilesMode->setButton(2);
406 }
407
408 connect((QObject*)reopeningWidget->reopenPreviouslyOpenedFilesMode, SIGNAL(clicked(int)), this, SLOT(reopenPreviouslyOpenedFilesMode_pressed(int)) );
409
410 dialog->addPage( reopeningWidget, i18n("Session Management"), "kgraphreopeningoptions", i18n("Session Management"), true);
411 */
412 // connect(dialog, SIGNAL(settingsChanged()), this, SLOT(settingsChanged()));
413
414 dialog->show();
415 }
416
applyNewToolbarConfig()417 void KGraphEditor::applyNewToolbarConfig()
418 {
419 applyMainWindowSettings(KConfigGroup(KSharedConfig::openConfig(), "kgrapheditor"));
420 }
421
422 // void KGraphViewer::reloadOnChangeMode_pressed(int value)
423 // {
424 // qCDebug(KGRAPHEDITOR_LOG) << "reloadOnChangeMode_pressed " << value;
425 // switch (value)
426 // {
427 // case 0:
428 // KGraphEditorSettings::setReloadOnChangeMode("yes");
429 // break;
430 // case 1:
431 // KGraphEditorSettings::setReloadOnChangeMode("no");
432 // break;
433 // case 2:
434 // KGraphEditorSettings::setReloadOnChangeMode("ask");
435 // break;
436 // default:
437 // qCWarning(KGRAPHEDITOR_LOG) << "Invalid reload on change mode value: " << value;
438 // return;
439 // }
440 // qCDebug(KGRAPHEDITOR_LOG) << "emiting";
441 // emit(settingsChanged());
442 // KGraphEditorSettings::save();
443 // }
444 //
445 // void KGraphViewer::openInExistingWindowMode_pressed(int value)
446 // {
447 // std::cerr << "openInExistingWindowMode_pressed " << value << std::endl;
448 // switch (value)
449 // {
450 // case 0:
451 // KGraphEditorSettings::setOpenInExistingWindowMode("yes");
452 // break;
453 // case 1:
454 // KGraphEditorSettings::setOpenInExistingWindowMode("no");
455 // break;
456 // case 2:
457 // KGraphEditorSettings::setOpenInExistingWindowMode("ask");
458 // break;
459 // default:
460 // qCWarning(KGRAPHEDITOR_LOG) << "Invalid OpenInExistingWindow value: " << value << endl;
461 // return;
462 // }
463 //
464 // std::cerr << "emiting" << std::endl;
465 // emit(settingsChanged());
466 // KGraphEditorSettings::save();
467 // }
468 //
469 // void KGraphViewer::reopenPreviouslyOpenedFilesMode_pressed(int value)
470 // {
471 // std::cerr << "reopenPreviouslyOpenedFilesMode_pressed " << value << std::endl;
472 // switch (value)
473 // {
474 // case 0:
475 // KGraphEditorSettings::setReopenPreviouslyOpenedFilesMode("yes");
476 // break;
477 // case 1:
478 // KGraphEditorSettings::setReopenPreviouslyOpenedFilesMode("no");
479 // break;
480 // case 2:
481 // KGraphEditorSettings::setReopenPreviouslyOpenedFilesMode("ask");
482 // break;
483 // default:
484 // qCWarning(KGRAPHEDITOR_LOG) << "Invalid ReopenPreviouslyOpenedFilesMode value: " << value << endl;
485 // return;
486 // }
487 //
488 // std::cerr << "emiting" << std::endl;
489 // emit(settingsChanged());
490 // KGraphEditorSettings::save();
491 // }
492
493
slotURLSelected(const QUrl & url)494 void KGraphEditor::slotURLSelected(const QUrl& url)
495 {
496 openUrl(url);
497 }
498
close(int index)499 void KGraphEditor::close(int index)
500 {
501 QWidget *tab = m_widget->widget(index);
502 m_openedFiles.removeAll(m_tabsFilesMap[tab]);
503 m_widget->removeTab(index);
504 tab->hide();
505 KParts::ReadOnlyPart *part = m_tabsPartsMap[tab];
506 m_manager->removePart(part);
507 m_tabsPartsMap.remove(tab);
508 m_tabsFilesMap.remove(tab);
509 delete part; part = nullptr;
510 /* delete tab;
511 tab = nullptr;*/
512 m_closeAction->setEnabled(m_widget->count() > 0);
513 }
514
close()515 void KGraphEditor::close()
516 {
517 int currentPage = m_widget->currentIndex();
518 if (currentPage != -1)
519 {
520 close(currentPage);
521 }
522 }
523
fileSave()524 void KGraphEditor::fileSave()
525 {
526 QWidget* currentPage = m_widget->currentWidget();
527 if (currentPage)
528 {
529 emit(saveTo(QUrl(m_tabsFilesMap[currentPage]).path()));
530 }
531 }
532
fileSaveAs()533 void KGraphEditor::fileSaveAs()
534 {
535 QWidget* currentPage = m_widget->currentWidget();
536 if (currentPage)
537 {
538 QFileDialog fileDialog(currentPage, i18n("Save current graph"));
539 fileDialog.setMimeTypeFilters(QStringList(QStringLiteral("text/vnd.graphviz")));
540 fileDialog.setAcceptMode(QFileDialog::AcceptSave);
541 if (fileDialog.exec() != QFileDialog::Accepted) {
542 return;
543 }
544 const QString fileName = fileDialog.selectedFiles().at(0);
545 if (fileName.isEmpty()) {
546 return;
547 }
548
549 m_tabsFilesMap[currentPage] = fileName;
550 emit(saveTo(fileName));
551 }
552 }
553
newTabSelectedSlot(int index)554 void KGraphEditor::newTabSelectedSlot(int index)
555 {
556 // qCDebug(KGRAPHEDITOR_LOG) << tab;
557 emit(hide((KParts::Part*)(m_manager->activePart())));
558 QWidget *tab = m_widget->widget(index);
559 if (tab) {
560 slotSetActiveGraph(m_tabsPartsMap[tab]);
561 m_manager->setActivePart(m_tabsPartsMap[tab]);
562 }
563 }
564
slotSetActiveGraph(KParts::ReadOnlyPart * part)565 void KGraphEditor::slotSetActiveGraph(KParts::ReadOnlyPart *part)
566 {
567 if (m_currentPart)
568 {
569 disconnect(this,SIGNAL(prepareAddNewElement(QMap<QString,QString>)),m_currentPart,SLOT(prepareAddNewElement(QMap<QString,QString>)));
570 disconnect(this,SIGNAL(prepareAddNewEdge(QMap<QString,QString>)),m_currentPart,SLOT(prepareAddNewEdge(QMap<QString,QString>)));
571 disconnect(this,SIGNAL(saveTo(QString)),m_currentPart,SLOT(saveTo(QString)));
572 disconnect(this,SIGNAL(removeNode(QString)),m_currentPart,SLOT(slotRemoveNode(QString)));
573 disconnect(this,SIGNAL(addAttribute(QString)),m_currentPart,SLOT(slotAddAttribute(QString)));
574 disconnect(this,SIGNAL(removeAttribute(QString,QString)),m_currentPart,SLOT(slotRemoveAttribute(QString,QString)));
575 disconnect(this,SIGNAL(update()),m_currentPart,SLOT(slotUpdate()));
576 disconnect(this,SIGNAL(selectNode(QString)),m_currentPart,SLOT(slotSelectNode(QString)));
577 disconnect(this,SIGNAL(saddNewEdge(QString,QString,QMap<QString,QString>)),
578 m_currentPart,SLOT(slotAddNewEdge(QString,QString,QMap<QString,QString>)));
579 disconnect(this,SIGNAL(renameNode(QString,QString)),
580 m_currentPart,SLOT(slotRenameNode(QString,QString)));
581 disconnect(this,SIGNAL(setAttribute(QString,QString,QString)),m_currentPart,SLOT(slotSetAttribute(QString,QString,QString)));
582 }
583 m_currentPart = part;
584 m_treeWidget->clear();
585 if (m_currentPart == nullptr)
586 {
587 return;
588 }
589 connect(this,SIGNAL(prepareAddNewElement(QMap<QString,QString>)),part,SLOT(prepareAddNewElement(QMap<QString,QString>)));
590 connect(this,SIGNAL(prepareAddNewEdge(QMap<QString,QString>)),part,SLOT(prepareAddNewEdge(QMap<QString,QString>)));
591 connect(this,SIGNAL(saveTo(QString)),part,SLOT(saveTo(QString)));
592 connect(this,SIGNAL(removeNode(QString)),part,SLOT(slotRemoveNode(QString)));
593 connect(this,SIGNAL(addAttribute(QString)),part,SLOT(slotAddAttribute(QString)));
594 connect(this,SIGNAL(removeAttribute(QString,QString)),part,SLOT(slotRemoveAttribute(QString,QString)));
595 connect(this,SIGNAL(update()),part,SLOT(slotUpdate()));
596 connect(this,SIGNAL(selectNode(QString)),part,SLOT(slotSelectNode(QString)));
597 connect( this,SIGNAL(removeElement(QString)),m_currentPart,SLOT(slotRemoveElement(QString)));
598 connect(this,SIGNAL(saddNewEdge(QString,QString,QMap<QString,QString>)),m_currentPart,SLOT(slotAddNewEdge(QString,QString,QMap<QString,QString>)));
599 connect(this,SIGNAL(renameNode(QString,QString)),m_currentPart,SLOT(slotRenameNode(QString,QString)));
600 connect(this,SIGNAL(setAttribute(QString,QString,QString)),m_currentPart,SLOT(slotSetAttribute(QString,QString,QString)));
601
602 QList<QString> nodesIds;//TODO = m_currentPart->nodesIds();
603 QList<QTreeWidgetItem *> items;
604 foreach (const QString& nodeId, nodesIds)
605 {
606 qCDebug(KGRAPHEDITOR_LOG)<< "new item " << nodeId;
607 QTreeWidgetItem* item = new QTreeWidgetItem((QTreeWidget*)nullptr, QStringList(nodeId));
608 item->setFlags(item->flags() | Qt::ItemIsEditable);
609 QMap<QString,QString> attributes;//TODO = m_currentPart->nodeAtributes(nodeId);
610 foreach (const QString& attrib, attributes.keys())
611 {
612 if (attrib != "_draw_" && attrib != "_ldraw_")
613 {
614 QStringList list(attrib);
615 list << attributes[attrib];
616 QTreeWidgetItem* child = new QTreeWidgetItem((QTreeWidget*)nullptr, list);
617 child->setFlags(child->flags() | Qt::ItemIsEditable);
618 item->addChild(child);
619 }
620 }
621 items.append(item);
622 }
623 qCDebug(KGRAPHEDITOR_LOG) << "inserting";
624 m_treeWidget->insertTopLevelItems(0, items);
625
626
627 connect( m_currentPart, SIGNAL(graphLoaded()),
628 this, SLOT(slotGraphLoaded()) );
629
630 connect( m_currentPart, SIGNAL(newNodeAdded(QString)),
631 this, SLOT(slotNewNodeAdded(QString)) );
632
633 connect( m_currentPart, SIGNAL(newEdgeAdded(QString,QString)),
634 this, SLOT(slotNewEdgeAdded(QString,QString)) );
635
636 connect( m_currentPart, SIGNAL(removeElement(QString)),
637 this, SLOT(slotRemoveElement(QString)) );
638
639 connect( m_currentPart, SIGNAL(selectionIs(QList<QString>,QPoint)),
640 this, SLOT(slotSelectionIs(QList<QString>,QPoint)) );
641
642 connect( m_currentPart, SIGNAL(newEdgeFinished(QString,QString,QMap<QString, QString>)),
643 this, SLOT(slotNewEdgeFinished(QString,QString,QMap<QString, QString>)) );
644
645 connect( m_currentPart, SIGNAL(hoverEnter(QString)),
646 this, SLOT(slotHoverEnter(QString)) );
647
648 connect( m_currentPart, SIGNAL(hoverLeave(QString)),
649 this, SLOT(slotHoverLeave(QString)) );
650 }
651
slotNewNodeAdded(const QString & id)652 void KGraphEditor::slotNewNodeAdded(const QString& id)
653 {
654 qCDebug(KGRAPHEDITOR_LOG) << id;
655 update();
656 }
657
slotNewEdgeAdded(const QString & ids,const QString & idt)658 void KGraphEditor::slotNewEdgeAdded(const QString& ids, const QString& idt)
659 {
660 qCDebug(KGRAPHEDITOR_LOG) << ids << idt;
661 update();
662 }
663
slotNewEdgeFinished(const QString & srcId,const QString & tgtId,const QMap<QString,QString> & attribs)664 void KGraphEditor::slotNewEdgeFinished( const QString& srcId, const QString& tgtId, const QMap<QString, QString>&attribs)
665 {
666 qCDebug(KGRAPHEDITOR_LOG) << srcId << tgtId << attribs;
667 emit saddNewEdge(srcId,tgtId,attribs);
668 update();
669 }
670
slotGraphLoaded()671 void KGraphEditor::slotGraphLoaded()
672 {
673 qCDebug(KGRAPHEDITOR_LOG);
674 disconnect(m_treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
675 this,SLOT(slotItemChanged(QTreeWidgetItem*,int)));
676 disconnect(m_treeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
677 this,SLOT(slotItemClicked(QTreeWidgetItem*,int)));
678
679 QList<QString> nodesIds;//TODO = m_currentPart->nodesIds();
680 QList<QTreeWidgetItem *> items;
681 foreach (const QString& nodeId, nodesIds)
682 {
683 qCDebug(KGRAPHEDITOR_LOG)<< "item " << nodeId;
684 QTreeWidgetItem* item;
685 QList<QTreeWidgetItem*> existingItems = m_treeWidget->findItems(nodeId,Qt::MatchRecursive|Qt::MatchExactly);
686 if (existingItems.isEmpty())
687 {
688 item = new QTreeWidgetItem((QTreeWidget*)nullptr, QStringList(nodeId));
689 items.append(item);
690 }
691 else
692 {
693 item = existingItems[0];
694 }
695 item->setFlags(item->flags() | Qt::ItemIsEditable);
696 QMap<QString,QString> attributes; //TODO = m_currentPart->nodeAtributes(nodeId);
697 QList<QString> keys = attributes.keys();
698 for (int i=0; i < item->childCount();i++)
699 {
700 if (keys.contains(item->child(i)->text(0)))
701 {
702 item->child(i)->setText(1,attributes[item->child(i)->text(0)]);
703 keys.removeAll(item->child(i)->text(0));
704 }
705 }
706 foreach (const QString &attrib, keys)
707 {
708 if (attrib != "_draw_" && attrib != "_ldraw_")
709 {
710 QStringList list(attrib);
711 list << attributes[attrib];
712 QTreeWidgetItem* child = new QTreeWidgetItem((QTreeWidget*)nullptr, list);
713 child->setFlags(child->flags() | Qt::ItemIsEditable);
714 item->addChild(child);
715 }
716 }
717 }
718 qCDebug(KGRAPHEDITOR_LOG) << "inserting";
719 m_treeWidget->insertTopLevelItems(0, items);
720 connect(m_treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
721 this,SLOT(slotItemChanged(QTreeWidgetItem*,int)));
722 connect(m_treeWidget, SIGNAL(itemClicked(QTreeWidgetItem*,int)),
723 this,SLOT(slotItemClicked(QTreeWidgetItem*,int)));
724 }
725
slotItemChanged(QTreeWidgetItem * item,int column)726 void KGraphEditor::slotItemChanged ( QTreeWidgetItem * item, int column )
727 {
728 qCDebug(KGRAPHEDITOR_LOG) ;
729 /* values column */
730 if (column == 0)
731 {
732 QString oldNodeName = m_currentTreeWidgetItemText;
733 QString newNodeName = item->text(0);
734 emit(renameNode(oldNodeName,newNodeName));
735 }
736 else if (column == 1)
737 {
738 /* there is a parent ; it is an attribute line */
739 if (item->parent())
740 {
741 QString nodeLabel = item->parent()->text(0);
742 QString attributeName = item->text(0);
743 QString attributeValue = item->text(1);
744 emit (setAttribute(nodeLabel,attributeName,attributeValue));
745 }
746 }
747 emit update();
748 }
749
slotItemClicked(QTreeWidgetItem * item,int column)750 void KGraphEditor::slotItemClicked ( QTreeWidgetItem * item, int column )
751 {
752 qCDebug(KGRAPHEDITOR_LOG) << column;
753 m_currentTreeWidgetItemText = item->text(0);
754
755 QString nodeName = item->parent() ?
756 item->parent()->text(0) :
757 item->text(0);
758 emit selectNode(nodeName);
759 }
760
slotEditNewVertex()761 void KGraphEditor::slotEditNewVertex()
762 {
763 if (m_currentPart == nullptr)
764 {
765 qCDebug(KGRAPHEDITOR_LOG) << "new vertex: no part selected";
766 return;
767 }
768 qCDebug(KGRAPHEDITOR_LOG) << "new vertex";
769 emit(prepareAddNewElement(m_newElementAttributes));
770 }
771
slotEditNewEdge()772 void KGraphEditor::slotEditNewEdge()
773 {
774 if (m_currentPart == nullptr)
775 {
776 qCDebug(KGRAPHEDITOR_LOG) << "new edge: no part selected";
777 return;
778 }
779 qCDebug(KGRAPHEDITOR_LOG) << "new edge";
780 emit(prepareAddNewEdge(m_newElementAttributes));
781 }
782
slotRemoveNode(const QString & nodeName)783 void KGraphEditor::slotRemoveNode(const QString& nodeName)
784 {
785 emit removeNode(nodeName);
786 emit update();
787 }
788
slotAddAttribute(const QString & attribName)789 void KGraphEditor::slotAddAttribute(const QString& attribName)
790 {
791 emit addAttribute(attribName);
792 emit update();
793 }
794
slotRemoveAttribute(const QString & nodeName,const QString & attribName)795 void KGraphEditor::slotRemoveAttribute(const QString& nodeName, const QString& attribName)
796 {
797 emit removeAttribute(nodeName,attribName);
798 emit update();
799 }
800
slotNewElementItemChanged(QTreeWidgetItem * item,int column)801 void KGraphEditor::slotNewElementItemChanged(QTreeWidgetItem* item ,int column)
802 {
803 qCDebug(KGRAPHEDITOR_LOG);
804 if (column == 0)
805 {
806 qCWarning(KGRAPHEDITOR_LOG) << "Item id change not handled";
807 return;
808 }
809 else if (column == 1)
810 {
811 m_newElementAttributes[item->text(0)] = item->text(1);
812 }
813 else
814 {
815 qCWarning(KGRAPHEDITOR_LOG) << "Unknown column" << column;
816 return;
817 }
818 }
819
slotAddNewElementAttribute(const QString & attrib)820 void KGraphEditor::slotAddNewElementAttribute(const QString& attrib)
821 {
822 m_newElementAttributes[attrib] = QString();
823 }
824
slotRemoveNewElementAttribute(const QString & attrib)825 void KGraphEditor::slotRemoveNewElementAttribute(const QString& attrib)
826 {
827 m_newElementAttributes.remove(attrib);
828 }
829
slotRemoveElement(const QString & id)830 void KGraphEditor::slotRemoveElement(const QString& id)
831 {
832 qCDebug(KGRAPHEDITOR_LOG) << id;
833 m_treeWidget->slotRemoveElement(id);
834 emit(removeElement(id));
835 }
836
slotSelectionIs(const QList<QString> & elements,const QPoint & p)837 void KGraphEditor::slotSelectionIs(const QList<QString>& elements , const QPoint& p)
838 {
839 qCDebug(KGRAPHEDITOR_LOG);
840 Q_UNUSED(p);
841 QList<QTreeWidgetItem*> items = m_treeWidget->selectedItems();
842 foreach (QTreeWidgetItem* item, items)
843 {
844 item->setSelected(false);
845 }
846 foreach (const QString &elementName, elements)
847 {
848 QList<QTreeWidgetItem*> items = m_treeWidget->findItems(elementName,Qt::MatchExactly,0);
849 foreach (QTreeWidgetItem* item, items)
850 {
851 item->setSelected(true);
852 }
853 }
854 }
855
slotParsingModeExternalToggled(bool value)856 void KGraphEditor::slotParsingModeExternalToggled(bool value)
857 {
858 if (value)
859 {
860 KGraphEditorSettings::setParsingMode("external");
861 }
862 // qCDebug(KGRAPHEDITOR_LOG) << "emiting";
863 // emit(settingsChanged());
864 KGraphEditorSettings::self()->save();
865 }
866
slotParsingModeInternalToggled(bool value)867 void KGraphEditor::slotParsingModeInternalToggled(bool value)
868 {
869 if (value)
870 {
871 KGraphEditorSettings::setParsingMode("internal");
872 }
873 // qCDebug(KGRAPHEDITOR_LOG) << "emiting";
874 // emit(settingsChanged());
875 KGraphEditorSettings::self()->save();
876 }
877
slotHoverEnter(const QString & id)878 void KGraphEditor::slotHoverEnter(const QString& id)
879 {
880 qCDebug(KGRAPHEDITOR_LOG) << id;
881 statusBar()->showMessage(id);
882 }
883
slotHoverLeave(const QString & id)884 void KGraphEditor::slotHoverLeave(const QString& id)
885 {
886 qCDebug(KGRAPHEDITOR_LOG) << id;
887 statusBar()->showMessage("");
888 }
889