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