Added automatic graph transformation on file open in GUI
[hypercube:hypercube.git] / GUI / gui.cpp
1 #include "gui.h"
2 #include "colorcombobox.h"
3 #include "numericedit.h"
4 #include "graphtab.h"
5 #include "icons.h"
6 #include "settings.h"
7 #include "CORE/config.h"
8 #include "IO/io.h"
9 #include "IO/encoding.h"
10 #include "IO/modules.h"
11
12
13 #define TAB() ((GraphTab*) _viewTab->currentWidget())
14
15 #define BLOCK(widget, action) \
16         widget->blockSignals(true); \
17         widget->action; \
18         widget->blockSignals(false)
19
20 #define ZOOM_STRING(zoom) QString("%1%").arg((int)((zoom) * 100))
21
22
23 static QString saveFilter(OutputProvider *provider);
24 static QString errorDescription(IO::Error error);
25
26
27 GUI::GUI()
28 {
29         createActions();
30         createMenus();
31         createToolBars();
32         createViews();
33         createProperties();
34         createStatusBar();
35
36         QHBoxLayout *layout = new QHBoxLayout;
37         layout->addWidget(_properties);
38         layout->addWidget(_viewTab);
39
40         QWidget *widget = new QWidget;
41         widget->setLayout(layout);
42         setCentralWidget(widget);
43
44         setWindowTitle("Hypercube");
45         setUnifiedTitleAndToolBarOnMac(true);
46
47         readSettings();
48 }
49
50 void GUI::createActions()
51 {
52         // Action Groups
53         _fileActionGroup = new QActionGroup(this);
54         _fileActionGroup->setExclusive(false);
55         _fileActionGroup->setEnabled(false);
56         _graphActionGroup = new QActionGroup(this);
57         _graphActionGroup->setExclusive(false);
58         _graphActionGroup->setEnabled(false);
59         _projectActionGroup = new QActionGroup(this);
60         _projectActionGroup->setExclusive(false);
61         _projectActionGroup->setEnabled(false);
62
63
64         // General actions
65         _exitAction = new QAction(tr("Exit"), this);
66         connect(_exitAction, SIGNAL(triggered()), this, SLOT(close()));
67
68         _aboutAction = new QAction(QIcon(QPixmap(APP_ICON)),
69           tr("About Hypercube"), this);
70         connect(_aboutAction, SIGNAL(triggered()), this, SLOT(about()));
71         _aboutQtAction = new QAction(tr("About Qt"), this);
72         connect(_aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
73
74         // File related actions
75         _openFileAction = new QAction(QIcon(QPixmap(OPEN_FILE_ICON)),
76           tr("Open file"), this);
77         connect(_openFileAction, SIGNAL(triggered()), this, SLOT(openFile()));
78         _saveFileAction = new QAction(QIcon(QPixmap(SAVE_FILE_ICON)),
79           tr("Save file"), this);
80         _saveFileAction->setActionGroup(_fileActionGroup);
81         connect(_saveFileAction, SIGNAL(triggered()), this, SLOT(saveFile()));
82         _saveAsAction = new QAction(QIcon(QPixmap(SAVE_AS_ICON)),
83           tr("Save as"), this);
84         _saveAsAction->setActionGroup(_fileActionGroup);
85         connect(_saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs()));
86         _saveAllAction = new QAction(QIcon(QPixmap(SAVE_ALL_ICON)),
87           tr("Save all"), this);
88         _saveAllAction->setActionGroup(_fileActionGroup);
89         connect(_saveAllAction, SIGNAL(triggered()), this, SLOT(saveAll()));
90         _closeFileAction = new QAction(QIcon(QPixmap(CLOSE_FILE_ICON)),
91           tr("Close file"), this);
92         _closeFileAction->setActionGroup(_fileActionGroup);
93         connect(_closeFileAction, SIGNAL(triggered()), this, SLOT(closeFile()));
94
95         // Graph related actions
96         _transformAction = new QAction(QIcon(QPixmap(TRANSFORM_GRAPH_ICON)),
97           tr("Transform graph"), this);
98         _transformAction->setActionGroup(_graphActionGroup);
99         connect(_transformAction, SIGNAL(triggered()), this,
100           SLOT(transformGraph()));
101         _reloadAction = new QAction(QIcon(QPixmap(RELOAD_GRAPH_ICON)),
102           tr("Reload graph"), this);
103         _reloadAction->setActionGroup(_graphActionGroup);
104         connect(_reloadAction, SIGNAL(triggered()), this, SLOT(reloadGraph()));
105
106         // Projections related actions
107         _projectAction = new QAction(QIcon(QPixmap(PROJECT_ICON)),
108           tr("Project appearance"), this);
109         _projectAction->setActionGroup(_projectActionGroup);
110         connect(_projectAction, SIGNAL(triggered()), this,
111           SLOT(projectGraph()));
112         _bindAction = new QAction(QIcon(QPixmap(BIND_ICON)),
113           tr("Project layout"), this);
114         _bindAction->setActionGroup(_projectActionGroup);
115         connect(_bindAction, SIGNAL(triggered()), this,
116           SLOT(bindGraph()));
117 }
118
119 void GUI::createMenus()
120 {
121         _fileMenu = menuBar()->addMenu(tr("File"));
122         _fileMenu->addAction(_openFileAction);
123         _fileMenu->addAction(_saveFileAction);
124         _fileMenu->addAction(_saveAsAction);
125         _fileMenu->addAction(_saveAllAction);
126         _fileMenu->addAction(_closeFileAction);
127         _fileMenu->addAction(_exitAction);
128
129         _graphMenu = menuBar()->addMenu(tr("Graph"));
130         _graphMenu->addAction(_transformAction);
131         _graphMenu->addAction(_reloadAction);
132
133         _projectionsMenu = menuBar()->addMenu(tr("Projections"));
134         _projectionsMenu->addAction(_bindAction);
135         _projectionsMenu->addAction(_projectAction);
136
137         _aboutMenu = menuBar()->addMenu(tr("Help"));
138         _aboutMenu->addAction(_aboutAction);
139         _aboutMenu->addAction(_aboutQtAction);
140 }
141
142 void GUI::createToolBars()
143 {
144         _fileToolBar = addToolBar(tr("File"));
145         _fileToolBar->addAction(_openFileAction);
146         _fileToolBar->addAction(_saveFileAction);
147         _fileToolBar->addAction(_saveAllAction);
148         _fileToolBar->addAction(_closeFileAction);
149
150         _graphToolBar = addToolBar(tr("Graph"));
151         _graphToolBar->addAction(_transformAction);
152         _graphToolBar->addAction(_reloadAction);
153
154         _projectionsToolBar = addToolBar(tr("Projections"));
155         _projectionsToolBar->addAction(_bindAction);
156         _projectionsToolBar->addAction(_projectAction);
157
158 #ifdef Q_WS_MAC
159         _fileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
160         _graphToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
161         _projectionsToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
162 #endif
163 }
164
165 void GUI::createProperties()
166 {
167         createGraphProperties();
168         createSAProperties();
169         createMiscProperties();
170
171         _properties = new QToolBox;
172
173         _properties->setBackgroundRole(QPalette::Window);
174         _properties->setSizePolicy(QSizePolicy(QSizePolicy::Maximum,
175           QSizePolicy::Ignored));
176         _properties->setMinimumWidth(qMax(_MiscProperties->sizeHint().width(),
177           qMax(_graphProperties->sizeHint().width(),
178           _SAProperties->sizeHint().width())));
179
180         _properties->addItem(_graphProperties, tr("Graph settings"));
181         _properties->addItem(_SAProperties, tr("Algorithm settings"));
182         _properties->addItem(_MiscProperties, tr("Miscellaneous"));
183 }
184
185 void GUI::createMiscProperties()
186 {
187         QGroupBox *encodingBox = new QGroupBox(tr("Encoding"));
188
189         _inputEncoding = new QComboBox();
190
191         for (Encoding **ep = encodings; *ep; ep++)
192                 _inputEncoding->addItem((*ep)->name());
193
194         connect(_inputEncoding, SIGNAL(currentIndexChanged(int)), this,
195           SLOT(setInputEncoding(int)));
196
197         QVBoxLayout *encodingLayout = new QVBoxLayout;
198         QFormLayout *encodingFormLayout = new QFormLayout;
199         encodingFormLayout->addRow(tr("Input encoding:"), _inputEncoding);
200         encodingLayout->addLayout(encodingFormLayout);
201         encodingLayout->addStretch();
202         encodingBox->setLayout(encodingLayout);
203
204
205         QGroupBox *displayBox = new QGroupBox(tr("Display"));
206
207         _antialiasing = new QCheckBox(tr("Use antialiasing"), this);
208         QVBoxLayout *displayLayout = new QVBoxLayout;
209         displayLayout->addWidget(_antialiasing);
210         displayLayout->addStretch();
211         displayBox->setLayout(displayLayout);
212
213         connect(_antialiasing, SIGNAL(stateChanged(int)),
214           this, SLOT(setAntialiasing(int)));
215
216
217         QGroupBox *argumentsBox = new QGroupBox(tr("CLI arguments"));
218
219         _arguments = new QLabel(this);
220         _arguments->setTextInteractionFlags(Qt::TextSelectableByMouse
221           | Qt::TextSelectableByKeyboard);
222         _arguments->setWordWrap(true);
223
224         _argumentsEscape = new QCheckBox(tr("Escape special characters"));
225
226         QVBoxLayout *argumentsLayout = new QVBoxLayout;
227         argumentsLayout->addWidget(_argumentsEscape);
228         argumentsLayout->addWidget(_arguments);
229         argumentsLayout->addStretch();
230         argumentsBox->setLayout(argumentsLayout);
231
232         connect(_argumentsEscape, SIGNAL(stateChanged(int)),
233           this, SLOT(setSpecialsEscaping()));
234
235
236         QVBoxLayout *layout = new QVBoxLayout;
237         layout->addWidget(encodingBox);
238         layout->addWidget(displayBox);
239         layout->addWidget(argumentsBox);
240
241         _MiscProperties = new QWidget;
242         _MiscProperties->setLayout(layout);
243 }
244
245 void GUI::createSAProperties()
246 {
247         QGroupBox *graphBox = new QGroupBox(tr("Graph layout"));
248
249         _nodeDistribution = new FloatEdit(10);
250         _edgeLength = new FloatEdit(10);
251         _edgeCrossings = new FloatEdit(10);
252
253         connect(_nodeDistribution, SIGNAL(valueChanged(float)),
254           this, SLOT(setNodeDistribution(float)));
255         connect(_edgeLength, SIGNAL(valueChanged(float)),
256           this, SLOT(setEdgeLength(float)));
257         connect(_edgeCrossings, SIGNAL(valueChanged(float)),
258           this, SLOT(setEdgeCrossings(float)));
259
260         QFormLayout *graphLayout = new QFormLayout;
261         graphLayout->addRow(tr("Node distribution:"), _nodeDistribution);
262         graphLayout->addRow(tr("Edge length:"), _edgeLength);
263         graphLayout->addRow(tr("Edge crossings:"), _edgeCrossings);
264         graphBox->setLayout(graphLayout);
265
266
267         QGroupBox *SABox = new QGroupBox(tr("SA parameters"));
268
269         _initTemp = new FloatEdit(10);
270         _finalTemp = new FloatEdit(10);
271         _coolFactor = new FloatEdit(10);
272         _numSteps = new IntEdit(10);
273
274         connect(_initTemp, SIGNAL(valueChanged(float)),
275           this, SLOT(setInitTemp(float)));
276         connect(_finalTemp, SIGNAL(valueChanged(float)),
277           this, SLOT(setFinalTemp(float)));
278         connect(_coolFactor, SIGNAL(valueChanged(float)),
279           this, SLOT(setCoolFactor(float)));
280         connect(_numSteps, SIGNAL(valueChanged(int)),
281           this, SLOT(setNumSteps(int)));
282
283         QFormLayout *SAlayout = new QFormLayout;
284         SAlayout->addRow(tr("Initial temperature:"), _initTemp);
285         SAlayout->addRow(tr("Final temperature:"), _finalTemp);
286         SAlayout->addRow(tr("Cooling factor:"), _coolFactor);
287         SAlayout->addRow(tr("Steps:"), _numSteps);
288         SABox->setLayout(SAlayout);
289
290 #ifdef SA_LOG_SUPPORT
291         QGroupBox *debugBox = new QGroupBox(tr("Debug"));
292         _debug = new QCheckBox(tr("Create debug output"), this);
293         QVBoxLayout *debugLayout = new QVBoxLayout;
294         debugLayout->addWidget(_debug, 0, Qt::AlignTop);
295         debugBox->setLayout(debugLayout);
296
297         connect(_debug, SIGNAL(stateChanged(int)),
298           this, SLOT(setSALogInfo(int)));
299 #endif
300
301
302         QVBoxLayout *layout = new QVBoxLayout;
303         layout->addWidget(graphBox);
304         layout->addWidget(SABox);
305 #ifdef SA_LOG_SUPPORT
306         layout->addWidget(debugBox);
307 #endif
308
309         _SAProperties = new QWidget;
310         _SAProperties->setLayout(layout);
311 }
312
313 void GUI::createGraphProperties()
314 {
315         _directedGraph = new QCheckBox(tr("Directed graph"), this);
316
317         _graphWidth = new QSpinBox();
318         _graphHeight = new QSpinBox();
319         _graphWidth->setMaximum(10000);
320         _graphHeight->setMaximum(10000);
321
322         connect(_directedGraph, SIGNAL(stateChanged(int)),
323           this, SLOT(directGraph(int)));
324
325         connect(_graphWidth, SIGNAL(valueChanged(int)),
326           this, SLOT(setGraphWidth(int)));
327         connect(_graphHeight, SIGNAL(valueChanged(int)),
328           this, SLOT(setGraphHeight(int)));
329
330         QGroupBox *graphBox = new QGroupBox(tr("Graph"));
331
332         QFormLayout *graphLayout = new QFormLayout;
333         graphLayout->addRow(tr("Width:"), _graphWidth);
334         graphLayout->addRow(tr("Height:"), _graphHeight);
335         graphLayout->addRow(_directedGraph);
336         graphBox->setLayout(graphLayout);
337
338
339         _vertexSize = new QSpinBox();
340         _edgeSize = new QSpinBox();
341         _edgeFontSize = new QSpinBox();
342         _vertexFontSize = new QSpinBox();
343         _edgeColor = new ColorComboBox();
344         _vertexColor = new ColorComboBox();
345         _vertexIDs = new QCheckBox(tr("Show vertex IDs"), this);
346         _edgeValues = new QCheckBox(tr("Show edge values"), this);
347         _coloredEdges = new QCheckBox(tr("Colored edges"), this);
348
349         _edgeFontSize->setMinimum(MIN_FONT_SIZE);
350         _vertexFontSize->setMinimum(MIN_FONT_SIZE);
351
352         connect(_edgeSize, SIGNAL(valueChanged(int)),
353           this, SLOT(setEdgeSize(int)));
354         connect(_vertexSize, SIGNAL(valueChanged(int)),
355           this, SLOT(setVertexSize(int)));
356         connect(_edgeFontSize, SIGNAL(valueChanged(int)),
357           this, SLOT(setEdgeFontSize(int)));
358         connect(_vertexFontSize, SIGNAL(valueChanged(int)),
359           this, SLOT(setVertexFontSize(int)));
360         connect(_coloredEdges, SIGNAL(stateChanged(int)),
361           this, SLOT(colorizeEdges(int)));
362
363         connect(_edgeColor, SIGNAL(activated(const QColor&)),
364           this, SLOT(setEdgeColor(const QColor&)));
365         connect(_vertexColor, SIGNAL(activated(const QColor&)),
366           this, SLOT(setVertexColor(const QColor&)));
367
368         connect(_edgeValues, SIGNAL(stateChanged(int)),
369           this, SLOT(showEdgeValues(int)));
370         connect(_vertexIDs, SIGNAL(stateChanged(int)),
371           this, SLOT(showVertexIDs(int)));
372
373
374         QGroupBox *vertexBox = new QGroupBox(tr("Vertexes"));
375         QGroupBox *edgeBox = new QGroupBox(tr("Edges"));
376
377         QFormLayout *edgeLayout = new QFormLayout;
378         QFormLayout *vertexLayout = new QFormLayout;
379
380         edgeLayout->addRow(tr("Size:"), _edgeSize);
381         edgeLayout->addRow(tr("Font size:"), _edgeFontSize);
382         edgeLayout->addRow(tr("Color:"), _edgeColor);
383         edgeLayout->addRow(_edgeValues);
384         edgeLayout->addRow(_coloredEdges);
385         edgeBox->setLayout(edgeLayout);
386
387         vertexLayout->addRow(tr("Size:"), _vertexSize);
388         vertexLayout->addRow(tr("Font size:"), _vertexFontSize);
389         vertexLayout->addRow(tr("Color:"), _vertexColor);
390         vertexLayout->addRow(_vertexIDs);
391         vertexBox->setLayout(vertexLayout);
392
393
394         QVBoxLayout *layout = new QVBoxLayout;
395
396         layout->addWidget(graphBox);
397         layout->addWidget(vertexBox);
398         layout->addWidget(edgeBox);
399
400         _graphProperties = new QWidget;
401         _graphProperties->setLayout(layout);
402 }
403
404 void GUI::createViews()
405 {
406         _viewTab = new QTabWidget;
407
408 #if QT_VERSION >= 0x040500
409         _viewTab->setTabsClosable(true);
410         connect(_viewTab, SIGNAL(tabCloseRequested(int)),
411           this, SLOT(tabClosed(int)));
412 #endif
413         connect(_viewTab, SIGNAL(currentChanged(int)),
414           this, SLOT(tabChanged(int)));
415 }
416
417 void GUI::createStatusBar()
418 {
419         _fileName = new QLabel();
420         _zoom = new QLabel();
421         _zoom->setAlignment(Qt::AlignHCenter);
422
423         statusBar()->addPermanentWidget(_fileName, 9);
424         statusBar()->addPermanentWidget(_zoom, 1);
425         statusBar()->setSizeGripEnabled(false);
426 }
427
428 void GUI::checkActions()
429 {
430         int cnt = _viewTab->count();
431         if (cnt == 0) {
432                 _fileActionGroup->setEnabled(false);
433                 _graphActionGroup->setEnabled(false);
434         } else if (cnt == 1)
435                 _projectActionGroup->setEnabled(false);
436 }
437
438 void GUI::tabClosed(int current)
439 {
440         GraphTab* tab = (GraphTab*)(_viewTab->widget(current));
441
442         _viewTab->removeTab(current);
443         delete tab;
444
445         checkActions();
446 }
447
448 void GUI::tabChanged(int current)
449 {
450         if (current == -1) {
451                 _fileName->setText(QString::null);
452                 _zoom->setText(QString::null);
453                 return;
454         }
455
456         GraphTab *tab = (GraphTab*) _viewTab->widget(current);
457
458         getSAProperties(tab);
459         getGraphProperties(tab);
460         getMiscProperties(tab);
461
462         _zoom->setText(ZOOM_STRING(tab->view()->zoom()));
463         _fileName->setText(tab->fileName());
464 }
465
466 void GUI::about()
467 {
468         QMessageBox::about(this, tr("About Hypercube"),
469           QString("<h3>") + QString("Hypercube ") + QString(APP_VERSION)
470           + QString("</h3><p>") + tr("Graph visualizing tool") + QString("<p/>")
471           + QString("<p>") + tr("Hypercube is distributed under the terms of the "
472                 "GNU General Public License version 3. For more info about Hypercube "
473                 "visit the project homepage at")
474           + QString(" <a href=\""APP_HOMEPAGE"\">"APP_HOMEPAGE"</a>.</p>"));
475 }
476
477 void GUI::openFile()
478 {
479         QStringList files = QFileDialog::getOpenFileNames(this, tr("Open file"));
480         QStringList list = files;
481         QStringList::Iterator it = list.begin();
482
483         while(it != list.end()) {
484                 openFile(*it);
485                 ++it;
486         }
487 }
488
489 void GUI::openFile(const QString &fileName)
490 {
491         GraphTab *tab = new GraphTab();
492
493         setSAProperties(tab);
494         setGraphProperties(tab);
495         setMiscProperties(tab);
496
497         IO::ioerr.str("");
498         IO::Error error = tab->readGraph(fileName);
499
500         if (error) {
501                 std::cerr << IO::ioerr.str();
502                 QMessageBox::critical(this, tr("Error"),
503                   fileName + QString("\n\n")
504                   + tr("Error loading graph") + QString(":\n")
505                   + errorDescription(error));
506                 delete tab;
507         } else {
508                 tab->transformGraph();
509
510                 QFileInfo fi(fileName);
511                 int index = _viewTab->addTab(tab, fi.fileName());
512
513                 connect(tab->view(), SIGNAL(zoomed(qreal)), SLOT(zoom(qreal)));
514
515                 _viewTab->setCurrentIndex(index);
516
517                 int cnt = _viewTab->count();
518                 if (cnt == 1) {
519                         _fileActionGroup->setEnabled(true);
520                         _graphActionGroup->setEnabled(true);
521                 } else if (cnt == 2)
522                         _projectActionGroup->setEnabled(true);
523         }
524 }
525
526 void GUI::saveFile()
527 {
528         if (TAB()->writeGraph() != IO::Ok)
529                 emit saveAs();
530 }
531
532 void GUI::saveAs()
533 {
534         QString filter,  selectedFilter;
535         OutputProvider **provider = outputProviders;
536
537         while (*provider) {
538                 filter += saveFilter(*provider);
539                 provider++;
540                 if (*provider)
541                         filter += QString(";;");
542         }
543
544         QString fileName = QFileDialog::getSaveFileName(this,
545           tr("Save file"), QString::null, filter, &selectedFilter);
546         if (!fileName.isEmpty()) {
547                 provider = outputProviders;
548                 while (*provider) {
549                         if (selectedFilter == saveFilter(*provider))
550                                 break;
551                         provider++;
552                 }
553
554                 QString suffix = QString('.') + QString((*provider)->type());
555                 if (!fileName.endsWith(suffix))
556                         fileName.append(suffix);
557
558                 IO::ioerr.str("");
559                 IO::Error error = TAB()->writeGraph(fileName, *provider);
560                 if (error) {
561                         std::cerr << IO::ioerr.str();
562                         QMessageBox::critical(this, tr("Error"),
563                           fileName + QString("\n\n")
564                           + tr("Error saving graph") + QString(":\n")
565                           + errorDescription(error));
566                 }
567         }
568 }
569
570 void GUI::saveAll()
571 {
572         int index = _viewTab->currentIndex();
573
574         for (int i = 0; i < _viewTab->count(); i++) {
575                 _viewTab->setCurrentIndex(i);
576                 saveFile();
577         }
578
579         _viewTab->setCurrentIndex(index);
580 }
581
582 void GUI::closeFile()
583 {
584         GraphTab* tab = TAB();
585
586         _viewTab->removeTab(_viewTab->indexOf(tab));
587         delete tab;
588
589         checkActions();
590 }
591
592 void GUI::transformGraph()
593 {
594         TAB()->transformGraph();
595 }
596
597 void GUI::reloadGraph()
598 {
599         IO::ioerr.str("");
600         IO::Error error = TAB()->readGraph();
601         if (error) {
602                 std::cerr << IO::ioerr.str();
603                 QMessageBox::critical(this, tr("Error"),
604                   tr("Error loading graph") + QString(":\n")
605                   + errorDescription(error));
606                 closeFile();
607         }
608 }
609
610 void GUI::bindGraph()
611 {
612         GraphTab* tab;
613
614         for (int i = 0; i < _viewTab->count(); i++) {
615                 if (_viewTab->currentIndex() == i)
616                         continue;
617                 tab = ((GraphTab*) _viewTab->widget(i));
618                 tab->bindTo(TAB()->graph());
619         }
620 }
621
622 void GUI::projectGraph()
623 {
624         GraphTab* tab;
625
626         for (int i = 0; i < _viewTab->count(); i++) {
627                 if (_viewTab->currentIndex() == i)
628                         continue;
629                 tab = ((GraphTab*) _viewTab->widget(i));
630                 tab->project(TAB()->graph());
631         }
632 }
633
634
635 void GUI::setNodeDistribution(float value)
636 {
637         if (TAB())
638                 TAB()->setNodeDistribution(value);
639         getArguments();
640 }
641
642 void GUI::setEdgeLength(float value)
643 {
644         if (TAB())
645                 TAB()->setEdgeLength(value);
646         getArguments();
647 }
648
649 void GUI::setEdgeCrossings(float value)
650 {
651         if (TAB())
652                 TAB()->setEdgeCrossings(value);
653         getArguments();
654 }
655
656 void GUI::setInitTemp(float value)
657 {
658         if (TAB())
659                 TAB()->setInitTemp(value);
660         getArguments();
661 }
662
663 void GUI::setFinalTemp(float value)
664 {
665         if (TAB())
666                 TAB()->setFinalTemp(value);
667         getArguments();
668 }
669
670 void GUI::setCoolFactor(float value)
671 {
672         if (TAB())
673                 TAB()->setCoolFactor(value);
674         getArguments();
675 }
676
677 void GUI::setNumSteps(int value)
678 {
679         if (TAB())
680                 TAB()->setNumSteps(value);
681         getArguments();
682 }
683
684 #ifdef SA_LOG_SUPPORT
685 void GUI::setSALogInfo(int state)
686 {
687         if (TAB())
688                 TAB()->setLogInfo((state == Qt::Checked) ? true : false);
689 }
690 #endif
691
692 void GUI::setGraphWidth(int width)
693 {
694         if (TAB())
695                 TAB()->setDimensions(QPoint(width, TAB()->dimensions().y()));
696         getArguments();
697 }
698
699 void GUI::setGraphHeight(int height)
700 {
701         if (TAB())
702                 TAB()->setDimensions(QPoint(TAB()->dimensions().x(), height));
703         getArguments();
704 }
705
706 void GUI::setVertexColor(const QColor &color)
707 {
708         if (TAB())
709                 TAB()->setVertexColor(color);
710         getArguments();
711 }
712
713 void GUI::setEdgeColor(const QColor &color)
714 {
715         if (TAB())
716                 TAB()->setEdgeColor(color);
717         getArguments();
718 }
719
720 void GUI::setVertexSize(int size)
721 {
722         if (TAB())
723                 TAB()->setVertexSize(size);
724         _edgeSize->setMaximum(size);
725         getArguments();
726 }
727
728 void GUI::setEdgeSize(int size)
729 {
730         if (TAB())
731                 TAB()->setEdgeSize(size);
732         getArguments();
733 }
734
735 void GUI::setEdgeFontSize(int size)
736 {
737         if (TAB())
738                 TAB()->setEdgeFontSize(size);
739         getArguments();
740 }
741
742 void GUI::setVertexFontSize(int size)
743 {
744         if (TAB())
745                 TAB()->setVertexFontSize(size);
746         getArguments();
747 }
748
749 void GUI::showEdgeValues(int state)
750 {
751         if (TAB())
752                 TAB()->showEdgeValues((state == Qt::Checked) ? true : false);
753         getArguments();
754 }
755
756 void GUI::showVertexIDs(int state)
757 {
758         if (TAB())
759                 TAB()->showVertexIDs((state == Qt::Checked) ? true : false);
760         getArguments();
761 }
762
763 void GUI::directGraph(int state)
764 {
765         if (TAB())
766                 TAB()->setDirectedGraph((state == Qt::Checked) ? true : false);
767         getArguments();
768 }
769
770 void GUI::colorizeEdges(int state)
771 {
772         if (TAB())
773                 TAB()->colorizeEdges((state == Qt::Checked) ? true : false);
774         _edgeColor->setEnabled((state == Qt::Checked) ? false : true);
775         getArguments();
776 }
777
778 void GUI::setInputEncoding(int index)
779 {
780         if (TAB())
781                 TAB()->setInputEncoding(*(encodings + index));
782         getArguments();
783 }
784
785 void GUI::setAntialiasing(int state)
786 {
787         if (TAB())
788                 TAB()->setAntialiasing((state == Qt::Checked) ? true : false);
789 }
790
791 void GUI::setSpecialsEscaping()
792 {
793         getArguments();
794 }
795
796
797 void GUI::setMiscProperties(GraphTab *tab)
798 {
799         Encoding* encoding = *(encodings + _inputEncoding->currentIndex());
800
801         tab->setInputEncoding(encoding);
802         tab->setAntialiasing((_antialiasing->checkState() == Qt::Checked)
803           ? true : false);
804 }
805
806 void GUI::setSAProperties(GraphTab *tab)
807 {
808         tab->setNodeDistribution(_nodeDistribution->value());
809         tab->setEdgeLength(_edgeLength->value());
810         tab->setEdgeCrossings(_edgeCrossings->value());
811         tab->setInitTemp(_initTemp->value());
812         tab->setFinalTemp(_finalTemp->value());
813         tab->setCoolFactor(_coolFactor->value());
814         tab->setNumSteps(_numSteps->value());
815 #ifdef SA_LOG_SUPPORT
816         tab->setLogInfo((_debug->checkState() == Qt::Checked) ? true : false);
817 #endif
818 }
819
820 void GUI::setGraphProperties(GraphTab *tab)
821 {
822         tab->showVertexIDs((_vertexIDs->checkState() == Qt::Checked)
823           ? true : false);
824         tab->showEdgeValues((_edgeValues->checkState() == Qt::Checked)
825           ? true : false);
826         tab->colorizeEdges((_coloredEdges->checkState() == Qt::Checked)
827           ? true : false);
828         tab->setDirectedGraph((_directedGraph->checkState() == Qt::Checked)
829           ? true : false);
830         tab->setDimensions(QPoint(_graphWidth->value(), _graphHeight->value()));
831         tab->setEdgeSize(_edgeSize->value());
832         tab->setVertexSize(_vertexSize->value());
833         tab->setEdgeColor(_edgeColor->color());
834         tab->setVertexColor(_vertexColor->color());
835         tab->setVertexFontSize(_vertexFontSize->value());
836         tab->setEdgeFontSize(_edgeFontSize->value());
837 }
838
839 void GUI::getArguments()
840 {
841         QString args;
842         int ef, vf;
843
844         ef = _edgeValues->checkState() ? _edgeFontSize->value() : 0;
845         vf = _vertexIDs->checkState() ? _vertexFontSize->value() : 0;
846
847         if (_graphWidth->value() != GRAPH_WIDTH
848           || _graphHeight->value() != GRAPH_HEIGHT)
849                 args.append(QString(" -s %1,%2").arg(_graphWidth->value())
850                   .arg(_graphHeight->value()));
851         if (_edgeSize->value() != EDGE_SIZE)
852                 args.append(QString(" -es %1").arg(_edgeSize->value()));
853         if (_vertexSize->value() != VERTEX_SIZE)
854                 args.append(QString(" -vs %1").arg(_vertexSize->value()));
855         if (_edgeColor->isEnabled() && _edgeColor->color() != EDGE_COLOR)
856                 args.append(QString(" -ec %1").arg(_edgeColor->color().name()));
857         if (_vertexColor->color() != VERTEX_COLOR)
858                 args.append(QString(" -vc %1").arg(_vertexColor->color().name()));
859         if (ef != EDGE_FONT_SIZE)
860                 args.append(QString(" -ef %1").arg(ef));
861         if (vf != VERTEX_FONT_SIZE)
862                 args.append(QString(" -vf %1").arg(vf));
863         if (_coloredEdges->checkState())
864                 args.append(QString(" -c"));
865         if (_directedGraph->checkState())
866                 args.append(QString(" -d"));
867
868         if (_nodeDistribution->value() != NODE_DISTRIBUTION)
869                 args.append(QString(" -nd %1").arg(_nodeDistribution->value()));
870         if (_edgeLength->value() != EDGE_LENGTH)
871                 args.append(QString(" -el %1").arg(_edgeLength->value()));
872         if (_edgeCrossings->value() != EDGE_CROSSINGS)
873                 args.append(QString(" -cr %1").arg(_edgeCrossings->value()));
874         if (_initTemp->value() != INIT_TEMP)
875                 args.append(QString(" -it %1").arg(_initTemp->value()));
876         if (_finalTemp->value() != FINAL_TEMP)
877                 args.append(QString(" -ft %1").arg(_finalTemp->value()));
878         if (_coolFactor->value() != COOL_FACTOR)
879                 args.append(QString(" -cf %1").arg(_coolFactor->value()));
880         if (_numSteps->value() != NUM_STEPS)
881                 args.append(QString(" -ns %1").arg(_numSteps->value()));
882
883         if (_inputEncoding->currentIndex() > 0)
884                 args.append(QString(" -e %1").arg(_inputEncoding->itemText(
885                   _inputEncoding->currentIndex())));
886
887         if (_argumentsEscape->isChecked())
888                 args = args.replace("#", "\\#");
889
890         _arguments->setText(args);
891 }
892
893 void GUI::getMiscProperties(GraphTab *tab)
894 {
895         int index = 0;
896
897         for (Encoding **e = encodings; *e; e++, index++)
898                 if (!strcmp((*e)->name(), tab->inputEncoding()->name()))
899                         break;
900
901         BLOCK(_inputEncoding, setCurrentIndex(index));
902         BLOCK(_antialiasing, setChecked(tab->antialiasing()));
903
904         getArguments();
905 }
906
907 void GUI::getSAProperties(GraphTab *tab)
908 {
909         BLOCK(_nodeDistribution, setValue(tab->nodeDistribution()));
910         BLOCK(_edgeLength, setValue(tab->edgeLength()));
911         BLOCK(_edgeCrossings, setValue(tab->edgeCrossings()));
912         BLOCK(_initTemp, setValue(tab->initTemp()));
913         BLOCK(_finalTemp, setValue(tab->finalTemp()));
914         BLOCK(_coolFactor, setValue(tab->coolFactor()));
915         BLOCK(_numSteps, setValue(tab->numSteps()));
916 #ifdef SA_LOG_SUPPORT
917         BLOCK(_debug, setChecked(tab->logInfo()));
918 #endif
919 }
920
921 void GUI::getGraphProperties(GraphTab *tab)
922 {
923         BLOCK(_graphWidth, setValue(tab->dimensions().x()));
924         BLOCK(_graphHeight, setValue(tab->dimensions().y()));
925         BLOCK(_edgeSize, setValue(tab->edgeSize()));
926         BLOCK(_vertexSize, setValue(tab->vertexSize()));
927         BLOCK(_edgeColor, setColor(tab->edgeColor()));
928         BLOCK(_vertexColor, setColor(tab->vertexColor()));
929         BLOCK(_vertexFontSize, setValue(tab->vertexFontSize()));
930         BLOCK(_edgeFontSize, setValue(tab->edgeFontSize()));
931         BLOCK(_vertexIDs, setChecked(tab->vertexIDs()));
932         BLOCK(_edgeValues, setChecked(tab->edgeValues()));
933         BLOCK(_coloredEdges, setChecked(tab->coloredEdges()));
934         BLOCK(_directedGraph, setChecked(tab->directedGraph()));
935
936         _edgeSize->setMaximum(tab->vertexSize());
937         _edgeColor->setEnabled(!tab->coloredEdges());
938 }
939
940 void GUI::zoom(qreal zoom)
941 {
942         _zoom->setText(ZOOM_STRING(zoom));
943 }
944
945 void GUI::writeSettings()
946 {
947         QSettings settings(ORGANIZATION, APPLICATION);
948
949         settings.beginGroup(WINDOW_GROUP);
950         settings.setValue(WINDOW_SIZE_SETTING, size());
951         settings.setValue(WINDOW_POSITION_SETTING, pos());
952         settings.endGroup();
953
954         settings.beginGroup(GRAPH_GROUP);
955         settings.setValue(GRAPH_WIDTH_SETTING, _graphWidth->value());
956         settings.setValue(GRAPH_HEIGHT_SETTING, _graphHeight->value());
957         settings.setValue(EDGE_VALUES_SETTING, _edgeValues->checkState());
958         settings.setValue(VERTEX_IDS_SETTING, _vertexIDs->checkState());
959         settings.setValue(COLORED_EDGES_SETTING, _coloredEdges->checkState());
960         settings.setValue(DIRECTED_GRAPH_SETTING, _directedGraph->checkState());
961         settings.setValue(EDGE_SIZE_SETTING, _edgeSize->value());
962         settings.setValue(VERTEX_SIZE_SETTING, _vertexSize->value());
963         settings.setValue(EDGE_FONT_SIZE_SETTING, _edgeFontSize->value());
964         settings.setValue(VERTEX_FONT_SIZE_SETTING, _vertexFontSize->value());
965         settings.setValue(EDGE_COLOR_SETTING, _edgeColor->color());
966         settings.setValue(VERTEX_COLOR_SETTING, _vertexColor->color());
967         settings.endGroup();
968
969         settings.beginGroup(ALGORITHM_GROUP);
970         settings.setValue(NODE_DISTRIBUTION_SETTING, _nodeDistribution->value());
971         settings.setValue(EDGE_LENGTH_SETTING, _edgeLength->value());
972         settings.setValue(EDGE_CROSSINGS_SETTING, _edgeCrossings->value());
973         settings.setValue(INIT_TEMP_SETTING, _initTemp->value());
974         settings.setValue(FINAL_TEMP_SETTING, _finalTemp->value());
975         settings.setValue(COOL_FACTOR_SETTING, _coolFactor->value());
976         settings.setValue(NUM_STEPS_SETTING, _numSteps->value());
977         settings.endGroup();
978
979         settings.beginGroup(MISC_GROUP);
980         settings.setValue(INPUT_ENCODING_SETTING, _inputEncoding->currentText());
981         settings.setValue(ANTIALIASING_SETTING, _antialiasing->checkState());
982         settings.setValue(ESCAPE_SPECIALS_SETTING, _argumentsEscape->checkState());
983         settings.endGroup();
984 }
985
986 void GUI::readSettings()
987 {
988         QSettings settings(ORGANIZATION, APPLICATION);
989
990         settings.beginGroup(WINDOW_GROUP);
991         resize(settings.value(WINDOW_SIZE_SETTING, QSize(800, 600)).toSize());
992         move(settings.value(WINDOW_POSITION_SETTING, QPoint(100, 100)).toPoint());
993         settings.endGroup();
994
995         settings.beginGroup(GRAPH_GROUP);
996         _graphWidth->setValue(settings.value(GRAPH_WIDTH_SETTING,
997           GRAPH_WIDTH).toInt());
998         _graphHeight->setValue(settings.value(GRAPH_HEIGHT_SETTING,
999           GRAPH_HEIGHT).toInt());
1000         _vertexIDs->setCheckState((Qt::CheckState)settings.value(
1001           VERTEX_IDS_SETTING, Qt::Checked).toInt());
1002         _edgeValues->setCheckState((Qt::CheckState)settings.value(
1003           EDGE_VALUES_SETTING, Qt::Unchecked).toInt());
1004         _coloredEdges->setCheckState((Qt::CheckState)settings.value(
1005           COLORED_EDGES_SETTING, Qt::Unchecked).toInt());
1006         _directedGraph->setCheckState((Qt::CheckState)settings.value(
1007           DIRECTED_GRAPH_SETTING, Qt::Unchecked).toInt());
1008         _vertexSize->setValue(settings.value(VERTEX_SIZE_SETTING,
1009           VERTEX_SIZE).toInt());
1010         _edgeSize->setValue(settings.value(EDGE_SIZE_SETTING, EDGE_SIZE).toInt());
1011         _edgeSize->setMaximum(_vertexSize->value());
1012         _edgeFontSize->setValue(settings.value(EDGE_FONT_SIZE_SETTING,
1013           EDGE_FONT_SIZE).toInt());
1014         _vertexFontSize->setValue(settings.value(VERTEX_FONT_SIZE_SETTING,
1015           VERTEX_FONT_SIZE).toInt());
1016         _edgeColor->setColor(settings.value(EDGE_COLOR_SETTING,
1017           QColor(EDGE_COLOR)).value<QColor>());
1018         _vertexColor->setColor(settings.value(VERTEX_COLOR_SETTING,
1019           QColor(VERTEX_COLOR)).value<QColor>());
1020         settings.endGroup();
1021
1022         settings.beginGroup(ALGORITHM_GROUP);
1023         _nodeDistribution->setValue(settings.value(NODE_DISTRIBUTION_SETTING,
1024           NODE_DISTRIBUTION).toFloat());
1025         _edgeLength->setValue(settings.value(EDGE_LENGTH_SETTING,
1026           EDGE_LENGTH).toFloat());
1027         _edgeCrossings->setValue(settings.value(EDGE_CROSSINGS_SETTING,
1028           EDGE_CROSSINGS).toFloat());
1029         _initTemp->setValue(settings.value(INIT_TEMP_SETTING, INIT_TEMP).toFloat());
1030         _finalTemp->setValue(settings.value(FINAL_TEMP_SETTING,
1031           FINAL_TEMP).toFloat());
1032         _coolFactor->setValue(settings.value(COOL_FACTOR_SETTING,
1033           COOL_FACTOR).toFloat());
1034         _numSteps->setValue(settings.value(NUM_STEPS_SETTING, NUM_STEPS).toInt());
1035         settings.endGroup();
1036
1037         settings.beginGroup(MISC_GROUP);
1038         int index = 0;
1039         QString ie = settings.value(INPUT_ENCODING_SETTING,
1040           (*encodings)->name()).toString();
1041         for (Encoding **ep = encodings; *ep; ep++, index++) {
1042                 if (!strcmp((*ep)->name(), ie.toAscii().constData())) {
1043                         _inputEncoding->setCurrentIndex(index);
1044                         break;
1045                 }
1046         }
1047         _antialiasing->setChecked((Qt::CheckState)settings.value(
1048           ANTIALIASING_SETTING, Qt::Unchecked).toBool());
1049         _argumentsEscape->setChecked((Qt::CheckState)settings.value(
1050           ESCAPE_SPECIALS_SETTING, Qt::Unchecked).toBool());
1051         settings.endGroup();
1052 }
1053
1054 void GUI::closeEvent(QCloseEvent *event)
1055 {
1056         writeSettings();
1057         event->accept();
1058 }
1059
1060
1061 QString saveFilter(OutputProvider *provider)
1062 {
1063         return QString(provider->description()) + QString(" (*.")
1064           + QString(provider->type()) + QString(")");
1065 }
1066
1067 QString errorDescription(IO::Error error)
1068 {
1069         switch(error) {
1070                 case IO::OpenError:
1071                         return  QObject::tr("Error opening file");
1072                 case IO::ReadError:
1073                         return QObject::tr("Error reading file");
1074                 case IO::WriteError:
1075                         return QObject::tr("Error writing file");
1076                 case IO::FormatError:
1077                         return QObject::tr("File format error");
1078                 default:
1079                         return QObject::tr("Unknown error");
1080         }
1081 }