1 /*******************************************************************************
2 **
3 ** Photivo
4 **
5 ** Copyright (C) 2008,2009 Jos De Laender <jos.de_laender@telenet.be>
6 ** Copyright (C) 2009-2011 Michael Munzert <mail@mm-log.com>
7 ** Copyright (C) 2013 Alexander Tzyganenko <tz@fast-report.com>
8 **
9 ** This file is part of Photivo.
10 **
11 ** Photivo is free software: you can redistribute it and/or modify
12 ** it under the terms of the GNU General Public License version 3
13 ** as published by the Free Software Foundation.
14 **
15 ** Photivo is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 ** GNU General Public License for more details.
19 **
20 ** You should have received a copy of the GNU General Public License
21 ** along with Photivo.  If not, see <http://www.gnu.org/licenses/>.
22 **
23 *******************************************************************************/
24 
25 #include "ptDefines.h"
26 #include "ptConfirmRequest.h"
27 #include "ptConstants.h"
28 #include "ptError.h"
29 #include "ptGuiOptions.h"
30 #include "ptMainWindow.h"
31 #include "ptMessageBox.h"
32 #include "ptSettings.h"
33 #include "ptTheme.h"
34 #include "ptViewWindow.h"
35 #include "ptWhiteBalances.h"
36 
37 #include "filters/ptFilterDM.h"
38 #include "filters/ptFilterBase.h"
39 #include "ptToolBox.h"
40 
41 #ifdef Q_OS_WIN
42   #include "ptEcWin7.h"
43 #endif
44 
45 #include <QDesktopWidget>
46 #include <QFileDialog>
47 
48 #include <iomanip>
49 #include <iostream>
50 #include <cassert>
51 
52 using namespace std;
53 
54 extern ptTheme* Theme;
55 extern ptViewWindow* ViewWindow;
56 extern QString ImageFileToOpen;
57 extern QString PtsFileToOpen;
58 extern short ImageCleanUp;
59 
60 void CB_MenuFileOpen(const short HaveFile);
61 void CB_OpenSettingsFile(QString SettingsFileName);
62 void CB_OpenFileButton();
63 void CB_ZoomStep(int direction);
64 void ReadSidecar(const QString& Sidecar);
65 
66 // undo-redo & clipboard support
67 void ptMakeUndo();
68 void ptMakeRedo();
69 void ptClearUndoRedo();
70 void ptMakeFullUndo();
71 void ptResetSettingsToDefault();
72 void ptCopySettingsToClipboard();
73 void ptPasteSettingsFromClipboard();
74 
75 
76 ////////////////////////////////////////////////////////////////////////////////
77 //
78 // Here follow a bunch of macro's to avoid repetitive code for lots of
79 // the Gui elements.
80 //
81 ////////////////////////////////////////////////////////////////////////////////
82 
83 // Connect a menu action.
84 
85 // Must be bool for the checkable menu items !
86 #define Macro_ConnectSomeMenu(Some)                                    \
87   connect( action ## Some,SIGNAL(triggered(bool)),                     \
88           this,SLOT(On ## Some ## Triggered(bool)));
89 
90 // Connect a button.
91 
92 #define Macro_ConnectSomeButton(Some)                                  \
93   connect(Some ## Button,SIGNAL(clicked()),                            \
94           this,SLOT(On ## Some ## ButtonClicked()));
95 
96 // Callback into main for a menu item activated.
97 
98 #define Macro_OnSomeMenuActivated(Some)                           \
99 void CB_Menu ## Some(const short Enabled);                        \
100 void ptMainWindow::On ## Some ## Triggered(const bool  Enabled) { \
101   ::CB_Menu ## Some(Enabled);                                     \
102 }
103 
104 // Leftover from removing the menu
105 void CB_MenuFileExit(const short);
106 
107 // Prototype
108 void Update(short Phase,
109             short SubPhase      = -1,
110             short WithIdentify  = 1,
111             short ProcessorMode = ptProcessorMode_Preview);
112 
113 void Update(const QString GuiName);
114 
115 //==============================================================================
116 
ptMainWindow(const QString Title)117 ptMainWindow::ptMainWindow(const QString Title)
118 : QMainWindow(NULL)
119 {
120   FUIState = uisNone;
121 
122   // Setup from the Gui builder.
123   setupUi(this);
124   setWindowTitle(Title);
125 
126   // Initialize Win 7 taskbar features
127   #ifdef Q_OS_WIN
128     ptEcWin7::CreateInstance(this);
129   #endif
130 
131   // Move the fullscreen button in the zoom bar a bit to the left
132   // to make space for the Mac window resize handle
133   #ifdef Q_OS_MAC
134     MacSpacer->setFixedWidth(16);
135   #endif
136 
137   MainSplitter->setStretchFactor(1,1);
138   ViewSplitter->setStretchFactor(0,1);
139 
140   // Some corrections that often go wrong in the manual
141   // layout using the designer.
142 
143   QList <QVBoxLayout *> VBoxes = MainTabBook->findChildren <QVBoxLayout *> ();
144   for (short i=0; i<VBoxes.size(); i++) {
145     VBoxes[i]->setMargin(2);
146     VBoxes[i]->setContentsMargins(2,2,2,2);
147   }
148 
149   // Initial value. We remember locally for the case that a
150   // a new photograph is from another camera. This is then detected
151   // for other whitebalances.
152   m_CameraMake  = Settings->GetString("CameraMake");
153   m_CameraModel = Settings->GetString("CameraModel");
154 
155   // Go and construct all the input,choice .. gui elements.
156   const QStringList Keys = Settings->GetKeys();
157   for (int i=0; i<Keys.size(); i++) {
158     const QString Key = Keys[i];
159     //printf("(%s,%d) '%s'\n",__FILE__,__LINE__,Key.toLocal8Bit().data());
160     switch (Settings->GetGuiType(Key)) {
161 
162       case ptGT_InputSlider :
163       case ptGT_Input       :
164         //printf("(%s,%d) Creating Input for '%s'\n",
165         //       __FILE__,__LINE__,Key.toLocal8Bit().data());
166         {
167         QString ParentName = Key + "Widget";
168         QString ObjectName = Key + "Input";
169         ptInput* Input =
170           new ptInput(this,
171                       ObjectName,
172                       ParentName,
173                       Settings->GetGuiType(Key) == ptGT_InputSlider,
174                       0,
175                       Settings->GetHasDefaultValue(Key),
176                       Settings->GetDefaultValue(Key),
177                       Settings->GetMinimumValue(Key),
178                       Settings->GetMaximumValue(Key),
179                       Settings->GetStep(Key),
180                       Settings->GetNrDecimals(Key),
181                       Settings->GetLabel(Key),
182                       Settings->GetToolTip(Key),
183                       ptTimeout_Input);
184         connect(Input,SIGNAL(valueChanged(QVariant)),
185                 this,SLOT(OnInputChanged(QVariant)));
186         //m_GuiInputs[ObjectName] = Input;
187         Settings->SetGuiInput(Key,Input);
188         }
189         break;
190       case ptGT_InputSliderHue :
191         //printf("(%s,%d) Creating Input for '%s'\n",
192         //       __FILE__,__LINE__,Key.toLocal8Bit().data());
193         {
194         QString ParentName = Key + "Widget";
195         QString ObjectName = Key + "Input";
196         ptInput* Input =
197           new ptInput(this,
198                       ObjectName,
199                       ParentName,
200                       1,
201                       1,
202                       Settings->GetHasDefaultValue(Key),
203                       Settings->GetDefaultValue(Key),
204                       Settings->GetMinimumValue(Key),
205                       Settings->GetMaximumValue(Key),
206                       Settings->GetStep(Key),
207                       Settings->GetNrDecimals(Key),
208                       Settings->GetLabel(Key),
209                       Settings->GetToolTip(Key),
210                       ptTimeout_Input);
211         connect(Input,SIGNAL(valueChanged(QVariant)),
212                 this,SLOT(OnInputChanged(QVariant)));
213         //m_GuiInputs[ObjectName] = Input;
214         Settings->SetGuiInput(Key,Input);
215         }
216         break;
217       case ptGT_Choice :
218         //printf("(%s,%d) Creating Choice for '%s'\n",
219         //       __FILE__,__LINE__,Key.toLocal8Bit().data());
220         {
221         QString ParentName = Key + "Widget";
222         QString ObjectName = Key + "Choice";
223         ptChoice* Choice =
224           new ptChoice(this,
225                        ObjectName,
226                        ParentName,
227                        Settings->GetHasDefaultValue(Key),
228                        Settings->GetDefaultValue(Key),
229                        Settings->GetInitialOptions(Key),
230                        Settings->GetToolTip(Key),
231                        ptTimeout_Input);
232         connect(Choice,SIGNAL(valueChanged(QVariant)),
233                 this,SLOT(OnInputChanged(QVariant)));
234         //m_GuiChoices[ObjectName] = Choice;
235         Settings->SetGuiChoice(Key,Choice);
236         }
237         break;
238 
239       case ptGT_Check :
240         //printf("(%s,%d) Creating Check for '%s'\n",
241         //       __FILE__,__LINE__,Key.toLocal8Bit().data());
242         {
243         QString ParentName = Key + "Widget";
244         QString ObjectName = Key + "Check";
245         ptCheck* Check =
246           new ptCheck(this,
247                       ObjectName,
248                       ParentName,
249                       Settings->GetDefaultValue(Key),
250                       Settings->GetLabel(Key),
251                       Settings->GetToolTip(Key));
252         connect(Check,SIGNAL(valueChanged(QVariant)),
253                 this,SLOT(OnInputChanged(QVariant)));
254         //m_GuiChecks[ObjectName] = Check;
255         Settings->SetGuiCheck(Key,Check);
256         }
257         break;
258 
259       default :
260         //printf("(%s,%d) No widget for '%s'\n",
261         //       __FILE__,__LINE__,Key.toLocal8Bit().data());
262         continue;
263     };
264     // To sync the state of the now created gui element we have
265     // to set the value. As the setting now has the gui element
266     // attached, it will be updated.
267     Settings->SetValue(Key,Settings->GetValue(Key));
268   }
269 
270   //
271   // Menu structure related.
272   //
273 
274   // menu removed ;-)
275 
276   // Leftover after menu was removed
277 
278   m_GroupBox = NULL;
279   m_GroupBoxesOrdered = NULL;
280   m_TabLayouts = NULL;
281   m_MovedTools = new QList<QWidget*>;
282 
283   // NOTE: Following function does the UI replacing and ptGroupBox creation.
284   // It also initializes new-style filters.
285   OnToolBoxesEnabledTriggered(0);
286 
287   // Inserting new-style filters postponed to here because a fully functional m_TabLayouts
288   // is needed.
289   for (ptFilterBase *hFilter: *GFilterDM) {
290     m_TabLayouts->at(hFilter->parentTabIdx())->insertWidget(hFilter->idxInParentTab(),
291                                                             hFilter->gui());
292   }
293 
294   //
295   // Run pipe related
296   //
297 
298   Macro_ConnectSomeButton(PreviewMode);
299   PreviewModeButton->setChecked(Settings->GetInt("PreviewMode"));
300 
301   Macro_ConnectSomeButton(Run);
302   RunButton->setEnabled(Settings->GetInt("RunMode"));
303 
304   Macro_ConnectSomeButton(TabProcessing);
305   Macro_ConnectSomeButton(TabSettings);
306   Macro_ConnectSomeButton(TabInfo);
307 
308   //
309   // Zoom related
310   //
311 
312   BottomContainer->setVisible(Settings->GetInt("ShowBottomContainer"));
313 
314   Macro_ConnectSomeButton(ZoomFit);
315   Macro_ConnectSomeButton(ZoomIn);
316   Macro_ConnectSomeButton(ZoomOut);
317   Macro_ConnectSomeButton(ZoomFull);
318   Macro_ConnectSomeButton(Batch);
319   Macro_ConnectSomeButton(FileMgr);
320   Macro_ConnectSomeButton(FullScreen);
321   FullScreenButton->setChecked(0);
322   Macro_ConnectSomeButton(LoadStyle);
323   Macro_ConnectSomeButton(PreviousImage);
324   Macro_ConnectSomeButton(NextImage);
325 
326 
327   //
328   // Connect Export button (not only for Gimp like the name suggests)
329   //
330   Macro_ConnectSomeButton(ToGimp);
331 
332   //
333   // Settings related
334   //
335 
336   Macro_ConnectSomeButton(BackgroundColor);
337   QPixmap BgPix(80, 14);
338   QColor  BgColor;
339   BgColor.setRed(Settings->GetInt("BackgroundRed"));
340   BgColor.setGreen(Settings->GetInt("BackgroundGreen"));
341   BgColor.setBlue(Settings->GetInt("BackgroundBlue"));
342   BgPix.fill(BgColor);
343   BackgroundColorButton->setIcon(BgPix);
344 
345   Macro_ConnectSomeButton(Reset);
346 
347   //
348   // TAB : Generic
349   //
350 
351   Macro_ConnectSomeButton(CameraColorProfile);
352 
353   Macro_ConnectSomeButton(PreviewColorProfile);
354 
355   Macro_ConnectSomeButton(OutputColorProfile);
356 
357   Macro_ConnectSomeButton(GimpExecCommand);
358 
359   Macro_ConnectSomeButton(StartupSettings);
360 
361   //
362   // TAB : Camera
363   //
364 
365   Macro_ConnectSomeButton(OpenFile);
366   Macro_ConnectSomeButton(OpenSettingsFile);
367   Macro_ConnectSomeButton(OpenPresetFile);
368   Macro_ConnectSomeButton(SpotWB);
369 
370   //
371   // TAB : Geometry
372   //
373 
374   // TODO: BJ Unhide when lensfun implementation has grown far enough
375   widget_158->setVisible(false);  //Camera
376   widget_159->setVisible(false);  //Lens
377 
378   Macro_ConnectSomeButton(RotateLeft);
379   Macro_ConnectSomeButton(RotateRight);
380   Macro_ConnectSomeButton(RotateAngle);
381   Macro_ConnectSomeButton(MakeCrop);
382   Macro_ConnectSomeButton(ConfirmCrop);
383   Macro_ConnectSomeButton(CancelCrop);
384   Macro_ConnectSomeButton(CropOrientation);
385   Macro_ConnectSomeButton(CropCenterHor);
386   Macro_ConnectSomeButton(CropCenterVert);
387 
388   //
389   // TAB : Output
390   //
391 
392   connect(TagsEditWidget,  SIGNAL(textChanged()),     this, SLOT(OnTagsEditTextChanged()));
393   connect(edtOutputSuffix, SIGNAL(editingFinished()), this, SLOT(Form_2_Settings()));
394   connect(edtImageTitle,   SIGNAL(editingFinished()), this, SLOT(Form_2_Settings()));
395   connect(edtCopyright,    SIGNAL(editingFinished()), this, SLOT(Form_2_Settings()));
396 
397 
398   Macro_ConnectSomeButton(OutputColorProfileReset);
399 
400   Macro_ConnectSomeButton(WritePipe);
401 
402   Settings->SetEnabled("OutputGamma",Settings->GetInt("OutputGammaCompensation"));
403   Settings->SetEnabled("OutputLinearity",Settings->GetInt("OutputGammaCompensation"));
404 
405   if (Settings->GetInt("SaveFormat")==ptSaveFormat_JPEG)
406     Settings->SetEnabled("SaveSampling",1);
407   else
408     Settings->SetEnabled("SaveSampling",0);
409 
410   if (Settings->GetInt("SaveFormat")==ptSaveFormat_JPEG ||
411       Settings->GetInt("SaveFormat")==ptSaveFormat_PNG||
412       Settings->GetInt("SaveFormat")==ptSaveFormat_PNG16)
413     Settings->SetEnabled("SaveQuality",1);
414   else
415     Settings->SetEnabled("SaveQuality",0);
416 
417   // hide some stuff instead of removing from the code
418   findChild<ptGroupBox *>(QString("TabToolBoxControl"))->setVisible(0);
419   findChild<ptGroupBox *>(QString("TabMemoryTest"))->setVisible(0);
420   findChild<ptGroupBox *>(QString("TabRememberSettings"))->setVisible(0);
421 
422   UpdateToolBoxes();
423 
424   // Set help pages
425   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabWhiteBalance"))->
426     SetHelpUri("http://photivo.org/photivo/manual/tabs/camera#white_balance");
427 
428   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabLensfunLensParameters"))->
429     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#lens_parameters");
430   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabLensfunCA"))->
431     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#chromatic_aberration");
432   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabLensfunVignette"))->
433     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#vignetting");
434   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabLensfunDistortion"))->
435     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#lens_distortion");
436   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabLensfunGeometry"))->
437     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#geometry_conversion");
438   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabDefish"))->
439     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#defish");
440   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabRotation"))->
441     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#rotation_and_perspective");
442   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabCrop"))->
443     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#crop");
444   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabLiquidRescale"))->
445     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#seam_carving");
446   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabResize"))->
447     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#resize");
448   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabFlip"))->
449     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#flip");
450   dynamic_cast<ptGroupBox*>(m_GroupBox->value("TabBlock"))->
451     SetHelpUri("http://photivo.org/photivo/manual/tabs/geometry#block");
452 
453   m_ActiveTabs.append(LocalTab);
454   m_ActiveTabs.append(GeometryTab);
455   m_ActiveTabs.append(RGBTab);
456   m_ActiveTabs.append(LabCCTab);
457   m_ActiveTabs.append(LabSNTab);
458   m_ActiveTabs.append(LabEyeCandyTab);
459   m_ActiveTabs.append(EyeCandyTab);
460   m_ActiveTabs.append(OutTab);
461 
462   m_StatusIcon = QIcon(QString::fromUtf8(":/dark/ui-graphics/indicator-active-tab.png"));
463 
464   // Profiles
465   QFileInfo PathInfo(Settings->GetString("CameraColorProfile"));
466   QString ShortFileName = PathInfo.fileName();
467   CameraColorProfileText->setText(ShortFileName);
468 
469   PathInfo.setFile(Settings->GetString("PreviewColorProfile"));
470   ShortFileName = PathInfo.fileName();
471   PreviewColorProfileText->setText(ShortFileName);
472 
473   PathInfo.setFile(Settings->GetString("OutputColorProfile"));
474   ShortFileName = PathInfo.fileName();
475   OutputColorProfileText->setText(ShortFileName);
476 
477   PathInfo.setFile(Settings->GetString("GimpExecCommand"));
478   ShortFileName = PathInfo.fileName();
479   GimpExecCommandText->setText(ShortFileName);
480 
481   // Photivo version string on info tab.
482   // Character replacements are hacks to avoid problems with make and stringify
483   // and certain special characters.
484   QString Temp(TOSTRING(APPVERSION));
485   AppVersionLabel->setText(Temp);
486   AppVersion2Label->setText(Temp);
487 
488   Tabbar = ProcessingTabBook->findChild<QTabBar*>();
489   Tabbar->installEventFilter(this);
490   WritePipeButton->installEventFilter(this);
491   ToGimpButton->installEventFilter(this);
492   ResetButton->installEventFilter(this);
493   LogoLabel->installEventFilter(this);
494 
495   m_ContextMenuOnTab = -1;
496 
497   // context menu for save button
498   m_AtnSavePipe = new QAction(tr("Save current pipe"), this);
499   connect(m_AtnSavePipe, SIGNAL(triggered()), this, SLOT(SaveMenuPipe()));
500   m_AtnSaveFull = new QAction(tr("Save full size"), this);
501   connect(m_AtnSaveFull, SIGNAL(triggered()), this, SLOT(SaveMenuFull()));
502   m_AtnSaveSettings = new QAction(tr("Save settings file"), this);
503   connect(m_AtnSaveSettings, SIGNAL(triggered()), this, SLOT(SaveMenuSettings()));
504   m_AtnSaveJobfile = new QAction(tr("Save job file"), this);
505   connect(m_AtnSaveJobfile, SIGNAL(triggered()), this, SLOT(SaveMenuJobfile()));
506   m_AtnSendToBatch = new QAction(tr("Send to batch"), this);
507   connect(m_AtnSendToBatch, SIGNAL(triggered()), this, SLOT(SaveMenuBatch()));
508 
509   // context menu for gimp button
510   m_AtnGimpSavePipe = new QAction(tr("Export current pipe"), this);
511   connect(m_AtnGimpSavePipe, SIGNAL(triggered()), this, SLOT(GimpSaveMenuPipe()));
512   m_AtnGimpSaveFull = new QAction(tr("Export full size"), this);
513   connect(m_AtnGimpSaveFull, SIGNAL(triggered()), this, SLOT(GimpSaveMenuFull()));
514 
515   // context menu for reset button
516   m_AtnMenuFullReset = new QAction(tr("Neutral reset"), this);
517   connect(m_AtnMenuFullReset, SIGNAL(triggered()), this, SLOT(MenuFullReset()));
518   m_AtnMenuUserReset = new QAction(tr("User reset"), this);
519   connect(m_AtnMenuUserReset, SIGNAL(triggered()), this, SLOT(MenuUserReset()));
520   m_AtnMenuOpenPreset = new QAction(tr("Open preset"), this);
521   connect(m_AtnMenuOpenPreset, SIGNAL(triggered()), this, SLOT(MenuOpenPreset()));
522   m_AtnMenuOpenSettings = new QAction(tr("Open settings"), this);
523   connect(m_AtnMenuOpenSettings, SIGNAL(triggered()), this, SLOT(MenuOpenSettings()));
524 
525   // context menu to show tools
526   m_AtnShowTools = new QAction(tr("&Show hidden tools"), this);
527   connect(m_AtnShowTools, SIGNAL(triggered()), this, SLOT(ShowToolsOnTab()));
528   m_AtnShowTools->setIcon(QIcon(*Theme->ptIconCheckGreen));
529   m_AtnShowTools->setIconVisibleInMenu(true);
530 
531   // Search bar
532   Macro_ConnectSomeButton(SearchReset);
533   Macro_ConnectSomeButton(SearchActiveTools);
534   Macro_ConnectSomeButton(SearchAllTools);
535   Macro_ConnectSomeButton(SearchFavouriteTools);
536   connect(SearchInputWidget, SIGNAL(textEdited(QString)), this, SLOT(StartSearchTimer(QString)));
537   SearchWidget->setVisible(Settings->GetInt("SearchBarEnable"));
538 #if (QT_VERSION >= 0x40700)
539   SearchInputWidget->setPlaceholderText(tr("Search"));
540 #endif
541   m_SearchInputTimer = new QTimer(this);
542   m_SearchInputTimer->setSingleShot(1);
543   connect(m_SearchInputTimer, SIGNAL(timeout()), this, SLOT(Search()));
544 
545   // Set the toolpane to show the pipe controls ...
546   MainTabBook->blockSignals(1);
547   MainTabBook->setCurrentWidget(TabProcessing);
548   MainTabBook->blockSignals(0);
549 
550   // ... and open the first pipe controls tab
551   ProcessingTabBook->blockSignals(1);
552   ProcessingTabBook->setCurrentIndex(0);
553   ProcessingTabBook->blockSignals(0);
554 
555   setAcceptDrops(true);     // Drag and drop
556 
557   // Timer to delay on resize operations.
558   // (avoiding excessive calculations and loops in the ZoomFit approach.)
559   m_ResizeTimer = new QTimer(this);
560   m_ResizeTimer->setSingleShot(1);
561   connect(m_ResizeTimer,
562           SIGNAL(timeout()),
563           this,
564           SLOT(ResizeTimerExpired()));
565   // This qualifies for an ugly hack :)
566   // Need an event at t=0 at toplevel.
567   m_Event0Timer = new QTimer(this);
568   m_Event0Timer->setSingleShot(1);
569   m_Event0Timer->start(0);
570   connect(m_Event0Timer,
571           SIGNAL(timeout()),
572           this,
573           SLOT(Event0TimerExpired()));
574 
575   FileMgrThumbMaxRowColWidget->setEnabled(Settings->GetInt("FileMgrUseThumbMaxRowCol"));
576 
577   UpdateCropToolUI();
578   UpdateLfunDistUI();
579   UpdateLfunCAUI();
580   UpdateLfunVignetteUI();
581   UpdateLiquidRescaleUI();
582   InitVisibleTools();
583   Settings->SetValue("PipeSize", Settings->GetValue("StartupPipeSize"));
584   if (Settings->GetInt("StartupUIMode") == ptStartupUIMode_Favourite)
585     ShowFavouriteTools();
586   if (Settings->GetInt("StartupUIMode") == ptStartupUIMode_AllTools)
587     ShowAllTools();
588 
589   // Show the file manager if no image loaded at startup, the image editor otherwise.
590   // Do this last in the constructor because it triggers thumbnail reading.
591 #ifndef PT_WITHOUT_FILEMGR
592   if (ImageFileToOpen == "" &&
593       Settings->GetInt("FileMgrStartupOpen") &&
594       !Settings->GetInt("PreventFileMgrStartup"))
595   {
596     SwitchUIState(uisFileMgr);
597   } else {
598     SwitchUIState(uisProcessing);
599   }
600 #else
601   SwitchUIState(uisProcessing);
602   findChild<ptGroupBox *>(QString("TabFileMgrSettings"))->setVisible(0);
603 #endif
604 
605   AutosaveSettingsWidget->setDisabled(Settings->GetInt("SaveConfirmation"));
606 }
607 
608 //==============================================================================
609 
610 void CB_Event0();
Event0TimerExpired()611 void ptMainWindow::Event0TimerExpired() {
612   ::CB_Event0();
613 }
614 
615 //==============================================================================
616 
617 // Setup the UI language combobox. Only done once after constructing MainWindow.
618 // The languages combobox is a regular QComboBox because its dynamic content (depends on
619 // available translation files) doesn't fit the logic of ptChoice (static, pre-defined lists).
PopulateTranslationsCombobox(const QStringList UiLanguages,const int LangIdx)620 void ptMainWindow::PopulateTranslationsCombobox(const QStringList UiLanguages, const int LangIdx) {
621   TranslationChoice->setFixedHeight(24);
622   TranslationChoice->addItem(tr("English (Default)"));
623   TranslationChoice->addItems(UiLanguages);
624   TranslationChoice->setCurrentIndex(LangIdx==-1 ? 0 : LangIdx+1);
625   connect(TranslationChoice, SIGNAL(currentIndexChanged(int)), this, SLOT(OnTranslationChoiceChanged(int)));
626 }
627 
628 //==============================================================================
629 
OnTranslationChoiceChanged(int idx)630 void ptMainWindow::OnTranslationChoiceChanged(int idx) {
631   TranslationLabel->setText(tr("Restart Photivo to change the language."));
632   if (idx == 0) {   // no translation
633     Settings->SetValue("TranslationMode", 0);
634     Settings->SetValue("UiLanguage", "");
635   } else {
636     Settings->SetValue("TranslationMode", 1);
637     Settings->SetValue("UiLanguage", TranslationChoice->itemText(idx));
638   }
639 }
640 
641 
642 ////////////////////////////////////////////////////////////////////////////////
643 //
644 // Event filter
645 //
646 ////////////////////////////////////////////////////////////////////////////////
647 
eventFilter(QObject * obj,QEvent * event)648 bool ptMainWindow::eventFilter(QObject *obj, QEvent *event)
649 {
650   if (event->type() == QEvent::ContextMenu) {
651     if (obj == Tabbar) {
652       // compute the tab number
653       QContextMenuEvent *mouseEvent = static_cast<QContextMenuEvent *>(event);
654       QPoint position = mouseEvent->pos();
655       int c = Tabbar->count();
656       int clickedItem = -1;
657 
658       for (int i=0; i<c; i++) {
659         if ( Tabbar->tabRect(i).contains( position ) ) {
660           clickedItem = i;
661           break;
662         }
663       }
664       // tools on this tab hidden?
665       short HaveHiddenTools = 0;
666       QStringList TempList = Settings->GetStringList("HiddenTools");
667       foreach (ptTempFilterBase* GroupBox, *m_GroupBox) {
668         if (TempList.contains(GroupBox->objectName())) {
669           short Tab = GroupBox->parentTabIdx();
670           if (Tab == clickedItem) HaveHiddenTools = 1;
671         }
672       }
673       if (clickedItem !=0 && HaveHiddenTools == 1) { // no hidden tools on camera tab
674         m_ContextMenuOnTab = clickedItem;
675         QMenu Menu(NULL);
676         Menu.setStyle(Theme->style());
677         Menu.setPalette(Theme->menuPalette());
678         Menu.addAction(m_AtnShowTools);
679         Menu.exec(static_cast<QContextMenuEvent *>(event)->globalPos());
680       }
681     } else if (obj == WritePipeButton) {
682       QMenu Menu(NULL);
683       Menu.setStyle(Theme->style());
684       Menu.setPalette(Theme->menuPalette());
685       Menu.addAction(m_AtnSavePipe);
686       Menu.addAction(m_AtnSaveFull);
687       Menu.addAction(m_AtnSaveSettings);
688       Menu.addAction(m_AtnSaveJobfile);
689       Menu.addAction(m_AtnSendToBatch);
690       Menu.exec(static_cast<QContextMenuEvent *>(event)->globalPos());
691     } else if (obj == ToGimpButton) {
692       QMenu Menu(NULL);
693       Menu.setStyle(Theme->style());
694       Menu.setPalette(Theme->menuPalette());
695       Menu.addAction(m_AtnGimpSavePipe);
696       Menu.addAction(m_AtnGimpSaveFull);
697       Menu.exec(static_cast<QContextMenuEvent *>(event)->globalPos());
698     } else if (obj == ResetButton) {
699       QMenu Menu(NULL);
700       Menu.setStyle(Theme->style());
701       Menu.setPalette(Theme->menuPalette());
702       Menu.addAction(m_AtnMenuUserReset);
703       Menu.addAction(m_AtnMenuFullReset);
704       Menu.addSeparator();
705       Menu.addAction(m_AtnMenuOpenPreset);
706       Menu.addAction(m_AtnMenuOpenSettings);
707       Menu.exec(static_cast<QContextMenuEvent *>(event)->globalPos());
708     }
709     return QObject::eventFilter(obj, event);
710   } else if (obj == LogoLabel &&
711              event->type() == QEvent::MouseButtonPress &&
712              static_cast <QMouseEvent*>(event)->button() == Qt::LeftButton) {
713     ::CB_OpenFileButton();
714     return 0;
715   } else {
716     // pass the event on to the parent class
717     return QObject::eventFilter(obj, event);
718   }
719 }
720 
721 ////////////////////////////////////////////////////////////////////////////////
722 //
723 // Slots for context menu on save button
724 //
725 ////////////////////////////////////////////////////////////////////////////////
726 
727 extern void SaveOutput(const short mode);
728 
SaveMenuPipe()729 void ptMainWindow::SaveMenuPipe() {
730   SaveOutput(ptOutputMode_Pipe);
731 }
SaveMenuFull()732 void ptMainWindow::SaveMenuFull() {
733   SaveOutput(ptOutputMode_Full);
734 }
SaveMenuSettings()735 void ptMainWindow::SaveMenuSettings() {
736   SaveOutput(ptOutputMode_Settingsfile);
737 }
SaveMenuJobfile()738 void ptMainWindow::SaveMenuJobfile() {
739   SaveOutput(ptOutputMode_Jobfile);
740 }
SaveMenuBatch()741 void ptMainWindow::SaveMenuBatch() {
742   SaveOutput(ptOutputMode_Batch);
743 }
744 
745 ////////////////////////////////////////////////////////////////////////////////
746 //
747 // Slots for context menu on gimp button
748 //
749 ////////////////////////////////////////////////////////////////////////////////
750 
751 extern void Export(const short mode);
752 
GimpSaveMenuPipe()753 void ptMainWindow::GimpSaveMenuPipe() {
754   Export(ptExportMode_GimpPipe);
755 }
GimpSaveMenuFull()756 void ptMainWindow::GimpSaveMenuFull() {
757   Export(ptExportMode_GimpFull);
758 }
759 
760 ////////////////////////////////////////////////////////////////////////////////
761 //
762 // Slots for context menu on reset button
763 //
764 ////////////////////////////////////////////////////////////////////////////////
765 
766 extern void ResetButtonHandler(const short mode);
767 
MenuFullReset()768 void ptMainWindow::MenuFullReset() {
769   ResetButtonHandler(ptResetMode_Full);
770 }
771 
MenuUserReset()772 void ptMainWindow::MenuUserReset() {
773   ResetButtonHandler(ptResetMode_User);
774 }
775 
MenuOpenPreset()776 void ptMainWindow::MenuOpenPreset() {
777   ResetButtonHandler(ptResetMode_OpenPreset);
778 }
779 
MenuOpenSettings()780 void ptMainWindow::MenuOpenSettings() {
781   ResetButtonHandler(ptResetMode_OpenSettings);
782 }
783 
784 ////////////////////////////////////////////////////////////////////////////////
785 //
786 // Slots for context menu on tabs
787 //
788 ////////////////////////////////////////////////////////////////////////////////
789 
ShowToolsOnTab()790 void ptMainWindow::ShowToolsOnTab() {
791   // show hidden tools on tab m_ContextMenuOnTab
792   QString ActiveTool= "";
793   QString TempString = "";
794   QStringList TempList = Settings->GetStringList("HiddenTools");
795   TempList.removeDuplicates();
796 
797   foreach (ptTempFilterBase* GroupBox, *m_GroupBox) {
798     TempString = GroupBox->objectName();
799 
800     if (TempList.contains(TempString)) {
801       short Tab = GroupBox->parentTabIdx();
802 
803       if (m_ContextMenuOnTab==Tab) {
804         GroupBox->guiWidget()->show();
805         TempList.removeOne(TempString);
806         Settings->SetValue("HiddenTools", TempList);
807 
808         if (GroupBox->isActive()) {
809           ActiveTool = TempString;
810         }
811       }
812     }
813   }
814   Settings->SetValue("HiddenTools", TempList);
815   // run processor if needed
816   if (ActiveTool != "") Update(ActiveTool);
817 }
818 
819 
820 ////////////////////////////////////////////////////////////////////////////////
821 //
822 // Added slot for messages to the single instance
823 //
824 ////////////////////////////////////////////////////////////////////////////////
825 
OtherInstanceMessage(const QString & msg)826 void ptMainWindow::OtherInstanceMessage(const QString &msg) {
827   // Settings file loaded via cli
828   if (msg.startsWith("::pts::")) {
829     PtsFileToOpen = msg;
830     PtsFileToOpen.remove(0,7);
831 
832     if (ptConfirmRequest::loadConfig(lcmSettingsFile, PtsFileToOpen)) {
833       CB_OpenSettingsFile(PtsFileToOpen);
834     }
835 
836   // Image file loaded via cli
837   } else if (msg.startsWith("::img::")) {
838     ImageFileToOpen = msg;
839     ImageFileToOpen.remove(0,7);
840     CB_MenuFileOpen(1);
841 
842   // image incoming from Gimp
843   } else if (msg.startsWith("::tmp::")) {
844     ImageFileToOpen = msg;
845     ImageFileToOpen.remove(0,7);
846     ImageCleanUp++;
847     CB_MenuFileOpen(1);
848   } else if (msg.startsWith("::sidecar::")) {
849     QString Sidecar = msg;
850     Sidecar.remove(0,11);
851     ReadSidecar(Sidecar);
852     Settings->SetValue("Sidecar", Sidecar);
853   }
854 
855 }
856 
857 //==============================================================================
858 
859 ////////////////////////////////////////////////////////////////////////////////
860 //
861 // GetCurrentTab
862 //
863 // Determine the current tab selected.
864 //
865 ////////////////////////////////////////////////////////////////////////////////
866 
GetCurrentTab()867 short ptMainWindow::GetCurrentTab() {
868   // I opt for matching onto widget name, rather than on
869   // index, as I feel that this is more robust for change.
870   if      (ProcessingTabBook->currentWidget() == CameraTab) return ptCameraTab;
871   else if (ProcessingTabBook->currentWidget() == LocalTab) return ptLocalTab;
872   else if (ProcessingTabBook->currentWidget() == GeometryTab) return ptGeometryTab;
873   else if (ProcessingTabBook->currentWidget() == RGBTab) return ptRGBTab;
874   else if (ProcessingTabBook->currentWidget() == LabCCTab) return ptLabCCTab;
875   else if (ProcessingTabBook->currentWidget() == LabSNTab) return ptLabSNTab;
876   else if (ProcessingTabBook->currentWidget() == LabEyeCandyTab) return ptLabEyeCandyTab;
877   else if (ProcessingTabBook->currentWidget() == EyeCandyTab) return ptEyeCandyTab;
878   else if (ProcessingTabBook->currentWidget() == OutTab) return ptOutTab;
879   else {
880      ptLogError(ptError_Argument,"Unforeseen tab.");
881      assert(0);
882      return 0;
883   }
884 }
885 
886 ////////////////////////////////////////////////////////////////////////////////
887 //
888 // All kind of Gui events.
889 // Translated back to a CB_ function into ptMain
890 //
891 ////////////////////////////////////////////////////////////////////////////////
892 
893 //==============================================================================
894 // Show/hide file manager window
895 
OpenBatchWindow()896 void ptMainWindow::OpenBatchWindow() {
897   SwitchUIState(uisBatch);
898 }
899 
CloseBatchWindow()900 void ptMainWindow::CloseBatchWindow() {
901   SwitchUIState(uisProcessing);
902 }
903 
OpenFileMgrWindow()904 void ptMainWindow::OpenFileMgrWindow() {
905   SwitchUIState(uisFileMgr);
906 }
907 
CloseFileMgrWindow()908 void ptMainWindow::CloseFileMgrWindow() {
909   SwitchUIState(uisProcessing);
910 }
911 
912 //==============================================================================
913 // Tabbook switching
914 
915 void CB_Tabs(const short Index);
on_ProcessingTabBook_currentChanged(const int Index)916 void ptMainWindow::on_ProcessingTabBook_currentChanged(const int Index) {
917   ::CB_Tabs(Index);
918 }
919 
920 //==============================================================================
921 
922 struct sToolBoxStructure {
923   QToolBox*             ToolBox;
924   QWidget*              Parent;
925   QVBoxLayout*          ParentLayout;
926   // The standard layout in toolbox pages.
927   QList <QWidget *>     Pages;
928   QList <QVBoxLayout *> PageLayouts;
929   // The alternative layout in groupboxes.
930   QList <ptGroupBox *>   GroupBoxes;
931   QList <QVBoxLayout *> GroupBoxLayouts;
932   // The widgets we foresaw moving.
933   QList <QWidget *>     Widgets;
934 };
935 
936 QList <sToolBoxStructure*> ToolBoxStructureList;
937 
AnalyzeToolBoxStructure()938 void ptMainWindow::AnalyzeToolBoxStructure() {
939   // QMap for all processing group boxes (without settings and info!)
940   // QMap Name -> ptGroupBox*
941   if (m_GroupBox) delete m_GroupBox;
942   m_GroupBox = new QMap<QString, ptTempFilterBase*>;
943   if (m_GroupBoxesOrdered) delete m_GroupBoxesOrdered;
944   m_GroupBoxesOrdered = new QList<QString>;
945   if (m_TabLayouts) delete m_TabLayouts;
946   m_TabLayouts = new QList<QVBoxLayout*>;
947 
948   // Each processing tab has one QToolBox containing a list of QWidgets as direct children.
949   // Each of those is one filter and will become one groupbox.
950   // The settings page and info page are represented by QToolBox "SettingsToolBox" and
951   // "InfoToolBox". They are excluded from the m_GroupBox and m_GrouBoxesOrdered lists. I.e.
952   // those lists only contain the filters on the proccessing page.
953   QList <QToolBox *> ToolBoxes;
954   short NumberOfTabs = ProcessingTabBook->count();
955   for (short i=0; i<NumberOfTabs; i++) {
956     ToolBoxes.append(ProcessingTabBook->widget(i)->findChildren <QToolBox *> ());
957   }
958   ToolBoxes.append(SettingsToolBox);
959   ToolBoxes.append(InfoToolBox);
960 
961   // iterate over the QToolBoxes
962   for (short itTab=0; itTab<ToolBoxes.size(); itTab++) {
963     sToolBoxStructure* ToolBoxStructure = new sToolBoxStructure;
964     ToolBoxStructureList.append(ToolBoxStructure);
965     ToolBoxStructure->ToolBox = ToolBoxes[itTab];
966     ToolBoxStructure->Parent =
967       qobject_cast <QWidget*>(ToolBoxes[itTab]->parent());
968     ToolBoxStructure->ParentLayout =
969       qobject_cast <QVBoxLayout*>(ToolBoxStructure->Parent->layout());
970     assert (ToolBoxStructure->ParentLayout);
971     if (ToolBoxStructure->ToolBox != SettingsToolBox &&
972         ToolBoxStructure->ToolBox != InfoToolBox) {
973       m_TabLayouts->append(ToolBoxStructure->ParentLayout);
974     }
975 
976     // iterate over the the QToolBox child widgets (i.e. the individual filters)
977     for (short itIdx=0; itIdx<ToolBoxes[itTab]->count(); itIdx++) {
978       // handle dummy entries for new-style filters
979       auto hNewFilter = GFilterDM->GetFilterFromName(ToolBoxes[itTab]->itemText(itIdx), false);
980       if (hNewFilter) {
981         hNewFilter->setPos(itTab, itIdx);
982         m_GroupBoxesOrdered->append(hNewFilter->uniqueName());
983         m_GroupBox->insert(hNewFilter->uniqueName(), hNewFilter);
984         continue;
985       }
986 
987       // create groupboxes etc. for old-style filters
988       QWidget* Page = ToolBoxes[itTab]->widget(itIdx);
989       QVBoxLayout* PageLayout = qobject_cast <QVBoxLayout*>(Page->layout());
990       ToolBoxStructure->Pages.append(Page);
991       ToolBoxStructure->PageLayouts.append(PageLayout);
992       // Alternative groupboxes. The layout of which still needs to be created.
993       ptGroupBox* GroupBox =
994         new ptGroupBox(ToolBoxStructure->ToolBox->itemText(itIdx),
995                        this,
996                        ToolBoxStructure->ToolBox->widget(itIdx)->objectName(),
997                        itTab<NumberOfTabs?ProcessingTabBook->widget(itTab)->objectName():"",
998                        itTab,
999                        itIdx);
1000 
1001       if (ToolBoxStructure->ToolBox != SettingsToolBox &&
1002           ToolBoxStructure->ToolBox != InfoToolBox) {
1003         m_GroupBox->insert(ToolBoxStructure->ToolBox->widget(itIdx)->objectName(),
1004                            GroupBox);
1005         m_GroupBoxesOrdered->append(ToolBoxStructure->ToolBox->widget(itIdx)->objectName());
1006       }
1007 
1008       QVBoxLayout* GroupBoxLayout = new QVBoxLayout(GroupBox->m_Widget);
1009       GroupBoxLayout->setSpacing(0);
1010       GroupBoxLayout->setMargin(0);
1011       ToolBoxStructure->GroupBoxes.append(GroupBox);
1012       ToolBoxStructure->GroupBoxLayouts.append(GroupBoxLayout);
1013       // The list of childwidgets.
1014       QList <QWidget *> DirectChildrenOfPage = findChildren <QWidget *> ();
1015       // findChildren is always recursive. Remove lots.
1016       for (short k=0; k<DirectChildrenOfPage.size();) {
1017         if (DirectChildrenOfPage[k]->parent() != Page) {
1018           DirectChildrenOfPage.removeAt(k);
1019         } else {
1020           k++;
1021         }
1022       }
1023       GInfo->Assert(DirectChildrenOfPage.size() == 1,
1024                     "Failed analyzing filter named " + ToolBoxes[itTab]->itemText(itIdx) +
1025                     ". If you see a FUID as the name you probably forgot to create the "
1026                     "corresponding new-style filter in ptMain::CreateAllFilters().", AT);
1027       ToolBoxStructure->Widgets.append(DirectChildrenOfPage[0]);
1028     }
1029   }
1030 }
1031 
1032 //==============================================================================
1033 
OnToolBoxesEnabledTriggered(const bool Enabled)1034 void ptMainWindow::OnToolBoxesEnabledTriggered(const bool Enabled) {
1035   if (ToolBoxStructureList.size() == 0) {
1036     AnalyzeToolBoxStructure();
1037   }
1038 
1039   // Empty all involved layouts.
1040   for (short Idx=0; Idx<ToolBoxStructureList.size(); Idx++) {
1041     sToolBoxStructure* ToolBoxStructure = ToolBoxStructureList[Idx];
1042     // 1. Parent.
1043     while (ToolBoxStructure->ParentLayout->count()) {
1044       ToolBoxStructure->ParentLayout->
1045         removeItem(ToolBoxStructure->ParentLayout->itemAt(0));
1046     }
1047     for (short j=0; j<ToolBoxStructure->Widgets.size(); j++) {
1048       // 2. Groupboxes.
1049       while (ToolBoxStructure->GroupBoxLayouts[j]->count()) {
1050         ToolBoxStructure->GroupBoxLayouts[j]->
1051           removeItem(ToolBoxStructure->GroupBoxLayouts[j]->itemAt(0));
1052       }
1053       // 3. Pages.
1054       while (ToolBoxStructure->PageLayouts[j]->count()) {
1055         ToolBoxStructure->PageLayouts[j]->
1056           removeItem(ToolBoxStructure->PageLayouts[j]->itemAt(0));
1057       }
1058     }
1059   }
1060 
1061   // Orphan widgets (TODO : maybe not really needed ..)
1062   for (short Idx=0; Idx<ToolBoxStructureList.size(); Idx++) {
1063     sToolBoxStructure* ToolBoxStructure = ToolBoxStructureList[Idx];
1064     for (short j=0; j<ToolBoxStructure->Widgets.size(); j++) {
1065       ToolBoxStructure->Widgets[j]->setParent(NULL);
1066       ToolBoxStructure->GroupBoxes[j]->setParent(NULL);
1067     }
1068     ToolBoxStructure->ToolBox->setParent(NULL);
1069   }
1070 
1071   // Now start relayouting.
1072 
1073   // Layout for groupbox mode.
1074   if (!Enabled) {
1075     for (short Idx=0; Idx<ToolBoxStructureList.size(); Idx++) {
1076       sToolBoxStructure* ToolBoxStructure = ToolBoxStructureList[Idx];
1077       for (short j=0; j<ToolBoxStructure->Widgets.size(); j++) {
1078         ToolBoxStructure->Widgets[j]->
1079           setParent(ToolBoxStructure->GroupBoxes[j]);
1080         ToolBoxStructure->GroupBoxLayouts[j]->
1081           addWidget(ToolBoxStructure->Widgets[j]);
1082         ToolBoxStructure->Widgets[j]->layout()->setSpacing(4);
1083         ToolBoxStructure->GroupBoxes[j]->setParent(ToolBoxStructure->Parent);
1084         ToolBoxStructure->ParentLayout->
1085           addWidget(ToolBoxStructure->GroupBoxes[j]);
1086       }
1087       ToolBoxStructure->ParentLayout->addStretch();
1088       ToolBoxStructure->ParentLayout->setSpacing(0);
1089       ToolBoxStructure->ParentLayout->setContentsMargins(0,0,0,0);
1090       ToolBoxStructure->ParentLayout->setMargin(0);
1091       ToolBoxStructure->Parent->show();
1092     }
1093   }
1094 
1095   // Layout for toolbox mode.
1096   if (Enabled) {
1097     GInfo->Raise("Toolbox mode is ancient and dysfunctional!", AT);
1098   }
1099 }
1100 
1101 
1102 //
1103 // Gimp
1104 //
1105 
OnToGimpButtonClicked()1106 void ptMainWindow::OnToGimpButtonClicked() {
1107 #ifdef DLRAW_GIMP_PLUGIN
1108   ::CB_MenuFileExit(1);
1109 #endif
1110   GimpSaveMenuPipe();
1111 }
1112 
1113 //
1114 // PreviewMode
1115 //
1116 
1117 void CB_PreviewModeButton(const QVariant State);
OnPreviewModeButtonClicked()1118 void ptMainWindow::OnPreviewModeButtonClicked() {
1119   if (PreviewModeButton->isChecked())
1120     ::CB_PreviewModeButton(1);
1121   else
1122     ::CB_PreviewModeButton(0);
1123 }
1124 
1125 //
1126 // Run
1127 //
1128 
1129 void CB_RunButton();
OnRunButtonClicked()1130 void ptMainWindow::OnRunButtonClicked() {
1131   ::CB_RunButton();
1132 }
1133 
1134 void CB_ResetButton();
OnResetButtonClicked()1135 void ptMainWindow::OnResetButtonClicked() {
1136   ::CB_ResetButton();
1137 }
1138 
1139 //
1140 // Zoom
1141 //
1142 
1143 void CB_ZoomFitButton();
OnZoomFitButtonClicked()1144 void ptMainWindow::OnZoomFitButtonClicked() {
1145   ::CB_ZoomFitButton();
1146 }
1147 
1148 void CB_ZoomFullButton();
OnZoomFullButtonClicked()1149 void ptMainWindow::OnZoomFullButtonClicked() {
1150   ::CB_ZoomFullButton();
1151 }
1152 
OnZoomInButtonClicked()1153 void ptMainWindow::OnZoomInButtonClicked() {
1154   ViewWindow->ZoomStep(1);
1155 }
1156 
OnZoomOutButtonClicked()1157 void ptMainWindow::OnZoomOutButtonClicked() {
1158   ViewWindow->ZoomStep(-1);
1159 }
1160 
1161 
1162 void CB_InputChanged(const QString ObjectName, const QVariant Value);
OnInputChanged(const QVariant Value)1163 void ptMainWindow::OnInputChanged(const QVariant Value) {
1164   QObject* Sender = sender();
1165   printf("(%s,%d) Sender : '%s'\n",
1166          __FILE__,__LINE__,Sender->objectName().toLocal8Bit().data());
1167   CB_InputChanged(Sender->objectName(),Value);
1168 
1169 }
1170 
1171 void CB_PreviousImageButton();
OnPreviousImageButtonClicked()1172 void ptMainWindow::OnPreviousImageButtonClicked() {
1173   ::CB_PreviousImageButton();
1174 }
1175 
1176 void CB_NextImageButton();
OnNextImageButtonClicked()1177 void ptMainWindow::OnNextImageButtonClicked() {
1178   ::CB_NextImageButton();
1179 }
1180 
1181 void CB_BatchButton();
OnBatchButtonClicked()1182 void ptMainWindow::OnBatchButtonClicked() {
1183   ::CB_BatchButton();
1184 }
1185 
1186 void CB_FileMgrButton();
OnFileMgrButtonClicked()1187 void ptMainWindow::OnFileMgrButtonClicked() {
1188   ::CB_FileMgrButton();
1189 }
1190 
1191 void CB_FullScreenButton(const int State);
OnFullScreenButtonClicked()1192 void ptMainWindow::OnFullScreenButtonClicked() {
1193   if (FullScreenButton->isChecked())
1194     ::CB_FullScreenButton(1);
1195   else
1196     ::CB_FullScreenButton(0);
1197 }
1198 
1199 void CB_LoadStyleButton();
OnLoadStyleButtonClicked()1200 void ptMainWindow::OnLoadStyleButtonClicked() {
1201   ::CB_LoadStyleButton();
1202 }
1203 
OnTabProcessingButtonClicked()1204 void ptMainWindow::OnTabProcessingButtonClicked() {
1205   // clean up first!
1206   if (m_MovedTools->size()>0) CleanUpMovedTools();
1207   SearchInputWidget->setText("");
1208   ViewWindow->setFocus();
1209 
1210   // apply changes at VisibleTools box
1211   if (MainTabBook->currentWidget() == TabSetting)
1212     ApplyVisibleTools();
1213 
1214   MainTabBook->setCurrentWidget(TabProcessing);
1215 }
1216 
OnTabSettingsButtonClicked()1217 void ptMainWindow::OnTabSettingsButtonClicked() {
1218   // clean up first!
1219   if (m_MovedTools->size()>0) CleanUpMovedTools();
1220   SearchInputWidget->setText("");
1221   ViewWindow->setFocus();
1222 
1223   if (MainTabBook->currentWidget() == TabSetting) {
1224     // apply changes at VisibleTools box
1225     ApplyVisibleTools();
1226     MainTabBook->setCurrentWidget(TabProcessing);
1227   }
1228   else {
1229     // update VisibleTools box
1230     UpdateVisibleTools();
1231     MainTabBook->setCurrentWidget(TabSetting);
1232   }
1233 }
1234 
OnTabInfoButtonClicked()1235 void ptMainWindow::OnTabInfoButtonClicked() {
1236   // clean up first!
1237   if (m_MovedTools->size()>0) CleanUpMovedTools();
1238   SearchInputWidget->setText("");
1239   ViewWindow->setFocus();
1240 
1241   // apply changes at VisibleTools box
1242   if (MainTabBook->currentWidget() == TabSetting)
1243     ApplyVisibleTools();
1244 
1245   if (MainTabBook->currentWidget() == TabInfo)
1246     MainTabBook->setCurrentWidget(TabProcessing);
1247   else {
1248     UpdateSettings();
1249     MainTabBook->setCurrentWidget(TabInfo);
1250   }
1251 }
1252 
1253 //
1254 // Settings
1255 //
1256 
1257 void CB_BackgroundColorButton();
OnBackgroundColorButtonClicked()1258 void ptMainWindow::OnBackgroundColorButtonClicked() {
1259   ::CB_BackgroundColorButton();
1260 }
1261 
1262 //
1263 // Tab Generic
1264 //
1265 
1266 void CB_CameraColorProfileButton();
OnCameraColorProfileButtonClicked()1267 void ptMainWindow::OnCameraColorProfileButtonClicked() {
1268   ::CB_CameraColorProfileButton();
1269 }
1270 
1271 void CB_PreviewColorProfileButton();
OnPreviewColorProfileButtonClicked()1272 void ptMainWindow::OnPreviewColorProfileButtonClicked() {
1273   ::CB_PreviewColorProfileButton();
1274 }
1275 
1276 void CB_OutputColorProfileButton();
OnOutputColorProfileButtonClicked()1277 void ptMainWindow::OnOutputColorProfileButtonClicked() {
1278   ::CB_OutputColorProfileButton();
1279 }
1280 
1281 void CB_GimpExecCommandButton();
OnGimpExecCommandButtonClicked()1282 void ptMainWindow::OnGimpExecCommandButtonClicked() {
1283   ::CB_GimpExecCommandButton();
1284 }
1285 
1286 void CB_StartupSettingsButton();
OnStartupSettingsButtonClicked()1287 void ptMainWindow::OnStartupSettingsButtonClicked() {
1288   ::CB_StartupSettingsButton();
1289 }
1290 
1291 
1292 //
1293 // Tab : Camera
1294 //
1295 
OnOpenFileButtonClicked()1296 void ptMainWindow::OnOpenFileButtonClicked() {
1297   ::CB_OpenFileButton();
1298 }
1299 void CB_OpenSettingsFileButton();
OnOpenSettingsFileButtonClicked()1300 void ptMainWindow::OnOpenSettingsFileButtonClicked() {
1301   ::CB_OpenSettingsFileButton();
1302 }
1303 void CB_OpenPresetFileButton();
OnOpenPresetFileButtonClicked()1304 void ptMainWindow::OnOpenPresetFileButtonClicked() {
1305   ::CB_OpenPresetFileButton();
1306 }
1307 
1308 void CB_SpotWBButton();
OnSpotWBButtonClicked()1309 void ptMainWindow::OnSpotWBButtonClicked() {
1310   ::CB_SpotWBButton();
1311 }
1312 
1313 //
1314 // Tab : Geometry
1315 //
1316 
1317 
1318 void CB_RotateLeftButton();
OnRotateLeftButtonClicked()1319 void ptMainWindow::OnRotateLeftButtonClicked() {
1320   ::CB_RotateLeftButton();
1321 }
1322 
1323 void CB_RotateRightButton();
OnRotateRightButtonClicked()1324 void ptMainWindow::OnRotateRightButtonClicked() {
1325   ::CB_RotateRightButton();
1326 }
1327 
1328 void CB_RotateAngleButton();
OnRotateAngleButtonClicked()1329 void ptMainWindow::OnRotateAngleButtonClicked() {
1330   ::CB_RotateAngleButton();
1331 }
1332 
1333 void CB_MakeCropButton();
OnMakeCropButtonClicked()1334 void ptMainWindow::OnMakeCropButtonClicked() {
1335   ::CB_MakeCropButton();
1336 }
1337 
1338 void CB_ConfirmCropButton();
OnConfirmCropButtonClicked()1339 void ptMainWindow::OnConfirmCropButtonClicked() {
1340   ::CB_ConfirmCropButton();
1341 }
1342 
1343 void CB_CancelCropButton();
OnCancelCropButtonClicked()1344 void ptMainWindow::OnCancelCropButtonClicked() {
1345   ::CB_CancelCropButton();
1346 }
1347 
1348 void CB_CropOrientationButton();
OnCropOrientationButtonClicked()1349 void ptMainWindow::OnCropOrientationButtonClicked() {
1350   ::CB_CropOrientationButton();
1351 }
1352 
1353 void CB_CropCenterHorButton();
OnCropCenterHorButtonClicked()1354 void ptMainWindow::OnCropCenterHorButtonClicked() {
1355   ::CB_CropCenterHorButton();
1356 }
1357 
1358 void CB_CropCenterVertButton();
OnCropCenterVertButtonClicked()1359 void ptMainWindow::OnCropCenterVertButtonClicked() {
1360   ::CB_CropCenterVertButton();
1361 }
1362 
1363 // Tab : Output
1364 
1365 void CB_OutputColorProfileResetButton();
OnOutputColorProfileResetButtonClicked()1366 void ptMainWindow::OnOutputColorProfileResetButtonClicked() {
1367   ::CB_OutputColorProfileResetButton();
1368 }
1369 
1370 void CB_WritePipeButton();
OnWritePipeButtonClicked()1371 void ptMainWindow::OnWritePipeButtonClicked() {
1372   ::CB_WritePipeButton();
1373 }
1374 
1375 void PrepareTags(const QString TagsInput);
OnTagsEditTextChanged()1376 void ptMainWindow::OnTagsEditTextChanged() {
1377   PrepareTags(TagsEditWidget->toPlainText());
1378 }
1379 
1380 // Intercept close event and translate to a FileExit.
closeEvent(QCloseEvent * Event)1381 void ptMainWindow::closeEvent(QCloseEvent *Event) {
1382   Event->ignore();
1383   ::CB_MenuFileExit(1);
1384 }
1385 
1386 // Fit the image again after a resize event.
1387 
resizeEvent(QResizeEvent *)1388 void ptMainWindow::resizeEvent(QResizeEvent*) {
1389   // Avoiding excessive calculations and ZoomFit loops.
1390   m_ResizeTimer->start(500); // 500 ms.
1391 }
1392 
ResizeTimerExpired()1393 void ptMainWindow::ResizeTimerExpired() {
1394   // 250 would be the size for the progress label then.
1395   if (Settings->GetInt("ZoomMode") == ptZoomMode_Fit) {
1396     ::CB_ZoomFitButton();
1397   }
1398 }
1399 
1400 ////////////////////////////////////////////////////////////////////////
1401 //
1402 // dragEnterEvent
1403 //
1404 ////////////////////////////////////////////////////////////////////////
1405 
dragEnterEvent(QDragEnterEvent * Event)1406 void ptMainWindow::dragEnterEvent(QDragEnterEvent* Event) {
1407   if (ViewWindow->interaction() != iaNone) {
1408     return;
1409   }
1410 
1411   // accept just text/uri-list mime format
1412   if (Event->mimeData()->hasFormat("text/uri-list")) {
1413     Event->acceptProposedAction();
1414   }
1415 }
1416 
1417 
1418 ////////////////////////////////////////////////////////////////////////
1419 //
1420 // dropEvent
1421 //
1422 ////////////////////////////////////////////////////////////////////////
1423 
dropEvent(QDropEvent * Event)1424 void ptMainWindow::dropEvent(QDropEvent* Event) {
1425   if (ViewWindow->interaction() != iaNone) {
1426     return;
1427   }
1428 
1429   QList<QUrl> UrlList;
1430   QString DropName;
1431   QFileInfo DropInfo;
1432 
1433   if (Event->mimeData()->hasUrls())
1434   {
1435     UrlList = Event->mimeData()->urls(); // returns list of QUrls
1436 
1437     // if just text was dropped, urlList is empty (size == 0)
1438     if ( UrlList.size() > 0) // if at least one QUrl is present in list
1439     {
1440       DropName = UrlList[0].toLocalFile(); // convert first QUrl to local path
1441       DropInfo.setFile( DropName ); // information about file
1442       if ( DropInfo.isFile() ) { // if is file
1443         if (DropInfo.completeSuffix()!="pts" && DropInfo.completeSuffix()!="ptj" &&
1444             DropInfo.completeSuffix()!="dls" && DropInfo.completeSuffix()!="dlj")
1445         {
1446           if (Settings->GetInt("FileMgrIsOpen"))
1447             CloseFileMgrWindow();
1448           ImageFileToOpen = DropName;
1449           CB_MenuFileOpen(1);
1450 
1451         } else {
1452           if (!Settings->GetInt("FileMgrIsOpen")) {
1453             if (ptConfirmRequest::loadConfig(lcmSettingsFile, DropName)) {
1454               CB_OpenSettingsFile(DropName);
1455             }
1456           }
1457         }
1458       }
1459     }
1460   }
1461   Event->acceptProposedAction();
1462 }
1463 
1464 void CB_FullScreenButton(const int State);
1465 void UpdateSettings();
1466 void CB_RunModeCheck(const QVariant Check);
1467 void CB_OpenPresetFileButton();
1468 void CB_InputChanged(const QString,const QVariant);
1469 void CB_ZoomFitButton();
1470 void CB_WritePipeButton();
1471 void CB_SpecialPreviewChoice(const QVariant Choice);
1472 void CB_MenuFileExit(const short);
1473 void ViewWindowShowStatus(short State);
1474 void CB_SearchBarEnableCheck(const QVariant State);
1475 
1476 // Catch keyboard shortcuts
keyPressEvent(QKeyEvent * Event)1477 void ptMainWindow::keyPressEvent(QKeyEvent *Event) {
1478   if (Event->key()==Qt::Key_Escape) {// back to used view
1479     if (Settings->GetInt("SpecialPreview") != ptSpecialPreview_RGB) {
1480         CB_SpecialPreviewChoice(ptSpecialPreview_RGB);
1481         return;
1482     } else if (SearchInputWidget->hasFocus()) {
1483       OnTabProcessingButtonClicked();
1484       return;
1485     } else if (Settings->GetInt("ShowToolContainer") == 0) {
1486         Settings->SetValue("ShowToolContainer", 1);
1487         UpdateSettings();
1488         return;
1489     } else if (Settings->GetInt("FullscreenActive") == 1) {
1490       ::CB_FullScreenButton(0);
1491       return;
1492     } else {
1493       if (Settings->GetInt("EscToExit") == 1) {
1494         ::CB_MenuFileExit(1);
1495       }
1496       return;
1497     }
1498   }
1499 
1500   if (SearchInputWidget->hasFocus() &&
1501       (Event->key()==Qt::Key_Return ||
1502        Event->key()==Qt::Key_Enter))
1503   {
1504     ViewWindow->setFocus();
1505     return;
1506   }
1507 
1508   if (Settings->GetInt("BlockTools") == 0 || ViewWindow->interaction() == iaCrop) {
1509     if (Event->key()==Qt::Key_F11) { // toggle full screen
1510       ::CB_FullScreenButton(!isFullScreen());
1511     } else if (Event->key()==Qt::Key_1 && Event->modifiers()==Qt::NoModifier) {
1512       CB_ZoomStep(1);
1513     } else if (Event->key()==Qt::Key_2 && Event->modifiers()==Qt::NoModifier) {
1514       CB_InputChanged("ZoomInput",100);
1515     } else if (Event->key()==Qt::Key_3 && Event->modifiers()==Qt::NoModifier) {
1516       CB_ZoomStep(-1);
1517     } else if (Event->key()==Qt::Key_4 && Event->modifiers()==Qt::NoModifier) {
1518       CB_ZoomFitButton();
1519     } else if (Event->key()==Qt::Key_Space) {
1520       Settings->SetValue("ShowToolContainer",1-Settings->GetInt("ShowToolContainer"));
1521       UpdateSettings();
1522       if (Settings->GetInt("ZoomMode") == ptZoomMode_Fit) {
1523         ViewWindow->ZoomToFit(0);
1524       }
1525     }
1526   }
1527 
1528   // most shortcuts should only work when we are not in special state like cropping
1529   if (Settings->GetInt("BlockTools")==0) {
1530     if (Event->key()==Qt::Key_F1) {
1531       QDesktopServices::openUrl(QString("http://photivo.org/photivo/manual"));
1532     } else if (Event->key()==Qt::Key_P && Event->modifiers()==Qt::NoModifier) {
1533       OnTabProcessingButtonClicked();
1534     } else if (Event->key()==Qt::Key_S && Event->modifiers()==Qt::NoModifier) {
1535       OnTabSettingsButtonClicked();
1536     } else if (Event->key()==Qt::Key_I && Event->modifiers()==Qt::NoModifier) {
1537       OnTabInfoButtonClicked();
1538     } else if (Event->key()==Qt::Key_M && Event->modifiers()==Qt::NoModifier) {
1539       ::CB_RunModeCheck(1-Settings->GetInt("RunMode"));
1540     } else if (Event->key()==Qt::Key_F5) {
1541       OnRunButtonClicked();
1542     } else if (Event->key()==Qt::Key_F3) {
1543       CB_SearchBarEnableCheck(1);
1544       if (!SearchInputWidget->hasFocus()) {
1545         SearchInputWidget->setText("");
1546         SearchInputWidget->setFocus();
1547       }
1548     } else if (Event->key() == Qt::Key_M && Event->modifiers() == Qt::ControlModifier) {
1549       SwitchUIState(uisFileMgr);
1550     } else if (Event->key() == Qt::Key_B && Event->modifiers() == Qt::ControlModifier) {
1551       SwitchUIState(uisBatch);
1552     } else if (Event->key()==Qt::Key_P && Event->modifiers()==Qt::ControlModifier) {
1553       CB_OpenPresetFileButton();
1554     } else if (Event->key()==Qt::Key_Q && Event->modifiers()==Qt::ControlModifier) {
1555       CB_MenuFileExit(1);
1556     } else if (Event->key()==Qt::Key_O && Event->modifiers()==Qt::ControlModifier) {
1557       CB_MenuFileOpen(0);
1558     } else if (Event->key()==Qt::Key_S && Event->modifiers()==Qt::ControlModifier) {
1559       CB_WritePipeButton();
1560     } else if (Event->key()==Qt::Key_G && Event->modifiers()==Qt::ControlModifier) {
1561       Update(ptProcessorPhase_ToGimp);
1562     } else if (Event->key()==Qt::Key_R && Event->modifiers()==Qt::ControlModifier) {
1563       resize(QSize(1200,900));
1564       QRect DesktopRect = (QApplication::desktop())->screenGeometry(this);
1565       move(QPoint(MAX((DesktopRect.width()-1200),0)/2,MAX((DesktopRect.height()-900)/2-20,0)));
1566     } else if (Event->key()==Qt::Key_1 && Event->modifiers()==Qt::AltModifier) {
1567       ProcessingTabBook->setCurrentIndex(0);
1568     } else if (Event->key()==Qt::Key_2 && Event->modifiers()==Qt::AltModifier) {
1569       ProcessingTabBook->setCurrentIndex(1);
1570     } else if (Event->key()==Qt::Key_3 && Event->modifiers()==Qt::AltModifier) {
1571       ProcessingTabBook->setCurrentIndex(2);
1572     } else if (Event->key()==Qt::Key_4 && Event->modifiers()==Qt::AltModifier) {
1573       ProcessingTabBook->setCurrentIndex(3);
1574     } else if (Event->key()==Qt::Key_5 && Event->modifiers()==Qt::AltModifier) {
1575       ProcessingTabBook->setCurrentIndex(4);
1576     } else if (Event->key()==Qt::Key_6 && Event->modifiers()==Qt::AltModifier) {
1577       ProcessingTabBook->setCurrentIndex(5);
1578     } else if (Event->key()==Qt::Key_7 && Event->modifiers()==Qt::AltModifier) {
1579       ProcessingTabBook->setCurrentIndex(6);
1580     } else if (Event->key()==Qt::Key_8 && Event->modifiers()==Qt::AltModifier) {
1581       ProcessingTabBook->setCurrentIndex(7);
1582     } else if (Event->key()==Qt::Key_9 && Event->modifiers()==Qt::AltModifier) {
1583       ProcessingTabBook->setCurrentIndex(8);
1584     } else if (Event->key()==Qt::Key_Period && Event->modifiers()==Qt::NoModifier) {
1585       ProcessingTabBook->setCurrentIndex(MIN(ProcessingTabBook->currentIndex()+1,ProcessingTabBook->count()));
1586     } else if (Event->key()==Qt::Key_Comma && Event->modifiers()==Qt::NoModifier) {
1587       ProcessingTabBook->setCurrentIndex(MAX(ProcessingTabBook->currentIndex()-1,0));
1588     } else if (Event->key()==Qt::Key_T && Event->modifiers()==Qt::NoModifier) {
1589       CB_PreviewModeButton(1-Settings->GetInt("PreviewTabMode"));
1590     } else if (Event->key()==Qt::Key_0 && Event->modifiers()==Qt::NoModifier) {
1591       if (Settings->GetInt("SpecialPreview")!=ptSpecialPreview_RGB)
1592         CB_SpecialPreviewChoice(ptSpecialPreview_RGB);
1593       else ViewWindowShowStatus(ptStatus_Done);
1594     } else if (Event->key()==Qt::Key_9 && Event->modifiers()==Qt::NoModifier) {
1595       if (Settings->GetInt("SpecialPreview")!=ptSpecialPreview_Structure)
1596         CB_SpecialPreviewChoice(ptSpecialPreview_Structure);
1597       else ViewWindowShowStatus(ptStatus_Done);
1598     } else if (Event->key()==Qt::Key_8 && Event->modifiers()==Qt::NoModifier) {
1599       if (Settings->GetInt("SpecialPreview")!=ptSpecialPreview_L)
1600         CB_SpecialPreviewChoice(ptSpecialPreview_L);
1601       else ViewWindowShowStatus(ptStatus_Done);
1602     } else if (Event->key()==Qt::Key_7 && Event->modifiers()==Qt::NoModifier) {
1603       if (Settings->GetInt("SpecialPreview")!=ptSpecialPreview_A)
1604         CB_SpecialPreviewChoice(ptSpecialPreview_A);
1605       else ViewWindowShowStatus(ptStatus_Done);
1606     } else if (Event->key()==Qt::Key_6 && Event->modifiers()==Qt::NoModifier) {
1607       if (Settings->GetInt("SpecialPreview")!=ptSpecialPreview_B)
1608         CB_SpecialPreviewChoice(ptSpecialPreview_B);
1609       else ViewWindowShowStatus(ptStatus_Done);
1610     } else if (Event->key()==Qt::Key_5 && Event->modifiers()==Qt::NoModifier) {
1611       if (Settings->GetInt("SpecialPreview")!=ptSpecialPreview_Gradient)
1612         CB_SpecialPreviewChoice(ptSpecialPreview_Gradient);
1613       else ViewWindowShowStatus(ptStatus_Done);
1614     } else if (Event->key()==Qt::Key_C && Event->modifiers()==Qt::NoModifier) {
1615       Settings->SetValue("ExposureIndicator",1-Settings->GetInt("ExposureIndicator"));
1616       Update(ptProcessorPhase_Preview);
1617     // hidden tools, needs GUI implementation
1618     } else if (Event->key()==Qt::Key_H && Event->modifiers()==Qt::NoModifier) {
1619       QString Tools = "";
1620       QString Tab = "";
1621       foreach (ptTempFilterBase* GroupBox, *m_GroupBox) {
1622         if (Settings->ToolIsHidden(GroupBox->objectName())) {
1623           Tab = ProcessingTabBook->tabText(GroupBox->parentTabIdx());
1624           Tools += Tab + ": " + GroupBox->caption() + "\n";
1625         }
1626       }
1627       if (Tools == "") Tools = tr("No tools hidden!");
1628       ptMessageBox::information(this,tr("Hidden tools"),Tools);
1629       /*findChild<QWidget *>(QString("TabGenCorrections"))->
1630         setVisible(1-findChild<QWidget *>(QString("TabGenCorrections"))->isVisible()); */
1631     } else if (Event->key()==Qt::Key_U && Event->modifiers()==Qt::NoModifier) {
1632       // show hidden tools on current tab
1633       m_ContextMenuOnTab = ProcessingTabBook->currentIndex();
1634       ShowToolsOnTab();
1635     } else if (Event->key()==Qt::Key_A && Event->modifiers()==Qt::NoModifier) {
1636       ShowActiveTools();
1637     } else if (Event->key()==Qt::Key_B && Event->modifiers()==Qt::NoModifier) {
1638       QString Tools = "";
1639       QString Tab = "";
1640       foreach (ptTempFilterBase* GroupBox, *m_GroupBox) {
1641         if (GroupBox->isBlocked()) {
1642           Tab = ProcessingTabBook->tabText(GroupBox->parentTabIdx());
1643           Tools += Tab + ": " + GroupBox->caption() + "\n";
1644         }
1645       }
1646       if (Tools == "") Tools = tr("No tools blocked!");
1647       ptMessageBox::information(this,tr("Blocked tools"),Tools);
1648     } else if (Event->key()==Qt::Key_R && Event->modifiers()==(Qt::ControlModifier | Qt::ShiftModifier)) {
1649       // Ctrl+Shift+R resets to default settings
1650       ptResetSettingsToDefault();
1651     } else if (Event->key()==Qt::Key_U && Event->modifiers()==(Qt::ControlModifier | Qt::ShiftModifier)) {
1652       // Ctrl+Shift+U resets to the last saved user settings
1653       ptMakeFullUndo();
1654     } else if (Event->key()==Qt::Key_Z && Event->modifiers()==Qt::ControlModifier) {
1655       // Ctrl+Z undo
1656       ptMakeUndo();
1657     } else if (Event->key()==Qt::Key_Y && Event->modifiers()==Qt::ControlModifier) {
1658       // Ctrl+Y redo
1659       ptMakeRedo();
1660     } else if (Event->key()==Qt::Key_Z && Event->modifiers()==(Qt::ControlModifier | Qt::ShiftModifier)) {
1661       // Ctrl+Shift+Z redo
1662       ptMakeRedo();
1663     } else if (Event->key()==Qt::Key_C && Event->modifiers()==(Qt::ControlModifier | Qt::ShiftModifier)) {
1664       // Ctrl+Shift+C copy settings
1665       ptCopySettingsToClipboard();
1666     } else if (Event->key()==Qt::Key_V && Event->modifiers()==(Qt::ControlModifier | Qt::ShiftModifier)) {
1667       // Ctrl+Shift+V paste settings
1668       ptPasteSettingsFromClipboard();
1669     }
1670   }
1671 }
1672 
wheelEvent(QWheelEvent * Event)1673 void ptMainWindow::wheelEvent(QWheelEvent * Event) {
1674   if (Event->delta() < 0 && ((QMouseEvent*)Event)->modifiers()==Qt::AltModifier) {
1675     ProcessingTabBook->setCurrentIndex(MIN(ProcessingTabBook->currentIndex()+1,ProcessingTabBook->count()));
1676   } else if (Event->delta() > 0 && ((QMouseEvent*)Event)->modifiers()==Qt::AltModifier) {
1677     ProcessingTabBook->setCurrentIndex(MAX(ProcessingTabBook->currentIndex()-1,0));
1678   }
1679 }
1680 
1681 ////////////////////////////////////////////////////////////////////////////////
1682 //
1683 // Search and moved tools
1684 //
1685 ////////////////////////////////////////////////////////////////////////////////
1686 
OnSearchResetButtonClicked()1687 void ptMainWindow::OnSearchResetButtonClicked() {
1688   OnTabProcessingButtonClicked();
1689 }
1690 
1691 //==============================================================================
1692 
OnSearchActiveToolsButtonClicked()1693 void ptMainWindow::OnSearchActiveToolsButtonClicked() {
1694   ShowActiveTools();
1695 }
1696 
1697 //==============================================================================
1698 
OnSearchAllToolsButtonClicked()1699 void ptMainWindow::OnSearchAllToolsButtonClicked() {
1700   ShowAllTools();
1701 }
1702 
1703 //==============================================================================
1704 
OnSearchFavouriteToolsButtonClicked()1705 void ptMainWindow::OnSearchFavouriteToolsButtonClicked() {
1706   ShowFavouriteTools();
1707 }
1708 
1709 //==============================================================================
1710 
StartSearchTimer(QString)1711 void ptMainWindow::StartSearchTimer(QString) {
1712   m_SearchInputTimer->start(50);
1713 }
1714 
1715 //==============================================================================
1716 
Search()1717 void ptMainWindow::Search() {
1718   const QString hSearchString = SearchInputWidget->text();
1719 
1720   if (hSearchString == "") {
1721     OnTabProcessingButtonClicked();
1722     return;
1723   }
1724 
1725   // apply changes at VisibleTools box
1726   if (MainTabBook->currentWidget() == TabSetting)
1727     ApplyVisibleTools();
1728 
1729   // clean up first!
1730   if (m_MovedTools->size()>0)
1731     CleanUpMovedTools();
1732 
1733   // iterate through toolboxes and remember those whose caption matches the search text
1734   for (QString hBoxName: *m_GroupBoxesOrdered) {
1735     ptTempFilterBase *hBox = m_GroupBox->value(hBoxName);
1736 
1737     // remember matching toolboxes
1738     if (hBox->caption().contains(hSearchString, Qt::CaseInsensitive)) {
1739       m_MovedTools->append(hBox->guiWidget());
1740     }
1741   }
1742 
1743   if (m_MovedTools->size() > 0)
1744     ShowMovedTools(tr("Search results:"));
1745 }
1746 
1747 //==============================================================================
1748 
ShowActiveTools()1749 void ptMainWindow::ShowActiveTools() {
1750   // apply changes at VisibleTools box
1751   if (MainTabBook->currentWidget() == TabSetting)
1752     ApplyVisibleTools();
1753 
1754   // clean up first!
1755   if (m_MovedTools->size()>0) CleanUpMovedTools();
1756   SearchInputWidget->setText("");
1757 
1758   for (QString hBoxName: *m_GroupBoxesOrdered) {
1759     ptTempFilterBase *hBox = m_GroupBox->value(hBoxName);
1760 
1761     if (hBox->isActive())
1762       m_MovedTools->append(hBox->guiWidget());
1763   }
1764 
1765   if (m_MovedTools->size() == 0) {
1766     ShowMovedTools(tr("No tools active!"));
1767   } else {
1768     ShowMovedTools(tr("Active tools:"));
1769   }
1770 }
1771 
1772 //==============================================================================
1773 
ShowAllTools()1774 void ptMainWindow::ShowAllTools() {
1775   // apply changes at VisibleTools box
1776   if (MainTabBook->currentWidget() == TabSetting)
1777     ApplyVisibleTools();
1778 
1779   // clean up first!
1780   if (m_MovedTools->size()>0) CleanUpMovedTools();
1781   SearchInputWidget->setText("");
1782 
1783   auto hHiddenTools = Settings->GetStringList("HiddenTools");
1784   for (QString hBoxName: *m_GroupBoxesOrdered) {
1785     if (!hHiddenTools.contains(hBoxName)) {
1786       m_MovedTools->append(m_GroupBox->value(hBoxName)->guiWidget());
1787     }
1788   }
1789 
1790   if (m_MovedTools->size() == 0) {
1791     ShowMovedTools(tr("No tools visible!"));
1792   } else {
1793     ShowMovedTools(tr("All visible tools:"));
1794   }
1795 }
1796 
1797 //==============================================================================
1798 
ShowFavouriteTools()1799 void ptMainWindow::ShowFavouriteTools() {
1800   // apply changes at VisibleTools box
1801   if (MainTabBook->currentWidget() == TabSetting)
1802     ApplyVisibleTools();
1803 
1804   // clean up first!
1805   if (m_MovedTools->size()>0) CleanUpMovedTools();
1806   SearchInputWidget->setText("");
1807 
1808   auto hFavTools = Settings->GetStringList("FavouriteTools");
1809   for (QString hBoxName: *m_GroupBoxesOrdered) {
1810     if (hFavTools.contains(hBoxName)) {
1811       m_MovedTools->append(m_GroupBox->value(hBoxName)->guiWidget());
1812     }
1813   }
1814 
1815   if (m_MovedTools->size() == 0) {
1816     ptMessageBox::information(this,tr("Favourite tools"),tr("No favourite tools!"));
1817     return;
1818   }
1819 
1820   ShowMovedTools(tr("Favourite tools:"));
1821 }
1822 
1823 //==============================================================================
1824 
ShowMovedTools(const QString ATitle)1825 void ptMainWindow::ShowMovedTools(const QString ATitle) {
1826   ToolContainerLabel->setText(ATitle);
1827   MainTabBook->setCurrentWidget(TabMovedTools);
1828 
1829   // clear previous contents from the moved tools page
1830   while (ToolContainer->layout()->count()!=0) {
1831     ToolContainer->layout()->takeAt(0);
1832   }
1833 
1834   // add new tools from moved tools list
1835   for (short i=0; i<m_MovedTools->size(); i++) {
1836     ToolContainer->layout()->addWidget(m_MovedTools->at(i));
1837   }
1838 
1839   static_cast<QVBoxLayout*>(ToolContainer->layout())->addStretch();
1840   static_cast<QVBoxLayout*>(ToolContainer->layout())->setSpacing(0);
1841   static_cast<QVBoxLayout*>(ToolContainer->layout())->setContentsMargins(0,0,0,0);
1842 }
1843 
1844 //==============================================================================
1845 
CleanUpMovedTools()1846 void ptMainWindow::CleanUpMovedTools() {
1847   for (QWidget *hToolBox: *m_MovedTools) {
1848     int hTabIdx   = -1;
1849     int hIdxInTab = -1;
1850     if (QString(hToolBox->metaObject()->className()) == "ptToolBox") {
1851       auto hFilt = GFilterDM->GetFilterFromName(hToolBox->objectName());
1852       hTabIdx    = hFilt->parentTabIdx();
1853       hIdxInTab  = hFilt->idxInParentTab();
1854     } else if (QString(hToolBox->metaObject()->className()) == "ptGroupBox") {
1855       hTabIdx   = ((ptGroupBox*)hToolBox)->GetTabNumber();
1856       hIdxInTab = ((ptGroupBox*)hToolBox)->GetIndexInTab();
1857     }
1858 
1859     m_TabLayouts->at(hTabIdx)->insertWidget(hIdxInTab, hToolBox);
1860   }
1861 
1862   m_MovedTools->clear();
1863 }
1864 
1865 ////////////////////////////////////////////////////////////////////////////////
1866 //
1867 // UpdateToolBoxes
1868 //
1869 ////////////////////////////////////////////////////////////////////////////////
1870 
UpdateToolBoxes()1871 void ptMainWindow::UpdateToolBoxes() {
1872   foreach (ptTempFilterBase* GroupBox, *m_GroupBox) {
1873     auto hGroupBox = qobject_cast<ptGroupBox*>(GroupBox);
1874     if (!hGroupBox) continue;
1875 
1876     if (Settings->ToolIsHidden(hGroupBox->objectName())) {
1877       hGroupBox->hide();
1878     } else {
1879       hGroupBox->show();
1880     }
1881     hGroupBox->Update();
1882   }
1883 
1884   // disable Raw tools when we have a bitmap
1885   QList<ptGroupBox *> m_RawTools;
1886   m_RawTools << static_cast<ptGroupBox*>(m_GroupBox->value("TabCameraColorSpace"))
1887              << static_cast<ptGroupBox*>(m_GroupBox->value("TabGenCorrections"))
1888              << static_cast<ptGroupBox*>(m_GroupBox->value("TabWhiteBalance"))
1889              << static_cast<ptGroupBox*>(m_GroupBox->value("TabDemosaicing"))
1890              << static_cast<ptGroupBox*>(m_GroupBox->value("TabHighlightRecovery"));
1891   bool hTemp = Settings->useRAWHandling();
1892   for (int i = 0; i < m_RawTools.size(); i++) {
1893     m_RawTools.at(i)->SetEnabled(hTemp);
1894   }
1895 
1896   // disable tools when we are in detail view
1897   QList<ptGroupBox *> m_DetailViewTools;
1898   m_DetailViewTools << static_cast<ptGroupBox*>(m_GroupBox->value("TabLensfunCA"))
1899                     << static_cast<ptGroupBox*>(m_GroupBox->value("TabLensfunVignette"))
1900                     << static_cast<ptGroupBox*>(m_GroupBox->value("TabLensfunDistortion"))
1901                     << static_cast<ptGroupBox*>(m_GroupBox->value("TabLensfunGeometry"))
1902                     << static_cast<ptGroupBox*>(m_GroupBox->value("TabDefish"))
1903                     << static_cast<ptGroupBox*>(m_GroupBox->value("TabCrop"))
1904                     << static_cast<ptGroupBox*>(m_GroupBox->value("TabLiquidRescale"))
1905                     << static_cast<ptGroupBox*>(m_GroupBox->value("TabResize"))
1906                     << static_cast<ptGroupBox*>(m_GroupBox->value("TabWebResize"));
1907 
1908   hTemp = !(Settings->GetInt("DetailViewActive") == 1);
1909   for (int i = 0; i < m_DetailViewTools.size(); i++) {
1910     m_DetailViewTools.at(i)->SetEnabled(hTemp);
1911   }
1912 }
1913 
1914 ////////////////////////////////////////////////////////////////////////////////
1915 //
1916 // UpdateSettings()
1917 //
1918 // Adapt the Gui elements according to GuiSettings
1919 // (for those gui elements that should be updated after a programmatic
1920 // recalculation)
1921 //
1922 ////////////////////////////////////////////////////////////////////////////////
1923 
1924 // #define SHOW_BT
1925 #ifdef SHOW_BT
1926 extern "C" {
1927   #include <execinfo.h>
1928 }
1929 #endif
1930 
UpdateSettings()1931 void ptMainWindow::UpdateSettings() {
1932 
1933   #ifdef SHOW_BT
1934 
1935     {
1936     void *array[10];
1937     size_t size;
1938     char **strings;
1939     size_t i;
1940     size = backtrace(array,10);
1941     strings = backtrace_symbols (array, size);
1942     printf ("Obtained %zd stack frames.\n", size);
1943     for (i = 0; i < size; i++)
1944       printf ("%s\n", strings[i]);
1945     free (strings);
1946     }
1947   #endif
1948 
1949   // State of Groupboxes
1950   foreach (ptTempFilterBase* GroupBox, *m_GroupBox) {
1951     auto hGroupBox = qobject_cast<ptGroupBox*>(GroupBox);
1952     if (hGroupBox)
1953       hGroupBox->SetActive(Settings->ToolIsActive(hGroupBox->objectName()));
1954   }
1955 
1956   // Status LED on tabs
1957   if(Settings->GetInt("TabStatusIndicator")) {
1958     ProcessingTabBook->setIconSize(QSize(Settings->GetInt("TabStatusIndicator"),
1959                                          Settings->GetInt("TabStatusIndicator")));
1960     QList <ptGroupBox *> Temp;
1961     for (int j=0; j<m_ActiveTabs.size();j++) {
1962       bool hIsActiveTab = GFilterDM->isActiveCacheGroup(j+1);  // +1 because Camera tab is not
1963       if (!hIsActiveTab) {                                     // in m_ActiveTabs
1964         Temp = m_ActiveTabs.at(j)->findChildren <ptGroupBox *> ();
1965         for (int i=0; i<Temp.size();i++) {
1966           if(Settings->ToolIsActive(Temp.at(i)->objectName())) {
1967             hIsActiveTab = true;
1968             break;
1969           }
1970         }
1971       }
1972 
1973       if (hIsActiveTab)
1974         ProcessingTabBook->setTabIcon(ProcessingTabBook->indexOf(m_ActiveTabs.at(j)),m_StatusIcon);
1975       else
1976         ProcessingTabBook->setTabIcon(ProcessingTabBook->indexOf(m_ActiveTabs.at(j)),QIcon());
1977     }
1978   } else {
1979     for (int j=0; j<m_ActiveTabs.size();j++)
1980       ProcessingTabBook->setTabIcon(ProcessingTabBook->indexOf(m_ActiveTabs.at(j)),QIcon());
1981   }
1982 
1983 
1984   // New Camera Color Space or profile ?
1985   int TmpCameraColor = Settings->GetInt("CameraColor");
1986   if (TmpCameraColor == ptCameraColor_Adobe_Profile) {
1987     Settings->SetEnabled("CameraColorProfileIntent",1);
1988     Settings->SetEnabled("CameraColorGamma",0);
1989     CameraColorProfileText->setEnabled(1);
1990   } else if (TmpCameraColor == ptCameraColor_Profile) {
1991     Settings->SetEnabled("CameraColorProfileIntent",1);
1992     Settings->SetEnabled("CameraColorGamma",1);
1993     CameraColorProfileText->setEnabled(1);
1994   } else if (TmpCameraColor == ptCameraColor_Flat) {
1995     Settings->SetEnabled("CameraColorProfileIntent",1);
1996     Settings->SetEnabled("CameraColorGamma",1);
1997     CameraColorProfileText->setEnabled(1);
1998   } else {
1999     Settings->SetEnabled("CameraColorProfileIntent",0);
2000     Settings->SetEnabled("CameraColorGamma",0);
2001     CameraColorProfileText->setEnabled(0);
2002   }
2003 
2004   Settings->SetEnabled("CaRed",Settings->GetInt("CaCorrect")==ptCACorrect_Manual);
2005   Settings->SetEnabled("CaBlue",Settings->GetInt("CaCorrect")==ptCACorrect_Manual);
2006 
2007   QFileInfo PathInfo(Settings->GetString("CameraColorProfile"));
2008   QString ShortFileName = PathInfo.baseName();
2009   CameraColorProfileText->setText(ShortFileName);
2010   // End CameraColorChoice.
2011 
2012 
2013   // Preview Color Profile.
2014   PathInfo.setFile(Settings->GetString("PreviewColorProfile"));
2015   ShortFileName = PathInfo.baseName();
2016   PreviewColorProfileText->setText(ShortFileName);
2017 
2018   bool Temp = Settings->GetInt("CMQuality") != ptCMQuality_FastSRGB;
2019   Settings->SetEnabled("PreviewColorProfileIntent", Temp);
2020   PreviewProfileWidget->setEnabled(Temp);
2021   // End Preview Color Profile.
2022 
2023   // Preview Color Profile.
2024   PathInfo.setFile(Settings->GetString("OutputColorProfile"));
2025   ShortFileName = PathInfo.baseName();
2026   OutputColorProfileText->setText(ShortFileName);
2027   // End Preview Color Profile.
2028 
2029   // GimpExecCommand
2030   PathInfo.setFile(Settings->GetString("GimpExecCommand"));
2031   ShortFileName = PathInfo.fileName();
2032   GimpExecCommandText->setText(ShortFileName);
2033   // GimpExecCommand
2034 
2035   // StartupSettings
2036   PathInfo.setFile(Settings->GetString("StartupSettingsFile"));
2037   ShortFileName = PathInfo.baseName();
2038   StartupSettingsText->setText(ShortFileName);
2039   // StartupSettings
2040 
2041   // New BlackPoint ?
2042   Settings->SetEnabled("BlackPoint",Settings->GetInt("ManualBlackPoint"));
2043   // End BlackPoint
2044 
2045   // New WhitePoint ?
2046   Settings->SetEnabled("WhitePoint",Settings->GetInt("ManualWhitePoint"));
2047   // End WhitePoint
2048 
2049   // New BadPixels ?
2050   if (Settings->GetInt("HaveBadPixels") == 2) {
2051     // Small routine that lets Shortfilename point to the basename.
2052     QFileInfo PathInfo(Settings->GetString("BadPixelsFileName"));
2053     QString ShortFileName = PathInfo.baseName();
2054     Settings->AddOrReplaceOption("BadPixels",ShortFileName,QVariant(2));
2055   }
2056   Settings->SetValue("BadPixels",Settings->GetInt("HaveBadPixels"));
2057   // End BadPixels.
2058 
2059   // New DarkFrame ?
2060   if (Settings->GetInt("HaveDarkFrame") == 2) {
2061     // Small routine that lets Shortfilename point to the basename.
2062     QFileInfo PathInfo(Settings->GetString("DarkFrameFileName"));
2063     QString ShortFileName = PathInfo.baseName();
2064     Settings->AddOrReplaceOption("DarkFrame",ShortFileName,QVariant(2));
2065   }
2066   Settings->SetValue("DarkFrame",Settings->GetInt("HaveDarkFrame"));
2067   // End DarkFrame.
2068 
2069   // New White balances,due to photo from other camera ?
2070   // Also the CameraMake model for lensfun is adapted.
2071   if (m_CameraMake != Settings->GetString("CameraMake")
2072       ||
2073       m_CameraModel != Settings->GetString("CameraModel") ) {
2074 
2075     m_CameraMake  = Settings->GetString("CameraMake");
2076     m_CameraModel = Settings->GetString("CameraModel");
2077     // New white balances !
2078     // First clear the whole WhiteBalanceChoice
2079     Settings->ClearOptions("WhiteBalance", 1);
2080 
2081     // Add the camera dependent custom ones.
2082     // First calculate which index our camera has int ptWhiteBalances.
2083     short WBIdx = 4; // To jump over the first 4 standard ones.
2084     while ( !ptWhiteBalances[WBIdx].m_Make.isEmpty()
2085             &&
2086             ( ptWhiteBalances[WBIdx].m_Make  != m_CameraMake
2087               ||
2088               ptWhiteBalances[WBIdx].m_Model != m_CameraModel
2089             )
2090           ) {
2091       WBIdx++;
2092     }
2093     // And then add the custom whitebalances.
2094     while (ptWhiteBalances[WBIdx].m_Make  == m_CameraMake
2095            &&
2096            ptWhiteBalances[WBIdx].m_Model == m_CameraModel){
2097       Settings->AddOrReplaceOption("WhiteBalance",
2098                                    ptWhiteBalances[WBIdx].m_Name,
2099                                    QVariant(WBIdx));
2100       WBIdx++;
2101     }
2102   }
2103 
2104   // Setting for interpolation passes only on DCB needed
2105 
2106   if (Settings->GetInt("Interpolation")==ptInterpolation_DCB ||
2107       Settings->GetInt("Interpolation")==ptInterpolation_DCBSoft ||
2108       Settings->GetInt("Interpolation")==ptInterpolation_DCBSharp)
2109     Settings->SetEnabled("InterpolationPasses",1);
2110   else
2111     Settings->SetEnabled("InterpolationPasses",0);
2112 
2113   // Preview Mode
2114   PreviewModeButton->setChecked(Settings->GetInt("PreviewMode"));
2115 
2116   // Run mode
2117   RunButton->setEnabled(Settings->GetInt("RunMode"));
2118 
2119   // PizeSize Widget
2120   PipeSizeWidget->setEnabled(1-
2121     (Settings->GetInt("AutomaticPipeSize") &&
2122      Settings->ToolIsActive("TabResize")));
2123 
2124   // Show containers
2125   BottomContainer->setVisible(Settings->GetInt("ShowBottomContainer"));
2126   ControlFrame->setVisible(Settings->GetInt("ShowToolContainer"));
2127 
2128   // Geometry
2129   ResizeHeightWidget->setVisible(Settings->GetInt("ResizeDimension") == ptResizeDimension_WidthHeight);
2130 
2131   // sRGB gamma compensation
2132   Settings->SetEnabled("OutputGamma",Settings->GetInt("OutputGammaCompensation"));
2133   Settings->SetEnabled("OutputLinearity",Settings->GetInt("OutputGammaCompensation"));
2134 
2135   // Save options
2136   if (Settings->GetInt("SaveFormat")==ptSaveFormat_JPEG)
2137     Settings->SetEnabled("SaveSampling",1);
2138   else
2139     Settings->SetEnabled("SaveSampling",0);
2140 
2141   if (Settings->GetInt("SaveFormat")==ptSaveFormat_JPEG ||
2142       Settings->GetInt("SaveFormat")==ptSaveFormat_PNG ||
2143       Settings->GetInt("SaveFormat")==ptSaveFormat_PNG16)
2144     Settings->SetEnabled("SaveQuality",1);
2145   else
2146     Settings->SetEnabled("SaveQuality",0);
2147 
2148   // Statusbar : photo
2149   QStringList InputFileNameList = Settings->GetStringList("InputFileNameList");
2150   if (InputFileNameList.count() > 0) {
2151     PathInfo.setFile(InputFileNameList[0]);
2152     ShortFileName = PathInfo.fileName();
2153 
2154     QString Tmp = "";
2155     QString Report = "";
2156     Report += Tmp.setNum(Settings->GetInt("ImageW"));
2157     Report += " x ";
2158     Report += Tmp.setNum(Settings->GetInt("ImageH"));
2159     Report += "     ";
2160     SizeFullLabel->setText(Report);
2161 
2162     int TmpScaled = Settings->GetInt("Scaled");
2163 
2164     Report = "";
2165     Report += Tmp.setNum(Settings->GetInt("PipeImageW") << TmpScaled);
2166     Report += " x ";
2167     Report += Tmp.setNum(Settings->GetInt("PipeImageH") << TmpScaled);
2168     Report += "     ";
2169     SizeFullCropLabel->setText(Report);
2170 
2171     Report = "";
2172     Report += Tmp.setNum(Settings->GetInt("PipeImageW"));
2173     Report += " x ";
2174     Report += Tmp.setNum(Settings->GetInt("PipeImageH"));
2175     Report += "     ";
2176     SizeCurrentLabel->setText(Report);
2177 
2178   } else {
2179     // Startup.
2180 
2181   }
2182 }
2183 
2184 //==============================================================================
2185 // Display strings from settings
Settings_2_Form()2186 void ptMainWindow::Settings_2_Form() {
2187   if (Settings->GetInt("JobMode") == 1) return;
2188 
2189   // Metadata
2190   edtOutputSuffix->setText(Settings->GetString("OutputFileNameSuffix"));
2191   edtImageTitle->setText(Settings->GetString("ImageTitle"));
2192   edtCopyright->setText( Settings->GetString("Copyright"));
2193 }
2194 
2195 //==============================================================================
2196 // Read settings from Form
Form_2_Settings()2197 void ptMainWindow::Form_2_Settings() {
2198   if (Settings->GetInt("JobMode") == 1) return;
2199 
2200   //Metadata
2201   Settings->SetValue("OutputFileNameSuffix", edtOutputSuffix->text().trimmed());
2202   Settings->SetValue("ImageTitle", edtImageTitle->text().trimmed());
2203   Settings->SetValue("Copyright",  edtCopyright->text().trimmed());
2204 }
2205 
2206 ////////////////////////////////////////////////////////////////////////////////
2207 
UpdateFilenameInfo(const QStringList FileNameList)2208 void ptMainWindow::UpdateFilenameInfo(const QStringList FileNameList) {
2209   QFileInfo fn(FileNameList[0]);
2210   if (FileNameList.length() > 0 ) {
2211     FileNameLabel->setText(fn.fileName());
2212     #ifdef Q_OS_WIN
2213       FilePathLabel->setText(fn.canonicalPath().replace(QString("/"), QString("\\")));
2214     #else
2215       FilePathLabel->setText(fn.canonicalPath());
2216     #endif
2217   } else {
2218     FileNameLabel->setText("");
2219     FilePathLabel->setText("");
2220   }
2221 }
2222 
2223 
2224 ////////////////////////////////////////////////////////////////////////////////
2225 //
2226 // UpdateExifInfo()
2227 // Update the exif info gui element.
2228 // TODO Optimize : slow.
2229 //
2230 ////////////////////////////////////////////////////////////////////////////////
2231 
UpdateExifInfo(Exiv2::ExifData ExifData)2232 void ptMainWindow::UpdateExifInfo(Exiv2::ExifData ExifData) {
2233 
2234   // Exif info for the info window (the previous infowindow)
2235 
2236   Exiv2::ExifData::iterator Pos;
2237   QString TheInfo;
2238   QString TempString = "";
2239 
2240   Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Image.Make"));
2241   if (Pos != ExifData.end() ) {
2242     std::stringstream str;
2243     str << *Pos;
2244     TheInfo.append(QString(str.str().c_str()));
2245   }
2246   while (TheInfo.endsWith(" ")) TheInfo.chop(1);
2247   TempString = TheInfo +": ";
2248   TheInfo="";
2249 
2250   Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Image.Model"));
2251   if (Pos != ExifData.end() ) {
2252     std::stringstream str;
2253     str << *Pos;
2254     TheInfo.append(QString(str.str().c_str()));
2255   }
2256   TempString = TempString + TheInfo;
2257   InfoCameraLabel->setText(TempString);
2258   TheInfo="";
2259 
2260   // Idea from UFRaw
2261   if (ExifData.findKey(Exiv2::ExifKey("Exif.Image.LensInfo")) != ExifData.end() ) {
2262     Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Image.LensInfo"));
2263     std::stringstream str;
2264     str << *Pos;
2265     TheInfo.append(QString(str.str().c_str()));
2266   } else if (ExifData.findKey(Exiv2::ExifKey("Exif.Nikon3.LensData")) != ExifData.end() ) {
2267     Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Nikon3.LensData"));
2268     std::stringstream str;
2269     str << *Pos;
2270     TheInfo.append(QString(str.str().c_str()));
2271   } else if (ExifData.findKey(Exiv2::ExifKey("Exif.Nikon3.Lens")) != ExifData.end() ) {
2272     Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Nikon3.Lens"));
2273     std::stringstream str;
2274     str << *Pos;
2275     TheInfo.append(QString(str.str().c_str()));
2276 #if EXIV2_TEST_VERSION(0,17,91)   /* Exiv2 0.18-pre1 */
2277   } else if (ExifData.findKey(Exiv2::ExifKey("Exif.CanonCs.LensType")) != ExifData.end() ) {
2278     Pos = ExifData.findKey(Exiv2::ExifKey("Exif.CanonCs.LensType"));
2279     std::stringstream str;
2280     str << *Pos;
2281     TheInfo.append(QString(str.str().c_str()));
2282 #endif
2283   } else if (ExifData.findKey(Exiv2::ExifKey("Exif.Canon.0x0095")) != ExifData.end() ) {
2284     Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Canon.0x0095"));
2285     std::stringstream str;
2286     str << *Pos;
2287     TheInfo.append(QString(str.str().c_str()));
2288   } else if (ExifData.findKey(Exiv2::ExifKey("Exif.Minolta.LensID")) != ExifData.end() ) {
2289     Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Minolta.LensID"));
2290     std::stringstream str;
2291     str << *Pos;
2292     TheInfo.append(QString(str.str().c_str()));
2293 #if EXIV2_TEST_VERSION(0,16,0)
2294   } else if (ExifData.findKey(Exiv2::ExifKey("Exif.Pentax.LensType")) != ExifData.end() ) {
2295     Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Pentax.LensType"));
2296     std::stringstream str;
2297     str << *Pos;
2298     TheInfo.append(QString(str.str().c_str()));
2299 #endif
2300   } else if (ExifData.findKey(Exiv2::ExifKey("Exif.OlympusEq.LensType")) != ExifData.end() ) {
2301     Pos = ExifData.findKey(Exiv2::ExifKey("Exif.OlympusEq.LensType"));
2302     std::stringstream str;
2303     str << *Pos;
2304     TheInfo.append(QString(str.str().c_str()));
2305   } else if (ExifData.findKey(Exiv2::ExifKey("Exif.Panasonic.LensType")) != ExifData.end() ) {
2306     Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Panasonic.LensType"));
2307     std::stringstream str;
2308     str << *Pos;
2309     TheInfo.append(QString(str.str().c_str()));
2310   }
2311   InfoLensLabel->setText(TheInfo);
2312   TheInfo="";
2313 
2314   Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Photo.DateTimeOriginal"));
2315   if (Pos != ExifData.end() ) {
2316     std::stringstream str;
2317     str << *Pos;
2318     TheInfo.append(QString(str.str().c_str()));
2319   }
2320   InfoTimeLabel->setText(TheInfo);
2321   TheInfo="";
2322 
2323   Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Photo.ExposureTime"));
2324   if (Pos != ExifData.end() ) {
2325     std::stringstream str;
2326     str << *Pos;
2327     TheInfo.append(QString(str.str().c_str()));
2328   } else {
2329     Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Photo.ShutterSpeedValue"));
2330     if (Pos != ExifData.end() ) {
2331       std::stringstream str;
2332       str << *Pos;
2333       TheInfo.append(QString(str.str().c_str()));
2334     }
2335   }
2336   TempString = TheInfo + tr(" at ");
2337   TheInfo="";
2338 
2339   Settings->SetValue("ApertureFromExif", 0.0);
2340   Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Photo.FNumber"));
2341   if (Pos != ExifData.end() ) {
2342     std::stringstream str;
2343     str << *Pos;
2344     Settings->SetValue("ApertureFromExif", QString(str.str().c_str()).remove("F", Qt::CaseInsensitive).toDouble());
2345     TheInfo.append(QString(str.str().c_str()));
2346   } else {
2347     Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Photo.ApertureValue"));
2348     if (Pos != ExifData.end() ) {
2349       std::stringstream str;
2350       str << *Pos;
2351       Settings->SetValue("ApertureFromExif", QString(str.str().c_str()).remove("F", Qt::CaseInsensitive).toDouble());
2352       TheInfo.append(QString(str.str().c_str()));
2353     }
2354   }
2355   TempString = TempString + TheInfo + tr(" with ISO ");
2356   TheInfo="";
2357 
2358   Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Photo.ISOSpeedRatings"));
2359   if (Pos != ExifData.end() ) {
2360     std::stringstream str;
2361     str << *Pos;
2362     TheInfo.append(QString(str.str().c_str()));
2363   }
2364   if (TheInfo == "" || TheInfo == " ") TheInfo = "NN";
2365   TempString = TempString + TheInfo;
2366   InfoExposureLabel->setText(TempString);
2367   TheInfo="";
2368 
2369   Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Photo.FocalLength"));
2370   if (Pos != ExifData.end() ) {
2371     std::stringstream str;
2372     str << *Pos;
2373     TheInfo.append(QString(str.str().c_str()));
2374   }
2375   if (TheInfo != "" && TheInfo != " ") {
2376     // save focal length (need 35mm equiv.)
2377     QString FL = TheInfo;
2378     while(FL.endsWith("m") || FL.endsWith(" ")) FL.chop(1);
2379     if (FL.toFloat() >= 4.0f && FL.toFloat() <= 6000.0f)
2380       Settings->SetValue("FocalLengthIn35mmFilm",FL.toFloat());
2381     else
2382       Settings->SetValue("FocalLengthIn35mmFilm",50.0);
2383   } else {
2384     Settings->SetValue("FocalLengthIn35mmFilm",50.0);
2385   }
2386   TempString = TheInfo;
2387   TheInfo="";
2388 
2389   Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Photo.FocalLengthIn35mmFilm"));
2390   if (Pos != ExifData.end() ) {
2391     std::stringstream str;
2392     str << *Pos;
2393     TheInfo.append(QString(str.str().c_str()));
2394   }
2395   if (TheInfo != "" && TheInfo != " " && TheInfo != TempString ) {
2396     TempString = TempString + tr(" (35mm equiv.: ") + TheInfo + ")";
2397     // save focal length (crop camera!)
2398     QString FL = TheInfo;
2399     while(FL.endsWith("m") || FL.endsWith(" ")) FL.chop(1);
2400     if (FL.toFloat() >= 4.0f && FL.toFloat() <= 6000.0f)
2401       Settings->SetValue("FocalLengthIn35mmFilm",FL.toFloat());
2402     else
2403       Settings->SetValue("FocalLengthIn35mmFilm",50.0);
2404   }
2405   InfoFocalLengthLabel->setText(TempString);
2406   TheInfo="";
2407 
2408   Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Photo.Flash"));
2409   if (Pos != ExifData.end() ) {
2410     std::stringstream str;
2411     str << *Pos;
2412     TheInfo.append(QString::fromLocal8Bit(str.str().c_str()));
2413   }
2414   InfoFlashLabel->setText(TheInfo);
2415   TheInfo="";
2416 
2417   Pos = ExifData.findKey(Exiv2::ExifKey("Exif.Photo.WhiteBalance"));
2418   if (Pos != ExifData.end() ) {
2419     std::stringstream str;
2420     str << *Pos;
2421     TheInfo.append(QString::fromLocal8Bit(str.str().c_str()));
2422   }
2423   InfoWhitebalanceLabel->setText(TheInfo);
2424   TheInfo="";
2425 
2426   // dcraw Data
2427   TheInfo = Settings->GetString("CameraMake") + ": " + Settings->GetString("CameraModel");
2428   InfoDcrawLabel->setText(TheInfo);
2429 }
2430 
2431 //==============================================================================
2432 
2433 
2434 ////////////////////////////////////////////////////////////////////////////////
2435 //
2436 // UpdateCropToolUI
2437 //
2438 ////////////////////////////////////////////////////////////////////////////////
2439 
UpdateCropToolUI()2440 void ptMainWindow::UpdateCropToolUI() {
2441   bool OnOff = false;
2442   if (ViewWindow != NULL) {   // when called from MainWindow constructor, ViewWindow doesn't yet exist
2443     if (ViewWindow->interaction() == iaCrop) {
2444       OnOff = true;
2445     }
2446   }
2447   CropWidget->setEnabled(!OnOff);
2448   MakeCropButton->setVisible(!OnOff);
2449   ConfirmCropButton->setVisible(OnOff);
2450   CancelCropButton->setVisible(OnOff);
2451   CropCenterHorButton->setVisible(OnOff);
2452   CropCenterVertButton->setVisible(OnOff);
2453 
2454   if (Settings->GetInt("FixedAspectRatio") != 0) {
2455     AspectRatioWLabel->setEnabled(true);
2456     AspectRatioHLabel->setEnabled(true);
2457     AspectRatioWWidget->setEnabled(true);
2458     AspectRatioHWidget->setEnabled(true);
2459   } else {
2460     AspectRatioWLabel->setEnabled(false);
2461     AspectRatioHLabel->setEnabled(false);
2462     AspectRatioWWidget->setEnabled(false);
2463     AspectRatioHWidget->setEnabled(false);
2464   }
2465 }
2466 
2467 
2468 ////////////////////////////////////////////////////////////////////////////////
2469 //
2470 // InitVisibleTools
2471 //
2472 ////////////////////////////////////////////////////////////////////////////////
2473 
InitVisibleTools()2474 void ptMainWindow::InitVisibleTools() {
2475   m_VisibleToolsModel = new ptVisibleToolsModel;
2476 
2477   // fill items corresponding to tabs
2478   for (int i=0; i < ProcessingTabBook->count(); i++) {
2479     QStandardItem *topItem = new QStandardItem(ProcessingTabBook->tabText(i));
2480     topItem->setFlags(Qt::NoItemFlags);
2481     m_VisibleToolsModel->appendRow(topItem);
2482   }
2483 
2484   QStringList hiddenTools = Settings->GetStringList("HiddenTools");
2485   QStringList favouriteTools = Settings->GetStringList("FavouriteTools");
2486 
2487   foreach (QString hBoxName, *m_GroupBoxesOrdered) {
2488     auto hFilt = m_GroupBox->value(hBoxName);
2489     auto item  = new QStandardItem(hFilt->caption());
2490 
2491     // set tool state and corresponding icon will be set automatically
2492     if (hiddenTools.contains(hBoxName))
2493       item->setData(tsHidden, Qt::UserRole+1);
2494     else
2495       if (favouriteTools.contains(hBoxName))
2496         item->setData(tsFavourite, Qt::UserRole+1);
2497       else
2498         item->setData(tsNormal, Qt::UserRole+1);
2499 
2500     // check if tool can be hidden and set corresponding flag
2501     if (hFilt->canHide())
2502       item->setData(0, Qt::UserRole+2);
2503     else
2504       item->setData(1, Qt::UserRole+2);
2505 
2506     m_VisibleToolsModel->item(hFilt->parentTabIdx())->appendRow(item);
2507   }
2508 
2509   // connect model with Visible Tools View
2510   VisibleToolsView->setModel(m_VisibleToolsModel);
2511   VisibleToolsView->setEditTriggers(QAbstractItemView::CurrentChanged |
2512                                     QAbstractItemView::DoubleClicked);
2513   VisibleToolsView->setItemDelegate(new ptVisibleToolsItemDelegate);
2514 }
2515 
2516 //==============================================================================
2517 
SwitchUIState(const ptUIState AState)2518 void ptMainWindow::SwitchUIState(const ptUIState AState)
2519 {
2520   if (FUIState == AState) return;
2521 
2522   FUIState = AState;
2523 
2524   switch (AState) {
2525     case uisProcessing:
2526       // Processing
2527       MainStack->setCurrentWidget(ProcessingPage);
2528       Settings->SetValue("FileMgrIsOpen", 0);
2529       Settings->SetValue("BatchIsOpen", 0);
2530       break;
2531     case uisFileMgr:
2532       // Filemanager
2533   #ifndef PT_WITHOUT_FILEMGR
2534       MainStack->setCurrentWidget(FileManagerPage);
2535       Settings->SetValue("FileMgrIsOpen", 1);
2536   #endif
2537       break;
2538     case uisBatch:
2539       MainStack->setCurrentWidget(BatchPage);
2540       Settings->SetValue("BatchIsOpen", 1);
2541       break;
2542     default:
2543       GInfo->Raise("Unknown UI state", AT);
2544   }
2545 }
2546 
2547 ////////////////////////////////////////////////////////////////////////////////
2548 //
2549 // ApplyVisibleTools
2550 //
2551 ////////////////////////////////////////////////////////////////////////////////
2552 
ApplyVisibleTools()2553 void ptMainWindow::ApplyVisibleTools() {
2554   QString FirstActive;
2555 
2556   foreach (QString hBoxName, *m_GroupBoxesOrdered) {
2557     auto hFilt    = m_GroupBox->value(hBoxName);
2558     auto hToolBox = hFilt->guiWidget();
2559 
2560     // find all items with necessary name (in different tabs)
2561     QList<QStandardItem *> itemList =
2562         m_VisibleToolsModel->findItems(hFilt->caption(), Qt::MatchExactly | Qt::MatchRecursive);
2563 
2564     // find item corresponding to proper tab (maybe their is a simplier way)
2565     QStandardItem *item = NULL;
2566     foreach (QStandardItem *it, itemList) {
2567       QString tabName = ProcessingTabBook->tabText(hFilt->parentTabIdx());
2568       if (m_VisibleToolsModel->indexFromItem(it).parent() ==
2569           m_VisibleToolsModel->indexFromItem(
2570               m_VisibleToolsModel->findItems(tabName, Qt::MatchExactly).first()) )
2571       {
2572         item = it;
2573         break;
2574       }
2575     }
2576 
2577     // hide/show tools according to state
2578     if (item->data(Qt::UserRole+1).toInt() == tsHidden) {
2579       QStringList hiddenTools = Settings->GetStringList("HiddenTools");
2580       // hide tool if it was visible
2581       if (!hiddenTools.contains(hBoxName)) {
2582         hiddenTools.append(hBoxName);
2583         hToolBox->hide();
2584         // find first active tool, which changes it's state
2585         if (hFilt->isActive() && FirstActive.size() == 0)
2586           FirstActive = hBoxName;
2587         Settings->SetValue("HiddenTools", hiddenTools);
2588       }
2589 
2590       QStringList favouriteTools = Settings->GetStringList("FavouriteTools");
2591       if (favouriteTools.contains(hBoxName)) {
2592         favouriteTools.removeAll(hBoxName);
2593         Settings->SetValue("FavouriteTools", favouriteTools);
2594       }
2595     }
2596 
2597     if (item->data(Qt::UserRole+1).toInt() == tsFavourite) {
2598       QStringList favouriteTools = Settings->GetStringList("FavouriteTools");
2599       if (!favouriteTools.contains(hBoxName)) {
2600         favouriteTools.append(hBoxName);
2601         Settings->SetValue("FavouriteTools", favouriteTools);
2602       }
2603 
2604       QStringList hiddenTools = Settings->GetStringList("HiddenTools");
2605       // show tool if it was hidden
2606       if (hiddenTools.contains(hBoxName)) {
2607         hiddenTools.removeAll(hBoxName);
2608         hToolBox->show();
2609         Settings->SetValue("HiddenTools", hiddenTools);
2610         // find first active tool, which changes it's state
2611         if (hFilt->isActive() && FirstActive.size() == 0)
2612           FirstActive = hBoxName;
2613       }
2614     }
2615 
2616     if (item->data(Qt::UserRole+1).toInt() == tsNormal) {
2617       QStringList hiddenTools = Settings->GetStringList("HiddenTools");
2618       // show tool if it was hidden
2619       if (hiddenTools.contains(hBoxName)) {
2620         hiddenTools.removeAll(hBoxName);
2621         hToolBox->show();
2622         Settings->SetValue("HiddenTools", hiddenTools);
2623         // find first active tool, which changes it's state
2624         if (hFilt->isActive() && FirstActive.size() == 0)
2625           FirstActive = hBoxName;
2626       }
2627 
2628       QStringList favouriteTools = Settings->GetStringList("FavouriteTools");
2629       if (favouriteTools.contains(hBoxName)) {
2630         favouriteTools.removeAll(hBoxName);
2631         Settings->SetValue("FavouriteTools", favouriteTools);
2632       }
2633     }
2634   }
2635 
2636   // Image need to be updated, if active tools have changed their state
2637   if (FirstActive.size() != 0)
2638     Update(FirstActive);
2639 }
2640 
2641 
2642 ////////////////////////////////////////////////////////////////////////////////
2643 //
2644 // UpdateVisibleTools
2645 //
2646 ////////////////////////////////////////////////////////////////////////////////
2647 
UpdateVisibleTools()2648 void ptMainWindow::UpdateVisibleTools() {
2649   QStringList hiddenTools = Settings->GetStringList("HiddenTools");
2650   QStringList favouriteTools = Settings->GetStringList("FavouriteTools");
2651 
2652   foreach (QString itGroupBox, *m_GroupBoxesOrdered) {
2653     auto hFilt = m_GroupBox->value(itGroupBox);
2654 
2655     // find all TreeItems with necessary name (in different tabs)
2656     QList<QStandardItem *> itemList =
2657         m_VisibleToolsModel->findItems(hFilt->caption(), Qt::MatchExactly | Qt::MatchRecursive);
2658 
2659     // find item corresponding to proper tab (maybe there is a simpler way)
2660     QStandardItem *item = NULL;
2661     foreach (QStandardItem *it, itemList) {
2662       QString tabName = ProcessingTabBook->tabText(hFilt->parentTabIdx());
2663       if (m_VisibleToolsModel->indexFromItem(it).parent() ==
2664           m_VisibleToolsModel->indexFromItem(
2665               m_VisibleToolsModel->findItems(tabName, Qt::MatchExactly).first() ))
2666       {
2667         item = it;
2668         break;
2669       }
2670     }
2671 
2672     // set tool state and corresponding icon will be set automatically
2673     if (hiddenTools.contains(itGroupBox)) {
2674       m_VisibleToolsModel->setData(m_VisibleToolsModel->indexFromItem(item),
2675                                    tsHidden, Qt::UserRole+1);
2676     } else {
2677       if (favouriteTools.contains(itGroupBox)) {
2678         m_VisibleToolsModel->setData(m_VisibleToolsModel->indexFromItem(item),
2679                                      tsFavourite, Qt::UserRole+1);
2680       } else {
2681         m_VisibleToolsModel->setData(m_VisibleToolsModel->indexFromItem(item),
2682                                      tsNormal, Qt::UserRole+1);
2683       }
2684     }
2685 
2686     // check if tool can be hidden and set corresponding flag
2687     if (Settings->ToolAlwaysVisible(itGroupBox))
2688       m_VisibleToolsModel->setData(m_VisibleToolsModel->indexFromItem(item), 1, Qt::UserRole+2);
2689     else
2690       m_VisibleToolsModel->setData(m_VisibleToolsModel->indexFromItem(item), 0, Qt::UserRole+2);
2691   }
2692 }
2693 
2694 
2695 ////////////////////////////////////////////////////////////////////////////////
2696 //
2697 // LoadUISettings
2698 //
2699 ////////////////////////////////////////////////////////////////////////////////
2700 
LoadUISettings(const QString & fileName)2701 void ptMainWindow::LoadUISettings(const QString &fileName) {
2702   QSettings UISettings(fileName, QSettings::IniFormat);
2703   UISettings.sync();
2704 
2705   if (UISettings.status() != QSettings::NoError) {
2706     ptMessageBox::critical(0, "Error", "Error reading UI file\n" + fileName);
2707     return;
2708   }
2709   if (UISettings.value("Magic") != "photivoUIFile") {
2710     ptMessageBox::warning(0, "Error", fileName + "\nis not an UI file.");
2711     return;
2712   }
2713 
2714   Settings->SetValue("FavouriteTools", UISettings.value("FavouriteTools").toStringList());
2715 
2716   QStringList hOldHidden = Settings->GetStringList("HiddenTools");
2717   QStringList hNewHidden = UISettings.value("HiddenTools").toStringList();
2718   QStringList Temp = hNewHidden;
2719 
2720   // find difference between previous and current hidden tools list
2721   hOldHidden.removeDuplicates();
2722   hNewHidden.removeDuplicates();
2723   foreach (QString str, hOldHidden) {
2724     if (hNewHidden.contains(str)) {
2725       hOldHidden.removeOne(str);
2726       hNewHidden.removeOne(str);
2727     }
2728   }
2729 
2730   // create a list of active tools which change their state
2731   QStringList hActiveTools;
2732   for (QString str: hNewHidden) {
2733     auto hFilt = m_GroupBox->value(str);
2734     hFilt->guiWidget()->hide();
2735     if (hFilt->isActive())
2736       hActiveTools.append(str);
2737   }
2738 
2739   Settings->SetValue("HiddenTools", Temp);
2740   for (QString str: hOldHidden) {
2741     auto hFilt = m_GroupBox->value(str);
2742     hFilt->guiWidget()->show();
2743     if (hFilt->isActive())
2744       hActiveTools.append(str);
2745   }
2746 
2747   // Image need to be updated, if active tools have changed their state
2748   foreach (QString str, *m_GroupBoxesOrdered) {
2749     if (hActiveTools.contains(str)) {
2750       Update(str);
2751       break;
2752     }
2753   }
2754 }
2755 
2756 
2757 ////////////////////////////////////////////////////////////////////////////////
2758 //
2759 // SaveUISettings
2760 //
2761 ////////////////////////////////////////////////////////////////////////////////
2762 
SaveUISettings(const QString & fileName) const2763 void ptMainWindow::SaveUISettings(const QString &fileName) const {
2764   QSettings UISettings(fileName, QSettings::IniFormat);
2765   UISettings.clear();
2766 
2767   UISettings.setValue("Magic", "photivoUIFile");
2768   UISettings.setValue("HiddenTools", Settings->GetStringList("HiddenTools"));
2769   UISettings.setValue("FavouriteTools", Settings->GetStringList("FavouriteTools"));
2770 
2771   UISettings.sync();
2772   if (UISettings.status() != QSettings::NoError)
2773     ptMessageBox::critical(0, "Error", "Error writing UI file\n" + fileName);
2774 }
2775 
2776 
2777 ////////////////////////////////////////////////////////////////////////////////
2778 //
2779 // OnVisibleToolsDiscardButtonClicked
2780 //
2781 ////////////////////////////////////////////////////////////////////////////////
2782 
OnVisibleToolsDiscardButtonClicked()2783 void ptMainWindow::OnVisibleToolsDiscardButtonClicked() {
2784   // update VisibleTools box
2785   UpdateVisibleTools();
2786 }
2787 
2788 
2789 ////////////////////////////////////////////////////////////////////////////////
2790 //
2791 // OnVisibleToolsLoadButtonClicked
2792 //
2793 ////////////////////////////////////////////////////////////////////////////////
2794 
OnVisibleToolsLoadButtonClicked()2795 void ptMainWindow::OnVisibleToolsLoadButtonClicked() {
2796   QString UIFilePattern = tr("Photivo UI file (*.ptu);;All files (*.*)");
2797   QString UIFileName = QFileDialog::getOpenFileName(this,
2798                                                     tr("Open UI"),
2799                                                     Settings->GetString("UIDirectory"),
2800                                                     UIFilePattern);
2801   if (UIFileName.size() == 0) return;
2802 
2803   LoadUISettings(UIFileName);
2804 
2805   // update VisibleTools box
2806   UpdateVisibleTools();
2807 }
2808 
2809 
2810 ////////////////////////////////////////////////////////////////////////////////
2811 //
2812 // OnVisibleToolsSaveButtonClicked
2813 //
2814 ////////////////////////////////////////////////////////////////////////////////
2815 
OnVisibleToolsSaveButtonClicked()2816 void ptMainWindow::OnVisibleToolsSaveButtonClicked() {
2817   // apply changes at VisibleTools box
2818   ApplyVisibleTools();
2819 
2820   QString UIFilePattern = tr("Photivo UI file (*.ptu);;All files (*.*)");
2821   QString UIFileName = QFileDialog::getSaveFileName(this,
2822                                                     tr("Save UI"),
2823                                                     Settings->GetString("UIDirectory"),
2824                                                     UIFilePattern);
2825   if (UIFileName.size() == 0) return;
2826 
2827   QFileInfo PathInfo(UIFileName);
2828   if (PathInfo.suffix().size() == 0)
2829     UIFileName += ".ptu";
2830 
2831   SaveUISettings(UIFileName);
2832 }
2833 
2834 
2835 ////////////////////////////////////////////////////////////////////////////////
2836 //
2837 // Update lensfun UI elements
2838 //
2839 ////////////////////////////////////////////////////////////////////////////////
2840 
UpdateLfunDistUI()2841 void ptMainWindow::UpdateLfunDistUI() {
2842   short DistModel = Settings->GetInt("LfunDistModel");
2843   LfunDistPoly3Container->setVisible(DistModel == ptLfunDistModel_Poly3);
2844   LfunDistPoly5Container->setVisible(DistModel == ptLfunDistModel_Poly5);
2845 #if LF_VERSION < (3 << 16)
2846   LfunDistFov1Container->setVisible(DistModel == ptLfunDistModel_Fov1);
2847 #endif
2848   LfunDistPTLensContainer->setVisible(DistModel == ptLfunDistModel_PTLens);
2849 }
2850 
UpdateLfunCAUI()2851 void ptMainWindow::UpdateLfunCAUI() {
2852   short CAModel = Settings->GetInt("LfunCAModel");
2853   LfunCALinearContainer->setVisible(CAModel == ptLfunCAModel_Linear);
2854   LfunCAPoly3Container->setVisible(CAModel == ptLfunCAModel_Poly3);
2855 }
2856 
UpdateLfunVignetteUI()2857 void ptMainWindow::UpdateLfunVignetteUI() {
2858   short VignetteModel = Settings->GetInt("LfunVignetteModel");
2859   LfunVignettePoly6Container->setVisible(VignetteModel == ptLfunVignetteModel_Poly6);
2860 }
2861 
2862 ////////////////////////////////////////////////////////////////////////////////
2863 //
2864 // Update liquid rescale UI elements
2865 //
2866 ////////////////////////////////////////////////////////////////////////////////
2867 
UpdateLiquidRescaleUI()2868 void ptMainWindow::UpdateLiquidRescaleUI() {
2869   short Scaling = Settings->GetInt("LqrScaling");
2870   LqrHorScaleWidget->setVisible(Scaling == ptLqr_ScaleRelative);
2871   LqrVertScaleWidget->setVisible(Scaling == ptLqr_ScaleRelative);
2872   LqrWHContainter->setVisible(Scaling == ptLqr_ScaleAbsolute);
2873 }
2874 
2875 
2876 ////////////////////////////////////////////////////////////////////////////////
2877 //
2878 // Destructor
2879 //
2880 ////////////////////////////////////////////////////////////////////////////////
2881 
~ptMainWindow()2882 ptMainWindow::~ptMainWindow() {
2883   while (ToolBoxStructureList.size()) {
2884     ToolBoxStructureList.removeAt(0);
2885   }
2886 }
2887 
2888 //==============================================================================
2889 
2890 #ifdef Q_OS_WIN
winEvent(MSG * message,long * result)2891 bool ptMainWindow::winEvent(MSG *message, long *result) {
2892   return ptEcWin7::GetInstance()->winEvent(message, result);
2893 }
2894 
2895 #endif
2896