Implement Moreland diverging color maps.
[gencolormap.git] / gui.cpp
1 /*
2  * Copyright (C) 2015, 2016 Computer Graphics Group, University of Siegen
3  * Written by Martin Lambers <martin.lambers@uni-siegen.de>
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  */
23
24 #include "gui.hpp"
25
26 #include <QApplication>
27 #include <QGuiApplication>
28 #include <QGridLayout>
29 #include <QTabWidget>
30 #include <QLabel>
31 #include <QMenu>
32 #include <QMenuBar>
33 #include <QFileDialog>
34 #include <QClipboard>
35 #include <QTextStream>
36 #include <QMessageBox>
37
38 #include "colormapwidgets.hpp"
39
40
41 GUI::GUI()
42 {
43     setWindowTitle("Generate Color Map");
44     setWindowIcon(QIcon(":cg-logo.png"));
45
46     _brewerseq_widget = new ColorMapBrewerSequentialWidget;
47     _brewerdiv_widget = new ColorMapBrewerDivergingWidget;
48     _brewerqual_widget = new ColorMapBrewerQualitativeWidget;
49     _cubehelix_widget = new ColorMapCubeHelixWidget;
50     _morelanddiv_widget = new ColorMapMorelandDivergingWidget;
51     connect(_brewerseq_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
52     connect(_brewerdiv_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
53     connect(_brewerqual_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
54     connect(_cubehelix_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
55     connect(_morelanddiv_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
56
57     QWidget *widget = new QWidget;
58     widget->setMinimumWidth(384 * qApp->devicePixelRatio());
59     QGridLayout *layout = new QGridLayout;
60
61     _tab_widget = new QTabWidget();
62     _tab_widget->addTab(_brewerseq_widget,   "Brewer-like Sequential");
63     _tab_widget->addTab(_brewerdiv_widget,   "Brewer-like Diverging");
64     _tab_widget->addTab(_brewerqual_widget,  "Brewer-like Qualitative");
65     _tab_widget->addTab(_cubehelix_widget,   "CubeHelix");
66     _tab_widget->addTab(_morelanddiv_widget, "Moreland Diverging");
67     connect(_tab_widget, SIGNAL(currentChanged(int)), this, SLOT(update()));
68     layout->addWidget(_tab_widget, 0, 0);
69     layout->addItem(new QSpacerItem(0, 0), 1, 0);
70     _reference_label = new QLabel(_brewerseq_widget->reference());
71     _reference_label->setWordWrap(true);
72     _reference_label->setOpenExternalLinks(true);
73     layout->addWidget(_reference_label, 2, 0);
74
75     _colormap_label = new QLabel();
76     _colormap_label->setScaledContents(true);
77     layout->addWidget(_colormap_label, 0, 1, 3, 1);
78
79     layout->setColumnStretch(0, 1);
80     layout->setRowStretch(1, 1);
81     widget->setLayout(layout);
82     setCentralWidget(widget);
83
84     QMenu* file_menu = menuBar()->addMenu("&File");
85     QAction* file_export_png_act = new QAction("Export as &PNG...", this);
86     connect(file_export_png_act, SIGNAL(triggered()), this, SLOT(file_export_png()));
87     file_menu->addAction(file_export_png_act);
88     QAction* file_export_csv_act = new QAction("Export as &CSV...", this);
89     connect(file_export_csv_act, SIGNAL(triggered()), this, SLOT(file_export_csv()));
90     file_menu->addAction(file_export_csv_act);
91     file_menu->addSeparator();
92     QAction* quit_act = new QAction("&Quit...", this);
93     quit_act->setShortcut(QKeySequence::Quit);
94     connect(quit_act, SIGNAL(triggered()), this, SLOT(close()));
95     file_menu->addAction(quit_act);
96     QMenu* edit_menu = menuBar()->addMenu("&Edit");
97     QAction* edit_reset_act = new QAction("&Reset", this);
98     connect(edit_reset_act, SIGNAL(triggered()), this, SLOT(edit_reset()));
99     edit_menu->addAction(edit_reset_act);
100     QAction* edit_copy_as_img_act = new QAction("Copy as &image", this);
101     connect(edit_copy_as_img_act, SIGNAL(triggered()), this, SLOT(edit_copy_as_img()));
102     edit_menu->addAction(edit_copy_as_img_act);
103     QAction* edit_copy_as_txt_act = new QAction("Copy as &text", this);
104     connect(edit_copy_as_txt_act, SIGNAL(triggered()), this, SLOT(edit_copy_as_txt()));
105     edit_copy_as_txt_act->setShortcut(QKeySequence::Copy);
106     edit_menu->addAction(edit_copy_as_txt_act);
107     QMenu* help_menu = menuBar()->addMenu("&Help");
108     QAction* help_about_act = new QAction("&About", this);
109     connect(help_about_act, SIGNAL(triggered()), this, SLOT(help_about()));
110     help_menu->addAction(help_about_act);
111
112     show();
113     update();
114 }
115
116 GUI::~GUI()
117 {
118 }
119
120 void GUI::update()
121 {
122     ColorMapWidget* currentWidget = reinterpret_cast<ColorMapWidget*>(_tab_widget->currentWidget());
123     _reference_label->setText(currentWidget->reference());
124     _colormap_label->setPixmap(QPixmap::fromImage(currentWidget->colorMapImage(32, _colormap_label->height())));
125 }
126
127 void GUI::file_export_png()
128 {
129     QString name = QFileDialog::getSaveFileName();
130     if (!name.isEmpty()) {
131         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
132         ColorMapWidget* currentWidget = reinterpret_cast<ColorMapWidget*>(_tab_widget->currentWidget());
133         currentWidget->colorMapImage(0, 1).save(name, "png");
134         QApplication::restoreOverrideCursor();
135     }
136 }
137
138 void GUI::file_export_csv()
139 {
140     QString name = QFileDialog::getSaveFileName();
141     if (!name.isEmpty()) {
142         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
143         QFile file(name);
144         if (file.open(QIODevice::ReadWrite)) {
145             ColorMapWidget* currentWidget = reinterpret_cast<ColorMapWidget*>(_tab_widget->currentWidget());
146             QVector<QColor> colormap = currentWidget->colorMap();
147             QTextStream stream(&file);
148             for (int i = 0; i < colormap.size(); i++) {
149                 stream << colormap[i].red()   << ", "
150                        << colormap[i].green() << ", "
151                        << colormap[i].blue()  << endl;
152             }
153         }
154         QApplication::restoreOverrideCursor();
155     }
156 }
157
158 void GUI::edit_reset()
159 {
160     ColorMapWidget* currentWidget = reinterpret_cast<ColorMapWidget*>(_tab_widget->currentWidget());
161     currentWidget->reset();
162 }
163
164 void GUI::edit_copy_as_img()
165 {
166     ColorMapWidget* currentWidget = reinterpret_cast<ColorMapWidget*>(_tab_widget->currentWidget());
167     QApplication::clipboard()->setImage(currentWidget->colorMapImage(0, 1));
168 }
169
170 void GUI::edit_copy_as_txt()
171 {
172     ColorMapWidget* currentWidget = reinterpret_cast<ColorMapWidget*>(_tab_widget->currentWidget());
173     QVector<QColor> colormap = currentWidget->colorMap();
174     QString string;
175     QTextStream stream(&string);
176     for (int i = 0; i < colormap.size() / 3; i++) {
177         stream << colormap[i].red()   << ", "
178                << colormap[i].green() << ", "
179                << colormap[i].blue()  << endl;
180     }
181     QApplication::clipboard()->setText(string);
182 }
183
184 void GUI::help_about()
185 {
186     QMessageBox::about(this, "About",
187                 "<p>gencolormap version 0.2</p>"
188                 "<p>Copyright (C) 2016<br>"
189                 "   <a href=\"http://www.cg.informatik.uni-siegen.de/\">"
190                 "   Computer Graphics Group, University of Siegen</a>.<br>"
191                 "   Written by <a href=\"http://www.cg.informatik.uni-siegen.de/lambers-martin\">Martin Lambers</a>.<br>"
192                 "   This is free software under the terms of the "
193                     "<a href=\"https://www.debian.org/legal/licenses/mit\">MIT/Expat License</a>. "
194                 "   There is NO WARRANTY, to the extent permitted by law."
195                 "</p>");
196 }
197
198 int main(int argc, char* argv[])
199 {
200     QApplication app(argc, argv);
201     GUI gui;
202     gui.show();
203     return app.exec();
204 }