Change black body color map to use linear lightness and saturation.
[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     _isolumseq_widget = new ColorMapIsoluminantSequentialWidget;
50     _isolumdiv_widget = new ColorMapIsoluminantDivergingWidget;
51     _isolumqual_widget = new ColorMapIsoluminantQualitativeWidget;
52     _unirainbow_widget = new ColorMapUniformRainbowWidget;
53     _blackbody_widget = new ColorMapBlackBodyWidget;
54     _cubehelix_widget = new ColorMapCubeHelixWidget;
55     _moreland_widget = new ColorMapMorelandWidget;
56     _mcnames_widget = new ColorMapMcNamesWidget;
57     connect(_brewerseq_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
58     connect(_brewerdiv_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
59     connect(_brewerqual_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
60     connect(_isolumseq_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
61     connect(_isolumdiv_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
62     connect(_isolumqual_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
63     connect(_unirainbow_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
64     connect(_blackbody_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
65     connect(_cubehelix_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
66     connect(_moreland_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
67     connect(_mcnames_widget, SIGNAL(colorMapChanged()), this, SLOT(update()));
68
69     QWidget *widget = new QWidget;
70     widget->setMinimumWidth(384 * qApp->devicePixelRatio());
71     QGridLayout *layout = new QGridLayout;
72
73     _category_widget = new QTabWidget();
74     _category_seq_widget = new QTabWidget();
75     _category_seq_widget->addTab(_brewerseq_widget, "Brewer-like");
76     _category_seq_widget->addTab(_isolumseq_widget, "Isoluminant");
77     _category_seq_widget->addTab(_blackbody_widget, "Black Body");
78     _category_seq_widget->addTab(_unirainbow_widget, "Uniform Rainbow");
79     _category_seq_widget->addTab(_cubehelix_widget, "CubeHelix");
80     //_category_seq_widget->addTab(_mcnames_widget, "McNames");
81     connect(_category_seq_widget, SIGNAL(currentChanged(int)), this, SLOT(update()));
82     _category_widget->addTab(_category_seq_widget, "Sequential");
83     _category_div_widget = new QTabWidget();
84     _category_div_widget->addTab(_brewerdiv_widget, "Brewer-like");
85     _category_div_widget->addTab(_isolumdiv_widget, "Isoluminant");
86     _category_div_widget->addTab(_moreland_widget, "Moreland");
87     connect(_category_div_widget, SIGNAL(currentChanged(int)), this, SLOT(update()));
88     _category_widget->addTab(_category_div_widget, "Diverging");
89     _category_qual_widget = new QTabWidget();
90     _category_qual_widget->addTab(_brewerqual_widget, "Brewer-like");
91     _category_qual_widget->addTab(_isolumqual_widget, "Isoluminant");
92     connect(_category_qual_widget, SIGNAL(currentChanged(int)), this, SLOT(update()));
93     _category_widget->addTab(_category_qual_widget, "Qualitative");
94     connect(_category_widget, SIGNAL(currentChanged(int)), this, SLOT(update()));
95     layout->addWidget(_category_widget, 0, 0);
96     layout->addItem(new QSpacerItem(0, 0), 1, 0);
97     _reference_label = new QLabel(_brewerseq_widget->reference());
98     _reference_label->setWordWrap(true);
99     _reference_label->setOpenExternalLinks(true);
100     layout->addWidget(_reference_label, 2, 0);
101
102     _colormap_label = new QLabel();
103     _colormap_label->setScaledContents(true);
104     layout->addWidget(_colormap_label, 0, 1, 3, 1);
105
106     layout->setColumnStretch(0, 1);
107     layout->setRowStretch(1, 1);
108     widget->setLayout(layout);
109     setCentralWidget(widget);
110
111     QMenu* file_menu = menuBar()->addMenu("&File");
112     QAction* file_export_png_act = new QAction("Export as &PNG...", this);
113     connect(file_export_png_act, SIGNAL(triggered()), this, SLOT(file_export_png()));
114     file_menu->addAction(file_export_png_act);
115     QAction* file_export_csv_act = new QAction("Export as &CSV...", this);
116     connect(file_export_csv_act, SIGNAL(triggered()), this, SLOT(file_export_csv()));
117     file_menu->addAction(file_export_csv_act);
118     file_menu->addSeparator();
119     QAction* quit_act = new QAction("&Quit...", this);
120     quit_act->setShortcut(QKeySequence::Quit);
121     connect(quit_act, SIGNAL(triggered()), this, SLOT(close()));
122     file_menu->addAction(quit_act);
123     QMenu* edit_menu = menuBar()->addMenu("&Edit");
124     QAction* edit_reset_act = new QAction("&Reset", this);
125     connect(edit_reset_act, SIGNAL(triggered()), this, SLOT(edit_reset()));
126     edit_menu->addAction(edit_reset_act);
127     QAction* edit_copy_as_img_act = new QAction("Copy as &image", this);
128     connect(edit_copy_as_img_act, SIGNAL(triggered()), this, SLOT(edit_copy_as_img()));
129     edit_menu->addAction(edit_copy_as_img_act);
130     QAction* edit_copy_as_txt_act = new QAction("Copy as &text", this);
131     connect(edit_copy_as_txt_act, SIGNAL(triggered()), this, SLOT(edit_copy_as_txt()));
132     edit_copy_as_txt_act->setShortcut(QKeySequence::Copy);
133     edit_menu->addAction(edit_copy_as_txt_act);
134     QMenu* help_menu = menuBar()->addMenu("&Help");
135     QAction* help_about_act = new QAction("&About", this);
136     connect(help_about_act, SIGNAL(triggered()), this, SLOT(help_about()));
137     help_menu->addAction(help_about_act);
138
139     show();
140     update();
141 }
142
143 GUI::~GUI()
144 {
145 }
146
147 ColorMapWidget* GUI::currentWidget()
148 {
149     QTabWidget* tw = reinterpret_cast<QTabWidget*>(_category_widget->currentWidget());
150     return reinterpret_cast<ColorMapWidget*>(tw->currentWidget());
151 }
152
153 void GUI::update()
154 {
155     _reference_label->setText(currentWidget()->reference());
156     _colormap_label->setPixmap(QPixmap::fromImage(currentWidget()->colorMapImage(32, _colormap_label->height())));
157 }
158
159 void GUI::file_export_png()
160 {
161     QString name = QFileDialog::getSaveFileName();
162     if (!name.isEmpty()) {
163         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
164         currentWidget()->colorMapImage(0, 1).save(name, "png");
165         QApplication::restoreOverrideCursor();
166     }
167 }
168
169 void GUI::file_export_csv()
170 {
171     QString name = QFileDialog::getSaveFileName();
172     if (!name.isEmpty()) {
173         QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
174         QFile file(name);
175         if (file.open(QIODevice::WriteOnly)) {
176             QVector<QColor> colormap = currentWidget()->colorMap();
177             QTextStream stream(&file);
178             for (int i = 0; i < colormap.size(); i++) {
179                 stream << colormap[i].red()   << ", "
180                        << colormap[i].green() << ", "
181                        << colormap[i].blue()  << endl;
182             }
183         }
184         QApplication::restoreOverrideCursor();
185     }
186 }
187
188 void GUI::edit_reset()
189 {
190     currentWidget()->reset();
191 }
192
193 void GUI::edit_copy_as_img()
194 {
195     QApplication::clipboard()->setImage(currentWidget()->colorMapImage(0, 1));
196 }
197
198 void GUI::edit_copy_as_txt()
199 {
200     QVector<QColor> colormap = currentWidget()->colorMap();
201     QString string;
202     QTextStream stream(&string);
203     for (int i = 0; i < colormap.size(); i++) {
204         stream << colormap[i].red()   << ", "
205                << colormap[i].green() << ", "
206                << colormap[i].blue()  << endl;
207     }
208     QApplication::clipboard()->setText(string);
209 }
210
211 void GUI::help_about()
212 {
213     QMessageBox::about(this, "About",
214                 "<p>gencolormap version 0.3</p>"
215                 "<p>Copyright (C) 2016<br>"
216                 "   <a href=\"http://www.cg.informatik.uni-siegen.de/\">"
217                 "   Computer Graphics Group, University of Siegen</a>.<br>"
218                 "   Written by <a href=\"http://www.cg.informatik.uni-siegen.de/lambers-martin\">Martin Lambers</a>.<br>"
219                 "   This is free software under the terms of the "
220                     "<a href=\"https://www.debian.org/legal/licenses/mit\">MIT/Expat License</a>. "
221                 "   There is NO WARRANTY, to the extent permitted by law."
222                 "</p>");
223 }
224
225 int main(int argc, char* argv[])
226 {
227     QApplication app(argc, argv);
228     GUI gui;
229     gui.show();
230     return app.exec();
231 }