1 /* $Id$Revision: */
2 /* vim:set shiftwidth=4 ts=8: */
3
4 /*************************************************************************
5 * Copyright (c) 2011 AT&T Intellectual Property
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * http://www.eclipse.org/legal/epl-v10.html
10 *
11 * Contributors: See CVS logs. Details at http://www.graphviz.org/
12 *************************************************************************/
13
14 #include <QtWidgets>
15 #include <qframe.h>
16 #include "mainwindow.h"
17 #include "mdichild.h"
18 #include "csettings.h"
19 #include "config.h"
20
21 #include <string.h>
22
23 QTextEdit *globTextEdit;
24
errorPipe(char * errMsg)25 int errorPipe(char *errMsg)
26 {
27 globTextEdit->setText(globTextEdit->toPlainText() + QString(errMsg));
28 return 0;
29 }
30
freeList(char ** lp,int count)31 static void freeList(char **lp, int count)
32 {
33 for (int i = 0; i < count; i++)
34 free(lp[i]);
35 free(lp);
36 }
37
LoadPlugins(QComboBox * cb,GVC_t * gvc,const char * kind,const char * more[],const char * prefer)38 static int LoadPlugins(QComboBox * cb, GVC_t * gvc, const char *kind,
39 const char *more[], const char *prefer)
40 {
41 int count;
42 char **lp = gvPluginList(gvc, kind, &count, NULL);
43 int idx = -1;
44
45 cb->clear();
46 for (int id = 0; id < count; id++) {
47 cb->addItem(QString(lp[id]));
48 if (prefer && (idx < 0) && !strcmp(prefer, lp[id]))
49 idx = id;
50 };
51 freeList(lp, count);
52
53 /* Add additional items if supplied */
54 if (more) {
55 int i = 0;
56 const char *s;
57 while ((s = more[i++])) {
58 cb->addItem(QString(s));
59 }
60 }
61
62 if (idx > 0)
63 cb->setCurrentIndex(idx);
64 else
65 idx = 0;
66
67 return idx;
68 }
69
createConsole()70 void CMainWindow::createConsole()
71 {
72 QDockWidget *dock = new QDockWidget(tr("Output Console"), NULL);
73 QTextEdit *textEdit = new QTextEdit(dock);
74
75 dock->
76 setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
77 // dock->setWidget(textEdit);
78 addDockWidget(Qt::BottomDockWidgetArea, dock);
79 QVBoxLayout *vL = new QVBoxLayout();
80
81
82 textEdit->setObjectName(QString::fromUtf8("textEdit"));
83 /* textEdit->setMinimumSize(QSize(0, 80));
84 textEdit->setMaximumSize(QSize(16777215, 120));*/
85 globTextEdit = textEdit;
86 agseterrf(errorPipe);
87
88 vL->addWidget(textEdit);
89 vL->setContentsMargins(1, 1, 1, 1);
90
91 QFrame *fr = new QFrame(dock);
92 vL->addWidget(fr);
93
94 QPushButton *logNewBtn =
95 new QPushButton(QIcon(":/images/new.png"), "", fr);
96 QPushButton *logSaveBtn =
97 new QPushButton(QIcon(":/images/save.png"), "", fr);
98 QHBoxLayout *consoleLayout = new QHBoxLayout();
99 consoleLayout->addWidget(logNewBtn);
100 connect(logNewBtn, SIGNAL(clicked()), this, SLOT(slotNewLog()));
101 connect(logSaveBtn, SIGNAL(clicked()), this, SLOT(slotSaveLog()));
102 consoleLayout->addWidget(logSaveBtn);
103 consoleLayout->addStretch();
104
105 consoleLayout->setContentsMargins(1, 1, 1, 1);;
106 consoleLayout->setContentsMargins(1, 1, 1, 1);
107
108 fr->setLayout(consoleLayout);
109
110 QFrame *mainFrame = new QFrame(dock);
111 mainFrame->setLayout(vL);
112
113
114 dock->setWidget(mainFrame);
115
116 }
117
118 static const char *xtra[] = {
119 "NONE",
120 (const char *) NULL
121 };
122
CMainWindow(char *** Files)123 CMainWindow::CMainWindow(char*** Files)
124 {
125
126 QWidget *centralwidget = new QWidget(this);
127 centralwidget->setObjectName(QString::fromUtf8("centralwidget"));
128 QVBoxLayout *verticalLayout_2 = new QVBoxLayout(centralwidget);
129 verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
130 QVBoxLayout *verticalLayout = new QVBoxLayout();
131 verticalLayout->setObjectName(QString::fromUtf8("verticalLayout"));
132 mdiArea = new QMdiArea(centralwidget);
133 mdiArea->setObjectName(QString::fromUtf8("mdiArea"));
134
135 verticalLayout->addWidget(mdiArea);
136 verticalLayout_2->setContentsMargins(1, 1, 1, 1);
137 verticalLayout_2->addLayout(verticalLayout);
138 setCentralWidget(centralwidget);
139 centralwidget->layout()->setContentsMargins(1, 1, 1, 1);
140 prevChild = NULL;
141
142 createConsole();
143
144
145
146
147
148
149 connect(mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow *)),
150 this, SLOT(slotRefreshMenus()));
151 windowMapper = new QSignalMapper(this);
152 connect(windowMapper, SIGNAL(mapped(QWidget *)),
153 this, SLOT(activateChild(QWidget *)));
154
155 frmSettings = new CFrmSettings();
156
157 actions();
158 menus();
159 toolBars();
160 statusBar();
161 updateMenus();
162
163 readSettings();
164
165 setWindowTitle(tr("GVEdit"));
166 this->resize(1024, 900);
167 this->move(0, 0);
168 setUnifiedTitleAndToolBarOnMac(true);
169 // (QComboBox*)frmSettings->findChild<QComboBox*>("cbLayout")
170 QComboBox *cb =
171 (QComboBox *) frmSettings->findChild < QComboBox * >("cbLayout");
172 dfltLayoutIdx = LoadPlugins(cb, frmSettings->gvc, "layout", NULL, "dot");
173 cb = (QComboBox *) frmSettings->findChild <
174 QComboBox * >("cbExtension");
175 dfltRenderIdx =
176 LoadPlugins(cb, frmSettings->gvc, "device", xtra, "png");
177 statusBar()->showMessage(tr("Ready"));
178 setWindowIcon(QIcon(":/images/icon.png"));
179 //load files specified in command line , one time task
180 char** files=*Files;
181 if (files)
182 while (*files) {
183 addFile(QString(*files));
184 files++;
185 }
186
187
188
189 }
190
closeEvent(QCloseEvent * event)191 void CMainWindow::closeEvent(QCloseEvent * event)
192 {
193 mdiArea->closeAllSubWindows();
194 if (mdiArea->currentSubWindow()) {
195 event->ignore();
196 } else {
197 writeSettings();
198 event->accept();
199 }
200 }
201
slotNew()202 void CMainWindow::slotNew()
203 {
204 MdiChild *child = createMdiChild();
205 child->newFile();
206 child->show();
207 }
208
addFile(QString fileName)209 void CMainWindow::addFile(QString fileName)
210 {
211 if (!fileName.isEmpty()) {
212 QMdiSubWindow *existing = findMdiChild(fileName);
213 if (existing) {
214 mdiArea->setActiveSubWindow(existing);
215 return;
216 }
217
218 MdiChild *child = createMdiChild();
219 if (child->loadFile(fileName)) {
220 statusBar()->showMessage(tr("File loaded"), 2000);
221 child->show();
222 slotRun(child);
223 } else {
224 child->close();
225 }
226 }
227 }
228
slotOpen()229 void CMainWindow::slotOpen()
230 {
231 QStringList filters;
232 filters << "*.cpp" << "*.cxx" << "*.cc";
233
234 QFileDialog fd;
235 // fd.setProxyModel(new FileFilterProxyModel());
236 fd.setNameFilter("XML (*.xml)");
237 QString fileName = fd.getOpenFileName(this);
238 // QFileDialog::getOpenFileName(this);
239
240 addFile(fileName);
241 }
242
slotSave()243 void CMainWindow::slotSave()
244 {
245 if (activeMdiChild() && activeMdiChild()->save())
246 statusBar()->showMessage(tr("File saved"), 2000);
247 }
248
slotSaveAs()249 void CMainWindow::slotSaveAs()
250 {
251 if (activeMdiChild() && activeMdiChild()->saveAs())
252 statusBar()->showMessage(tr("File saved"), 2000);
253 }
254
slotCut()255 void CMainWindow::slotCut()
256 {
257 if (activeMdiChild())
258 activeMdiChild()->cut();
259 }
260
slotCopy()261 void CMainWindow::slotCopy()
262 {
263 if (activeMdiChild())
264 activeMdiChild()->copy();
265 }
266
slotPaste()267 void CMainWindow::slotPaste()
268 {
269 if (activeMdiChild())
270 activeMdiChild()->paste();
271 }
272
slotAbout()273 void CMainWindow::slotAbout()
274 {
275 QString abs (tr("<b>GVEdit</b> Graph File Editor For Graphviz"
276 " version: 1.02\n"
277 "Graphviz version: "));
278
279 abs += tr (gvcVersion (frmSettings->gvc));
280 QMessageBox::about(this, tr("About GVEdit"), abs);
281 }
282
setChild()283 void CMainWindow::setChild ()
284 {
285 if (prevChild != activeMdiChild()) {
286 QString msg;
287 msg.append("working on ");
288 msg.append(activeMdiChild()->currentFile());
289 msg.append("\n");
290 errorPipe((char *) msg.toLatin1().constData());
291 prevChild = activeMdiChild();
292 }
293 }
294
slotSettings()295 void CMainWindow::slotSettings()
296 {
297 setChild ();
298 frmSettings->showSettings(activeMdiChild());
299 }
300
slotRun(MdiChild * m)301 void CMainWindow::slotRun(MdiChild * m)
302 {
303 setChild ();
304
305
306
307 // if ((activeMdiChild()) && (!activeMdiChild()->firstTime()))
308 if(m)
309 frmSettings->runSettings(m);
310 else
311 frmSettings->runSettings(activeMdiChild());
312 // if ((activeMdiChild()) && (activeMdiChild()->firstTime()))
313 // frmSettings->showSettings(activeMdiChild());
314
315
316 }
317
318
319
slotNewLog()320 void CMainWindow::slotNewLog()
321 {
322 globTextEdit->clear();
323 }
324
slotSaveLog()325 void CMainWindow::slotSaveLog()
326 {
327
328 if (globTextEdit->toPlainText().trimmed().length() == 0) {
329 QMessageBox::warning(this, tr("GvEdit"), tr("Nothing to save!"),
330 QMessageBox::Ok, QMessageBox::Ok);
331 return;
332
333
334 }
335
336 QString fileName = QFileDialog::getSaveFileName(this, tr("Open File"),
337 "/",
338 tr("Text File(*.*)"));
339 if (!fileName.isEmpty()) {
340
341 QFile file(fileName);
342 if (!file.open(QFile::WriteOnly | QFile::Text)) {
343 QMessageBox::warning(this, tr("MDI"),
344 tr("Cannot write file %1:\n%2.")
345 .arg(fileName)
346 .arg(file.errorString()));
347 return;
348 }
349
350 QTextStream out(&file);
351 out << globTextEdit->toPlainText();
352 return;
353 }
354
355
356 }
357
updateFileMenu()358 void CMainWindow::updateFileMenu()
359 {
360 if (!activeMdiChild()) {
361 saveAct->setEnabled(false);
362 saveAsAct->setEnabled(false);
363 pasteAct->setEnabled(false);
364 closeAct->setEnabled(false);
365 closeAllAct->setEnabled(false);
366 tileAct->setEnabled(false);
367 cascadeAct->setEnabled(false);
368 nextAct->setEnabled(false);
369 previousAct->setEnabled(false);
370 separatorAct->setVisible(false);
371 settingsAct->setEnabled(false);
372 layoutAct->setEnabled(false);
373 } else {
374 saveAct->setEnabled(true);
375 saveAsAct->setEnabled(true);
376 pasteAct->setEnabled(true);
377 closeAct->setEnabled(true);
378 closeAllAct->setEnabled(true);
379 tileAct->setEnabled(true);
380 cascadeAct->setEnabled(true);
381 nextAct->setEnabled(true);
382 previousAct->setEnabled(true);
383 separatorAct->setVisible(true);
384 settingsAct->setEnabled(true);
385 layoutAct->setEnabled(true);
386
387 if (activeMdiChild()->textCursor().hasSelection()) {
388 cutAct->setEnabled(true);
389 copyAct->setEnabled(true);
390
391 } else {
392 cutAct->setEnabled(false);
393 copyAct->setEnabled(false);
394
395 }
396
397
398
399 }
400
401 }
402
slotRefreshMenus()403 void CMainWindow::slotRefreshMenus()
404 {
405 updateMenus();
406 }
407
updateMenus()408 void CMainWindow::updateMenus()
409 {
410 this->updateFileMenu();
411 this->updateWindowMenu();
412
413 }
414
updateWindowMenu()415 void CMainWindow::updateWindowMenu()
416 {
417 mWindow->clear();
418 mWindow->addAction(closeAct);
419 mWindow->addAction(closeAllAct);
420 mWindow->addSeparator();
421 mWindow->addAction(tileAct);
422 mWindow->addAction(cascadeAct);
423 mWindow->addSeparator();
424 mWindow->addAction(nextAct);
425 mWindow->addAction(previousAct);
426 mWindow->addAction(separatorAct);
427
428 QList < QMdiSubWindow * >windows = mdiArea->subWindowList();
429 separatorAct->setVisible(!windows.isEmpty());
430
431 for (int i = 0; i < windows.size(); ++i) {
432 if (windows.at(i)->widget()->inherits("MdiChild")) {
433 MdiChild *child =
434 qobject_cast < MdiChild * >(windows.at(i)->widget());
435 QString text;
436 if (i < 9) {
437 text = tr("&%1 %2").arg(i + 1)
438 .arg(child->userFriendlyCurrentFile());
439 } else {
440 text = tr("%1 %2").arg(i + 1)
441 .arg(child->userFriendlyCurrentFile());
442 }
443 QAction *action = mWindow->addAction(text);
444 action->setCheckable(true);
445 action->setChecked(child == activeMdiChild());
446 connect(action, SIGNAL(triggered()), windowMapper,
447 SLOT(map()));
448 windowMapper->setMapping(action, windows.at(i));
449 }
450 }
451 }
452
createMdiChild()453 MdiChild *CMainWindow::createMdiChild()
454 {
455 MdiChild *child = new MdiChild;
456 child->parentFrm = this;
457 QMdiSubWindow *s = mdiArea->addSubWindow(child);
458 s->resize(800, 600);
459 s->move(mdiArea->subWindowList().count() * 5,
460 mdiArea->subWindowList().count() * 5);
461 connect(child, SIGNAL(copyAvailable(bool)), cutAct,
462 SLOT(setEnabled(bool)));
463 connect(child, SIGNAL(copyAvailable(bool)), copyAct,
464 SLOT(setEnabled(bool)));
465 child->layoutIdx = dfltLayoutIdx;
466 child->renderIdx = dfltRenderIdx;
467
468 return child;
469 }
470
actions()471 void CMainWindow::actions()
472 {
473 newAct = new QAction(QIcon(":/images/new.png"), tr("&New"), this);
474 newAct->setShortcuts(QKeySequence::New);
475 newAct->setStatusTip(tr("Create a new file"));
476 connect(newAct, SIGNAL(triggered()), this, SLOT(slotNew()));
477
478 openAct =
479 new QAction(QIcon(":/images/open.png"), tr("&Open..."), this);
480 openAct->setShortcuts(QKeySequence::Open);
481 openAct->setStatusTip(tr("Open an existing file"));
482 connect(openAct, SIGNAL(triggered()), this, SLOT(slotOpen()));
483
484 saveAct = new QAction(QIcon(":/images/save.png"), tr("&Save"), this);
485 saveAct->setShortcuts(QKeySequence::Save);
486 saveAct->setStatusTip(tr("Save the document to disk"));
487 connect(saveAct, SIGNAL(triggered()), this, SLOT(slotSave()));
488
489 saveAsAct = new QAction(tr("Save &As..."), this);
490 saveAsAct->setShortcuts(QKeySequence::SaveAs);
491 saveAsAct->setStatusTip(tr("Save the document under a new name"));
492 connect(saveAsAct, SIGNAL(triggered()), this, SLOT(slotSaveAs()));
493 exitAct = new QAction(tr("E&xit"), this);
494 #if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0))
495 exitAct->setShortcuts(QKeySequence::Quit);
496 #endif
497 exitAct->setStatusTip(tr("Exit the application"));
498 connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
499 cutAct = new QAction(QIcon(":/images/cut.png"), tr("Cu&t"), this);
500 cutAct->setShortcuts(QKeySequence::Cut);
501 cutAct->
502 setStatusTip(tr
503 ("Cut the current selection's contents to the "
504 "clipboard"));
505 connect(cutAct, SIGNAL(triggered()), this, SLOT(slotCut()));
506
507 copyAct = new QAction(QIcon(":/images/copy.png"), tr("&Copy"), this);
508 copyAct->setShortcuts(QKeySequence::Copy);
509 copyAct->
510 setStatusTip(tr
511 ("Copy the current selection's contents to the "
512 "clipboard"));
513 connect(copyAct, SIGNAL(triggered()), this, SLOT(slotCopy()));
514
515 pasteAct =
516 new QAction(QIcon(":/images/paste.png"), tr("&Paste"), this);
517 pasteAct->setShortcuts(QKeySequence::Paste);
518 pasteAct->
519 setStatusTip(tr
520 ("Paste the clipboard's contents into the current "
521 "selection"));
522 connect(pasteAct, SIGNAL(triggered()), this, SLOT(slotPaste()));
523
524 closeAct = new QAction(tr("Cl&ose"), this);
525 closeAct->setStatusTip(tr("Close the active window"));
526 connect(closeAct, SIGNAL(triggered()), mdiArea,
527 SLOT(closeActiveSubWindow()));
528
529 closeAllAct = new QAction(tr("Close &All"), this);
530 closeAllAct->setStatusTip(tr("Close all the windows"));
531 connect(closeAllAct, SIGNAL(triggered()), mdiArea,
532 SLOT(closeAllSubWindows()));
533
534 tileAct = new QAction(tr("&Tile"), this);
535 tileAct->setStatusTip(tr("Tile the windows"));
536 connect(tileAct, SIGNAL(triggered()), mdiArea, SLOT(tileSubWindows()));
537
538 cascadeAct = new QAction(tr("&Cascade"), this);
539 cascadeAct->setStatusTip(tr("Cascade the windows"));
540 connect(cascadeAct, SIGNAL(triggered()), mdiArea,
541 SLOT(cascadeSubWindows()));
542
543 nextAct = new QAction(tr("Ne&xt"), this);
544 nextAct->setShortcuts(QKeySequence::NextChild);
545 nextAct->setStatusTip(tr("Move the focus to the next window"));
546 connect(nextAct, SIGNAL(triggered()), mdiArea,
547 SLOT(activateNextSubWindow()));
548
549 previousAct = new QAction(tr("Pre&vious"), this);
550 previousAct->setShortcuts(QKeySequence::PreviousChild);
551 previousAct->setStatusTip(tr("Move the focus to the previous window"));
552 connect(previousAct, SIGNAL(triggered()), mdiArea,
553 SLOT(activatePreviousSubWindow()));
554
555 separatorAct = new QAction(this);
556 separatorAct->setSeparator(true);
557
558 aboutAct = new QAction(tr("&About"), this);
559 aboutAct->setStatusTip(tr("Show the application's About box"));
560 connect(aboutAct, SIGNAL(triggered()), this, SLOT(slotAbout()));
561
562
563
564 settingsAct =
565 new QAction(QIcon(":/images/settings.png"), tr("Settings"), this);
566 settingsAct->setStatusTip(tr("Show Graphviz Settings"));
567 connect(settingsAct, SIGNAL(triggered()), this, SLOT(slotSettings()));
568 settingsAct->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_F5));
569
570
571
572
573 layoutAct = new QAction(QIcon(":/images/run.png"), tr("Layout"), this);
574 layoutAct->setStatusTip(tr("Layout the active graph"));
575 connect(layoutAct, SIGNAL(triggered()), this, SLOT(slotRun()));
576 layoutAct->setShortcut(QKeySequence(Qt::Key_F5));
577
578
579
580 }
581
menus()582 void CMainWindow::menus()
583 {
584 mFile = menuBar()->addMenu(tr("&File"));
585 mEdit = menuBar()->addMenu(tr("&Edit"));
586 mWindow = menuBar()->addMenu(tr("&Window"));
587 mGraph = menuBar()->addMenu(tr("&Graph"));
588 mHelp = menuBar()->addMenu(tr("&Help"));
589
590
591 mFile->addAction(newAct);
592 mFile->addAction(openAct);
593 mFile->addAction(saveAct);
594 mFile->addAction(saveAsAct);
595 mFile->addSeparator();
596
597 mFile->addAction(exitAct);
598
599 mEdit->addAction(cutAct);
600 mEdit->addAction(copyAct);
601 mEdit->addAction(pasteAct);
602
603 mGraph->addAction(settingsAct);
604 mGraph->addAction(layoutAct);
605 mGraph->addSeparator();
606 loadPlugins();
607
608 updateWindowMenu();
609 connect(mWindow, SIGNAL(aboutToShow()), this,
610 SLOT(slotRefreshMenus()));
611 mHelp->addAction(aboutAct);
612 }
613
toolBars()614 void CMainWindow::toolBars()
615 {
616 tbFile = addToolBar(tr("File"));
617 tbFile->addAction(newAct);
618 tbFile->addAction(openAct);
619 tbFile->addAction(saveAct);
620
621 tbEdit = addToolBar(tr("Edit"));
622 tbEdit->addAction(cutAct);
623 tbEdit->addAction(copyAct);
624 tbEdit->addAction(pasteAct);
625
626 tbGraph = addToolBar(tr("Graph"));
627 tbGraph->addAction(settingsAct);
628 tbGraph->addAction(layoutAct);
629
630 }
631
632
readSettings()633 void CMainWindow::readSettings()
634 {
635 QSettings settings("Trolltech", "MDI Example");
636 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
637 QSize size = settings.value("size", QSize(400, 400)).toSize();
638 move(pos);
639 resize(size);
640 }
641
writeSettings()642 void CMainWindow::writeSettings()
643 {
644 QSettings settings("Trolltech", "MDI Example");
645 settings.setValue("pos", pos());
646 settings.setValue("size", size());
647 }
648
activeMdiChild()649 MdiChild *CMainWindow::activeMdiChild()
650 {
651 if (QMdiSubWindow * activeSubWindow = mdiArea->activeSubWindow()) {
652 if (activeSubWindow->widget()->inherits("MdiChild"))
653 return qobject_cast < MdiChild * >(activeSubWindow->widget());
654 else
655 return qobject_cast <
656 ImageViewer * >(activeSubWindow->widget())->graphWindow;
657
658 }
659 return 0;
660 }
661
findMdiChild(const QString & fileName)662 QMdiSubWindow *CMainWindow::findMdiChild(const QString & fileName)
663 {
664 QString canonicalFilePath = QFileInfo(fileName).canonicalFilePath();
665
666 foreach(QMdiSubWindow * window, mdiArea->subWindowList()) {
667 if (window->widget()->inherits("MdiChild")) {
668
669 MdiChild *mdiChild =
670 qobject_cast < MdiChild * >(window->widget());
671 if (mdiChild->currentFile() == canonicalFilePath)
672 return window;
673 } else {
674
675 MdiChild *mdiChild =
676 qobject_cast <
677 ImageViewer * >(window->widget())->graphWindow;
678 if (mdiChild->currentFile() == canonicalFilePath)
679 return window;
680 }
681
682
683
684 }
685 return 0;
686 }
687
activateChild(QWidget * window)688 void CMainWindow::activateChild(QWidget * window)
689 {
690 if (!window)
691 return;
692 mdiArea->setActiveSubWindow(qobject_cast < QMdiSubWindow * >(window));
693 }
694
loadPlugins()695 void CMainWindow::loadPlugins()
696 {
697
698 }
699