DigiKam – digital photo management application
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1933 lines
71 KiB

  1. /* ============================================================
  2. *
  3. * This file is a part of digiKam project
  4. * http://www.digikam.org
  5. *
  6. * Date : 2006-01-20
  7. * Description : main image editor GUI implementation
  8. *
  9. * Copyright (C) 2006-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
  10. *
  11. * This program is free software; you can redistribute it
  12. * and/or modify it under the terms of the GNU General
  13. * Public License as published by the Free Software Foundation;
  14. * either version 2, or (at your option)
  15. * any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * ============================================================ */
  23. // C Ansi includes.
  24. extern "C"
  25. {
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. }
  29. // C++ includes.
  30. #include <cmath>
  31. // TQt includes.
  32. #include <tqlabel.h>
  33. #include <tqdockarea.h>
  34. #include <tqlayout.h>
  35. #include <tqtooltip.h>
  36. #include <tqtoolbutton.h>
  37. #include <tqsplitter.h>
  38. #include <tqdir.h>
  39. #include <tqfileinfo.h>
  40. #include <tqfile.h>
  41. #include <tqcursor.h>
  42. #include <tqtimer.h>
  43. #include <tqfileinfo.h>
  44. // KDE includes.
  45. #include <kprinter.h>
  46. #include <kkeydialog.h>
  47. #include <tdeversion.h>
  48. #include <tdeaction.h>
  49. #include <kedittoolbar.h>
  50. #include <tdeaboutdata.h>
  51. #include <kcursor.h>
  52. #include <kstdaction.h>
  53. #include <tdeapplication.h>
  54. #include <tdeconfig.h>
  55. #include <tdelocale.h>
  56. #include <tdefiledialog.h>
  57. #include <tdemenubar.h>
  58. #include <kimageio.h>
  59. #include <tdeaccel.h>
  60. #include <tdemessagebox.h>
  61. #include <tdeglobal.h>
  62. #include <kstandarddirs.h>
  63. #include <kiconloader.h>
  64. #include <tdeio/netaccess.h>
  65. #include <tdeio/job.h>
  66. #include <kprotocolinfo.h>
  67. #include <tdeglobalsettings.h>
  68. #include <tdetoolbar.h>
  69. #include <kstatusbar.h>
  70. #include <kprogress.h>
  71. #include <twin.h>
  72. #include <kcombobox.h>
  73. // Local includes.
  74. #include "ddebug.h"
  75. #include "dpopupmenu.h"
  76. #include "canvas.h"
  77. #include "dimginterface.h"
  78. #include "imagedialog.h"
  79. #include "imageplugin.h"
  80. #include "imagepluginloader.h"
  81. #include "imageresize.h"
  82. #include "imageprint.h"
  83. #include "filesaveoptionsbox.h"
  84. #include "statusprogressbar.h"
  85. #include "iccsettingscontainer.h"
  86. #include "exposurecontainer.h"
  87. #include "iofilesettingscontainer.h"
  88. #include "savingcontextcontainer.h"
  89. #include "loadingcacheinterface.h"
  90. #include "slideshowsettings.h"
  91. #include "themeengine.h"
  92. #include "rawcameradlg.h"
  93. #include "editorstackview.h"
  94. #include "editortooliface.h"
  95. #include "editorwindowprivate.h"
  96. #include "editorwindow.h"
  97. #include "editorwindow.moc"
  98. void tqt_enter_modal( TQWidget *widget );
  99. void tqt_leave_modal( TQWidget *widget );
  100. namespace Digikam
  101. {
  102. EditorWindow::EditorWindow(const char *name)
  103. : TDEMainWindow(0, name, WType_TopLevel)
  104. {
  105. d = new EditorWindowPriv;
  106. m_themeMenuAction = 0;
  107. m_contextMenu = 0;
  108. m_canvas = 0;
  109. m_imagePluginLoader = 0;
  110. m_undoAction = 0;
  111. m_redoAction = 0;
  112. m_fullScreenAction = 0;
  113. m_saveAction = 0;
  114. m_saveAsAction = 0;
  115. m_revertAction = 0;
  116. m_fileDeleteAction = 0;
  117. m_forwardAction = 0;
  118. m_backwardAction = 0;
  119. m_firstAction = 0;
  120. m_lastAction = 0;
  121. m_undoAction = 0;
  122. m_redoAction = 0;
  123. m_stackView = 0;
  124. m_fullScreen = false;
  125. m_rotatedOrFlipped = false;
  126. m_setExifOrientationTag = true;
  127. m_cancelSlideShow = false;
  128. // Settings containers instance.
  129. d->ICCSettings = new ICCSettingsContainer();
  130. d->exposureSettings = new ExposureSettingsContainer();
  131. d->toolIface = new EditorToolIface(this);
  132. m_IOFileSettings = new IOFileSettingsContainer();
  133. m_savingContext = new SavingContextContainer();
  134. }
  135. EditorWindow::~EditorWindow()
  136. {
  137. delete m_canvas;
  138. delete m_IOFileSettings;
  139. delete m_savingContext;
  140. delete d->ICCSettings;
  141. delete d->exposureSettings;
  142. delete d;
  143. }
  144. EditorStackView* EditorWindow::editorStackView() const
  145. {
  146. return m_stackView;
  147. }
  148. void EditorWindow::setupContextMenu()
  149. {
  150. m_contextMenu = new DPopupMenu(this);
  151. TDEActionCollection *ac = actionCollection();
  152. if( ac->action("editorwindow_backward") ) ac->action("editorwindow_backward")->plug(m_contextMenu);
  153. if( ac->action("editorwindow_forward") ) ac->action("editorwindow_forward")->plug(m_contextMenu);
  154. m_contextMenu->insertSeparator();
  155. if( ac->action("editorwindow_slideshow") ) ac->action("editorwindow_slideshow")->plug(m_contextMenu);
  156. if( ac->action("editorwindow_rotate_left") ) ac->action("editorwindow_rotate_left")->plug(m_contextMenu);
  157. if( ac->action("editorwindow_rotate_right") ) ac->action("editorwindow_rotate_right")->plug(m_contextMenu);
  158. if( ac->action("editorwindow_crop") ) ac->action("editorwindow_crop")->plug(m_contextMenu);
  159. m_contextMenu->insertSeparator();
  160. if( ac->action("editorwindow_delete") ) ac->action("editorwindow_delete")->plug(m_contextMenu);
  161. }
  162. void EditorWindow::setupStandardConnections()
  163. {
  164. // -- Canvas connections ------------------------------------------------
  165. connect(m_canvas, TQT_SIGNAL(signalToggleOffFitToWindow()),
  166. TQT_TQOBJECT(this), TQT_SLOT(slotToggleOffFitToWindow()));
  167. connect(m_canvas, TQT_SIGNAL(signalShowNextImage()),
  168. TQT_TQOBJECT(this), TQT_SLOT(slotForward()));
  169. connect(m_canvas, TQT_SIGNAL(signalShowPrevImage()),
  170. TQT_TQOBJECT(this), TQT_SLOT(slotBackward()));
  171. connect(m_canvas, TQT_SIGNAL(signalRightButtonClicked()),
  172. TQT_TQOBJECT(this), TQT_SLOT(slotContextMenu()));
  173. connect(m_stackView, TQT_SIGNAL(signalZoomChanged(bool, bool, double)),
  174. TQT_TQOBJECT(this), TQT_SLOT(slotZoomChanged(bool, bool, double)));
  175. connect(m_canvas, TQT_SIGNAL(signalChanged()),
  176. TQT_TQOBJECT(this), TQT_SLOT(slotChanged()));
  177. connect(m_canvas, TQT_SIGNAL(signalUndoStateChanged(bool, bool, bool)),
  178. TQT_TQOBJECT(this), TQT_SLOT(slotUndoStateChanged(bool, bool, bool)));
  179. connect(m_canvas, TQT_SIGNAL(signalSelected(bool)),
  180. TQT_TQOBJECT(this), TQT_SLOT(slotSelected(bool)));
  181. connect(m_canvas, TQT_SIGNAL(signalPrepareToLoad()),
  182. TQT_TQOBJECT(this), TQT_SLOT(slotPrepareToLoad()));
  183. connect(m_canvas, TQT_SIGNAL(signalLoadingStarted(const TQString &)),
  184. TQT_TQOBJECT(this), TQT_SLOT(slotLoadingStarted(const TQString &)));
  185. connect(m_canvas, TQT_SIGNAL(signalLoadingFinished(const TQString &, bool)),
  186. TQT_TQOBJECT(this), TQT_SLOT(slotLoadingFinished(const TQString &, bool)));
  187. connect(m_canvas, TQT_SIGNAL(signalLoadingProgress(const TQString &, float)),
  188. TQT_TQOBJECT(this), TQT_SLOT(slotLoadingProgress(const TQString &, float)));
  189. connect(m_canvas, TQT_SIGNAL(signalSavingStarted(const TQString&)),
  190. TQT_TQOBJECT(this), TQT_SLOT(slotSavingStarted(const TQString&)));
  191. connect(m_canvas, TQT_SIGNAL(signalSavingFinished(const TQString&, bool)),
  192. TQT_TQOBJECT(this), TQT_SLOT(slotSavingFinished(const TQString&, bool)));
  193. connect(m_canvas, TQT_SIGNAL(signalSavingProgress(const TQString&, float)),
  194. TQT_TQOBJECT(this), TQT_SLOT(slotSavingProgress(const TQString&, float)));
  195. connect(m_canvas, TQT_SIGNAL(signalSelectionChanged(const TQRect&)),
  196. TQT_TQOBJECT(this), TQT_SLOT(slotSelectionChanged(const TQRect&)));
  197. // -- if rotating/flipping set the rotatedflipped flag to true -----------
  198. connect(d->rotateLeftAction, TQT_SIGNAL(activated()),
  199. TQT_TQOBJECT(this), TQT_SLOT(slotRotatedOrFlipped()));
  200. connect(d->rotateRightAction, TQT_SIGNAL(activated()),
  201. TQT_TQOBJECT(this), TQT_SLOT(slotRotatedOrFlipped()));
  202. connect(d->flipHorizAction, TQT_SIGNAL(activated()),
  203. TQT_TQOBJECT(this), TQT_SLOT(slotRotatedOrFlipped()));
  204. connect(d->flipVertAction, TQT_SIGNAL(activated()),
  205. TQT_TQOBJECT(this), TQT_SLOT(slotRotatedOrFlipped()));
  206. // -- status bar connections --------------------------------------
  207. connect(m_nameLabel, TQT_SIGNAL(signalCancelButtonPressed()),
  208. TQT_TQOBJECT(this), TQT_SLOT(slotNameLabelCancelButtonPressed()));
  209. connect(m_nameLabel, TQT_SIGNAL(signalCancelButtonPressed()),
  210. d->toolIface, TQT_SLOT(slotToolAborted()));
  211. }
  212. void EditorWindow::setupStandardActions()
  213. {
  214. // -- Standard 'File' menu actions ---------------------------------------------
  215. m_backwardAction = KStdAction::back(TQT_TQOBJECT(this), TQT_SLOT(slotBackward()),
  216. actionCollection(), "editorwindow_backward");
  217. m_forwardAction = KStdAction::forward(TQT_TQOBJECT(this), TQT_SLOT(slotForward()),
  218. actionCollection(), "editorwindow_forward");
  219. m_firstAction = new TDEAction(i18n("&First"), "go-first",
  220. TDEStdAccel::shortcut( TDEStdAccel::Home),
  221. TQT_TQOBJECT(this), TQT_SLOT(slotFirst()),
  222. actionCollection(), "editorwindow_first");
  223. m_lastAction = new TDEAction(i18n("&Last"), "go-last",
  224. TDEStdAccel::shortcut( TDEStdAccel::End),
  225. TQT_TQOBJECT(this), TQT_SLOT(slotLast()),
  226. actionCollection(), "editorwindow_last");
  227. m_saveAction = KStdAction::save(TQT_TQOBJECT(this), TQT_SLOT(slotSave()),
  228. actionCollection(), "editorwindow_save");
  229. m_saveAsAction = KStdAction::saveAs(TQT_TQOBJECT(this), TQT_SLOT(slotSaveAs()),
  230. actionCollection(), "editorwindow_saveas");
  231. m_revertAction = KStdAction::revert(TQT_TQOBJECT(this), TQT_SLOT(slotRevert()),
  232. actionCollection(), "editorwindow_revert");
  233. m_saveAction->setEnabled(false);
  234. m_saveAsAction->setEnabled(false);
  235. m_revertAction->setEnabled(false);
  236. d->filePrintAction = new TDEAction(i18n("Print Image..."), "document-print",
  237. CTRL+Key_P,
  238. TQT_TQOBJECT(this), TQT_SLOT(slotFilePrint()),
  239. actionCollection(), "editorwindow_print");
  240. m_fileDeleteAction = new TDEAction(i18n("Move to Trash"), "edittrash",
  241. Key_Delete,
  242. TQT_TQOBJECT(this), TQT_SLOT(slotDeleteCurrentItem()),
  243. actionCollection(), "editorwindow_delete");
  244. KStdAction::close(TQT_TQOBJECT(this), TQT_SLOT(close()), actionCollection(), "editorwindow_close");
  245. // -- Standard 'Edit' menu actions ---------------------------------------------
  246. d->copyAction = KStdAction::copy(TQT_TQOBJECT(m_canvas), TQT_SLOT(slotCopy()),
  247. actionCollection(), "editorwindow_copy");
  248. d->copyAction->setEnabled(false);
  249. m_undoAction = new TDEToolBarPopupAction(i18n("Undo"), "edit-undo",
  250. TDEStdAccel::shortcut(TDEStdAccel::Undo),
  251. TQT_TQOBJECT(m_canvas), TQT_SLOT(slotUndo()),
  252. actionCollection(), "editorwindow_undo");
  253. connect(m_undoAction->popupMenu(), TQT_SIGNAL(aboutToShow()),
  254. TQT_TQOBJECT(this), TQT_SLOT(slotAboutToShowUndoMenu()));
  255. connect(m_undoAction->popupMenu(), TQT_SIGNAL(activated(int)),
  256. TQT_TQOBJECT(m_canvas), TQT_SLOT(slotUndo(int)));
  257. m_undoAction->setEnabled(false);
  258. m_redoAction = new TDEToolBarPopupAction(i18n("Redo"), "edit-redo",
  259. TDEStdAccel::shortcut(TDEStdAccel::Redo),
  260. TQT_TQOBJECT(m_canvas), TQT_SLOT(slotRedo()),
  261. actionCollection(), "editorwindow_redo");
  262. connect(m_redoAction->popupMenu(), TQT_SIGNAL(aboutToShow()),
  263. TQT_TQOBJECT(this), TQT_SLOT(slotAboutToShowRedoMenu()));
  264. connect(m_redoAction->popupMenu(), TQT_SIGNAL(activated(int)),
  265. TQT_TQOBJECT(m_canvas), TQT_SLOT(slotRedo(int)));
  266. m_redoAction->setEnabled(false);
  267. d->selectAllAction = new TDEAction(i18n("Select All"),
  268. 0,
  269. CTRL+Key_A,
  270. TQT_TQOBJECT(m_canvas),
  271. TQT_SLOT(slotSelectAll()),
  272. actionCollection(),
  273. "editorwindow_selectAll");
  274. d->selectNoneAction = new TDEAction(i18n("Select None"),
  275. 0,
  276. CTRL+SHIFT+Key_A,
  277. TQT_TQOBJECT(m_canvas),
  278. TQT_SLOT(slotSelectNone()),
  279. actionCollection(),
  280. "editorwindow_selectNone");
  281. // -- Standard 'View' menu actions ---------------------------------------------
  282. d->zoomPlusAction = KStdAction::zoomIn(TQT_TQOBJECT(this), TQT_SLOT(slotIncreaseZoom()),
  283. actionCollection(), "editorwindow_zoomplus");
  284. d->zoomMinusAction = KStdAction::zoomOut(TQT_TQOBJECT(this), TQT_SLOT(slotDecreaseZoom()),
  285. actionCollection(), "editorwindow_zoomminus");
  286. d->zoomTo100percents = new TDEAction(i18n("Zoom to 100%"), "zoom-original",
  287. ALT+CTRL+Key_0, // NOTE: Photoshop 7 use ALT+CTRL+0.
  288. TQT_TQOBJECT(this), TQT_SLOT(slotZoomTo100Percents()),
  289. actionCollection(), "editorwindow_zoomto100percents");
  290. d->zoomFitToWindowAction = new TDEToggleAction(i18n("Fit to &Window"), "view_fit_window",
  291. CTRL+SHIFT+Key_E, // NOTE: Gimp 2 use CTRL+SHIFT+E.
  292. TQT_TQOBJECT(this), TQT_SLOT(slotToggleFitToWindow()),
  293. actionCollection(), "editorwindow_zoomfit2window");
  294. d->zoomFitToSelectAction = new TDEAction(i18n("Fit to &Selection"), "zoom-fit-best",
  295. ALT+CTRL+Key_S, TQT_TQOBJECT(this), TQT_SLOT(slotFitToSelect()),
  296. actionCollection(), "editorwindow_zoomfit2select");
  297. d->zoomFitToSelectAction->setEnabled(false);
  298. d->zoomFitToSelectAction->setWhatsThis(i18n("This option can be used to zoom the image to the "
  299. "current selection area."));
  300. d->zoomCombo = new KComboBox(true);
  301. d->zoomCombo->setDuplicatesEnabled(false);
  302. d->zoomCombo->setFocusPolicy(TQ_ClickFocus);
  303. d->zoomCombo->setInsertionPolicy(TQComboBox::NoInsertion);
  304. d->zoomComboAction = new KWidgetAction(d->zoomCombo, i18n("Zoom"), 0, 0, 0,
  305. actionCollection(), "editorwindow_zoomto");
  306. d->zoomCombo->insertItem(TQString("10%"));
  307. d->zoomCombo->insertItem(TQString("25%"));
  308. d->zoomCombo->insertItem(TQString("50%"));
  309. d->zoomCombo->insertItem(TQString("75%"));
  310. d->zoomCombo->insertItem(TQString("100%"));
  311. d->zoomCombo->insertItem(TQString("150%"));
  312. d->zoomCombo->insertItem(TQString("200%"));
  313. d->zoomCombo->insertItem(TQString("300%"));
  314. d->zoomCombo->insertItem(TQString("450%"));
  315. d->zoomCombo->insertItem(TQString("600%"));
  316. d->zoomCombo->insertItem(TQString("800%"));
  317. d->zoomCombo->insertItem(TQString("1200%"));
  318. connect(d->zoomCombo, TQT_SIGNAL(activated(int)),
  319. TQT_TQOBJECT(this), TQT_SLOT(slotZoomSelected()) );
  320. connect(d->zoomCombo, TQT_SIGNAL(returnPressed(const TQString&)),
  321. TQT_TQOBJECT(this), TQT_SLOT(slotZoomTextChanged(const TQString &)) );
  322. // Do not use std KDE action for full screen because action text is too large for app. toolbar.
  323. m_fullScreenAction = new TDEToggleAction(i18n("Full Screen"), "view-fullscreen",
  324. CTRL+SHIFT+Key_F, TQT_TQOBJECT(this),
  325. TQT_SLOT(slotToggleFullScreen()),
  326. actionCollection(), "editorwindow_fullscreen");
  327. m_fullScreenAction->setWhatsThis(i18n("Toggle the window to full screen mode"));
  328. d->slideShowAction = new TDEAction(i18n("Slideshow"), "slideshow", Key_F9,
  329. TQT_TQOBJECT(this), TQT_SLOT(slotToggleSlideShow()),
  330. actionCollection(),"editorwindow_slideshow");
  331. d->viewUnderExpoAction = new TDEToggleAction(i18n("Under-Exposure Indicator"), "underexposure",
  332. Key_F10, TQT_TQOBJECT(this),
  333. TQT_SLOT(slotToggleUnderExposureIndicator()),
  334. actionCollection(),"editorwindow_underexposure");
  335. d->viewOverExpoAction = new TDEToggleAction(i18n("Over-Exposure Indicator"), "overexposure",
  336. Key_F11, TQT_TQOBJECT(this),
  337. TQT_SLOT(slotToggleOverExposureIndicator()),
  338. actionCollection(),"editorwindow_overexposure");
  339. d->viewCMViewAction = new TDEToggleAction(i18n("Color Managed View"), "tv",
  340. Key_F12, TQT_TQOBJECT(this),
  341. TQT_SLOT(slotToggleColorManagedView()),
  342. actionCollection(),"editorwindow_cmview");
  343. // -- Standard 'Transform' menu actions ---------------------------------------------
  344. d->resizeAction = new TDEAction(i18n("&Resize..."), "resize_image", 0,
  345. TQT_TQOBJECT(this), TQT_SLOT(slotResize()),
  346. actionCollection(), "editorwindow_resize");
  347. d->cropAction = new TDEAction(i18n("Crop"), "crop",
  348. CTRL+Key_X,
  349. TQT_TQOBJECT(m_canvas), TQT_SLOT(slotCrop()),
  350. actionCollection(), "editorwindow_crop");
  351. d->cropAction->setEnabled(false);
  352. d->cropAction->setWhatsThis(i18n("This option can be used to crop the image. "
  353. "Select a region of the image to enable this action."));
  354. // -- Standard 'Flip' menu actions ---------------------------------------------
  355. d->flipHorizAction = new TDEAction(i18n("Flip Horizontally"), "mirror", CTRL+Key_Asterisk,
  356. TQT_TQOBJECT(m_canvas), TQT_SLOT(slotFlipHoriz()),
  357. actionCollection(), "editorwindow_flip_horiz");
  358. d->flipHorizAction->setEnabled(false);
  359. d->flipVertAction = new TDEAction(i18n("Flip Vertically"), "flip", CTRL+Key_Slash,
  360. TQT_TQOBJECT(m_canvas), TQT_SLOT(slotFlipVert()),
  361. actionCollection(), "editorwindow_flip_vert");
  362. d->flipVertAction->setEnabled(false);
  363. // -- Standard 'Rotate' menu actions ----------------------------------------
  364. d->rotateLeftAction = new TDEAction(i18n("Rotate Left"),
  365. "object-rotate-left", SHIFT+CTRL+Key_Left,
  366. TQT_TQOBJECT(m_canvas), TQT_SLOT(slotRotate270()),
  367. actionCollection(),
  368. "editorwindow_rotate_left");
  369. d->rotateLeftAction->setEnabled(false);
  370. d->rotateRightAction = new TDEAction(i18n("Rotate Right"),
  371. "object-rotate-right", SHIFT+CTRL+Key_Right,
  372. TQT_TQOBJECT(m_canvas), TQT_SLOT(slotRotate90()),
  373. actionCollection(),
  374. "editorwindow_rotate_right");
  375. d->rotateRightAction->setEnabled(false);
  376. // -- Standard 'Configure' menu actions ----------------------------------------
  377. d->showMenuBarAction = KStdAction::showMenubar(TQT_TQOBJECT(this), TQT_SLOT(slotShowMenuBar()), actionCollection());
  378. KStdAction::keyBindings(TQT_TQOBJECT(this), TQT_SLOT(slotEditKeys()), actionCollection());
  379. KStdAction::configureToolbars(TQT_TQOBJECT(this), TQT_SLOT(slotConfToolbars()), actionCollection());
  380. KStdAction::preferences(TQT_TQOBJECT(this), TQT_SLOT(slotSetup()), actionCollection());
  381. // -----------------------------------------------------------------------------------------
  382. m_themeMenuAction = new TDESelectAction(i18n("&Themes"), 0, actionCollection(), "theme_menu");
  383. m_themeMenuAction->setItems(ThemeEngine::instance()->themeNames());
  384. connect(m_themeMenuAction, TQT_SIGNAL(activated(const TQString&)),
  385. TQT_TQOBJECT(this), TQT_SLOT(slotChangeTheme(const TQString&)));
  386. connect(ThemeEngine::instance(), TQT_SIGNAL(signalThemeChanged()),
  387. TQT_TQOBJECT(this), TQT_SLOT(slotThemeChanged()));
  388. // -- Standard 'Help' menu actions ---------------------------------------------
  389. d->donateMoneyAction = new TDEAction(i18n("Donate..."),
  390. 0, 0,
  391. TQT_TQOBJECT(this), TQT_SLOT(slotDonateMoney()),
  392. actionCollection(),
  393. "editorwindow_donatemoney");
  394. d->contributeAction = new TDEAction(i18n("Contribute..."),
  395. 0, 0,
  396. TQT_TQOBJECT(this), TQT_SLOT(slotContribute()),
  397. actionCollection(),
  398. "editorwindow_contribute");
  399. d->rawCameraListAction = new TDEAction(i18n("Supported RAW Cameras"),
  400. "kdcraw",
  401. 0,
  402. TQT_TQOBJECT(this),
  403. TQT_SLOT(slotRawCameraList()),
  404. actionCollection(),
  405. "editorwindow_rawcameralist");
  406. }
  407. void EditorWindow::setupStandardAccelerators()
  408. {
  409. d->accelerators = new TDEAccel(this);
  410. d->accelerators->insert("Exit fullscreen", i18n("Exit Fullscreen mode"),
  411. i18n("Exit out of the fullscreen mode"),
  412. Key_Escape, TQT_TQOBJECT(this), TQT_SLOT(slotEscapePressed()),
  413. false, true);
  414. d->accelerators->insert("Next Image Key_Space", i18n("Next Image"),
  415. i18n("Load Next Image"),
  416. Key_Space, TQT_TQOBJECT(this), TQT_SLOT(slotForward()),
  417. false, true);
  418. d->accelerators->insert("Previous Image SHIFT+Key_Space", i18n("Previous Image"),
  419. i18n("Load Previous Image"),
  420. SHIFT+Key_Space, TQT_TQOBJECT(this), TQT_SLOT(slotBackward()),
  421. false, true);
  422. d->accelerators->insert("Previous Image Key_Backspace", i18n("Previous Image"),
  423. i18n("Load Previous Image"),
  424. Key_Backspace, TQT_TQOBJECT(this), TQT_SLOT(slotBackward()),
  425. false, true);
  426. d->accelerators->insert("Next Image Key_Next", i18n("Next Image"),
  427. i18n("Load Next Image"),
  428. Key_Next, TQT_TQOBJECT(this), TQT_SLOT(slotForward()),
  429. false, true);
  430. d->accelerators->insert("Previous Image Key_Prior", i18n("Previous Image"),
  431. i18n("Load Previous Image"),
  432. Key_Prior, TQT_TQOBJECT(this), TQT_SLOT(slotBackward()),
  433. false, true);
  434. d->accelerators->insert("Zoom Plus Key_Plus", i18n("Zoom In"),
  435. i18n("Zoom in on Image"),
  436. Key_Plus, TQT_TQOBJECT(this), TQT_SLOT(slotIncreaseZoom()),
  437. false, true);
  438. d->accelerators->insert("Zoom Plus Key_Minus", i18n("Zoom Out"),
  439. i18n("Zoom out of Image"),
  440. Key_Minus, TQT_TQOBJECT(this), TQT_SLOT(slotDecreaseZoom()),
  441. false, true);
  442. d->accelerators->insert("Redo CTRL+Key_Y", i18n("Redo"),
  443. i18n("Redo Last action"),
  444. CTRL+Key_Y, TQT_TQOBJECT(m_canvas), TQT_SLOT(slotRedo()),
  445. false, true);
  446. }
  447. void EditorWindow::setupStatusBar()
  448. {
  449. m_nameLabel = new StatusProgressBar(statusBar());
  450. m_nameLabel->setAlignment(TQt::AlignCenter);
  451. m_nameLabel->setMaximumHeight(fontMetrics().height()+2);
  452. statusBar()->addWidget(m_nameLabel, 100);
  453. d->selectLabel = new TQLabel(i18n("No selection"), statusBar());
  454. d->selectLabel->setAlignment(TQt::AlignCenter);
  455. d->selectLabel->setMaximumHeight(fontMetrics().height()+2);
  456. statusBar()->addWidget(d->selectLabel, 100);
  457. TQToolTip::add(d->selectLabel, i18n("Information about current selection area"));
  458. m_resLabel = new TQLabel(statusBar());
  459. m_resLabel->setAlignment(TQt::AlignCenter);
  460. m_resLabel->setMaximumHeight(fontMetrics().height()+2);
  461. statusBar()->addWidget(m_resLabel, 100);
  462. TQToolTip::add(m_resLabel, i18n("Information about image size"));
  463. d->underExposureIndicator = new TQToolButton(statusBar());
  464. d->underExposureIndicator->setIconSet(SmallIcon("underexposure"));
  465. d->underExposureIndicator->setToggleButton(true);
  466. statusBar()->addWidget(d->underExposureIndicator, 1);
  467. d->overExposureIndicator = new TQToolButton(statusBar());
  468. d->overExposureIndicator->setIconSet(SmallIcon("overexposure"));
  469. d->overExposureIndicator->setToggleButton(true);
  470. statusBar()->addWidget(d->overExposureIndicator, 1);
  471. d->cmViewIndicator = new TQToolButton(statusBar());
  472. d->cmViewIndicator->setIconSet(SmallIcon("tv"));
  473. d->cmViewIndicator->setToggleButton(true);
  474. statusBar()->addWidget(d->cmViewIndicator, 1);
  475. connect(d->underExposureIndicator, TQT_SIGNAL(toggled(bool)),
  476. TQT_TQOBJECT(this), TQT_SLOT(slotToggleUnderExposureIndicator()));
  477. connect(d->overExposureIndicator, TQT_SIGNAL(toggled(bool)),
  478. TQT_TQOBJECT(this), TQT_SLOT(slotToggleOverExposureIndicator()));
  479. connect(d->cmViewIndicator, TQT_SIGNAL(toggled(bool)),
  480. TQT_TQOBJECT(this), TQT_SLOT(slotToggleColorManagedView()));
  481. }
  482. void EditorWindow::printImage(KURL url)
  483. {
  484. uchar* ptr = m_canvas->interface()->getImage();
  485. int w = m_canvas->interface()->origWidth();
  486. int h = m_canvas->interface()->origHeight();
  487. bool hasAlpha = m_canvas->interface()->hasAlpha();
  488. bool sixteenBit = m_canvas->interface()->sixteenBit();
  489. if (!ptr || !w || !h)
  490. return;
  491. DImg image(w, h, sixteenBit, hasAlpha, ptr);
  492. KPrinter printer;
  493. TQString appName = TDEApplication::kApplication()->aboutData()->appName();
  494. printer.setDocName( url.filename() );
  495. printer.setCreator( appName );
  496. #if KDE_IS_VERSION(3,2,0)
  497. printer.setUsePrinterResolution(true);
  498. #endif
  499. KPrinter::addDialogPage( new ImageEditorPrintDialogPage(image, this, TQString(appName.append(" page")).ascii() ));
  500. if ( printer.setup( this, i18n("Print %1").arg(printer.docName().section('/', -1)) ) )
  501. {
  502. ImagePrint printOperations(image, printer, url.filename());
  503. if (!printOperations.printImageWithTQt())
  504. {
  505. KMessageBox::error(this, i18n("Failed to print file: '%1'")
  506. .arg(url.filename()));
  507. }
  508. }
  509. }
  510. void EditorWindow::slotEditKeys()
  511. {
  512. KKeyDialog dialog(true, this);
  513. dialog.insert( actionCollection(), i18n( "General" ) );
  514. TQPtrList<ImagePlugin> pluginList = ImagePluginLoader::instance()->pluginList();
  515. for (ImagePlugin* plugin = pluginList.first();
  516. plugin; plugin = pluginList.next())
  517. {
  518. if (plugin)
  519. {
  520. dialog.insert( plugin->actionCollection(), plugin->name() );
  521. }
  522. }
  523. dialog.configure();
  524. }
  525. void EditorWindow::slotResize()
  526. {
  527. ImageResize dlg(this);
  528. dlg.exec();
  529. }
  530. void EditorWindow::slotAboutToShowUndoMenu()
  531. {
  532. m_undoAction->popupMenu()->clear();
  533. TQStringList titles;
  534. m_canvas->getUndoHistory(titles);
  535. if(!titles.isEmpty())
  536. {
  537. int id = 1;
  538. TQStringList::Iterator iter = titles.begin();
  539. for(; iter != titles.end(); ++iter,++id)
  540. {
  541. m_undoAction->popupMenu()->insertItem(*iter, id);
  542. }
  543. }
  544. }
  545. void EditorWindow::slotAboutToShowRedoMenu()
  546. {
  547. m_redoAction->popupMenu()->clear();
  548. TQStringList titles;
  549. m_canvas->getRedoHistory(titles);
  550. if(!titles.isEmpty())
  551. {
  552. int id = 1;
  553. TQStringList::Iterator iter = titles.begin();
  554. for(; iter != titles.end(); ++iter,++id)
  555. {
  556. m_redoAction->popupMenu()->insertItem(*iter, id);
  557. }
  558. }
  559. }
  560. void EditorWindow::slotConfToolbars()
  561. {
  562. saveMainWindowSettings(TDEGlobal::config(), "ImageViewer Settings");
  563. KEditToolbar dlg(factory(), this);
  564. connect(&dlg, TQT_SIGNAL(newToolbarConfig()),
  565. TQT_TQOBJECT(this), TQT_SLOT(slotNewToolbarConfig()));
  566. dlg.exec();
  567. }
  568. void EditorWindow::slotNewToolbarConfig()
  569. {
  570. applyMainWindowSettings(TDEGlobal::config(), "ImageViewer Settings");
  571. }
  572. void EditorWindow::slotIncreaseZoom()
  573. {
  574. m_stackView->increaseZoom();
  575. }
  576. void EditorWindow::slotDecreaseZoom()
  577. {
  578. m_stackView->decreaseZoom();
  579. }
  580. void EditorWindow::slotToggleFitToWindow()
  581. {
  582. d->zoomPlusAction->setEnabled(true);
  583. d->zoomComboAction->setEnabled(true);
  584. d->zoomMinusAction->setEnabled(true);
  585. m_stackView->toggleFitToWindow();
  586. }
  587. void EditorWindow::slotFitToSelect()
  588. {
  589. d->zoomPlusAction->setEnabled(true);
  590. d->zoomComboAction->setEnabled(true);
  591. d->zoomMinusAction->setEnabled(true);
  592. m_stackView->fitToSelect();
  593. }
  594. void EditorWindow::slotZoomTo100Percents()
  595. {
  596. d->zoomPlusAction->setEnabled(true);
  597. d->zoomComboAction->setEnabled(true);
  598. d->zoomMinusAction->setEnabled(true);
  599. m_stackView->zoomTo100Percents();
  600. }
  601. void EditorWindow::slotZoomSelected()
  602. {
  603. TQString txt = d->zoomCombo->currentText();
  604. txt = txt.left(txt.find('%'));
  605. slotZoomTextChanged(txt);
  606. }
  607. void EditorWindow::slotZoomTextChanged(const TQString &txt)
  608. {
  609. bool r = false;
  610. double zoom = TDEGlobal::locale()->readNumber(txt, &r) / 100.0;
  611. if (r && zoom > 0.0)
  612. m_stackView->setZoomFactor(zoom);
  613. }
  614. void EditorWindow::slotZoomChanged(bool isMax, bool isMin, double zoom)
  615. {
  616. d->zoomPlusAction->setEnabled(!isMax);
  617. d->zoomMinusAction->setEnabled(!isMin);
  618. d->zoomCombo->blockSignals(true);
  619. d->zoomCombo->setCurrentText(TQString::number(lround(zoom*100.0)) + TQString("%"));
  620. d->zoomCombo->blockSignals(false);
  621. }
  622. void EditorWindow::slotToggleOffFitToWindow()
  623. {
  624. d->zoomFitToWindowAction->blockSignals(true);
  625. d->zoomFitToWindowAction->setChecked(false);
  626. d->zoomFitToWindowAction->blockSignals(false);
  627. }
  628. void EditorWindow::slotEscapePressed()
  629. {
  630. if (m_fullScreen)
  631. m_fullScreenAction->activate();
  632. }
  633. void EditorWindow::plugActionAccel(TDEAction* action)
  634. {
  635. if (!action)
  636. return;
  637. d->accelerators->insert(action->text(),
  638. action->text(),
  639. action->whatsThis(),
  640. action->shortcut(),
  641. action,
  642. TQT_SLOT(activate()));
  643. }
  644. void EditorWindow::unplugActionAccel(TDEAction* action)
  645. {
  646. d->accelerators->remove(action->text());
  647. }
  648. void EditorWindow::loadImagePlugins()
  649. {
  650. TQPtrList<ImagePlugin> pluginList = m_imagePluginLoader->pluginList();
  651. for (ImagePlugin* plugin = pluginList.first();
  652. plugin; plugin = pluginList.next())
  653. {
  654. if (plugin)
  655. {
  656. guiFactory()->addClient(plugin);
  657. plugin->setEnabledSelectionActions(false);
  658. }
  659. else
  660. DDebug() << "Invalid plugin to add!" << endl;
  661. }
  662. }
  663. void EditorWindow::unLoadImagePlugins()
  664. {
  665. TQPtrList<ImagePlugin> pluginList = m_imagePluginLoader->pluginList();
  666. for (ImagePlugin* plugin = pluginList.first();
  667. plugin; plugin = pluginList.next())
  668. {
  669. if (plugin)
  670. {
  671. guiFactory()->removeClient(plugin);
  672. plugin->setEnabledSelectionActions(false);
  673. }
  674. }
  675. }
  676. void EditorWindow::readStandardSettings()
  677. {
  678. TDEConfig* config = kapp->config();
  679. config->setGroup("ImageViewer Settings");
  680. // Restore full screen Mode ?
  681. if (config->readBoolEntry("FullScreen", false))
  682. {
  683. m_fullScreenAction->activate();
  684. m_fullScreen = true;
  685. }
  686. // Restore Auto zoom action ?
  687. bool autoZoom = config->readBoolEntry("AutoZoom", true);
  688. if (autoZoom)
  689. d->zoomFitToWindowAction->activate();
  690. }
  691. void EditorWindow::applyStandardSettings()
  692. {
  693. TDEConfig* config = kapp->config();
  694. // -- Settings for Color Management stuff ----------------------------------------------
  695. config->setGroup("Color Management");
  696. d->ICCSettings->enableCMSetting = config->readBoolEntry("EnableCM", false);
  697. d->ICCSettings->askOrApplySetting = config->readBoolEntry("BehaviourICC", false);
  698. d->ICCSettings->BPCSetting = config->readBoolEntry("BPCAlgorithm",false);
  699. d->ICCSettings->managedViewSetting = config->readBoolEntry("ManagedView", false);
  700. d->ICCSettings->renderingSetting = config->readNumEntry("RenderingIntent");
  701. d->ICCSettings->inputSetting = config->readPathEntry("InProfileFile", TQString());
  702. d->ICCSettings->workspaceSetting = config->readPathEntry("WorkProfileFile", TQString());
  703. d->ICCSettings->monitorSetting = config->readPathEntry("MonitorProfileFile", TQString());
  704. d->ICCSettings->proofSetting = config->readPathEntry("ProofProfileFile", TQString());
  705. d->viewCMViewAction->setEnabled(d->ICCSettings->enableCMSetting);
  706. d->viewCMViewAction->setChecked(d->ICCSettings->managedViewSetting);
  707. d->cmViewIndicator->setEnabled(d->ICCSettings->enableCMSetting);
  708. d->cmViewIndicator->setOn(d->ICCSettings->managedViewSetting);
  709. setColorManagedViewIndicatorToolTip(d->ICCSettings->enableCMSetting, d->ICCSettings->managedViewSetting);
  710. m_canvas->setICCSettings(d->ICCSettings);
  711. // -- JPEG, PNG, TIFF JPEG2000 files format settings --------------------------------------
  712. config->setGroup("ImageViewer Settings");
  713. // JPEG quality slider settings : 1 - 100 ==> libjpeg settings : 25 - 100.
  714. m_IOFileSettings->JPEGCompression = (int)((75.0/100.0)*
  715. (float)config->readNumEntry("JPEGCompression", 75)
  716. + 26.0 - (75.0/100.0));
  717. m_IOFileSettings->JPEGSubSampling = config->readNumEntry("JPEGSubSampling", 1); // Medium subsampling
  718. // PNG compression slider settings : 1 - 9 ==> libpng settings : 100 - 1.
  719. m_IOFileSettings->PNGCompression = (int)(((1.0-100.0)/8.0)*
  720. (float)config->readNumEntry("PNGCompression", 1)
  721. + 100.0 - ((1.0-100.0)/8.0));
  722. // TIFF compression setting.
  723. m_IOFileSettings->TIFFCompression = config->readBoolEntry("TIFFCompression", false);
  724. // JPEG2000 quality slider settings : 1 - 100
  725. m_IOFileSettings->JPEG2000Compression = config->readNumEntry("JPEG2000Compression", 100);
  726. // JPEG2000 LossLess setting.
  727. m_IOFileSettings->JPEG2000LossLess = config->readBoolEntry("JPEG2000LossLess", true);
  728. // -- RAW images decoding settings ------------------------------------------------------
  729. // If digiKam Color Management is enable, no need to correct color of decoded RAW image,
  730. // else, sRGB color workspace will be used.
  731. if (d->ICCSettings->enableCMSetting)
  732. m_IOFileSettings->rawDecodingSettings.outputColorSpace = DRawDecoding::RAWCOLOR;
  733. else
  734. m_IOFileSettings->rawDecodingSettings.outputColorSpace = DRawDecoding::SRGB;
  735. m_IOFileSettings->rawDecodingSettings.sixteenBitsImage = config->readBoolEntry("SixteenBitsImage", false);
  736. m_IOFileSettings->rawDecodingSettings.whiteBalance = (DRawDecoding::WhiteBalance)config->readNumEntry("WhiteBalance",
  737. DRawDecoding::CAMERA);
  738. m_IOFileSettings->rawDecodingSettings.customWhiteBalance = config->readNumEntry("CustomWhiteBalance", 6500);
  739. m_IOFileSettings->rawDecodingSettings.customWhiteBalanceGreen = config->readDoubleNumEntry("CustomWhiteBalanceGreen", 1.0);
  740. m_IOFileSettings->rawDecodingSettings.RGBInterpolate4Colors = config->readBoolEntry("RGBInterpolate4Colors", false);
  741. m_IOFileSettings->rawDecodingSettings.DontStretchPixels = config->readBoolEntry("DontStretchPixels", false);
  742. m_IOFileSettings->rawDecodingSettings.enableNoiseReduction = config->readBoolEntry("EnableNoiseReduction", false);
  743. m_IOFileSettings->rawDecodingSettings.unclipColors = config->readNumEntry("UnclipColors", 0);
  744. m_IOFileSettings->rawDecodingSettings.RAWQuality = (DRawDecoding::DecodingQuality)config->readNumEntry("RAWQuality",
  745. DRawDecoding::BILINEAR);
  746. m_IOFileSettings->rawDecodingSettings.NRThreshold = config->readNumEntry("NRThreshold", 100);
  747. m_IOFileSettings->rawDecodingSettings.enableCACorrection = config->readBoolEntry("EnableCACorrection", false);
  748. m_IOFileSettings->rawDecodingSettings.caMultiplier[0] = config->readDoubleNumEntry("caRedMultiplier", 1.0);
  749. m_IOFileSettings->rawDecodingSettings.caMultiplier[1] = config->readDoubleNumEntry("caBlueMultiplier", 1.0);
  750. m_IOFileSettings->rawDecodingSettings.brightness = config->readDoubleNumEntry("RAWBrightness", 1.0);
  751. m_IOFileSettings->rawDecodingSettings.medianFilterPasses = config->readNumEntry("MedianFilterPasses", 0);
  752. m_IOFileSettings->useRAWImport = config->readBoolEntry("UseRawImportTool", false);
  753. // -- GUI Settings -------------------------------------------------------
  754. TQSizePolicy rightSzPolicy(TQSizePolicy::Preferred, TQSizePolicy::Expanding, 2, 1);
  755. if(config->hasKey("Splitter Sizes"))
  756. m_splitter->setSizes(config->readIntListEntry("Splitter Sizes"));
  757. else
  758. m_canvas->setSizePolicy(rightSzPolicy);
  759. d->fullScreenHideToolBar = config->readBoolEntry("FullScreen Hide ToolBar", false);
  760. slotThemeChanged();
  761. // -- Exposure Indicators Settings ---------------------------------------
  762. TQColor black(TQt::black);
  763. TQColor white(TQt::white);
  764. d->exposureSettings->underExposureIndicator = config->readBoolEntry("UnderExposureIndicator", false);
  765. d->exposureSettings->overExposureIndicator = config->readBoolEntry("OverExposureIndicator", false);
  766. d->exposureSettings->underExposureColor = config->readColorEntry("UnderExposureColor", &white);
  767. d->exposureSettings->overExposureColor = config->readColorEntry("OverExposureColor", &black);
  768. d->viewUnderExpoAction->setChecked(d->exposureSettings->underExposureIndicator);
  769. d->viewOverExpoAction->setChecked(d->exposureSettings->overExposureIndicator);
  770. d->underExposureIndicator->setOn(d->exposureSettings->underExposureIndicator);
  771. d->overExposureIndicator->setOn(d->exposureSettings->overExposureIndicator);
  772. setUnderExposureToolTip(d->exposureSettings->underExposureIndicator);
  773. setOverExposureToolTip(d->exposureSettings->overExposureIndicator);
  774. m_canvas->setExposureSettings(d->exposureSettings);
  775. }
  776. void EditorWindow::saveStandardSettings()
  777. {
  778. TDEConfig* config = kapp->config();
  779. config->setGroup("ImageViewer Settings");
  780. config->writeEntry("AutoZoom", d->zoomFitToWindowAction->isChecked());
  781. config->writeEntry("Splitter Sizes", m_splitter->sizes());
  782. config->writeEntry("FullScreen", m_fullScreenAction->isChecked());
  783. config->writeEntry("UnderExposureIndicator", d->exposureSettings->underExposureIndicator);
  784. config->writeEntry("OverExposureIndicator", d->exposureSettings->overExposureIndicator);
  785. config->sync();
  786. }
  787. /** Method used by Editor Tools. Only Zoom+ and Zoom- are currently supported.
  788. TODO: Fix this behavour when editor tool preview widgets will be factored.
  789. */
  790. void EditorWindow::toggleZoomActions(bool val)
  791. {
  792. d->zoomMinusAction->setEnabled(val);
  793. d->zoomPlusAction->setEnabled(val);
  794. }
  795. void EditorWindow::toggleStandardActions(bool val)
  796. {
  797. d->zoomComboAction->setEnabled(val);
  798. d->zoomTo100percents->setEnabled(val);
  799. d->zoomFitToWindowAction->setEnabled(val);
  800. d->zoomFitToSelectAction->setEnabled(val);
  801. toggleZoomActions(val);
  802. d->rotateLeftAction->setEnabled(val);
  803. d->rotateRightAction->setEnabled(val);
  804. d->flipHorizAction->setEnabled(val);
  805. d->flipVertAction->setEnabled(val);
  806. d->filePrintAction->setEnabled(val);
  807. d->resizeAction->setEnabled(val);
  808. m_fileDeleteAction->setEnabled(val);
  809. m_saveAsAction->setEnabled(val);
  810. d->selectAllAction->setEnabled(val);
  811. d->selectNoneAction->setEnabled(val);
  812. d->slideShowAction->setEnabled(val);
  813. // these actions are special: They are turned off if val is false,
  814. // but if val is true, they may be turned on or off.
  815. if (val)
  816. {
  817. // Trigger sending of signalUndoStateChanged
  818. // Note that for saving and loading, this is not necessary
  819. // because the signal will be sent later anyway.
  820. m_canvas->updateUndoState();
  821. }
  822. else
  823. {
  824. m_saveAction->setEnabled(val);
  825. m_undoAction->setEnabled(val);
  826. m_redoAction->setEnabled(val);
  827. }
  828. TQPtrList<ImagePlugin> pluginList = m_imagePluginLoader->pluginList();
  829. for (ImagePlugin* plugin = pluginList.first();
  830. plugin; plugin = pluginList.next())
  831. {
  832. if (plugin)
  833. {
  834. plugin->setEnabledActions(val);
  835. }
  836. }
  837. }
  838. void EditorWindow::slotToggleFullScreen()
  839. {
  840. if (m_fullScreen) // out of fullscreen
  841. {
  842. m_canvas->setBackgroundColor(m_bgColor);
  843. setWindowState( windowState() & ~WindowFullScreen );
  844. menuBar()->show();
  845. statusBar()->show();
  846. leftDock()->show();
  847. rightDock()->show();
  848. topDock()->show();
  849. bottomDock()->show();
  850. TQObject* obj = child("ToolBar","TDEToolBar");
  851. if (obj)
  852. {
  853. TDEToolBar* toolBar = static_cast<TDEToolBar*>(TQT_TQWIDGET(obj));
  854. if (m_fullScreenAction->isPlugged(toolBar) && d->removeFullScreenButton)
  855. m_fullScreenAction->unplug(toolBar);
  856. if (toolBar->isHidden())
  857. showToolBars();
  858. }
  859. // -- remove the gui action accels ----
  860. unplugActionAccel(m_forwardAction);
  861. unplugActionAccel(m_backwardAction);
  862. unplugActionAccel(m_firstAction);
  863. unplugActionAccel(m_lastAction);
  864. unplugActionAccel(m_saveAction);
  865. unplugActionAccel(m_saveAsAction);
  866. unplugActionAccel(d->zoomPlusAction);
  867. unplugActionAccel(d->zoomMinusAction);
  868. unplugActionAccel(d->zoomFitToWindowAction);
  869. unplugActionAccel(d->zoomFitToSelectAction);
  870. unplugActionAccel(d->cropAction);
  871. unplugActionAccel(d->filePrintAction);
  872. unplugActionAccel(m_fileDeleteAction);
  873. unplugActionAccel(d->selectAllAction);
  874. unplugActionAccel(d->selectNoneAction);
  875. toggleGUI2FullScreen();
  876. m_fullScreen = false;
  877. }
  878. else // go to fullscreen
  879. {
  880. m_canvas->setBackgroundColor(TQColor(TQt::black));
  881. // hide the menubar and the statusbar
  882. menuBar()->hide();
  883. statusBar()->hide();
  884. topDock()->hide();
  885. leftDock()->hide();
  886. rightDock()->hide();
  887. bottomDock()->hide();
  888. TQObject* obj = child("ToolBar","TDEToolBar");
  889. if (obj)
  890. {
  891. TDEToolBar* toolBar = static_cast<TDEToolBar*>(TQT_TQWIDGET(obj));
  892. if (d->fullScreenHideToolBar)
  893. {
  894. hideToolBars();
  895. }
  896. else
  897. {
  898. showToolBars();
  899. if ( !m_fullScreenAction->isPlugged(toolBar) )
  900. {
  901. m_fullScreenAction->plug(toolBar);
  902. d->removeFullScreenButton=true;
  903. }
  904. else
  905. {
  906. // If FullScreen button is enable in toolbar settings
  907. // We don't remove it when we out of fullscreen mode.
  908. d->removeFullScreenButton=false;
  909. }
  910. }
  911. }
  912. // -- Insert all the gui actions into the accel --
  913. plugActionAccel(m_forwardAction);
  914. plugActionAccel(m_backwardAction);
  915. plugActionAccel(m_firstAction);
  916. plugActionAccel(m_lastAction);
  917. plugActionAccel(m_saveAction);
  918. plugActionAccel(m_saveAsAction);
  919. plugActionAccel(d->zoomPlusAction);
  920. plugActionAccel(d->zoomMinusAction);
  921. plugActionAccel(d->zoomFitToWindowAction);
  922. plugActionAccel(d->zoomFitToSelectAction);
  923. plugActionAccel(d->cropAction);
  924. plugActionAccel(d->filePrintAction);
  925. plugActionAccel(m_fileDeleteAction);
  926. plugActionAccel(d->selectAllAction);
  927. plugActionAccel(d->selectNoneAction);
  928. toggleGUI2FullScreen();
  929. showFullScreen();
  930. m_fullScreen = true;
  931. }
  932. }
  933. void EditorWindow::slotRotatedOrFlipped()
  934. {
  935. m_rotatedOrFlipped = true;
  936. }
  937. void EditorWindow::slotLoadingProgress(const TQString&, float progress)
  938. {
  939. m_nameLabel->setProgressValue((int)(progress*100.0));
  940. }
  941. void EditorWindow::slotSavingProgress(const TQString&, float progress)
  942. {
  943. m_nameLabel->setProgressValue((int)(progress*100.0));
  944. }
  945. bool EditorWindow::promptForOverWrite()
  946. {
  947. TQFileInfo fi(m_canvas->currentImageFilePath());
  948. TQString warnMsg(i18n("About to overwrite file \"%1\"\nAre you sure?")
  949. .arg(fi.fileName()));
  950. return (KMessageBox::warningContinueCancel(this,
  951. warnMsg,
  952. i18n("Warning"),
  953. i18n("Overwrite"),
  954. "editorWindowSaveOverwrite")
  955. == KMessageBox::Continue);
  956. }
  957. bool EditorWindow::promptUserSave(const KURL& url)
  958. {
  959. if (m_saveAction->isEnabled())
  960. {
  961. // if window is iconified, show it
  962. if (isMinimized())
  963. {
  964. KWin::deIconifyWindow(winId());
  965. }
  966. int result = KMessageBox::warningYesNoCancel(this,
  967. i18n("The image '%1' has been modified.\n"
  968. "Do you want to save it?")
  969. .arg(url.filename()),
  970. TQString(),
  971. KStdGuiItem::save(),
  972. KStdGuiItem::discard());
  973. if (result == KMessageBox::Yes)
  974. {
  975. bool saving = false;
  976. if (m_canvas->isReadOnly())
  977. saving = saveAs();
  978. else if (promptForOverWrite())
  979. saving = save();
  980. // save and saveAs return false if they were cancelled and did not enter saving at all
  981. // In this case, do not call enter_loop because exit_loop will not be called.
  982. if (saving)
  983. {
  984. // Waiting for asynchronous image file saving operation runing in separate thread.
  985. m_savingContext->synchronizingState = SavingContextContainer::SynchronousSaving;
  986. enter_loop();
  987. m_savingContext->synchronizingState = SavingContextContainer::NormalSaving;
  988. return m_savingContext->synchronousSavingResult;
  989. }
  990. else
  991. {
  992. return false;
  993. }
  994. }
  995. else if (result == KMessageBox::No)
  996. {
  997. m_saveAction->setEnabled(false);
  998. return true;
  999. }
  1000. else
  1001. {
  1002. return false;
  1003. }
  1004. }
  1005. return true;
  1006. }
  1007. bool EditorWindow::waitForSavingToComplete()
  1008. {
  1009. // avoid reentrancy - return false means we have reentered the loop already.
  1010. if (m_savingContext->synchronizingState == SavingContextContainer::SynchronousSaving)
  1011. return false;
  1012. if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
  1013. {
  1014. // Waiting for asynchronous image file saving operation runing in separate thread.
  1015. m_savingContext->synchronizingState = SavingContextContainer::SynchronousSaving;
  1016. KMessageBox::queuedMessageBox(this,
  1017. KMessageBox::Information,
  1018. i18n("Please wait while the image is being saved..."));
  1019. enter_loop();
  1020. m_savingContext->synchronizingState = SavingContextContainer::NormalSaving;
  1021. }
  1022. return true;
  1023. }
  1024. void EditorWindow::enter_loop()
  1025. {
  1026. TQWidget dummy(0, 0, WType_Dialog | WShowModal);
  1027. dummy.setFocusPolicy( TQ_NoFocus );
  1028. tqt_enter_modal(&dummy);
  1029. tqApp->enter_loop();
  1030. tqt_leave_modal(&dummy);
  1031. }
  1032. void EditorWindow::slotSelected(bool val)
  1033. {
  1034. // Update menu actions.
  1035. d->cropAction->setEnabled(val);
  1036. d->zoomFitToSelectAction->setEnabled(val);
  1037. d->copyAction->setEnabled(val);
  1038. for (ImagePlugin* plugin = m_imagePluginLoader->pluginList().first();
  1039. plugin; plugin = m_imagePluginLoader->pluginList().next())
  1040. {
  1041. if (plugin)
  1042. {
  1043. plugin->setEnabledSelectionActions(val);
  1044. }
  1045. }
  1046. TQRect sel = m_canvas->getSelectedArea();
  1047. // Update histogram into sidebar.
  1048. emit signalSelectionChanged(sel);
  1049. // Update status bar
  1050. if (val)
  1051. d->selectLabel->setText(TQString("(%1, %2) (%3 x %4)").arg(sel.x()).arg(sel.y())
  1052. .arg(sel.width()).arg(sel.height()));
  1053. else
  1054. d->selectLabel->setText(i18n("No selection"));
  1055. }
  1056. void EditorWindow::hideToolBars()
  1057. {
  1058. TQPtrListIterator<TDEToolBar> it = toolBarIterator();
  1059. TDEToolBar* bar;
  1060. for(;it.current()!=0L; ++it)
  1061. {
  1062. bar = it.current();
  1063. if (bar->area())
  1064. bar->area()->hide();
  1065. else
  1066. bar->hide();
  1067. }
  1068. }
  1069. void EditorWindow::showToolBars()
  1070. {
  1071. TQPtrListIterator<TDEToolBar> it = toolBarIterator();
  1072. TDEToolBar* bar;
  1073. for( ; it.current()!=0L ; ++it)
  1074. {
  1075. bar = it.current();
  1076. if (bar->area())
  1077. bar->area()->show();
  1078. else
  1079. bar->show();
  1080. }
  1081. }
  1082. void EditorWindow::slotPrepareToLoad()
  1083. {
  1084. // Disable actions as appropriate during loading
  1085. emit signalNoCurrentItem();
  1086. toggleActions(false);
  1087. slotUpdateItemInfo();
  1088. }
  1089. void EditorWindow::slotLoadingStarted(const TQString& /*filename*/)
  1090. {
  1091. setCursor( KCursor::waitCursor() );
  1092. m_nameLabel->progressBarMode(StatusProgressBar::ProgressBarMode, i18n("Loading: "));
  1093. }
  1094. void EditorWindow::slotLoadingFinished(const TQString& filename, bool success)
  1095. {
  1096. m_nameLabel->progressBarMode(StatusProgressBar::TextMode);
  1097. slotUpdateItemInfo();
  1098. // Enable actions as appropriate after loading
  1099. // No need to re-enable image properties sidebar here, it's will be done
  1100. // automatically by a signal from canvas
  1101. toggleActions(success);
  1102. unsetCursor();
  1103. // Note: in showfoto, we using a null filename to clear canvas.
  1104. if (!success && filename != TQString())
  1105. {
  1106. TQFileInfo fi(filename);
  1107. TQString message = i18n("Failed to load image \"%1\"").arg(fi.fileName());
  1108. KMessageBox::error(this, message);
  1109. DWarning() << "Failed to load image " << fi.fileName() << endl;
  1110. }
  1111. }
  1112. void EditorWindow::slotNameLabelCancelButtonPressed()
  1113. {
  1114. // If we saving an image...
  1115. if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
  1116. {
  1117. m_savingContext->abortingSaving = true;
  1118. m_canvas->abortSaving();
  1119. }
  1120. // If we preparing SlideShow...
  1121. m_cancelSlideShow = true;
  1122. }
  1123. void EditorWindow::slotSave()
  1124. {
  1125. if (m_canvas->isReadOnly())
  1126. saveAs();
  1127. else if (promptForOverWrite())
  1128. save();
  1129. }
  1130. void EditorWindow::slotSavingStarted(const TQString& /*filename*/)
  1131. {
  1132. setCursor( KCursor::waitCursor() );
  1133. // Disable actions as appropriate during saving
  1134. emit signalNoCurrentItem();
  1135. toggleActions(false);
  1136. m_nameLabel->progressBarMode(StatusProgressBar::CancelProgressBarMode, i18n("Saving: "));
  1137. }
  1138. void EditorWindow::slotSavingFinished(const TQString& filename, bool success)
  1139. {
  1140. if (m_savingContext->savingState == SavingContextContainer::SavingStateSave)
  1141. {
  1142. // from save()
  1143. m_savingContext->savingState = SavingContextContainer::SavingStateNone;
  1144. if (!success)
  1145. {
  1146. if (!m_savingContext->abortingSaving)
  1147. {
  1148. KMessageBox::error(this, i18n("Failed to save file\n\"%1\"\nto\n\"%2\".")
  1149. .arg(m_savingContext->destinationURL.filename())
  1150. .arg(m_savingContext->destinationURL.path()));
  1151. }
  1152. finishSaving(false);
  1153. return;
  1154. }
  1155. DDebug() << "renaming to " << m_savingContext->destinationURL.path() << endl;
  1156. if (!moveFile())
  1157. {
  1158. finishSaving(false);
  1159. return;
  1160. }
  1161. m_canvas->setUndoHistoryOrigin();
  1162. // remove image from cache since it has changed
  1163. LoadingCacheInterface::cleanFromCache(m_savingContext->destinationURL.path());
  1164. // this won't be in the cache, but does not hurt to do it anyway
  1165. LoadingCacheInterface::cleanFromCache(filename);
  1166. // restore state of disabled actions. saveIsComplete can start any other task
  1167. // (loading!) which might itself in turn change states
  1168. finishSaving(true);
  1169. saveIsComplete();
  1170. // Take all actions necessary to update information and re-enable sidebar
  1171. slotChanged();
  1172. }
  1173. else if (m_savingContext->savingState == SavingContextContainer::SavingStateSaveAs)
  1174. {
  1175. m_savingContext->savingState = SavingContextContainer::SavingStateNone;
  1176. // from saveAs()
  1177. if (!success)
  1178. {
  1179. if (!m_savingContext->abortingSaving)
  1180. {
  1181. KMessageBox::error(this, i18n("Failed to save file\n\"%1\"\nto\n\"%2\".")
  1182. .arg(m_savingContext->destinationURL.filename())
  1183. .arg(m_savingContext->destinationURL.path()));
  1184. }
  1185. finishSaving(false);
  1186. return;
  1187. }
  1188. // Only try to write exif if both src and destination are jpeg files
  1189. DDebug() << "renaming to " << m_savingContext->destinationURL.path() << endl;
  1190. if (!moveFile())
  1191. {
  1192. finishSaving(false);
  1193. return;
  1194. }
  1195. m_canvas->setUndoHistoryOrigin();
  1196. LoadingCacheInterface::cleanFromCache(m_savingContext->destinationURL.path());
  1197. LoadingCacheInterface::cleanFromCache(filename);
  1198. finishSaving(true);
  1199. saveAsIsComplete();
  1200. // Take all actions necessary to update information and re-enable sidebar
  1201. slotChanged();
  1202. }
  1203. }
  1204. void EditorWindow::finishSaving(bool success)
  1205. {
  1206. m_savingContext->synchronousSavingResult = success;
  1207. if (m_savingContext->saveTempFile)
  1208. {
  1209. delete m_savingContext->saveTempFile;
  1210. m_savingContext->saveTempFile = 0;
  1211. }
  1212. // Exit of internal TQt event loop to unlock promptUserSave() method.
  1213. if (m_savingContext->synchronizingState == SavingContextContainer::SynchronousSaving)
  1214. tqApp->exit_loop();
  1215. // Enable actions as appropriate after saving
  1216. toggleActions(true);
  1217. unsetCursor();
  1218. m_nameLabel->progressBarMode(StatusProgressBar::TextMode);
  1219. // On error, continue using current image
  1220. if (!success)
  1221. {
  1222. m_canvas->switchToLastSaved(m_savingContext->srcURL.path());
  1223. }
  1224. }
  1225. void EditorWindow::startingSave(const KURL& url)
  1226. {
  1227. // avoid any reentrancy. Should be impossible anyway since actions will be disabled.
  1228. if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
  1229. return;
  1230. if (!checkPermissions(url))
  1231. return;
  1232. m_savingContext->srcURL = url;
  1233. m_savingContext->destinationURL = m_savingContext->srcURL;
  1234. m_savingContext->destinationExisted = true;
  1235. m_savingContext->originalFormat = m_canvas->currentImageFileFormat();
  1236. m_savingContext->format = m_savingContext->originalFormat;
  1237. m_savingContext->abortingSaving = false;
  1238. m_savingContext->savingState = SavingContextContainer::SavingStateSave;
  1239. // use magic file extension which tells the digikamalbums ioslave to ignore the file
  1240. m_savingContext->saveTempFile = new KTempFile(m_savingContext->srcURL.directory(false),
  1241. ".digikamtempfile.tmp");
  1242. m_savingContext->saveTempFile->setAutoDelete(true);
  1243. m_canvas->saveAs(m_savingContext->saveTempFile->name(), m_IOFileSettings,
  1244. m_setExifOrientationTag && (m_rotatedOrFlipped || m_canvas->exifRotated()));
  1245. }
  1246. bool EditorWindow::startingSaveAs(const KURL& url)
  1247. {
  1248. if (m_savingContext->savingState != SavingContextContainer::SavingStateNone)
  1249. return false;
  1250. TQString mimetypes = KImageIO::mimeTypes(KImageIO::Writing).join(" ");
  1251. mimetypes.append(" image/tiff");
  1252. DDebug () << "mimetypes=" << mimetypes << endl;
  1253. m_savingContext->srcURL = url;
  1254. FileSaveOptionsBox *options = new FileSaveOptionsBox();
  1255. KFileDialog imageFileSaveDialog(m_savingContext->srcURL.isLocalFile() ?
  1256. m_savingContext->srcURL.directory() : TQDir::homeDirPath(),
  1257. TQString(),
  1258. this,
  1259. "imageFileSaveDialog",
  1260. false,
  1261. options);
  1262. connect(&imageFileSaveDialog, TQT_SIGNAL(filterChanged(const TQString &)),
  1263. options, TQT_SLOT(slotImageFileFormatChanged(const TQString &)));
  1264. connect(&imageFileSaveDialog, TQT_SIGNAL(fileSelected(const TQString &)),
  1265. options, TQT_SLOT(slotImageFileSelected(const TQString &)));
  1266. ImageDialogPreview *preview = new ImageDialogPreview(&imageFileSaveDialog);
  1267. imageFileSaveDialog.setPreviewWidget(preview);
  1268. imageFileSaveDialog.setOperationMode(KFileDialog::Saving);
  1269. imageFileSaveDialog.setMode(KFile::File);
  1270. imageFileSaveDialog.setCaption(i18n("New Image File Name"));
  1271. imageFileSaveDialog.setFilter(mimetypes);
  1272. TQFileInfo info(m_savingContext->srcURL.fileName());
  1273. TDEConfig* config = kapp->config();
  1274. config->setGroup("ImageViewer Settings");
  1275. TQString ext = config->readEntry("LastSavedImageTypeMime", "png");
  1276. TQString fileName = info.baseName(false) + TQString(".") + ext;
  1277. imageFileSaveDialog.setSelection(fileName);
  1278. // Start dialog and check if canceled.
  1279. if ( imageFileSaveDialog.exec() != KFileDialog::Accepted )
  1280. return false;
  1281. // Update file save settings in editor instance.
  1282. options->applySettings();
  1283. applyStandardSettings();
  1284. KURL newURL = imageFileSaveDialog.selectedURL();
  1285. // Check if target image format have been selected from Combo List of SaveAs dialog.
  1286. m_savingContext->format = KImageIO::typeForMime(imageFileSaveDialog.currentMimeFilter());
  1287. if ( m_savingContext->format.isEmpty() )
  1288. {
  1289. // Else, check if target image format have been add to target image file name using extension.
  1290. TQFileInfo fi(newURL.path());
  1291. m_savingContext->format = fi.extension(false);
  1292. if ( m_savingContext->format.isEmpty() )
  1293. {
  1294. // If format is empty then file format is same as that of the original file.
  1295. m_savingContext->format = TQImageIO::imageFormat(m_savingContext->srcURL.path());
  1296. }
  1297. else
  1298. {
  1299. // Else, check if format from file name extension is include on file mime type list.
  1300. TQString imgExtPattern;
  1301. TQStringList imgExtList = TQStringList::split(" ", mimetypes);
  1302. for (TQStringList::ConstIterator it = imgExtList.begin() ; it != imgExtList.end() ; ++it)
  1303. {
  1304. imgExtPattern.append (KImageIO::typeForMime(*it).upper());
  1305. imgExtPattern.append (" ");
  1306. }
  1307. imgExtPattern.append (" TIF TIFF");
  1308. if ( imgExtPattern.contains("JPEG") )
  1309. {
  1310. imgExtPattern.append (" JPG");
  1311. imgExtPattern.append (" JPE");
  1312. }
  1313. if ( !imgExtPattern.contains( m_savingContext->format.upper() ) )
  1314. {
  1315. KMessageBox::error(this, i18n("Target image file format \"%1\" unsupported.")
  1316. .arg(m_savingContext->format));
  1317. DWarning() << k_funcinfo << "target image file format " << m_savingContext->format << " unsupported!" << endl;
  1318. return false;
  1319. }
  1320. }
  1321. }
  1322. if (!newURL.isValid())
  1323. {
  1324. KMessageBox::error(this, i18n("Failed to save file\n\"%1\" to\n\"%2\".")
  1325. .arg(newURL.filename())
  1326. .arg(newURL.path().section('/', -2, -2)));
  1327. DWarning() << k_funcinfo << "target URL is not valid !" << endl;
  1328. return false;
  1329. }
  1330. config->writeEntry("LastSavedImageTypeMime", m_savingContext->format);
  1331. config->sync();
  1332. // if new and original url are equal use slotSave() ------------------------------
  1333. KURL currURL(m_savingContext->srcURL);
  1334. currURL.cleanPath();
  1335. newURL.cleanPath();
  1336. if (currURL.equals(newURL))
  1337. {
  1338. slotSave();
  1339. return false;
  1340. }
  1341. // Check for overwrite ----------------------------------------------------------
  1342. TQFileInfo fi(newURL.path());
  1343. m_savingContext->destinationExisted = fi.exists();
  1344. if ( m_savingContext->destinationExisted )
  1345. {
  1346. int result =
  1347. KMessageBox::warningYesNo( this, i18n("A file named \"%1\" already "
  1348. "exists. Are you sure you want "
  1349. "to overwrite it?")
  1350. .arg(newURL.filename()),
  1351. i18n("Overwrite File?"),
  1352. i18n("Overwrite"),
  1353. KStdGuiItem::cancel() );
  1354. if (result != KMessageBox::Yes)
  1355. return false;
  1356. // There will be two message boxes if the file is not writable.
  1357. // This may be controversial, and it may be changed, but it was a deliberate decision.
  1358. if (!checkPermissions(newURL))
  1359. return false;
  1360. }
  1361. // Now do the actual saving -----------------------------------------------------
  1362. // use magic file extension which tells the digikamalbums ioslave to ignore the file
  1363. m_savingContext->saveTempFile = new KTempFile(newURL.directory(false), ".digikamtempfile.tmp");
  1364. m_savingContext->destinationURL = newURL;
  1365. m_savingContext->originalFormat = m_canvas->currentImageFileFormat();
  1366. m_savingContext->savingState = SavingContextContainer::SavingStateSaveAs;
  1367. m_savingContext->saveTempFile->setAutoDelete(true);
  1368. m_savingContext->abortingSaving = false;
  1369. m_canvas->saveAs(m_savingContext->saveTempFile->name(), m_IOFileSettings,
  1370. m_setExifOrientationTag && (m_rotatedOrFlipped || m_canvas->exifRotated()),
  1371. m_savingContext->format.lower());
  1372. return true;
  1373. }
  1374. bool EditorWindow::checkPermissions(const KURL& url)
  1375. {
  1376. //TODO: Check that the permissions can actually be changed
  1377. // if write permissions are not available.
  1378. TQFileInfo fi(url.path());
  1379. if (fi.exists() && !fi.isWritable())
  1380. {
  1381. int result =
  1382. KMessageBox::warningYesNo( this, i18n("You do not have write permissions "
  1383. "for the file named \"%1\". "
  1384. "Are you sure you want "
  1385. "to overwrite it?")
  1386. .arg(url.filename()),
  1387. i18n("Overwrite File?"),
  1388. i18n("Overwrite"),
  1389. KStdGuiItem::cancel() );
  1390. if (result != KMessageBox::Yes)
  1391. return false;
  1392. }
  1393. return true;
  1394. }
  1395. bool EditorWindow::moveFile()
  1396. {
  1397. TQCString dstFileName = TQFile::encodeName(m_savingContext->destinationURL.path());
  1398. // Store old permissions:
  1399. // Just get the current umask.
  1400. mode_t curr_umask = umask(S_IREAD | S_IWRITE);
  1401. // Restore the umask.
  1402. umask(curr_umask);
  1403. // For new files respect the umask setting.
  1404. mode_t filePermissions = (S_IREAD | S_IWRITE | S_IROTH | S_IWOTH | S_IRGRP | S_IWGRP) & ~curr_umask;
  1405. // For existing files, use the mode of the original file.
  1406. if (m_savingContext->destinationExisted)
  1407. {
  1408. struct stat stbuf;
  1409. if (::stat(dstFileName, &stbuf) == 0)
  1410. {
  1411. filePermissions = stbuf.st_mode;
  1412. }
  1413. }
  1414. // rename tmp file to dest
  1415. if (::rename(TQFile::encodeName(m_savingContext->saveTempFile->name()), dstFileName) != 0)
  1416. {
  1417. KMessageBox::error(this, i18n("Failed to overwrite original file"),
  1418. i18n("Error Saving File"));
  1419. return false;
  1420. }
  1421. // restore permissions
  1422. if (::chmod(dstFileName, filePermissions) != 0)
  1423. {
  1424. DWarning() << "Failed to restore file permissions for file " << dstFileName << endl;
  1425. }
  1426. return true;
  1427. }
  1428. void EditorWindow::slotToggleColorManagedView()
  1429. {
  1430. d->cmViewIndicator->blockSignals(true);
  1431. d->viewCMViewAction->blockSignals(true);
  1432. bool cmv = false;
  1433. if (d->ICCSettings->enableCMSetting)
  1434. {
  1435. cmv = !d->ICCSettings->managedViewSetting;
  1436. d->ICCSettings->managedViewSetting = cmv;
  1437. m_canvas->setICCSettings(d->ICCSettings);
  1438. // Save Color Managed View setting in config file. For performance
  1439. // reason, no need to flush file, it cached in memory and will be flushed
  1440. // to disk at end of session.
  1441. TDEConfig* config = kapp->config();
  1442. config->setGroup("Color Management");
  1443. config->writeEntry("ManagedView", cmv);
  1444. }
  1445. d->cmViewIndicator->setOn(cmv);
  1446. d->viewCMViewAction->setChecked(cmv);
  1447. setColorManagedViewIndicatorToolTip(d->ICCSettings->enableCMSetting, cmv);
  1448. d->cmViewIndicator->blockSignals(false);
  1449. d->viewCMViewAction->blockSignals(false);
  1450. }
  1451. void EditorWindow::setColorManagedViewIndicatorToolTip(bool available, bool cmv)
  1452. {
  1453. TQToolTip::remove(d->cmViewIndicator);
  1454. TQString tooltip;
  1455. if (available)
  1456. {
  1457. if (cmv)
  1458. tooltip = i18n("Color Managed View is enabled");
  1459. else
  1460. tooltip = i18n("Color Managed View is disabled");
  1461. }
  1462. else
  1463. {
  1464. tooltip = i18n("Color Management is not configured, so the Color Managed View is not available");
  1465. }
  1466. TQToolTip::add(d->cmViewIndicator, tooltip);
  1467. }
  1468. void EditorWindow::slotToggleUnderExposureIndicator()
  1469. {
  1470. d->underExposureIndicator->blockSignals(true);
  1471. d->viewUnderExpoAction->blockSignals(true);
  1472. bool uei = !d->exposureSettings->underExposureIndicator;
  1473. d->underExposureIndicator->setOn(uei);
  1474. d->viewUnderExpoAction->setChecked(uei);
  1475. d->exposureSettings->underExposureIndicator = uei;
  1476. m_canvas->setExposureSettings(d->exposureSettings);
  1477. setUnderExposureToolTip(uei);
  1478. d->underExposureIndicator->blockSignals(false);
  1479. d->viewUnderExpoAction->blockSignals(false);
  1480. }
  1481. void EditorWindow::setUnderExposureToolTip(bool uei)
  1482. {
  1483. TQToolTip::remove(d->underExposureIndicator);
  1484. TQToolTip::add(d->underExposureIndicator,
  1485. uei ? i18n("Under-Exposure indicator is enabled")
  1486. : i18n("Under-Exposure indicator is disabled"));
  1487. }
  1488. void EditorWindow::slotToggleOverExposureIndicator()
  1489. {
  1490. d->overExposureIndicator->blockSignals(true);
  1491. d->viewOverExpoAction->blockSignals(true);
  1492. bool oei = !d->exposureSettings->overExposureIndicator;
  1493. d->overExposureIndicator->setOn(oei);
  1494. d->viewOverExpoAction->setChecked(oei);
  1495. d->exposureSettings->overExposureIndicator = oei;
  1496. m_canvas->setExposureSettings(d->exposureSettings);
  1497. setOverExposureToolTip(oei);
  1498. d->overExposureIndicator->blockSignals(false);
  1499. d->viewOverExpoAction->blockSignals(false);
  1500. }
  1501. void EditorWindow::setOverExposureToolTip(bool oei)
  1502. {
  1503. TQToolTip::remove(d->overExposureIndicator);
  1504. TQToolTip::add(d->overExposureIndicator,
  1505. oei ? i18n("Over-Exposure indicator is enabled")
  1506. : i18n("Over-Exposure indicator is disabled"));
  1507. }
  1508. void EditorWindow::slotDonateMoney()
  1509. {
  1510. TDEApplication::kApplication()->invokeBrowser("http://www.digikam.org/?q=donation");
  1511. }
  1512. void EditorWindow::slotContribute()
  1513. {
  1514. TDEApplication::kApplication()->invokeBrowser("http://www.digikam.org/?q=contrib");
  1515. }
  1516. void EditorWindow::slotToggleSlideShow()
  1517. {
  1518. TDEConfig* config = kapp->config();
  1519. config->setGroup("ImageViewer Settings");
  1520. bool startWithCurrent = config->readBoolEntry("SlideShowStartCurrent", false);
  1521. SlideShowSettings settings;
  1522. settings.delay = config->readNumEntry("SlideShowDelay", 5) * 1000;
  1523. settings.printName = config->readBoolEntry("SlideShowPrintName", true);
  1524. settings.printDate = config->readBoolEntry("SlideShowPrintDate", false);
  1525. settings.printApertureFocal = config->readBoolEntry("SlideShowPrintApertureFocal", false);
  1526. settings.printExpoSensitivity = config->readBoolEntry("SlideShowPrintExpoSensitivity", false);
  1527. settings.printMakeModel = config->readBoolEntry("SlideShowPrintMakeModel", false);
  1528. settings.printComment = config->readBoolEntry("SlideShowPrintComment", false);
  1529. settings.loop = config->readBoolEntry("SlideShowLoop", false);
  1530. slideShow(startWithCurrent, settings);
  1531. }
  1532. void EditorWindow::slotSelectionChanged(const TQRect& sel)
  1533. {
  1534. d->selectLabel->setText(TQString("(%1, %2) (%3 x %4)").arg(sel.x()).arg(sel.y())
  1535. .arg(sel.width()).arg(sel.height()));
  1536. }
  1537. void EditorWindow::slotRawCameraList()
  1538. {
  1539. RawCameraDlg dlg(this);
  1540. dlg.exec();
  1541. }
  1542. void EditorWindow::slotThemeChanged()
  1543. {
  1544. TQStringList themes(ThemeEngine::instance()->themeNames());
  1545. int index = themes.findIndex(ThemeEngine::instance()->getCurrentThemeName());
  1546. if (index == -1)
  1547. index = themes.findIndex(i18n("Default"));
  1548. m_themeMenuAction->setCurrentItem(index);
  1549. TDEConfig* config = kapp->config();
  1550. config->setGroup("ImageViewer Settings");
  1551. if (!config->readBoolEntry("UseThemeBackgroundColor", true))
  1552. m_bgColor = config->readColorEntry("BackgroundColor", &TQt::black);
  1553. else
  1554. m_bgColor = ThemeEngine::instance()->baseColor();
  1555. m_canvas->setBackgroundColor(m_bgColor);
  1556. }
  1557. void EditorWindow::slotChangeTheme(const TQString& theme)
  1558. {
  1559. ThemeEngine::instance()->slotChangeTheme(theme);
  1560. }
  1561. void EditorWindow::setToolStartProgress(const TQString& toolName)
  1562. {
  1563. m_nameLabel->setProgressValue(0);
  1564. m_nameLabel->progressBarMode(StatusProgressBar::CancelProgressBarMode, TQString("%1: ").arg(toolName));
  1565. }
  1566. void EditorWindow::setToolProgress(int progress)
  1567. {
  1568. m_nameLabel->setProgressValue(progress);
  1569. }
  1570. void EditorWindow::setToolStopProgress()
  1571. {
  1572. m_nameLabel->setProgressValue(0);
  1573. m_nameLabel->progressBarMode(StatusProgressBar::TextMode);
  1574. slotUpdateItemInfo();
  1575. }
  1576. void EditorWindow::slotShowMenuBar()
  1577. {
  1578. if (menuBar()->isVisible())
  1579. menuBar()->hide();
  1580. else
  1581. menuBar()->show();
  1582. }
  1583. } // namespace Digikam