1 /**
2 * This file is a part of Luminance HDR package.
3 * ----------------------------------------------------------------------
4 * Copyright (C) 2006-2007 Giuseppe Rota
5 * Copyright (C) 2011-2013 Davide Anastasia
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * ----------------------------------------------------------------------
21 *
22 * @author Giuseppe Rota <grota@users.sourceforge.net>
23 * Original Work
24 *
25 * @author Franco Comida <fcomida@users.sourceforge.net>
26 * Improvements, bugfixing
27 *
28 * @author Davide Anastasia <davideanastasia@users.sourceforge.net>
29 * Implementation of the SDI functionalities
30 * New Central Widget based on QTabWidget
31 * Division of the Central Widget using QSplitter
32 *
33 */
34
35 #ifdef QT_DEBUG
36 #include <QDebug>
37 #endif
38
39 #define BOOST_BIND_GLOBAL_PLACEHOLDERS
40
41 #include <QDesktopServices>
42 #include <QDir>
43 #include <QFileDialog>
44 #include <QFileInfo>
45 #include <QMessageBox>
46 #include <QMimeData>
47 #include <QSignalMapper>
48 #include <QString>
49 #include <QTextStream>
50 #include <QTimer>
51 #include <QWhatsThis>
52 #include <QtConcurrentRun>
53
54 #include <boost/bind.hpp>
55
56 #include "MainWindow/ui_MainWindow.h"
57
58 #include <MainWindow/DnDOption.h>
59 #include <MainWindow/DonationDialog.h>
60 #include <MainWindow/MainWindow.h>
61 #include <MainWindow/UpdateChecker.h>
62
63 #include <Fileformat/pfsoutldrimage.h>
64 #include <Libpfs/frame.h>
65 #include <Libpfs/manip/copy.h>
66 #include <Libpfs/manip/cut.h>
67 #include <Libpfs/manip/gamma_levels.h>
68 #include <Libpfs/manip/rotate.h>
69 #include <Libpfs/params.h>
70
71 #include <Common/CommonFunctions.h>
72 #include <Common/archs.h>
73 #include <Common/config.h>
74 #include <Common/global.h>
75
76 #include <OsIntegration/osintegration.h>
77
78 #include <BatchHDR/BatchHDRDialog.h>
79 #include <BatchTM/BatchTMDialog.h>
80
81 #include <TransplantExif/TransplantExifDialog.h>
82 #include <Viewers/HdrViewer.h>
83 #include <Viewers/LdrViewer.h>
84 #include <Viewers/LuminanceRangeWidget.h>
85
86 #include <UI/ExportToHtmlDialog.h>
87 #include <UI/GammaAndLevels.h>
88 #include <UI/ImageQualityDialog.h>
89 #include <UI/SupportedCamerasDialog.h>
90 #include <UI/TiffModeDialog.h>
91 #include <UI/UMessageBox.h>
92
93 #ifdef HAVE_CFITSIO
94 #include <UI/FitsImporter.h>
95 #endif
96
97 #include <Core/IOWorker.h>
98 #include <Core/TMWorker.h>
99 #include <HdrWizard/AutoAntighosting.h>
100 #include <HdrWizard/HdrWizard.h>
101 #include <HdrWizard/WhiteBalance.h>
102 #ifdef WITH_HELPBROWSER
103 #include <HelpBrowser/helpbrowser.h>
104 #endif
105 #include <LibpfsAdditions/formathelper.h>
106 #include <Preferences/PreferencesDialog.h>
107 #include <PreviewPanel/PreviewPanel.h>
108 #include <Projection/ProjectionsDialog.h>
109 #include <Resize/ResizeDialog.h>
110 #include <TonemappingPanel/TMOProgressIndicator.h>
111 #include <TonemappingPanel/TonemappingPanel.h>
112
113 namespace {
getLdrFileNameFromSaveDialog(const QString & suggestedFileName,QWidget * parent=0)114 QString getLdrFileNameFromSaveDialog(const QString &suggestedFileName,
115 QWidget *parent = 0) {
116 QString filetypes = QObject::tr("All LDR formats");
117 filetypes += QLatin1String(
118 " (*.jpg *.jpeg *.png *.ppm *.pbm *.bmp *.JPG *.JPEG *.PNG *.PPM *.PBM "
119 "*.BMP);;");
120 filetypes += QLatin1String("JPEG (*.jpg *.jpeg *.JPG *.JPEG);;");
121 filetypes += QLatin1String("PNG (*.png *.PNG);;");
122 filetypes += QLatin1String("PPM PBM (*.ppm *.pbm *.PPM *.PBM);;");
123 filetypes += QLatin1String("BMP (*.bmp *.BMP);;");
124 filetypes += QLatin1String("TIFF (*.tif *.tiff *.TIF *.TIFF)");
125
126 QFileInfo qfi(suggestedFileName);
127 QString outputFilename = QFileDialog::getSaveFileName(
128 parent, QObject::tr("Save the LDR image as..."),
129 LuminanceOptions().getDefaultPathLdrOut() + QDir::separator() +
130 qfi.completeBaseName() + "." + qfi.suffix(),
131 filetypes);
132
133 if (!outputFilename.isEmpty()) {
134 QFileInfo qfi(outputFilename);
135
136 LuminanceOptions().setDefaultPathLdrOut(qfi.path());
137 }
138 return outputFilename;
139 }
140
getHdrFileNameFromSaveDialog(const QString & suggestedFileName,QWidget * parent=0)141 QString getHdrFileNameFromSaveDialog(const QString &suggestedFileName,
142 QWidget *parent = 0) {
143 #ifdef QT_DEBUG
144 qDebug() << "MainWindow::getHdrFileNameFromSaveDialog(" << suggestedFileName
145 << ")";
146 #endif
147
148 QStringList validHdrExtensions;
149 validHdrExtensions << "exr"
150 << "hdr"
151 << "tif"
152 << "tiff"
153 << "pfs";
154
155 QString filetypes = QObject::tr("All HDR formats");
156 filetypes += QLatin1String(
157 " (*.exr *.EXR *.tiff *.TIFF *.hdr *.HDR *.pic *.PIC *.pfs *.PFS);;");
158 filetypes += QLatin1String("OpenEXR (*.exr *.EXR);;");
159 filetypes += QLatin1String("HDR TIFF (*.tiff *.tif *.TIFF *.TIT);;");
160 filetypes += QLatin1String("Radiance RGBE (*.hdr *.pic *.HDR *.PIC);;");
161 filetypes += QLatin1String("PFS Stream (*.pfs *.PFS);;");
162
163 QFileInfo qfi(suggestedFileName);
164
165 QString suffix = qfi.suffix();
166
167 if (suffix.isEmpty()) {
168 suffix = "exr";
169 }
170
171 if (!validHdrExtensions.contains(suffix, Qt::CaseInsensitive)) {
172 suffix = "exr";
173 }
174
175 QString outputFilename = QFileDialog::getSaveFileName(
176 parent, QObject::tr("Save the HDR image as..."),
177 LuminanceOptions().getDefaultPathLdrIn() + QDir::separator() +
178 qfi.completeBaseName() + "." + suffix,
179 filetypes);
180
181 if (!outputFilename.isEmpty()) {
182 QFileInfo qfi(outputFilename);
183
184 LuminanceOptions().setDefaultPathHdrOut(qfi.path());
185 }
186 return outputFilename;
187 }
188
getCropCoords(GenericViewer * gv,int & x_ul,int & y_ul,int & x_br,int & y_br)189 void getCropCoords(GenericViewer *gv, int &x_ul, int &y_ul, int &x_br,
190 int &y_br) {
191 assert(gv != nullptr);
192
193 QRect cropRect = gv->getSelectionRect().normalized();
194 cropRect.getCoords(&x_ul, &y_ul, &x_br, &y_br);
195 }
196
getCurrentViewerMode(const QTabWidget & curr_tab_widget)197 GenericViewer::ViewerMode getCurrentViewerMode(
198 const QTabWidget &curr_tab_widget) {
199 if (curr_tab_widget.count() <= 0) {
200 return GenericViewer::FIT_WINDOW;
201 } else {
202 GenericViewer *g_v = qobject_cast<GenericViewer *>(curr_tab_widget.currentWidget());
203 return g_v->getViewerMode();
204 }
205 }
206 }
207
208 // static members!
209 int MainWindow::sm_NumMainWindows = 0;
210 int MainWindow::sm_counter = 0;
211 QMap<int, MainWindow *> MainWindow::sm_mainWindowMap =
212 QMap<int, MainWindow *>();
213 QScopedPointer<UpdateChecker> MainWindow::sm_updateChecker;
214 #ifdef WITH_HELPBROWSER
215 HelpBrowser *MainWindow::sm_helpBrowser = nullptr;
216 #endif
217
MainWindow(QWidget * parent)218 MainWindow::MainWindow(QWidget *parent)
219 : QMainWindow(parent),
220 m_Ui(new Ui::MainWindow),
221 m_isFullscreenViewer(false),
222 m_exportQueueSize(0),
223 m_interpolationMethod(BilinearInterp),
224 m_firstWindow(0),
225 m_winId(0) {
226 init();
227 }
228
MainWindow(pfs::Frame * curr_frame,const QString & new_file,const QStringList & inputFileNames,bool needSaving,QWidget * parent)229 MainWindow::MainWindow(pfs::Frame *curr_frame, const QString &new_file,
230 const QStringList &inputFileNames, bool needSaving,
231 QWidget *parent)
232 : QMainWindow(parent),
233 m_Ui(new Ui::MainWindow),
234 m_isFullscreenViewer(false),
235 m_exportQueueSize(0),
236 m_interpolationMethod(BilinearInterp),
237 m_firstWindow(0),
238 m_winId(0) {
239 init();
240
241 emit load_success(curr_frame, new_file, inputFileNames, needSaving);
242 }
243
~MainWindow()244 MainWindow::~MainWindow() {
245 }
246
init()247 void MainWindow::init() {
248 sm_NumMainWindows++;
249 sm_counter++;
250 m_winId = sm_counter;
251 sm_mainWindowMap.insert(m_winId, this);
252 m_firstWindow = 0;
253
254 num_ldr_generated = 0;
255 curr_num_ldr_open = 0;
256 splash = 0;
257 m_processingAWB = false;
258
259 if (sm_NumMainWindows == 1) {
260 // Register symbols on the first activation!
261 qRegisterMetaType<QImage>("QImage");
262 qRegisterMetaType<pfs::Frame *>("pfs::Frame*");
263 qRegisterMetaType<TonemappingOptions>("TonemappingOptions");
264 qRegisterMetaType<TonemappingOptions *>("TonemappingOptions*");
265 qRegisterMetaType<HdrViewer *>("HdrViewer*");
266 qRegisterMetaType<LdrViewer *>("LdrViewer*");
267 qRegisterMetaType<GenericViewer *>("GenericViewer*");
268 qRegisterMetaType<QVector<float>>("QVector<float>");
269 qRegisterMetaType<pfs::Params>("pfs::Params");
270 qRegisterMetaType<pfs::Params *>("pfs::Params*");
271 qRegisterMetaType<InterpolationMethod>("InterpolationMethod");
272 }
273
274 createUI();
275 loadOptions();
276 createMenus();
277 createToolBar();
278 createCentralWidget();
279 createStatusBar();
280 setupIO();
281 setupTM();
282 setupQueue();
283 createConnections();
284
285 OsIntegration::getInstance().init(this);
286
287 if (sm_NumMainWindows == 1) {
288 if (OsIntegration::getInstance().isRunningOnSameCpuPlatform()) {
289 sm_updateChecker.reset(new UpdateChecker(this));
290 connect(sm_updateChecker.data(), &UpdateChecker::updateAvailable,
291 this, &MainWindow::onUpdateAvailable);
292
293 m_firstWindow = 2;
294 } else
295 m_firstWindow = 1;
296 }
297 }
298
createUI()299 void MainWindow::createUI() {
300 m_Ui->setupUi(this);
301 setAttribute(Qt::WA_DeleteOnClose);
302
303 restoreState(LuminanceOptions()
304 .value(QStringLiteral("MainWindowState"))
305 .toByteArray());
306 restoreGeometry(LuminanceOptions()
307 .value(QStringLiteral("MainWindowGeometry"))
308 .toByteArray());
309
310 if (isFullScreen()) m_Ui->actionShow_Full_Screen->setChecked(true);
311
312 setAcceptDrops(true);
313 setWindowModified(false);
314 setWindowTitle(QString("Luminance HDR " LUMINANCEVERSION
315 " [*]")); // + " " + g_GIT_SHA1);
316 }
317
createCentralWidget()318 void MainWindow::createCentralWidget() {
319 // Central Widget Area
320 m_centralwidget_splitter = new QSplitter; //(this);
321 m_bottom_splitter = new QSplitter; //(this);
322 m_bottom_splitter->setOrientation(Qt::Vertical);
323
324 setCentralWidget(m_centralwidget_splitter);
325
326 m_PreviewPanel = new PreviewPanel();
327
328 // create tonemapping panel
329 m_tonemapPanel = new TonemappingPanel(
330 sm_NumMainWindows, m_PreviewPanel); //(m_centralwidget_splitter);
331
332 connect(m_Ui->actionRealtimePreviews, &QAction::toggled, m_tonemapPanel,
333 &TonemappingPanel::setRealtimePreviews);
334 connect(m_Ui->actionRealtimePreviews, &QAction::toggled, this,
335 &MainWindow::setRealtimePreviewsActive);
336
337 m_tabwidget = new QTabWidget; //(m_centralwidget_splitter);
338
339 m_tabwidget->setDocumentMode(true);
340 m_tabwidget->setTabsClosable(true);
341
342 m_centralwidget_splitter->addWidget(m_tonemapPanel);
343 m_centralwidget_splitter->addWidget(m_bottom_splitter);
344
345 m_bottom_splitter->addWidget(m_tabwidget);
346
347 m_bottom_splitter->setStretchFactor(0, 10);
348 m_bottom_splitter->setStretchFactor(1, 1);
349 m_centralwidget_splitter->setStretchFactor(0, 1);
350 m_centralwidget_splitter->setStretchFactor(1, 5);
351
352 // create preview panel
353 m_PreviewscrollArea = new QScrollArea;
354 m_PreviewscrollArea->setWidgetResizable(true);
355 m_PreviewscrollArea->setWidget(m_PreviewPanel);
356
357 m_centralwidget_splitter->addWidget(m_PreviewscrollArea);
358 m_centralwidget_splitter->setCollapsible(2, false);
359
360 if (LuminanceOptions().getPreviewPanelMode()) {
361 showPreviewsOnTheBottom();
362 } else {
363 showPreviewsOnTheRight();
364 }
365
366 connect(m_tabwidget, &QTabWidget::tabCloseRequested, this,
367 &MainWindow::removeTab);
368 connect(m_tabwidget, &QTabWidget::currentChanged, this,
369 &MainWindow::updateActions);
370 connect(m_tabwidget, &QTabWidget::currentChanged, this,
371 &MainWindow::updateSoftProofing);
372 connect(m_tonemapPanel, &TonemappingPanel::startTonemapping, this,
373 &MainWindow::tonemapImage);
374 connect(m_tonemapPanel, &TonemappingPanel::startExport, this,
375 &MainWindow::exportImage);
376 connect(this, &MainWindow::updatedHDR, m_tonemapPanel,
377 &TonemappingPanel::updatedHDR);
378 connect(this, &QObject::destroyed, m_PreviewPanel, &QObject::deleteLater);
379
380 m_centralwidget_splitter->restoreState(
381 LuminanceOptions()
382 .value(QStringLiteral("MainWindowSplitterState"))
383 .toByteArray());
384 m_centralwidget_splitter->restoreGeometry(
385 LuminanceOptions()
386 .value(QStringLiteral("MainWindowSplitterGeometry"))
387 .toByteArray());
388 m_bottom_splitter->restoreState(
389 LuminanceOptions()
390 .value(QStringLiteral("MainWindowBottomSplitterState"))
391 .toByteArray());
392 m_bottom_splitter->restoreGeometry(
393 LuminanceOptions()
394 .value(QStringLiteral("MainWindowBottomSplitterGeometry"))
395 .toByteArray());
396
397 QPalette pal = m_tabwidget->palette();
398 pal.setColor(QPalette::Dark, Qt::darkGray);
399 m_tabwidget->setPalette(pal);
400
401 m_tabwidget->setBackgroundRole(QPalette::Dark);
402 m_tabwidget->setAutoFillBackground(true);
403
404 // replace with ->tabBar() one day, or subclass
405 QTabBar *tabBar = m_tabwidget->findChild<QTabBar *>(
406 QStringLiteral("qt_tabwidget_tabbar"));
407 tabBar->setAutoFillBackground(true);
408 tabBar->setBackgroundRole(QPalette::Window);
409
410 m_PreviewscrollArea->hide();
411 }
412
createToolBar()413 void MainWindow::createToolBar() {
414 // main toolbars setup
415 QActionGroup *toolBarOptsGroup = new QActionGroup(this);
416 toolBarOptsGroup->addAction(m_Ui->actionText_Under_Icons);
417 toolBarOptsGroup->addAction(m_Ui->actionIcons_Only);
418 toolBarOptsGroup->addAction(m_Ui->actionText_Alongside_Icons);
419 toolBarOptsGroup->addAction(m_Ui->actionText_Only);
420 m_Ui->menuToolbars->addAction(m_Ui->toolBar->toggleViewAction());
421
422 connect(m_Ui->actionText_Under_Icons, &QAction::triggered, this,
423 &MainWindow::Text_Under_Icons);
424 connect(m_Ui->actionIcons_Only, &QAction::triggered, this,
425 &MainWindow::Icons_Only);
426 connect(m_Ui->actionText_Alongside_Icons, &QAction::triggered, this,
427 &MainWindow::Text_Alongside_Icons);
428 connect(m_Ui->actionText_Only, &QAction::triggered, this,
429 &MainWindow::Text_Only);
430
431 // Preview Panel
432 QActionGroup *previewPanelOptsGroup = new QActionGroup(this);
433 previewPanelOptsGroup->addAction(m_Ui->actionShow_on_the_right);
434 previewPanelOptsGroup->addAction(m_Ui->actionShow_on_the_bottom);
435 connect(m_Ui->actionShow_on_the_right, &QAction::triggered, this,
436 &MainWindow::showPreviewsOnTheRight);
437 connect(m_Ui->actionShow_on_the_bottom, &QAction::triggered, this,
438 &MainWindow::showPreviewsOnTheBottom);
439 }
440
createMenus()441 void MainWindow::createMenus() {
442 // icons (missing icons in some icon-theme)
443 if (!QIcon::hasThemeIcon(QStringLiteral("document-save-all")))
444 m_Ui->fileSaveAllAction->setIcon(
445 QIcon(":/program-icons/document-save-all"));
446 if (!QIcon::hasThemeIcon(QStringLiteral("zoom")))
447 m_Ui->fitToWindowAct->setIcon(QIcon(":/program-icons/zoom"));
448 if (!QIcon::hasThemeIcon(QStringLiteral("whitebalance")))
449 m_Ui->actionWhite_Balance->setIcon(
450 QIcon(":/program-icons/whitebalance"));
451 if (!QIcon::hasThemeIcon(QStringLiteral("transform-crop")))
452 m_Ui->cropToSelectionAction->setIcon(
453 QIcon(":/program-icons/transform-crop"));
454 if (!QIcon::hasThemeIcon(QStringLiteral("edit-selection-none")))
455 m_Ui->removeSelectionAction->setIcon(
456 QIcon(":/program-icons/edit-select-none"));
457 if (!QIcon::hasThemeIcon(QStringLiteral("globe")))
458 m_Ui->actionExportToHTML->setIcon(QIcon(":/program-icons/globe"));
459 if (!QIcon::hasThemeIcon(QStringLiteral("selection-move-to-layer-below")))
460 m_Ui->Transplant_Exif_Data_action->setIcon(
461 QIcon(":/program-icons/selection-move-to-layer-below"));
462 if (!QIcon::hasThemeIcon(QStringLiteral("tab-close")))
463 m_Ui->actionRemove_Tab->setIcon(QIcon(":/program-icons/tab-close"));
464 if (!QIcon::hasThemeIcon(QStringLiteral("help-donate")))
465 m_Ui->actionDonate->setIcon(QIcon(":/program-icons/help-donate"));
466 if (!QIcon::hasThemeIcon(QStringLiteral("document-save-as-template")))
467 m_Ui->actionSave_Hdr_Preview->setIcon(
468 QIcon(":/program-icons/document-save-as-template"));
469 if (!QIcon::hasThemeIcon(QStringLiteral("help-whatsthis")))
470 m_Ui->actionWhat_s_This->setIcon(
471 QIcon(":/program-icons/help-whatsthis"));
472
473 // About(s)
474 connect(m_Ui->actionAbout_Qt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
475 connect(m_Ui->actionWhat_s_This, &QAction::triggered, this,
476 &MainWindow::enterWhatsThis);
477
478 // I/O
479 connect(m_Ui->fileExitAction, &QAction::triggered, this, &QWidget::close);
480
481 // Crop & Rotation
482 connect(m_Ui->cropToSelectionAction, &QAction::triggered, this,
483 &MainWindow::cropToSelection);
484 m_Ui->cropToSelectionAction->setEnabled(false);
485
486 connect(m_Ui->removeSelectionAction, &QAction::triggered, this,
487 &MainWindow::disableCrop);
488
489 connect(m_Ui->menuWindows, &QMenu::aboutToShow, this,
490 &MainWindow::updateWindowMenu);
491 connect(m_Ui->actionMinimize, &QAction::triggered, this,
492 &QWidget::showMinimized);
493 connect(m_Ui->actionMaximize, &QAction::triggered, this,
494 &QWidget::showMaximized);
495 connect(m_Ui->actionShowPreviewPanel, &QAction::toggled, this,
496 &MainWindow::showPreviewPanel);
497 connect(m_Ui->actionShowPreviewPanel, &QAction::toggled, this,
498 &MainWindow::setPreviewPanelActive);
499
500 // recent files
501 initRecentFileActions();
502 updateRecentFileActions();
503
504 #ifndef HAVE_CFITSIO
505 m_Ui->actionFits_Importer->setVisible(false);
506 #endif
507 }
508
createStatusBar()509 void MainWindow::createStatusBar() {
510 statusBar()->showMessage(
511 tr("Ready. Now open an existing HDR image or create a new one!"),
512 10000);
513 }
514
createConnections()515 void MainWindow::createConnections() {
516 windowMapper = new QSignalMapper(this);
517 connect(windowMapper, static_cast<void (QSignalMapper::*)(QWidget *)>(
518 &QSignalMapper::mapped),
519 this, &MainWindow::setActiveMainWindow);
520 connect(&m_futureWatcher, &QFutureWatcherBase::finished, this,
521 &MainWindow::whiteBalanceDone);
522 }
523
loadOptions()524 void MainWindow::loadOptions() {
525 // load from settings the path where hdrs have been previously opened/loaded
526
527 // load from settings the main toolbar visualization mode
528 switch (LuminanceOptions().getMainWindowToolBarMode()) {
529 case Qt::ToolButtonIconOnly:
530 Icons_Only();
531 m_Ui->actionIcons_Only->setChecked(true);
532 break;
533 case Qt::ToolButtonTextOnly:
534 Text_Only();
535 m_Ui->actionText_Only->setChecked(true);
536 break;
537 case Qt::ToolButtonTextBesideIcon:
538 Text_Alongside_Icons();
539 m_Ui->actionText_Alongside_Icons->setChecked(true);
540 break;
541 case Qt::ToolButtonTextUnderIcon:
542 Text_Under_Icons();
543 m_Ui->actionText_Under_Icons->setChecked(true);
544 break;
545 }
546 m_Ui->actionShowPreviewPanel->setChecked(
547 LuminanceOptions().isPreviewPanelActive());
548 m_Ui->actionRealtimePreviews->setChecked(
549 LuminanceOptions().isRealtimePreviewsActive());
550 m_Ui->actionRealtimePreviews->setEnabled(
551 LuminanceOptions().isPreviewPanelActive());
552
553 bool isPreviewPanelRight = LuminanceOptions().getPreviewPanelMode() == 0;
554 m_Ui->actionShow_on_the_bottom->setChecked(!isPreviewPanelRight);
555 m_Ui->actionShow_on_the_right->setChecked(isPreviewPanelRight);
556 }
557
on_actionDonate_triggered()558 void MainWindow::on_actionDonate_triggered() {
559 DonationDialog::openDonationPage();
560 }
561
on_fileNewAction_triggered()562 void MainWindow::on_fileNewAction_triggered() {
563 createNewHdr(
564 QStringList()); // redirect on createNewHdr-method to avoid moc warning
565 }
566
createNewHdr(const QStringList & files)567 void MainWindow::createNewHdr(const QStringList &files) {
568 QScopedPointer<HdrWizard> wizard(
569 new HdrWizard(this, files, m_inputFilesName, m_inputExpoTimes,
570 QSqlDatabase::database(m_tonemapPanel->getDatabaseConnection())));
571 if (wizard->exec() == QDialog::Accepted) {
572 emit load_success(wizard->getPfsFrameHDR(), wizard->getCaptionTEXT(),
573 wizard->getInputFilesNames(), true);
574 }
575 }
576
on_fileOpenAction_triggered()577 void MainWindow::on_fileOpenAction_triggered() {
578 QString filetypes = tr("All HDR formats ");
579 QStringList hdrExtensionsList = getAllHdrFileExtensions();
580 filetypes += QLatin1String("(");
581 foreach (const QString &s, hdrExtensionsList) {
582 filetypes += "*" + s + " ";
583 }
584 filetypes += QLatin1String(");;");
585 filetypes += QLatin1String("OpenEXR (*.exr *.EXR);;");
586 filetypes += QLatin1String("Radiance RGBE (*.hdr *.pic *.HDR *.PIC);;");
587 filetypes += QLatin1String("TIFF images (*.TIFF *.TIF *.tiff *.tif);;");
588 #if HAVE_CFITSIO
589 filetypes += QLatin1String("FITS (*.fit *.FIT *.fits *.FITS);;");
590 #endif
591 filetypes += QLatin1String(
592 "RAW images (*.crw *.cr2 *.nef *.dng *.mrw *.orf *.kdc *.dcr *.arw "
593 "*.raf "
594 "*.ptx *.pef *.x3f *.raw "
595 "*.rw2 *.sr2 *.3fr *.mef *.mos *.erf *.nrw *.mef *.mos *.erf *.nrw "
596 "*.srw");
597 filetypes += QLatin1String(
598 "*.CRW *.CR2 *.NEF *.DNG *.MRW *.ORF *.KDC "
599 "*.DCR *.ARW *.RAF *.PTX *.PEF "
600 "*.X3F *.RAW *.RW2 *.SR2 "
601 "*.3FR *.MEF *.MOS *.ERF *.NRW *.SRW);;");
602 filetypes += QLatin1String("PFS stream (*.pfs *.PFS)");
603
604 QStringList files = QFileDialog::getOpenFileNames(
605 this, tr("Load one or more HDR images..."),
606 LuminanceOptions().getDefaultPathHdrIn(), filetypes);
607
608 if (files.isEmpty()) return;
609
610 // Update working folder
611 // All the files are in the same folder, so I pick the first as reference to
612 // update the settings
613 QFileInfo qfi(files.first());
614
615 LuminanceOptions().setDefaultPathHdrIn(qfi.absolutePath());
616
617 foreach (const QString &filename, files) {
618 // emit open_hdr_frame(filename);
619 QMetaObject::invokeMethod(m_IOWorker, "read_hdr_frame",
620 Qt::QueuedConnection,
621 Q_ARG(QString, filename));
622 }
623 }
624
on_fileSaveAllAction_triggered()625 void MainWindow::on_fileSaveAllAction_triggered() {
626 if (m_tabwidget->count() <= 0) return;
627
628 QString dir = QFileDialog::getExistingDirectory(
629 this, tr("Save files in"), LuminanceOptions().getDefaultPathLdrOut());
630
631 if (!dir.isEmpty()) {
632 LuminanceOptions().setDefaultPathLdrOut(dir);
633
634 for (int i = 0; i < m_tabwidget->count(); i++) {
635 QWidget *wgt = m_tabwidget->widget(i);
636 GenericViewer *g_v = qobject_cast<GenericViewer *>(wgt);
637
638 if (!g_v->isHDR()) {
639 LdrViewer *l_v = qobject_cast<LdrViewer *>(g_v);
640
641 QString ldr_name = QFileInfo(getCurrentHDRName()).baseName();
642 QString outfname = LuminanceOptions().getDefaultPathLdrOut() +
643 "/" + ldr_name + "_" +
644 l_v->getFileNamePostFix() + ".jpg";
645
646 QString inputfname;
647 if (!m_inputFilesName.isEmpty()) {
648 inputfname = m_inputFilesName.first();
649 } else {
650 inputfname = "FromHdrFile";
651 }
652
653 QMetaObject::invokeMethod(
654 m_IOWorker, "write_ldr_frame", Qt::QueuedConnection,
655 Q_ARG(GenericViewer *, l_v), Q_ARG(QString, outfname),
656 Q_ARG(QString, inputfname),
657 Q_ARG(QVector<float>, QVector<float>()),
658 Q_ARG(TonemappingOptions *, l_v->getTonemappingOptions()),
659 Q_ARG(pfs::Params, pfs::Params("quality", 100u)));
660 }
661 }
662 }
663 }
664
on_fileSaveAsAction_triggered()665 void MainWindow::on_fileSaveAsAction_triggered() {
666 if (m_tabwidget->count() <= 0) return;
667
668 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
669 if (g_v->isHDR()) {
670 // In this case I'm saving an HDR
671 QString separator = "";
672 if (!m_HdrCaption.isEmpty()) {
673 separator = "-";
674 }
675 QString fname = getHdrFileNameFromSaveDialog(
676 g_v->getFileName() + separator + m_HdrCaption , this);
677
678 if (fname.isEmpty()) return;
679
680 QFileInfo qfi(fname);
681 QString format = qfi.suffix();
682
683 pfs::Params p;
684 if (format == QLatin1String("tif") || format == QLatin1String("tiff")) {
685 TiffModeDialog t(true, -1, this);
686 if (t.exec() == QDialog::Rejected) return;
687
688 p.set("tiff_mode", t.getTiffWriterMode());
689 }
690
691 // CALL m_IOWorker->write_hdr_frame(qobject_cast<HdrViewer*>(g_v),
692 // fname);
693 QMetaObject::invokeMethod(
694 m_IOWorker, "write_hdr_frame", Qt::QueuedConnection,
695 Q_ARG(GenericViewer *, qobject_cast<HdrViewer *>(g_v)),
696 Q_ARG(QString, fname), Q_ARG(pfs::Params, p));
697 } else {
698 // In this case I'm saving an LDR
699
700 LdrViewer *l_v = qobject_cast<LdrViewer *>(g_v);
701
702 if (l_v == nullptr) return;
703
704 QString ldr_name = QFileInfo(getCurrentHDRName()).baseName();
705
706 QString proposedFileName =
707 ldr_name + "_" + l_v->getFileNamePostFix() + ".jpg";
708
709 // QString outputFilename = getLdrFileNameFromSaveDialog(ldr_name + "_"
710 // +
711 // l_v->getFileNamePostFix() + ".jpg", this);
712 QString outputFilename =
713 getLdrFileNameFromSaveDialog(proposedFileName, this);
714
715 if (outputFilename.isEmpty()) return;
716
717 QString format = QFileInfo(outputFilename).suffix();
718
719 if (format.isEmpty()) { // default as JPG
720 format = QStringLiteral("jpg");
721 outputFilename += QLatin1String(".jpg");
722 }
723
724 pfs::Params p;
725 if (format == QLatin1String("png") || format == QLatin1String("jpg")) {
726 ImageQualityDialog savedFileQuality(l_v->getFrame(), format, -1,
727 this);
728 savedFileQuality.setWindowTitle(QObject::tr("Save as...") +
729 format.toUpper());
730 if (savedFileQuality.exec() == QDialog::Rejected) return;
731
732 p.set("quality", (size_t)savedFileQuality.getQuality());
733 }
734
735 if (format == QLatin1String("tif") || format == QLatin1String("tiff")) {
736 TiffModeDialog t(false, -1, this);
737 if (t.exec() == QDialog::Rejected) return;
738
739 p.set("tiff_mode", t.getTiffWriterMode());
740 }
741
742 QString inputfname;
743 if (!m_inputFilesName.isEmpty()) {
744 inputfname = m_inputFilesName.first();
745 } else {
746 inputfname = "FromHdrFile";
747 }
748
749 QMetaObject::invokeMethod(
750 m_IOWorker, "write_ldr_frame", Qt::QueuedConnection,
751 Q_ARG(GenericViewer *, l_v), Q_ARG(QString, outputFilename),
752 Q_ARG(QString, inputfname), Q_ARG(QVector<float>, m_inputExpoTimes),
753 Q_ARG(TonemappingOptions *, l_v->getTonemappingOptions()),
754 Q_ARG(pfs::Params, p));
755 }
756 }
757
save_hdr_success(GenericViewer * saved_hdr,const QString & fname)758 void MainWindow::save_hdr_success(GenericViewer *saved_hdr,
759 const QString &fname) {
760 QFileInfo qfi(fname);
761
762 setCurrentFile(qfi.absoluteFilePath());
763 setWindowModified(false);
764
765 // update name on the tab label
766 m_tabwidget->setTabText(m_tabwidget->indexOf(saved_hdr), qfi.fileName());
767 }
768
save_hdr_failed(const QString & fname)769 void MainWindow::save_hdr_failed(const QString &fname) {
770 // TODO give some kind of feedback to the user!
771 // TODO pass the name of the file, so the user know which file didn't save
772 // correctly
773 // DONE!!! Once again, use unified style?
774 QMessageBox::warning(0, QLatin1String(""),
775 tr("Failed to save %1").arg(fname), QMessageBox::Ok,
776 QMessageBox::NoButton);
777 }
778
save_ldr_success(GenericViewer * saved_ldr,const QString & fname)779 void MainWindow::save_ldr_success(GenericViewer *saved_ldr,
780 const QString &fname) {
781 if (!saved_ldr->isHDR())
782 m_tabwidget->setTabText(m_tabwidget->indexOf(saved_ldr),
783 QFileInfo(fname).fileName());
784 }
785
save_ldr_failed(const QString & fname)786 void MainWindow::save_ldr_failed(const QString &fname) {
787 // TODO give some kind of feedback to the user!
788 // TODO pass the name of the file, so the user know which file didn't save
789 // correctly
790 // DONE!!! Once again, use unified style?
791 QMessageBox::warning(0, QLatin1String(""),
792 tr("Failed to save %1").arg(fname), QMessageBox::Ok,
793 QMessageBox::NoButton);
794 }
795
on_actionSave_Hdr_Preview_triggered()796 void MainWindow::on_actionSave_Hdr_Preview_triggered() {
797 if (m_tabwidget->count() <= 0) return;
798
799 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
800
801 if (!g_v->isHDR()) return;
802 try {
803 QString ldr_name = QFileInfo(getCurrentHDRName()).baseName();
804
805 QString outfname = getLdrFileNameFromSaveDialog(
806 ldr_name + "_" + g_v->getFileNamePostFix() + ".jpg", this);
807
808 if (outfname.isEmpty()) return;
809
810 QString inputfname;
811 if (!m_inputFilesName.isEmpty()) {
812 inputfname = m_inputFilesName.first();
813 } else {
814 inputfname = "FromHdrFile";
815 }
816
817 QMetaObject::invokeMethod(
818 m_IOWorker, "write_ldr_frame", Qt::QueuedConnection,
819 Q_ARG(GenericViewer *, g_v), Q_ARG(QString, outfname),
820 Q_ARG(QString, inputfname), Q_ARG(QVector<float>, QVector<float>()),
821 Q_ARG(TonemappingOptions *, nullptr),
822 Q_ARG(pfs::Params, pfs::Params("quality", 100u)));
823 } catch (...) {
824 return;
825 }
826 }
827
updateActions(int w)828 void MainWindow::updateActions(int w) {
829 #ifdef QT_DEBUG
830 qDebug() << "MainWindow::updateActions(" << w << ")";
831 #endif
832 bool hasImage = w >= 0;
833 GenericViewer *g_v = hasImage ? qobject_cast<GenericViewer *>(m_tabwidget->widget(w)) : 0;
834 bool isHdr = g_v ? g_v->isHDR() : false;
835 bool isLdr = g_v ? !g_v->isHDR() : false;
836 LuminanceOptions luminance_opts;
837 bool hasPrinterProfile =
838 !luminance_opts.getPrinterProfileFileName().isEmpty();
839
840 updateMagnificationButtons(g_v); // g_v ? g_v : 0
841
842 m_Ui->fileSaveAsAction->setEnabled(hasImage);
843 m_Ui->actionRemove_Tab->setEnabled(hasImage);
844 m_Ui->actionSave_Hdr_Preview->setEnabled(hasImage && isHdr);
845 m_Ui->fileSaveAllAction->setEnabled(hasImage && curr_num_ldr_open >= 2);
846
847 // Histogram
848 m_Ui->menuHDR_Histogram->setEnabled(isHdr);
849 m_Ui->Low_dynamic_range->setEnabled(isHdr);
850 m_Ui->Fit_to_dynamic_range->setEnabled(isHdr);
851 m_Ui->Shrink_dynamic_range->setEnabled(isHdr);
852 m_Ui->Extend_dynamic_range->setEnabled(isHdr);
853 m_Ui->Decrease_exposure->setEnabled(isHdr);
854 m_Ui->Increase_exposure->setEnabled(isHdr);
855
856 m_Ui->actionResizeHDR->setEnabled(isHdr);
857 m_Ui->action_Projective_Transformation->setEnabled(isHdr);
858 m_Ui->actionExportToHTML->setEnabled(isHdr);
859 m_Ui->rotateccw->setEnabled(isHdr);
860 m_Ui->rotatecw->setEnabled(isHdr);
861
862 m_Ui->actionFix_Histogram->setEnabled(isLdr);
863 m_Ui->actionWhite_Balance->setEnabled(hasImage && !m_processingAWB);
864 m_Ui->actionSoft_Proofing->setEnabled(isLdr && hasPrinterProfile);
865 m_Ui->actionGamut_Check->setEnabled(isLdr && hasPrinterProfile);
866
867 bool hasCropping = isHdr && tm_status.curr_tm_frame &&
868 tm_status.curr_tm_frame->hasSelection();
869 m_Ui->cropToSelectionAction->setEnabled(hasCropping);
870 m_Ui->removeSelectionAction->setEnabled(hasCropping);
871
872 m_Ui->actionLock->setEnabled(hasImage && curr_num_ldr_open >= 1);
873 m_Ui->actionShow_Image_Full_Screen->setEnabled(hasImage);
874 }
875
on_rotateccw_triggered()876 void MainWindow::on_rotateccw_triggered() { dispatchrotate(false); }
877
on_rotatecw_triggered()878 void MainWindow::on_rotatecw_triggered() { dispatchrotate(true); }
879
dispatchrotate(bool clockwise)880 void MainWindow::dispatchrotate(bool clockwise) {
881 if (m_tabwidget->count() <= 0) return;
882
883 GenericViewer *curr_g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
884
885 m_Ui->rotateccw->setEnabled(false);
886 m_Ui->rotatecw->setEnabled(false);
887
888 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
889 pfs::Frame *rotated = pfs::rotate(curr_g_v->getFrame(), clockwise);
890
891 curr_g_v->setFrame(rotated);
892 if (!curr_g_v->needsSaving()) {
893 curr_g_v->setNeedsSaving(true);
894
895 int index = m_tabwidget->indexOf(curr_g_v);
896 QString text = m_tabwidget->tabText(index);
897 m_tabwidget->setTabText(index, text.prepend("(*) "));
898
899 setWindowModified(true);
900 }
901 emit updatedHDR(curr_g_v->getFrame());
902 QApplication::restoreOverrideCursor();
903
904 m_Ui->rotateccw->setEnabled(true);
905 m_Ui->rotatecw->setEnabled(true);
906 }
907
on_actionResizeHDR_triggered()908 void MainWindow::on_actionResizeHDR_triggered() {
909 if (m_tabwidget->count() <= 0) return;
910
911 GenericViewer *curr_g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
912
913 ResizeDialog *resizedialog = new ResizeDialog(this, curr_g_v->getFrame());
914 if (resizedialog->exec() == QDialog::Accepted) {
915 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
916
917 curr_g_v->setFrame(resizedialog->getResizedFrame());
918 if (!curr_g_v->needsSaving()) {
919 curr_g_v->setNeedsSaving(true);
920
921 int index = m_tabwidget->indexOf(curr_g_v);
922 QString text = m_tabwidget->tabText(index);
923 m_tabwidget->setTabText(index, text.prepend("(*) "));
924
925 setWindowModified(true);
926 }
927 emit updatedHDR(curr_g_v->getFrame());
928 QApplication::restoreOverrideCursor();
929 }
930 delete resizedialog;
931 }
932
on_actionExportToHTML_triggered()933 void MainWindow::on_actionExportToHTML_triggered() {
934 if (m_tabwidget->count() <= 0) return;
935
936 GenericViewer *curr_g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
937 ExportToHtmlDialog *exportDialog =
938 new ExportToHtmlDialog(this, curr_g_v->getFrame());
939
940 exportDialog->exec();
941 delete exportDialog;
942 }
943
on_actionSupported_Cameras_triggered()944 void MainWindow::on_actionSupported_Cameras_triggered() {
945 SupportedCamerasDialog *supportedDialog = new SupportedCamerasDialog(this);
946
947 supportedDialog->exec();
948 delete supportedDialog;
949 }
950
on_action_Projective_Transformation_triggered()951 void MainWindow::on_action_Projective_Transformation_triggered() {
952 if (m_tabwidget->count() <= 0) return;
953
954 GenericViewer *curr_g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
955
956 ProjectionsDialog *projTranfsDialog =
957 new ProjectionsDialog(this, curr_g_v->getFrame());
958 if (projTranfsDialog->exec() == QDialog::Accepted) {
959 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
960
961 curr_g_v->setFrame(projTranfsDialog->getTranformedFrame());
962 if (!curr_g_v->needsSaving()) {
963 curr_g_v->setNeedsSaving(true);
964
965 int index = m_tabwidget->indexOf(curr_g_v);
966 QString text = m_tabwidget->tabText(index);
967 m_tabwidget->setTabText(index, text.prepend("(*) "));
968
969 setWindowModified(true);
970 }
971 emit updatedHDR(curr_g_v->getFrame());
972 QApplication::restoreOverrideCursor();
973 }
974 delete projTranfsDialog;
975 }
976
on_Decrease_exposure_triggered()977 void MainWindow::on_Decrease_exposure_triggered() {
978 if (m_tabwidget->count() <= 0) return;
979
980 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
981 HdrViewer *curr_hdr_v = qobject_cast<HdrViewer *>(g_v);
982 if (curr_hdr_v != nullptr) curr_hdr_v->lumRange()->decreaseExposure();
983 }
984
on_Extend_dynamic_range_triggered()985 void MainWindow::on_Extend_dynamic_range_triggered() {
986 if (m_tabwidget->count() <= 0) return;
987
988 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
989 HdrViewer *curr_hdr_v = qobject_cast<HdrViewer *>(g_v);
990 if (curr_hdr_v != nullptr) curr_hdr_v->lumRange()->extendRange();
991 }
992
on_Fit_to_dynamic_range_triggered()993 void MainWindow::on_Fit_to_dynamic_range_triggered() {
994 if (m_tabwidget->count() <= 0) return;
995
996 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
997 HdrViewer *curr_hdr_v = qobject_cast<HdrViewer *>(g_v);
998 if (curr_hdr_v != nullptr) curr_hdr_v->lumRange()->fitToDynamicRange();
999 }
1000
on_Increase_exposure_triggered()1001 void MainWindow::on_Increase_exposure_triggered() {
1002 if (m_tabwidget->count() <= 0) return;
1003
1004 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
1005 HdrViewer *curr_hdr_v = qobject_cast<HdrViewer *>(g_v);
1006 if (curr_hdr_v != nullptr) curr_hdr_v->lumRange()->increaseExposure();
1007 }
1008
on_Shrink_dynamic_range_triggered()1009 void MainWindow::on_Shrink_dynamic_range_triggered() {
1010 if (m_tabwidget->count() <= 0) return;
1011
1012 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
1013 HdrViewer *curr_hdr_v = qobject_cast<HdrViewer *>(g_v);
1014 if (curr_hdr_v != nullptr) curr_hdr_v->lumRange()->shrinkRange();
1015 }
1016
on_Low_dynamic_range_triggered()1017 void MainWindow::on_Low_dynamic_range_triggered() {
1018 if (m_tabwidget->count() <= 0) return;
1019
1020 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
1021 HdrViewer *curr_hdr_v = qobject_cast<HdrViewer *>(g_v);
1022 if (curr_hdr_v != nullptr) curr_hdr_v->lumRange()->lowDynamicRange();
1023 }
1024
1025 // Zoom = Viewers (START)
on_zoomInAct_triggered()1026 void MainWindow::on_zoomInAct_triggered() {
1027 if (m_tabwidget->count() <= 0) return;
1028
1029 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
1030
1031 g_v->zoomIn();
1032 }
1033
on_zoomOutAct_triggered()1034 void MainWindow::on_zoomOutAct_triggered() {
1035 if (m_tabwidget->count() <= 0) return;
1036
1037 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
1038
1039 g_v->zoomOut();
1040 }
1041
on_fitToWindowAct_triggered()1042 void MainWindow::on_fitToWindowAct_triggered() {
1043 if (m_tabwidget->count() <= 0) return;
1044
1045 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
1046
1047 g_v->fitToWindow();
1048 }
1049
on_actionFill_to_Window_triggered()1050 void MainWindow::on_actionFill_to_Window_triggered() {
1051 if (m_tabwidget->count() <= 0) return;
1052
1053 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
1054
1055 g_v->fillToWindow();
1056 }
1057
on_normalSizeAct_triggered()1058 void MainWindow::on_normalSizeAct_triggered() {
1059 if (m_tabwidget->count() <= 0) return;
1060
1061 GenericViewer *g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
1062
1063 g_v->normalSize();
1064 }
1065 // Zoom = Viewers (END)
1066
1067 #ifdef WITH_HELPBROWSER
on_documentationAction_triggered()1068 void MainWindow::on_documentationAction_triggered() {
1069 if (sm_helpBrowser == nullptr) {
1070 sm_helpBrowser =
1071 new HelpBrowser(0, QStringLiteral("Luminance HDR Help"));
1072 sm_helpBrowser->setAttribute(Qt::WA_DeleteOnClose);
1073 connect(sm_helpBrowser, &QObject::destroyed, sm_helpBrowser,
1074 &QObject::deleteLater);
1075 connect(sm_helpBrowser, &HelpBrowser::closed, this,
1076 &MainWindow::helpBrowserClosed);
1077 sm_helpBrowser->show();
1078 } else {
1079 sm_helpBrowser->show();
1080 sm_helpBrowser->activateWindow();
1081 sm_helpBrowser->raise();
1082 }
1083 }
1084
helpBrowserClosed()1085 void MainWindow::helpBrowserClosed() {
1086 sm_helpBrowser = nullptr;
1087 }
1088 #endif
1089
enterWhatsThis()1090 void MainWindow::enterWhatsThis() { QWhatsThis::enterWhatsThisMode(); }
1091
openRecentFile()1092 void MainWindow::openRecentFile() {
1093 QAction *action = qobject_cast<QAction *>(sender());
1094 if (action) {
1095 // emit open_hdr_frame(action->data().toString());
1096 QMetaObject::invokeMethod(m_IOWorker, "read_hdr_frame",
1097 Qt::QueuedConnection,
1098 Q_ARG(QString, action->data().toString()));
1099 }
1100 }
1101
setupIO()1102 void MainWindow::setupIO() {
1103 // progress bar
1104 m_ProgressBar = new QProgressBar(this);
1105 m_ProgressBar->hide();
1106 statusBar()->addWidget(m_ProgressBar);
1107
1108 // Init Object/Thread
1109 m_IOThread = new QThread;
1110 m_IOWorker = new IOWorker;
1111
1112 m_IOWorker->moveToThread(m_IOThread);
1113
1114 // Memory Management
1115 connect(this, &QObject::destroyed, m_IOWorker, &QObject::deleteLater);
1116 connect(m_IOWorker, &QObject::destroyed, m_IOThread, &QObject::deleteLater);
1117
1118 // Open
1119 connect(m_IOWorker, SIGNAL(read_hdr_success(pfs::Frame *, const QString &)),
1120 this, SLOT(load_success(pfs::Frame *, const QString &)));
1121 connect(m_IOWorker, &IOWorker::read_hdr_failed, this,
1122 &MainWindow::load_failed);
1123
1124 // Save HDR
1125 connect(m_IOWorker,
1126 SIGNAL(write_hdr_success(GenericViewer *, const QString &)), this,
1127 SLOT(save_hdr_success(GenericViewer *, const QString &)));
1128 connect(m_IOWorker, &IOWorker::write_hdr_failed, this,
1129 &MainWindow::save_hdr_failed);
1130 // Save LDR
1131 connect(m_IOWorker,
1132 SIGNAL(write_ldr_success(GenericViewer *, const QString &)), this,
1133 SLOT(save_ldr_success(GenericViewer *, const QString &)));
1134 connect(m_IOWorker, &IOWorker::write_ldr_failed, this,
1135 &MainWindow::save_ldr_failed);
1136
1137 // progress bar handling
1138 connect(m_IOWorker, &IOWorker::setValue, m_ProgressBar,
1139 &QProgressBar::setValue);
1140 connect(m_IOWorker, &IOWorker::setMaximum, m_ProgressBar,
1141 &QProgressBar::setMaximum);
1142 connect(m_IOWorker, &IOWorker::IO_init, this, &MainWindow::ioBegin);
1143 connect(m_IOWorker, &IOWorker::IO_finish, this, &MainWindow::ioEnd);
1144
1145 // start thread waiting for signals (I/O requests)
1146 m_IOThread->start();
1147 }
1148
ioBegin()1149 void MainWindow::ioBegin() {
1150 statusBar()->clearMessage();
1151
1152 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
1153
1154 // statusBar()->addWidget(m_ProgressBar);
1155 m_ProgressBar->setMaximum(0);
1156 m_ProgressBar->show();
1157 }
1158
ioEnd()1159 void MainWindow::ioEnd() {
1160 // statusBar()->removeWidget(m_ProgressBar);
1161 m_ProgressBar->reset();
1162 m_ProgressBar->hide();
1163
1164 QApplication::restoreOverrideCursor();
1165
1166 statusBar()->showMessage(tr("Done!"), 800);
1167 }
1168
load_failed(const QString & errorMessage)1169 void MainWindow::load_failed(const QString &errorMessage) {
1170 m_ProgressBar->reset();
1171 m_ProgressBar->hide();
1172
1173 QApplication::restoreOverrideCursor();
1174
1175 // TODO: use unified style?
1176 QMessageBox::critical(this, tr("Aborting..."), errorMessage,
1177 QMessageBox::Ok, QMessageBox::NoButton);
1178 }
1179
load_success(pfs::Frame * new_hdr_frame,const QString & new_fname,const QStringList & inputFileNames,bool needSaving)1180 void MainWindow::load_success(pfs::Frame *new_hdr_frame,
1181 const QString &new_fname,
1182 const QStringList &inputFileNames,
1183 bool needSaving) {
1184 if (tm_status.is_hdr_ready) {
1185 MainWindow *other = new MainWindow(new_hdr_frame, new_fname,
1186 inputFileNames, needSaving);
1187 other->move(x() + 40, y() + 40);
1188 other->show();
1189 } else {
1190 #ifdef QT_DEBUG
1191 qDebug() << "Filename: " << new_fname;
1192 #endif
1193 HdrViewer *newhdr = new HdrViewer(new_hdr_frame, this, needSaving);
1194
1195 newhdr->setAttribute(Qt::WA_DeleteOnClose);
1196
1197 connect(newhdr, &GenericViewer::selectionReady, this,
1198 &MainWindow::enableCrop);
1199 connect(newhdr, &GenericViewer::changed, this,
1200 &MainWindow::syncViewers);
1201 connect(newhdr, &GenericViewer::changed, this,
1202 &MainWindow::updateMagnificationButtons);
1203 connect(newhdr, &GenericViewer::reparent, this,
1204 &MainWindow::reparentViewer);
1205 connect(newhdr, &GenericViewer::goNext, this,
1206 &MainWindow::showNextViewer);
1207 connect(newhdr, &GenericViewer::goPrevious, this,
1208 &MainWindow::showPreviousViewer);
1209 connect(newhdr, &GenericViewer::syncViewers, this,
1210 &MainWindow::setSyncViewers);
1211
1212 newhdr->setViewerMode(getCurrentViewerMode(*m_tabwidget));
1213
1214 QFileInfo qfileinfo(new_fname);
1215 if (!qfileinfo.exists()) {
1216 // it doesn't exist on the file system, so I have just got back a
1217 // file from some creational operation (new hdr, crop...)
1218 m_inputFilesName = inputFileNames;
1219 QFileInfo fi1(m_inputFilesName.first());
1220
1221 if (m_inputFilesName.first() != m_inputFilesName.last()) {
1222 QFileInfo fi2(m_inputFilesName.last());
1223
1224 m_outputFileNamePrefix =
1225 fi1.completeBaseName() + "-" + fi2.completeBaseName();
1226 }
1227 else {
1228 m_outputFileNamePrefix = fi1.completeBaseName();
1229 }
1230 // newhdr->setFileName(QString(tr("Untitled")));
1231 newhdr->setFileName(m_outputFileNamePrefix);
1232 m_tabwidget->addTab(newhdr, QString(new_fname).prepend("(*) "));
1233 m_HdrCaption = new_fname;
1234
1235 setWindowModified(true);
1236 } else {
1237 m_outputFileNamePrefix = new_fname;
1238 // the new file exists on the file system, so I can use this value
1239 // to set captions and so on
1240 newhdr->setFileName(new_fname);
1241 m_tabwidget->addTab(newhdr, qfileinfo.fileName());
1242
1243 setCurrentFile(new_fname);
1244 setWindowModified(needSaving);
1245 }
1246
1247 tm_status.is_hdr_ready = true;
1248 tm_status.curr_tm_frame = newhdr;
1249
1250 m_tabwidget->setCurrentWidget(newhdr);
1251
1252 m_tonemapPanel->setEnabled(true);
1253 m_tonemapPanel->updatedHDR(new_hdr_frame);
1254 m_Ui->actionShowPreviewPanel->setEnabled(true);
1255
1256 showPreviewPanel(m_Ui->actionShowPreviewPanel->isChecked());
1257
1258 // signal: I have a new HDR open
1259 emit updatedHDR(newhdr->getFrame());
1260 }
1261 }
1262
on_OptionsAction_triggered()1263 void MainWindow::on_OptionsAction_triggered() {
1264 PreferencesDialog *opts = new PreferencesDialog(this);
1265 opts->setAttribute(Qt::WA_DeleteOnClose);
1266 if (opts->exec() == QDialog::Accepted) {
1267 m_Ui->actionShowPreviewPanel->setChecked(
1268 LuminanceOptions().isPreviewPanelActive());
1269 }
1270 }
1271
on_Transplant_Exif_Data_action_triggered()1272 void MainWindow::on_Transplant_Exif_Data_action_triggered() {
1273 TransplantExifDialog *transplant = new TransplantExifDialog(this);
1274 transplant->setAttribute(Qt::WA_DeleteOnClose);
1275 transplant->exec();
1276 }
1277
dragEnterEvent(QDragEnterEvent * event)1278 void MainWindow::dragEnterEvent(QDragEnterEvent *event) {
1279 event->acceptProposedAction();
1280 }
1281
dropEvent(QDropEvent * event)1282 void MainWindow::dropEvent(QDropEvent *event) {
1283 if (event->mimeData()->hasUrls()) {
1284 openFiles(convertUrlListToFilenameList(event->mimeData()->urls()));
1285 }
1286 event->acceptProposedAction();
1287 }
1288
openFile(const QString & filename)1289 void MainWindow::openFile(const QString &filename) {
1290 QMetaObject::invokeMethod(m_IOWorker, "read_hdr_frame",
1291 Qt::QueuedConnection, Q_ARG(QString, filename));
1292 }
1293
openFiles(const QStringList & files)1294 void MainWindow::openFiles(const QStringList &files) {
1295 if (files.size() > 0) {
1296 switch (DnDOptionDialog::showDndDialog(this, files)) {
1297 case DnDOptionDialog::ACTION_NEW_HDR: {
1298 createNewHdr(files);
1299 } break;
1300 case DnDOptionDialog::ACTION_OPEN_HDR: {
1301 foreach (const QString &filename, files) { openFile(filename); }
1302 } break;
1303 }
1304 }
1305 }
1306
Text_Under_Icons()1307 void MainWindow::Text_Under_Icons() {
1308 m_Ui->toolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
1309 LuminanceOptions().setMainWindowToolBarMode(Qt::ToolButtonTextUnderIcon);
1310 }
1311
Icons_Only()1312 void MainWindow::Icons_Only() {
1313 m_Ui->toolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
1314 LuminanceOptions().setMainWindowToolBarMode(Qt::ToolButtonIconOnly);
1315 }
1316
Text_Alongside_Icons()1317 void MainWindow::Text_Alongside_Icons() {
1318 m_Ui->toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
1319 LuminanceOptions().setMainWindowToolBarMode(Qt::ToolButtonTextBesideIcon);
1320 }
1321
Text_Only()1322 void MainWindow::Text_Only() {
1323 m_Ui->toolBar->setToolButtonStyle(Qt::ToolButtonTextOnly);
1324 LuminanceOptions().setMainWindowToolBarMode(Qt::ToolButtonTextOnly);
1325 }
1326
onUpdateAvailable()1327 void MainWindow::onUpdateAvailable() {
1328 m_Ui->actionUpdateAvailable->setVisible(true);
1329 }
1330
on_actionUpdateAvailable_triggered()1331 void MainWindow::on_actionUpdateAvailable_triggered() {
1332 if (sm_updateChecker) {
1333 sm_updateChecker->trayMessageClicked();
1334 }
1335 }
1336
on_actionAbout_Luminance_triggered()1337 void MainWindow::on_actionAbout_Luminance_triggered() { UMessageBox::about(); }
1338
1339 /*
1340 * Window Menu Display and Functionalities
1341 */
updateWindowMenu()1342 void MainWindow::updateWindowMenu() {
1343 // Remove current elements inside the menuWindows
1344 foreach (QAction *Action_MW, openMainWindows) {
1345 openMainWindows.removeAll(Action_MW);
1346 m_Ui->menuWindows->removeAction(Action_MW);
1347 delete Action_MW;
1348 }
1349
1350 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1351 MainWindow *MW = qobject_cast<MainWindow *>(widget);
1352 if (MW != nullptr) {
1353 QAction *action =
1354 m_Ui->menuWindows->addAction(MW->getCurrentHDRName());
1355
1356 action->setCheckable(true);
1357 action->setChecked(MW == this);
1358 // connect(action, SIGNAL(triggered()), windowMapper, SLOT(map()));
1359 connect(action, SIGNAL(triggered()), windowMapper, SLOT(map()));
1360 windowMapper->setMapping(action, MW);
1361
1362 openMainWindows.push_back(action);
1363 }
1364 }
1365 }
1366
1367 /*
1368 * This function sets the active Main Window
1369 * when the file name is selected inside the "Window" menu
1370 */
setActiveMainWindow(QWidget * w)1371 void MainWindow::setActiveMainWindow(QWidget *w) {
1372 MainWindow *MW = qobject_cast<MainWindow *>(w);
1373
1374 if (MW == nullptr) return;
1375
1376 MW->raise();
1377 MW->activateWindow();
1378 return;
1379 }
1380
on_actionBring_All_to_Front_triggered()1381 void MainWindow::on_actionBring_All_to_Front_triggered() {
1382 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
1383 MainWindow *MW = qobject_cast<MainWindow *>(widget);
1384 if (MW != nullptr) {
1385 MW->raise();
1386 }
1387 }
1388 }
1389
on_actionBatch_HDR_triggered()1390 void MainWindow::on_actionBatch_HDR_triggered() {
1391 BatchHDRDialog *batch_hdr_dialog = new BatchHDRDialog(this, QSqlDatabase::database(m_tonemapPanel->getDatabaseConnection()));
1392 batch_hdr_dialog->exec();
1393 delete batch_hdr_dialog;
1394 }
1395
on_actionBatch_Tone_Mapping_triggered()1396 void MainWindow::on_actionBatch_Tone_Mapping_triggered() {
1397 BatchTMDialog *batchdialog = new BatchTMDialog(this, QSqlDatabase::database(m_tonemapPanel->getDatabaseConnection()));
1398 batchdialog->exec();
1399 delete batchdialog;
1400 }
1401
cropToSelection()1402 void MainWindow::cropToSelection() {
1403 if (m_tabwidget->count() <= 0) return;
1404
1405 GenericViewer *curr_g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
1406
1407 if (!curr_g_v->isHDR()) return;
1408 if (!curr_g_v->hasSelection()) return;
1409
1410 QRect cropRect = curr_g_v->getSelectionRect();
1411 int x_ul, y_ul, x_br, y_br;
1412 cropRect.getCoords(&x_ul, &y_ul, &x_br, &y_br);
1413 disableCrop();
1414 pfs::Frame *original_frame = curr_g_v->getFrame();
1415 pfs::Frame *cropped_frame =
1416 pfs::cut(original_frame, x_ul, y_ul, x_br, y_br);
1417
1418 emit load_success(cropped_frame, QString(tr("Cropped Image")),
1419 m_inputFilesName, true);
1420
1421 curr_g_v->removeSelection();
1422 }
1423
enableCrop(bool isReady)1424 void MainWindow::enableCrop(bool isReady) {
1425 m_Ui->cropToSelectionAction->setEnabled(isReady);
1426 m_Ui->removeSelectionAction->setEnabled(isReady);
1427 }
1428
disableCrop()1429 void MainWindow::disableCrop() {
1430 if (m_tabwidget->count() <= 0) return;
1431
1432 GenericViewer *curr_g_v = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
1433
1434 if (!curr_g_v->isHDR()) return;
1435
1436 curr_g_v->removeSelection();
1437 m_Ui->cropToSelectionAction->setEnabled(false);
1438 m_Ui->removeSelectionAction->setEnabled(false);
1439 }
1440
changeEvent(QEvent * event)1441 void MainWindow::changeEvent(QEvent *event) {
1442 if (event->type() == QEvent::LanguageChange) {
1443 m_Ui->retranslateUi(this);
1444 setWindowTitle(QString("Luminance HDR " LUMINANCEVERSION " [*]"));
1445 }
1446
1447 QWidget::changeEvent(event);
1448 }
1449
closeEvent(QCloseEvent * event)1450 void MainWindow::closeEvent(QCloseEvent *event) {
1451 if (!maybeSave()) {
1452 event->ignore();
1453 return;
1454 }
1455 if (m_isFullscreenViewer) {
1456 reparentViewer(m_g_v_fullscreen);
1457 }
1458 sm_NumMainWindows--;
1459 if (sm_NumMainWindows == 0) {
1460 #ifdef WITH_HELPBROWSER
1461 if (sm_helpBrowser) {
1462 sm_helpBrowser->close();
1463 }
1464 #endif
1465 }
1466
1467 if (sm_NumMainWindows == 0) {
1468 // Last MainWindow is dead...
1469 LuminanceOptions().setValue(QStringLiteral("MainWindowState"),
1470 saveState());
1471 LuminanceOptions().setValue(QStringLiteral("MainWindowGeometry"),
1472 saveGeometry());
1473 LuminanceOptions().setValue(QStringLiteral("MainWindowSplitterState"),
1474 m_centralwidget_splitter->saveState());
1475 LuminanceOptions().setValue(
1476 QStringLiteral("MainWindowSplitterGeometry"),
1477 m_centralwidget_splitter->saveGeometry());
1478 LuminanceOptions().setValue(
1479 QStringLiteral("MainWindowBottomSplitterState"),
1480 m_bottom_splitter->saveState());
1481 LuminanceOptions().setValue(
1482 QStringLiteral("MainWindowBottomSplitterGeometry"),
1483 m_bottom_splitter->saveGeometry());
1484
1485 sm_updateChecker.reset();
1486 } else {
1487 sm_mainWindowMap.take(m_winId);
1488 int winId = sm_mainWindowMap.firstKey();
1489 MainWindow *p = sm_mainWindowMap[winId];
1490 disconnect(sm_updateChecker.data(), &UpdateChecker::updateAvailable, p,
1491 &MainWindow::onUpdateAvailable);
1492 sm_updateChecker->setParent(p);
1493 connect(sm_updateChecker.data(), &UpdateChecker::updateAvailable, p,
1494 &MainWindow::onUpdateAvailable);
1495 }
1496
1497 // Let's close all threads
1498 m_IOThread->quit(); // should be idle, quit() ok
1499 m_IOThread->wait();
1500 if (!m_TMProgressBar->isTerminated()) // MainWindow closed while
1501 // tonemapping is running
1502 {
1503 m_TMProgressBar->requestTermination();
1504 }
1505 m_TMThread->quit();
1506 m_TMThread->wait();
1507 m_QueueThread->quit(); // should be idle, quit() ok
1508 m_QueueThread->wait();
1509
1510 clearRecentFileActions();
1511 QMainWindow::closeEvent(event);
1512 }
1513
event(QEvent * event)1514 bool MainWindow::event(QEvent *event) {
1515 bool result = QMainWindow::event(event);
1516 if (event->type() == QEvent::WindowActivate && m_firstWindow == 1) {
1517 m_firstWindow = 2;
1518 if (LuminanceOptions().doShowWindowsOnWindows64Message()) {
1519 QMessageBox::warning(
1520 this, QStringLiteral("Luminance HDR 32-bit on 64-bit"),
1521 tr("It appears that you are running the 32-bit version "
1522 "<strong>Luminance HDR</strong> on a 64-bit system. <br>"
1523 "Please download the <strong>64-bit</strong> version from "
1524 "<a "
1525 "href=\"http://qtpfsgui.sourceforge.net\">http://"
1526 "qtpfsgui.sourceforge.net</a> "
1527 "to get the best Luminance HDR experience!"),
1528 QMessageBox::Ok, QMessageBox::NoButton);
1529 }
1530 }
1531 return result;
1532 }
1533
maybeSave()1534 bool MainWindow::maybeSave() {
1535 // if no HDR is open, return true
1536 if (!tm_status.is_hdr_ready) return true;
1537
1538 if (tm_status.curr_tm_frame->needsSaving()) {
1539 int ret = UMessageBox::saveDialog(
1540 tr("Unsaved changes..."), tr("This HDR image has unsaved "
1541 "changes.<br>Do you want to save it?"),
1542 this);
1543 switch (ret) {
1544 case QMessageBox::Save: {
1545 // if save == success return true;
1546 // else return false;
1547 // QString fname =
1548 // getHdrFileNameFromSaveDialog(QStringLiteral("Untitled"),
1549 // this);
1550 QString fname = getHdrFileNameFromSaveDialog(
1551 m_outputFileNamePrefix + "-" + m_HdrCaption, this);
1552
1553 if (!fname.isEmpty()) {
1554 // TODO : can I launch a signal and wait that it gets
1555 // executed
1556 // fully?
1557 return m_IOWorker->write_hdr_frame(
1558 qobject_cast<HdrViewer *>(tm_status.curr_tm_frame),
1559 fname);
1560 } else {
1561 return false;
1562 }
1563 } break;
1564 case QMessageBox::Discard: {
1565 return true;
1566 } break;
1567 case QMessageBox::Cancel:
1568 default: { return false; } break;
1569 }
1570 } else
1571 return true;
1572 }
1573
setupTM()1574 void MainWindow::setupTM() {
1575 // TODO: Building TM Thread
1576 tm_status.is_hdr_ready = false;
1577 tm_status.curr_tm_frame = nullptr;
1578 tm_status.curr_tm_options = nullptr;
1579
1580 m_tonemapPanel->setEnabled(false);
1581
1582 m_TMProgressBar = new TMOProgressIndicator;
1583 m_TMProgressBar->hide();
1584 statusBar()->addWidget(m_TMProgressBar);
1585
1586 connect(this, &QObject::destroyed, m_TMProgressBar, &QObject::deleteLater);
1587
1588 m_TMWorker = new TMWorker;
1589 m_TMThread = new QThread;
1590
1591 m_TMWorker->moveToThread(m_TMThread);
1592
1593 // Memory Management
1594 connect(this, &QObject::destroyed, m_TMWorker, &QObject::deleteLater);
1595 connect(m_TMWorker, &QObject::destroyed, m_TMThread, &QObject::deleteLater);
1596
1597 // get back result!
1598 connect(m_TMWorker, &TMWorker::tonemapSuccess, this,
1599 &MainWindow::addLdrFrame);
1600 connect(m_TMWorker, SIGNAL(tonemapFailed(QString)), this,
1601 SLOT(tonemapFailed(QString)));
1602
1603 // progress bar handling
1604 connect(m_TMWorker, &TMWorker::tonemapBegin, this,
1605 &MainWindow::tonemapBegin);
1606 connect(m_TMWorker, &TMWorker::tonemapEnd, this, &MainWindow::tonemapEnd);
1607
1608 connect(m_TMWorker, &TMWorker::tonemapSetValue, m_TMProgressBar,
1609 &TMOProgressIndicator::setValue);
1610 connect(m_TMWorker, &TMWorker::tonemapSetMaximum, m_TMProgressBar,
1611 &TMOProgressIndicator::setMaximum);
1612 connect(m_TMWorker, &TMWorker::tonemapSetMinimum, m_TMProgressBar,
1613 &TMOProgressIndicator::setMinimum);
1614 connect(m_TMProgressBar, &TMOProgressIndicator::terminate, m_TMWorker,
1615 &TMWorker::tonemapRequestTermination, Qt::DirectConnection);
1616
1617 // start thread waiting for signals (I/O requests)
1618 m_TMThread->start();
1619 }
1620
setupQueue()1621 void MainWindow::setupQueue() {
1622 m_QueueProgressBar = new TMOProgressIndicator;
1623 m_QueueProgressBar->hide();
1624 statusBar()->addWidget(m_QueueProgressBar);
1625
1626 connect(this, &QObject::destroyed, m_QueueProgressBar,
1627 &QObject::deleteLater);
1628
1629 m_QueueWorker = new TMWorker;
1630 m_QueueThread = new QThread;
1631
1632 m_QueueWorker->moveToThread(m_QueueThread);
1633
1634 // Memory Management
1635 connect(this, &QObject::destroyed, m_QueueWorker, &QObject::deleteLater);
1636 connect(m_QueueWorker, &QObject::destroyed, m_QueueThread,
1637 &QObject::deleteLater);
1638
1639 // get back result!
1640 // connect(m_QueueWorker, SIGNAL(tonemapSuccess(pfs::Frame*,
1641 // TonemappingOptions*)),
1642 // this, SLOT(addLdrFrame(pfs::Frame*, TonemappingOptions*)));
1643 connect(m_QueueWorker, SIGNAL(tonemapFailed(QString)), this,
1644 SLOT(tonemapFailed(QString)));
1645
1646 // progress bar handling
1647 connect(m_QueueWorker, &TMWorker::tonemapBegin, this,
1648 &MainWindow::exportBegin);
1649 connect(m_QueueWorker, &TMWorker::tonemapEnd, this, &MainWindow::exportEnd);
1650
1651 connect(m_QueueWorker, &TMWorker::tonemapSetValue, m_QueueProgressBar,
1652 &TMOProgressIndicator::setValue);
1653 connect(m_QueueWorker, &TMWorker::tonemapSetMaximum, m_QueueProgressBar,
1654 &TMOProgressIndicator::setMaximum);
1655 connect(m_QueueWorker, &TMWorker::tonemapSetMinimum, m_QueueProgressBar,
1656 &TMOProgressIndicator::setMinimum);
1657 connect(m_QueueProgressBar, &TMOProgressIndicator::terminate, m_QueueWorker,
1658 &TMWorker::tonemapRequestTermination, Qt::DirectConnection);
1659
1660 // start thread waiting for signals (I/O requests)
1661 m_QueueThread->start();
1662 }
1663
tonemapBegin()1664 void MainWindow::tonemapBegin() {
1665 // statusBar()->addWidget(m_TMProgressBar);
1666 m_TMProgressBar->setMaximum(0);
1667 m_TMProgressBar->show();
1668 }
1669
tonemapEnd()1670 void MainWindow::tonemapEnd() {
1671 // statusBar()->removeWidget(m_TMProgressBar);
1672 m_TMProgressBar->hide();
1673 m_TMProgressBar->reset();
1674 }
1675
exportBegin()1676 void MainWindow::exportBegin() {
1677 m_QueueProgressBar->setMaximum(0);
1678 m_QueueProgressBar->show();
1679 }
1680
exportEnd()1681 void MainWindow::exportEnd() {
1682 m_tonemapPanel->setExportQueueSize(--m_exportQueueSize);
1683 m_QueueProgressBar->hide();
1684 m_QueueProgressBar->reset();
1685 }
1686
tonemapImage(TonemappingOptions * opts)1687 void MainWindow::tonemapImage(TonemappingOptions *opts) {
1688 #ifdef QT_DEBUG
1689 qDebug() << "Start Tone Mapping";
1690 #endif
1691
1692 // Warning when using size dependent TMOs with smaller sizes
1693 if ((opts->tmoperator == fattal) &&
1694 (opts->operator_options.fattaloptions.fftsolver == false) &&
1695 (opts->xsize != opts->origxsize) &&
1696 (LuminanceOptions().isShowFattalWarning())) {
1697 UMessageBox warningDialog(this);
1698 warningDialog.setText(tr("Fattal Warning"));
1699 warningDialog.setInformativeText(
1700 tr("This tonemapping operator depends on the size of the input "
1701 " image. Applying this operator on the full size image will "
1702 "most probably result in a different image. "
1703 "\n\nDo you want to continue?"));
1704 warningDialog.setStandardButtons(
1705 QMessageBox::Yes | QMessageBox::YesToAll | QMessageBox::No);
1706 warningDialog.setDefaultButton(QMessageBox::No);
1707 warningDialog.setIcon(QMessageBox::Warning);
1708
1709 switch (warningDialog.exec()) {
1710 case QMessageBox::Yes: {
1711 } break;
1712 case QMessageBox::YesAll: {
1713 LuminanceOptions().setShowFattalWarning(false);
1714 } break;
1715 case QMessageBox::No:
1716 default: { return; }
1717 }
1718 }
1719
1720 m_PreviewPanel->setEnabled(false);
1721
1722 tm_status.curr_tm_options = opts;
1723
1724 if (tm_status.curr_tm_frame->hasSelection()) {
1725 opts->tonemapSelection = true;
1726
1727 getCropCoords(tm_status.curr_tm_frame, opts->selection_x_up_left,
1728 opts->selection_y_up_left, opts->selection_x_bottom_right,
1729 opts->selection_y_bottom_right);
1730 } else
1731 opts->tonemapSelection = false;
1732
1733 HdrViewer *hdr_viewer = qobject_cast<HdrViewer *>(tm_status.curr_tm_frame);
1734 if (hdr_viewer) {
1735 #ifdef QT_DEBUG
1736 qDebug() << "MainWindow(): emit getTonemappedFrame()";
1737 #endif
1738 // CALL m_TMWorker->getTonemappedFrame(hdr_viewer->getHDRPfsFrame(),
1739 // opts);
1740 QMetaObject::invokeMethod(
1741 m_TMWorker, "computeTonemap", Qt::QueuedConnection,
1742 Q_ARG(pfs::Frame *, hdr_viewer->getFrame()),
1743 Q_ARG(TonemappingOptions *, opts),
1744 Q_ARG(InterpolationMethod, m_interpolationMethod));
1745 }
1746 }
1747
exportImage(TonemappingOptions * opts)1748 void MainWindow::exportImage(TonemappingOptions *opts) {
1749 HdrViewer *hdr_viewer = qobject_cast<HdrViewer *>(tm_status.curr_tm_frame);
1750 if (hdr_viewer) {
1751 Params params = pfsadditions::FormatHelper::getParamsFromSettings(
1752 KEY_FILEFORMAT_QUEUE, false);
1753 QString hdrName = QFileInfo(getCurrentHDRName()).baseName();
1754
1755 QString inputfname;
1756 if (!m_inputFilesName.isEmpty()) inputfname = m_outputFileNamePrefix;
1757
1758 QString exportDir = LuminanceOptions().getExportDir();
1759
1760 m_tonemapPanel->setExportQueueSize(++m_exportQueueSize);
1761
1762 QMetaObject::invokeMethod(
1763 m_QueueWorker, "computeTonemapAndExport", Qt::QueuedConnection,
1764 Q_ARG(pfs::Frame *, hdr_viewer->getFrame()),
1765 Q_ARG(TonemappingOptions *, opts), Q_ARG(pfs::Params, params),
1766 Q_ARG(QString, exportDir), Q_ARG(QString, hdrName),
1767 Q_ARG(QString, inputfname), Q_ARG(QVector<float>, m_inputExpoTimes),
1768 Q_ARG(InterpolationMethod, m_interpolationMethod));
1769 }
1770 }
1771
addLdrFrame(pfs::Frame * frame,TonemappingOptions * tm_options)1772 void MainWindow::addLdrFrame(pfs::Frame *frame,
1773 TonemappingOptions *tm_options) {
1774 if (m_tonemapPanel->doAutoLevels()) {
1775 float threshold, minL, maxL, gammaL;
1776 threshold = m_tonemapPanel->getAutoLevelsThreshold();
1777 QScopedPointer<QImage> temp_qimage(fromLDRPFStoQImage(frame));
1778 computeAutolevels(temp_qimage.data(), threshold, minL, maxL, gammaL);
1779 pfs::gammaAndLevels(frame, minL, maxL, 0.f, 1.f, gammaL);
1780 }
1781
1782 GenericViewer *n =
1783 static_cast<GenericViewer *>(m_tabwidget->currentWidget());
1784 if (m_tonemapPanel->replaceLdr() && n != nullptr && !n->isHDR()) {
1785 n->setFrame(frame, tm_options);
1786 } else {
1787 curr_num_ldr_open++;
1788 num_ldr_generated++;
1789
1790 n = new LdrViewer(frame, tm_options, this, true);
1791
1792 connect(n, &GenericViewer::changed, this, &MainWindow::syncViewers);
1793 connect(n, &GenericViewer::changed, this,
1794 &MainWindow::updateMagnificationButtons);
1795 connect(n, &GenericViewer::reparent, this, &MainWindow::reparentViewer);
1796 connect(n, &GenericViewer::goNext, this, &MainWindow::showNextViewer);
1797 connect(n, &GenericViewer::goPrevious, this,
1798 &MainWindow::showPreviousViewer);
1799 connect(n, &GenericViewer::syncViewers, this,
1800 &MainWindow::setSyncViewers);
1801
1802 if (num_ldr_generated == 1)
1803 m_tabwidget->addTab(n, tr("Untitled"));
1804 else
1805 m_tabwidget->addTab(n, tr("Untitled %1").arg(num_ldr_generated));
1806
1807 n->setViewerMode(getCurrentViewerMode(*m_tabwidget));
1808 }
1809 m_tabwidget->setCurrentWidget(n);
1810
1811 m_PreviewPanel->setEnabled(true);
1812
1813 if (m_Ui->actionSoft_Proofing->isChecked()) {
1814 LdrViewer *viewer = static_cast<LdrViewer *>(n);
1815 viewer->doSoftProofing(false);
1816 } else if (m_Ui->actionGamut_Check->isChecked()) {
1817 LdrViewer *viewer = static_cast<LdrViewer *>(n);
1818 viewer->doSoftProofing(true);
1819 }
1820 }
1821
tonemapFailed(const QString & error_msg)1822 void MainWindow::tonemapFailed(const QString &error_msg) {
1823 if (error_msg != QLatin1String("Canceled")) {
1824 QMessageBox::critical(this, tr("Luminance HDR"),
1825 tr("Error: %1").arg(error_msg), QMessageBox::Ok,
1826 QMessageBox::NoButton);
1827 }
1828 m_tonemapPanel->setEnabled(true);
1829 m_PreviewPanel->setEnabled(true);
1830 m_TMProgressBar->hide();
1831 }
1832
1833 /*
1834 * Lock Handling
1835 */
on_actionLock_toggled(bool)1836 void MainWindow::on_actionLock_toggled(bool /*toggled*/) {
1837 if (m_Ui->actionLock->isChecked() && m_tabwidget->count()) {
1838 syncViewers(qobject_cast<GenericViewer *>(m_tabwidget->currentWidget()));
1839 }
1840 }
1841
syncViewers(GenericViewer * sender)1842 void MainWindow::syncViewers(GenericViewer *sender) {
1843 if (sender == nullptr) return;
1844 if (!m_Ui->actionLock->isChecked()) return;
1845
1846 for (int idx = 0; idx < m_tabwidget->count(); idx++) {
1847 GenericViewer *viewer = qobject_cast<GenericViewer *>(m_tabwidget->widget(idx));
1848 if (viewer == nullptr)
1849 return; // this happens when a tab is removed and sync viewers is
1850 // active,
1851 // fixes a crash
1852 if (sender != viewer) {
1853 viewer->blockSignals(true);
1854 viewer->syncViewer(sender);
1855 viewer->blockSignals(false);
1856 }
1857 }
1858 }
1859
showPreviewPanel(bool b)1860 void MainWindow::showPreviewPanel(bool b) {
1861 m_Ui->actionRealtimePreviews->setEnabled(b);
1862 m_tonemapPanel->setRealtimePreviews(b && LuminanceOptions().isRealtimePreviewsActive());
1863 if (b) {
1864 if (tm_status.is_hdr_ready) {
1865 m_PreviewscrollArea->show();
1866 // ask panel to refresh itself
1867 m_PreviewPanel->setAutolevels(
1868 m_tonemapPanel->doAutoLevels(),
1869 m_tonemapPanel->getAutoLevelsThreshold());
1870 m_PreviewPanel->updatePreviews(tm_status.curr_tm_frame->getFrame());
1871
1872 // connect signals
1873 connect(this, SIGNAL(updatedHDR(pfs::Frame *)), m_PreviewPanel,
1874 SLOT(updatePreviews(pfs::Frame *)));
1875 connect(m_PreviewPanel, &PreviewPanel::startTonemapping, this,
1876 &MainWindow::tonemapImage);
1877 connect(m_PreviewPanel, &PreviewPanel::startTonemapping,
1878 m_tonemapPanel, &TonemappingPanel::updateTonemappingParams);
1879 connect(m_tonemapPanel, SIGNAL(autoLevels(bool, float)), this,
1880 SLOT(updatePreviews(bool, float)));
1881 }
1882 } else {
1883 m_PreviewscrollArea->hide();
1884
1885 // disconnect signals
1886 disconnect(this, SIGNAL(updatedHDR(pfs::Frame *)), m_PreviewPanel,
1887 SLOT(updatePreviews(pfs::Frame *)));
1888 disconnect(m_PreviewPanel, &PreviewPanel::startTonemapping, this,
1889 &MainWindow::tonemapImage);
1890 disconnect(m_PreviewPanel, &PreviewPanel::startTonemapping,
1891 m_tonemapPanel, &TonemappingPanel::updateTonemappingParams);
1892 disconnect(m_tonemapPanel, SIGNAL(autoLevels(bool, float)), this,
1893 SLOT(updatePreviews(bool, float)));
1894 }
1895 }
1896
updatePreviews(bool b,float th)1897 void MainWindow::updatePreviews(bool b, float th) {
1898 if (m_Ui->actionShowPreviewPanel->isChecked()) {
1899 if (tm_status.is_hdr_ready) {
1900 m_PreviewPanel->setAutolevels(b, th);
1901 // ask panel to refresh itself
1902 m_PreviewPanel->updatePreviews(tm_status.curr_tm_frame->getFrame());
1903 }
1904 }
1905 }
1906
updateMagnificationButtons(GenericViewer * c_v)1907 void MainWindow::updateMagnificationButtons(GenericViewer *c_v) {
1908 if (c_v == nullptr) return;
1909 bool isNormalSize = c_v->isNormalSize();
1910 bool isFilledToWindow = c_v->isFilledToWindow();
1911 bool isFittedToWindow = c_v->isFittedToWindow();
1912
1913 m_Ui->zoomInAct->setChecked(isFilledToWindow || isFittedToWindow);
1914 m_Ui->zoomInAct->setEnabled(isFilledToWindow || isFittedToWindow);
1915 m_Ui->zoomOutAct->setChecked(isFittedToWindow);
1916 m_Ui->zoomOutAct->setEnabled(!isFittedToWindow);
1917
1918 m_Ui->normalSizeAct->setChecked(isNormalSize);
1919 m_Ui->normalSizeAct->setEnabled(!isNormalSize);
1920 m_Ui->fitToWindowAct->setChecked(isFittedToWindow);
1921 m_Ui->fitToWindowAct->setEnabled(!isFittedToWindow);
1922 m_Ui->actionFill_to_Window->setChecked(isFilledToWindow);
1923 m_Ui->actionFill_to_Window->setEnabled(!isFilledToWindow);
1924 }
1925
on_actionRemove_Tab_triggered()1926 void MainWindow::on_actionRemove_Tab_triggered() {
1927 removeTab(m_tabwidget->currentIndex());
1928 }
1929
removeTab(int t)1930 void MainWindow::removeTab(int t) {
1931 #ifdef QT_DEBUG
1932 qDebug() << "MainWindow::remove_image(" << t << ")";
1933 #endif
1934 if (t < 0) return;
1935
1936 GenericViewer *w = qobject_cast<GenericViewer *>(m_tabwidget->widget(t));
1937 w->blockSignals(true);
1938 if (w->isHDR()) {
1939 bool doClose = false;
1940
1941 #ifdef QT_DEBUG
1942 qDebug() << "Remove HDR from MainWindow";
1943 #endif
1944 if (w->needsSaving()) {
1945 if (maybeSave()) {
1946 // if discard OR saved
1947 doClose = true;
1948 }
1949 // if FALSE, it means that the user said "Cancel"
1950 // or the saving operation went wrong
1951 // and we don't need to remove any tab
1952 else {
1953 w->blockSignals(false);
1954 }
1955 } else
1956 doClose = true;
1957
1958 if (doClose) {
1959 m_tabwidget->removeTab(t);
1960 w->deleteLater(); // delete yourself whenever you want
1961
1962 showPreviewPanel(false);
1963 setWindowModified(false);
1964
1965 tm_status.is_hdr_ready = false;
1966 tm_status.curr_tm_frame = nullptr;
1967 tm_status.curr_tm_options = nullptr;
1968
1969 m_tonemapPanel->setEnabled(false);
1970
1971 m_inputFilesName.clear();
1972 m_inputExpoTimes.clear();
1973
1974 m_PreviewscrollArea->hide();
1975 }
1976 } else {
1977 curr_num_ldr_open--;
1978 m_tabwidget->removeTab(t);
1979 w->deleteLater(); // delete yourself whenever you want
1980
1981 if (curr_num_ldr_open == 1) m_Ui->fileSaveAllAction->setEnabled(false);
1982 }
1983 }
1984
getCurrentHDRName()1985 QString MainWindow::getCurrentHDRName() {
1986 if (tm_status.is_hdr_ready) {
1987 return tm_status.curr_tm_frame->getFileName();
1988 } else {
1989 return QString(tr("Untitled HDR"));
1990 }
1991 }
1992
setMainWindowModified(bool b)1993 void MainWindow::setMainWindowModified(bool b) {
1994 if (b) {
1995 if (tm_status.is_hdr_ready) {
1996 tm_status.curr_tm_frame->setNeedsSaving(true);
1997 setWindowModified(true);
1998 }
1999 } else {
2000 if (tm_status.is_hdr_ready) {
2001 tm_status.curr_tm_frame->setNeedsSaving(false);
2002 }
2003 setWindowModified(false);
2004 }
2005 }
2006
2007 /*
2008 * Recent File Handling
2009 */
setCurrentFile(const QString & fileName)2010 void MainWindow::setCurrentFile(const QString &fileName) {
2011 QStringList files =
2012 LuminanceOptions().value(KEY_RECENT_FILES).toStringList();
2013 files.removeAll(fileName);
2014 files.prepend(fileName);
2015 while (files.size() > MAX_RECENT_FILES) {
2016 files.removeLast();
2017 }
2018
2019 LuminanceOptions().setValue(KEY_RECENT_FILES, files);
2020
2021 // Update ALL MainWindow
2022 foreach (QWidget *widget, QApplication::topLevelWidgets()) {
2023 MainWindow *mainWin = qobject_cast<MainWindow *>(widget);
2024 if (mainWin) mainWin->updateRecentFileActions();
2025 }
2026
2027 OsIntegration::getInstance().addRecentFile(fileName);
2028 }
2029
updateRecentFileActions()2030 void MainWindow::updateRecentFileActions() {
2031 QStringList files =
2032 LuminanceOptions().value(KEY_RECENT_FILES).toStringList();
2033
2034 int numRecentFiles = qMin(files.size(), (int)MAX_RECENT_FILES);
2035 separatorRecentFiles->setVisible(numRecentFiles > 0);
2036
2037 for (int i = 0; i < numRecentFiles; ++i) {
2038 QString text = QStringLiteral("&%1 %2").arg(i + 1).arg(
2039 QFileInfo(files[i]).fileName());
2040 recentFileActs[i]->setText(text);
2041 recentFileActs[i]->setData(files[i]);
2042 recentFileActs[i]->setVisible(true);
2043 }
2044 for (int j = numRecentFiles; j < MAX_RECENT_FILES; ++j) {
2045 recentFileActs[j]->setVisible(false);
2046 }
2047 }
2048
initRecentFileActions()2049 void MainWindow::initRecentFileActions() {
2050 separatorRecentFiles = m_Ui->menuFile->addSeparator();
2051
2052 for (int i = 0; i < MAX_RECENT_FILES; ++i) {
2053 recentFileActs[i] = new QAction(this);
2054 recentFileActs[i]->setVisible(false);
2055 m_Ui->menuFile->addAction(recentFileActs[i]);
2056 connect(recentFileActs[i], &QAction::triggered, this,
2057 &MainWindow::openRecentFile);
2058 }
2059 }
2060
clearRecentFileActions()2061 void MainWindow::clearRecentFileActions() {
2062 for (int i = 0; i < MAX_RECENT_FILES; ++i) {
2063 delete recentFileActs[i];
2064 }
2065 }
2066
on_actionFix_Histogram_toggled(bool checked)2067 void MainWindow::on_actionFix_Histogram_toggled(bool checked) {
2068 if (checked) {
2069 GenericViewer *current = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
2070 if (current == nullptr) return;
2071 if (current->isHDR()) return;
2072
2073 QScopedPointer<GammaAndLevels> g_n_l(
2074 new GammaAndLevels(this, current->getQImage()));
2075
2076 m_Ui->actionFix_Histogram->setDisabled(true);
2077
2078 connect(g_n_l.data(), SIGNAL(updateQImage(QImage)), current,
2079 SLOT(setQImage(QImage)));
2080 int exit_status = g_n_l->exec();
2081
2082 if (exit_status == 1) {
2083 #ifdef QT_DEBUG
2084 qDebug() << "GammaAndLevels accepted!";
2085 #endif
2086 // pfs::Frame * frame = current->getFrame();
2087 pfs::gammaAndLevels(
2088 current->getFrame(), g_n_l->getBlackPointInput(),
2089 g_n_l->getWhitePointInput(), g_n_l->getBlackPointOutput(),
2090 g_n_l->getWhitePointOutput(), g_n_l->getGamma());
2091
2092 // current->setFrame(frame);
2093 } else {
2094 #ifdef QT_DEBUG
2095 qDebug() << "GammaAndLevels refused!";
2096 #endif
2097 current->setQImage(g_n_l->getReferenceQImage());
2098 }
2099
2100 m_Ui->actionFix_Histogram->setDisabled(false);
2101 m_Ui->actionFix_Histogram->setChecked(false);
2102 }
2103 }
2104
2105
on_actionWhite_Balance_triggered()2106 void MainWindow::on_actionWhite_Balance_triggered() {
2107 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
2108 m_Ui->actionWhite_Balance->setEnabled(false);
2109 m_processingAWB = true;
2110 m_viewerToProcess = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
2111 m_tabwidget->setTabEnabled(m_tabwidget->currentIndex(), false);
2112
2113 Frame *frame = m_viewerToProcess->getFrame();
2114
2115 m_futureWatcher.setFuture(QtConcurrent::run(
2116 boost::bind(whiteBalance, boost::ref(*frame), WB_COLORBALANCE)));
2117 }
2118
whiteBalanceDone()2119 void MainWindow::whiteBalanceDone() {
2120 QApplication::restoreOverrideCursor();
2121 m_processingAWB = false;
2122 m_Ui->actionWhite_Balance->setEnabled(true);
2123 m_viewerToProcess->setEnabled(true);
2124 m_tabwidget->setTabEnabled(m_tabwidget->indexOf(m_viewerToProcess), true);
2125 m_tabwidget->setCurrentWidget(m_viewerToProcess);
2126 m_viewerToProcess->updatePixmap();
2127 if (m_viewerToProcess->isHDR()) {
2128 m_viewerToProcess->setNeedsSaving(true);
2129 m_PreviewPanel->updatePreviews(tm_status.curr_tm_frame->getFrame());
2130 }
2131 }
2132
on_actionSoft_Proofing_toggled(bool doProof)2133 void MainWindow::on_actionSoft_Proofing_toggled(bool doProof) {
2134 GenericViewer *current = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
2135 if (current == nullptr) return;
2136 if (current->isHDR()) return;
2137 LdrViewer *viewer = static_cast<LdrViewer *>(current);
2138 if (doProof) {
2139 #ifdef QT_DEBUG
2140 qDebug() << "MainWindow:: do soft proofing";
2141 #endif
2142 if (m_Ui->actionGamut_Check->isChecked())
2143 m_Ui->actionGamut_Check->setChecked(false);
2144 viewer->doSoftProofing(false);
2145 } else {
2146 #ifdef QT_DEBUG
2147 qDebug() << "MainWindow:: undo soft proofing";
2148 #endif
2149 viewer->undoSoftProofing();
2150 }
2151 }
2152
on_actionGamut_Check_toggled(bool doGamut)2153 void MainWindow::on_actionGamut_Check_toggled(bool doGamut) {
2154 GenericViewer *current = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
2155 if (current == nullptr) return;
2156 if (current->isHDR()) return;
2157 LdrViewer *viewer = static_cast<LdrViewer *>(current);
2158 if (doGamut) {
2159 #ifdef QT_DEBUG
2160 qDebug() << "MainWindow:: do gamut check";
2161 #endif
2162 if (m_Ui->actionSoft_Proofing->isChecked())
2163 m_Ui->actionSoft_Proofing->setChecked(false);
2164 viewer->doSoftProofing(true);
2165 } else {
2166 #ifdef QT_DEBUG
2167 qDebug() << "MainWindow:: undo gamut check";
2168 #endif
2169 viewer->undoSoftProofing();
2170 }
2171 }
2172
updateSoftProofing(int i)2173 void MainWindow::updateSoftProofing(int i) {
2174 QWidget *wgt = m_tabwidget->widget(i);
2175 GenericViewer *g_v = qobject_cast<GenericViewer *>(wgt);
2176
2177 if (g_v == nullptr) return;
2178 if (!g_v->isHDR()) {
2179 LdrViewer *l_v = static_cast<LdrViewer *>(g_v);
2180 if (!m_Ui->actionSoft_Proofing->isChecked() &&
2181 !m_Ui->actionGamut_Check->isChecked()) {
2182 l_v->undoSoftProofing();
2183 } else if (m_Ui->actionSoft_Proofing->isChecked()) {
2184 l_v->doSoftProofing(false);
2185 } else if (m_Ui->actionGamut_Check->isChecked()) {
2186 l_v->doSoftProofing(true);
2187 }
2188 }
2189 }
2190
showPreviewsOnTheRight()2191 void MainWindow::showPreviewsOnTheRight() {
2192 m_PreviewscrollArea->setParent(m_centralwidget_splitter);
2193 LuminanceOptions().setPreviewPanelMode(0);
2194 }
2195
showPreviewsOnTheBottom()2196 void MainWindow::showPreviewsOnTheBottom() {
2197 m_PreviewscrollArea->setParent(m_bottom_splitter);
2198 LuminanceOptions().setPreviewPanelMode(1);
2199 }
2200
on_actionFits_Importer_triggered()2201 void MainWindow::on_actionFits_Importer_triggered() {
2202 #ifdef HAVE_CFITSIO
2203 FitsImporter importer;
2204
2205 if (importer.exec() == QDialog::Accepted) {
2206 emit load_success(importer.getFrame(), tr("FITS Image"), importer.getFilenames(), true);
2207 }
2208 #endif
2209 }
2210
on_actionShow_Full_Screen_toggled(bool b)2211 void MainWindow::on_actionShow_Full_Screen_toggled(bool b) {
2212 b ? this->showFullScreen() : this->showMaximized();
2213 }
2214
on_actionShow_Image_Full_Screen_triggered()2215 void MainWindow::on_actionShow_Image_Full_Screen_triggered() {
2216 if (m_isFullscreenViewer) {
2217 return;
2218 }
2219 m_isFullscreenViewer = true;
2220 m_fullscreenViewerIndex = m_tabwidget->currentIndex();
2221 m_tabText = m_tabwidget->tabText(m_fullscreenViewerIndex);
2222 m_g_v_fullscreen = qobject_cast<GenericViewer *>(m_tabwidget->currentWidget());
2223 m_g_v_fullscreen->setParent(0);
2224 m_g_v_fullscreen->showFullScreen();
2225 }
2226
reparentViewer(GenericViewer * g_v,bool close)2227 void MainWindow::reparentViewer(GenericViewer *g_v, bool close) {
2228 m_tabwidget->insertTab(m_fullscreenViewerIndex, g_v, m_tabText);
2229 m_tabwidget->setCurrentIndex(m_fullscreenViewerIndex);
2230 g_v->showNormal();
2231 m_isFullscreenViewer = false;
2232 if (close) {
2233 on_actionRemove_Tab_triggered();
2234 }
2235 }
2236
showNextViewer(GenericViewer * g_v)2237 void MainWindow::showNextViewer(GenericViewer *g_v) {
2238 int count = m_tabwidget->count();
2239 if (count >= 1) {
2240 reparentViewer(g_v);
2241 int idx = m_tabwidget->currentIndex();
2242 int next = (idx + 1) % (count + 1);
2243 m_tabwidget->setCurrentIndex(next);
2244 on_actionShow_Image_Full_Screen_triggered();
2245 }
2246 }
2247
showPreviousViewer(GenericViewer * g_v)2248 void MainWindow::showPreviousViewer(GenericViewer *g_v) {
2249 int count = m_tabwidget->count();
2250 if (count >= 1) {
2251 reparentViewer(g_v);
2252 int idx = m_tabwidget->currentIndex();
2253 int previous;
2254 if (idx == 0) {
2255 previous = count;
2256 } else {
2257 previous = (idx - 1) % (count + 1);
2258 }
2259 m_tabwidget->setCurrentIndex(previous);
2260 on_actionShow_Image_Full_Screen_triggered();
2261 }
2262 }
2263
setSyncViewers(GenericViewer * g_v)2264 void MainWindow::setSyncViewers(GenericViewer *g_v) {
2265 if (g_v == nullptr) return;
2266 m_Ui->actionLock->setChecked(!m_Ui->actionLock->isChecked());
2267 if (m_Ui->actionLock->isChecked() && (m_tabwidget->count() - 1)) {
2268 syncViewers(g_v);
2269 }
2270 }
2271
on_actionSelect_Interpolation_Method_toggled(bool b)2272 void MainWindow::on_actionSelect_Interpolation_Method_toggled(bool b) {
2273 m_interpolationMethod = b ? LanczosInterp : BilinearInterp;
2274 }
2275
on_actionOnline_Documentation_triggered()2276 void MainWindow::on_actionOnline_Documentation_triggered() {
2277 QDesktopServices::openUrl(
2278 QUrl(QStringLiteral("http://luminancehdr.readthedocs.io/en/latest/")));
2279 }
2280
on_actionDevelopers_Website_triggered()2281 void MainWindow::on_actionDevelopers_Website_triggered() {
2282 QDesktopServices::openUrl(
2283 QUrl(QStringLiteral("https://github.com/LuminanceHDR/")));
2284 }
2285
on_actionLuminance_HDR_Website_triggered()2286 void MainWindow::on_actionLuminance_HDR_Website_triggered() {
2287 QDesktopServices::openUrl(
2288 QUrl(QStringLiteral("http://qtpfsgui.sourceforge.net/")));
2289 }
2290
setRealtimePreviewsActive(bool b)2291 void MainWindow::setRealtimePreviewsActive(bool b) {
2292 LuminanceOptions().setRealtimePreviewsActive(b);
2293 }
2294
setPreviewPanelActive(bool b)2295 void MainWindow::setPreviewPanelActive(bool b) {
2296 LuminanceOptions().setPreviewPanelActive(b);
2297 }
2298