diff --git a/rtdata/languages/Deutsch b/rtdata/languages/Deutsch index 8410ec7b1..9ce148fa7 100644 --- a/rtdata/languages/Deutsch +++ b/rtdata/languages/Deutsch @@ -34,6 +34,7 @@ CURVEEDITOR_TOOLTIPLINEAR;Zurücksetzen der Kurve (linear) CURVEEDITOR_TOOLTIPLOAD;Laden einer Kurve CURVEEDITOR_TOOLTIPSAVE;Speichern der aktuellen Kurve CURVEEDITOR_TYPE;Typ: +EDITWINDOW_TITLE;Bildbearbeitung EXIFFILTER_APERTURE;Blende EXIFFILTER_CAMERA;Kamera EXIFFILTER_DIALOGLABEL;Exif Filter @@ -480,6 +481,7 @@ PREFERENCES_LINEDENOISE;Zeilenrausch-Filter PREFERENCES_LIVETHUMBNAILS;Live Voransichten (langsamer) PREFERENCES_MONITORICC;Monitor-Profil PREFERENCES_MULTITAB;Multi-Reiter Modus +PREFERENCES_MULTITABDUALMON;Multi-Reiter Modus, auf zweitem Monitor wenn verfügbar PREFERENCES_OUTDIR;Ausgabe-Verzeichnis PREFERENCES_OUTDIRFOLDER;Speichern in Verzeichnis PREFERENCES_OUTDIRFOLDERHINT;Ablegen der gespeicherten Bilder in ein ausgewähltes Verzeichnis diff --git a/rtdata/languages/default b/rtdata/languages/default index 0c24c68c0..115f00b31 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -21,6 +21,7 @@ CURVEEDITOR_TOOLTIPLINEAR;Reset curve to linear CURVEEDITOR_TOOLTIPLOAD;Load a curve from file CURVEEDITOR_TOOLTIPSAVE;Save current curve CURVEEDITOR_TYPE;Type: +EDITWINDOW_TITLE;Image Edit EXIFFILTER_APERTURE;Aperture EXIFFILTER_CAMERA;Camera EXIFFILTER_DIALOGLABEL;Exif Filter @@ -463,6 +464,7 @@ PREFERENCES_LINEDENOISE;Line noise filter PREFERENCES_LIVETHUMBNAILS;Live Thumbnails (slower) PREFERENCES_MONITORICC;Monitor Profile PREFERENCES_MULTITAB;Multiple tabs mode +PREFERENCES_MULTITABDUALMON;Multiple tabs mode, if available on second monitor PREFERENCES_OUTDIR;Output Directory PREFERENCES_OUTDIRFOLDER;Save to folder PREFERENCES_OUTDIRFOLDERHINT;Put the saved images to the selected folder diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt index 1a11190d1..c15cf79e0 100644 --- a/rtgui/CMakeLists.txt +++ b/rtgui/CMakeLists.txt @@ -1,6 +1,6 @@ set (BASESOURCEFILES - batchtoolpanelcoord.cc paramsedited.cc cropwindow.cc previewhandler.cc previewwindow.cc navigator.cc indclippedpanel.cc filterpanel.cc + editwindow.cc batchtoolpanelcoord.cc paramsedited.cc cropwindow.cc previewhandler.cc previewwindow.cc navigator.cc indclippedpanel.cc filterpanel.cc cursormanager.cc rtwindow.cc renamedlg.cc recentbrowser.cc placesbrowser.cc filepanel.cc editorpanel.cc batchqueuepanel.cc ilabel.cc thumbbrowserbase.cc adjuster.cc filebrowserentry.cc filebrowser.cc filethumbnailbuttonset.cc cachemanager.cc cacheimagedata.cc shcselector.cc perspective.cc diff --git a/rtgui/editwindow.cc b/rtgui/editwindow.cc new file mode 100644 index 000000000..6287407e0 --- /dev/null +++ b/rtgui/editwindow.cc @@ -0,0 +1,187 @@ +/* +* This file is part of RawTherapee. +* +* RawTherapee is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* RawTherapee is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with RawTherapee. If not, see . +*/ + +#include +#include +#include +#include +#include + +static EditWindow* editWnd = NULL; + +// Check if the system has more than one display and option is set +bool EditWindow::isMultiDisplayEnabled() { + return options.multiDisplayMode>0 && Gdk::Screen::get_default()->get_n_monitors ()>1; +} + +// Should only be created once, auto-creates window on correct display +EditWindow* EditWindow::getInstance(RTWindow* p) +{ + + if ( editWnd == NULL ) + { + static Glib::Mutex smutex_; + Glib::Mutex::Lock lock(smutex_); + if ( editWnd == 0 ) + { + editWnd = new EditWindow(p); + + // Determine the other display and maximize the window on that + const Glib::RefPtr< Gdk::Window >& wnd=p->get_window(); + int monNo=p->get_screen()->get_monitor_at_window (wnd); + + Gdk::Rectangle lMonitorRect; + editWnd->get_screen()->get_monitor_geometry(monNo==0 ? 1:0, lMonitorRect); + editWnd->move(lMonitorRect.get_x(), lMonitorRect.get_y()); + editWnd->maximize(); + editWnd->show(); + } else { + editWnd->show_all(); + } + } + + return editWnd; +} + +EditWindow::EditWindow (RTWindow* p) : parent(p) , isFullscreen(false) { + +#ifdef GLIBMM_EXCEPTIONS_ENABLED + try { set_default_icon_from_file (argv0+"/images/logoicon16.png"); + } catch(Glib::Exception& ex) { printf ("%s\n", ex.what().c_str()); } +#else + { std::auto_ptr error; + set_default_icon_from_file (argv0+"/images/logoicon16.png", error); + } +#endif //GLIBMM_EXCEPTIONS_ENABLED + + set_title("RawTherapee "+ M("EDITWINDOW_TITLE")); + property_allow_shrink() = true; + set_modal(false); + set_resizable(true); + + property_destroy_with_parent().set_value(false); + signal_window_state_event().connect( sigc::mem_fun(*this, &EditWindow::on_window_state_event) ); + + mainNB = Gtk::manage (new Gtk::Notebook ()); + mainNB->set_scrollable (true); + mainNB->signal_switch_page().connect_notify( sigc::mem_fun(*this, &EditWindow::on_mainNB_switch_page) ); + + signal_key_press_event().connect( sigc::mem_fun(*this, &EditWindow::keyPressed) ); + + Gtk::VBox* mainBox = Gtk::manage (new Gtk::VBox ()); + mainBox->pack_start (*mainNB); + + add (*mainBox); + show_all (); +} + +void EditWindow::on_realize () { + Gtk::Window::on_realize (); + + cursorManager.init (get_window()); +} + +bool EditWindow::on_window_state_event(GdkEventWindowState* event) { + if (!event->new_window_state) { + // Window mode + options.windowMaximized = false; + } + else if (event->new_window_state & (GDK_WINDOW_STATE_MAXIMIZED|GDK_WINDOW_STATE_FULLSCREEN)) { + // Fullscreen mode + options.windowMaximized = true; + } + return true; +} + +void EditWindow::on_mainNB_switch_page(GtkNotebookPage* page, guint page_num) { + if (page_num > 1) { + EditorPanel *ep = (EditorPanel *)mainNB->get_nth_page(page_num); + ep->setAspect(); + } +} + +void EditWindow::addEditorPanel (EditorPanel* ep, const std::string &name) { + if (epanels.find(name)!=epanels.end()) { + // remove existing panel + mainNB->remove_page (*epanels[name]); + epanels.erase (name); + filesEdited.erase (name); + } + + ep->setParent (parent); + + // construct closeable tab for the image + Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); + hb->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::FILE, Gtk::ICON_SIZE_MENU))); + hb->pack_start (*Gtk::manage (new Gtk::Label (name))); + Gtk::Button* closeb = Gtk::manage (new Gtk::Button ()); + closeb->set_image (*Gtk::manage(new Gtk::Image (Gtk::Stock::CLOSE, Gtk::ICON_SIZE_MENU))); + closeb->set_relief (Gtk::RELIEF_NONE); + closeb->set_focus_on_click (false); + // make the button as small as possible + Glib::RefPtr style = Gtk::RcStyle::create (); + style->set_xthickness (0); + style->set_ythickness (0); + + closeb->modify_style (style); + closeb->signal_clicked().connect( sigc::bind (sigc::mem_fun(*this, &EditWindow::remEditorPanel) , ep)); + hb->pack_end (*closeb); + hb->set_spacing (2); + hb->show_all (); + + mainNB->append_page (*ep, *hb); + mainNB->set_current_page (mainNB->page_num (*ep)); + mainNB->set_tab_reorderable (*ep, true); + + epanels[ name ] = ep; + filesEdited.insert ( name ); + parent->fpanel->refreshEditedState (filesEdited); +} + +void EditWindow::remEditorPanel (EditorPanel* ep) { + epanels.erase (ep->getShortName()); + filesEdited.erase (ep->getShortName ()); + parent->fpanel->refreshEditedState (filesEdited); + + mainNB->remove_page (*ep); + // TODO: save options if wanted +} + +bool EditWindow::keyPressed (GdkEventKey* event) { + if(event->keyval == GDK_F11) { + toggleFullscreen(); + return true; + } else { + EditorPanel* ep = (EditorPanel*)mainNB->get_nth_page (mainNB->get_current_page()); + return ep->handleShortcutKey (event); + } +} + +void EditWindow::toggleFullscreen () { + isFullscreen ? unfullscreen() : fullscreen(); + isFullscreen = !isFullscreen; +} + +bool EditWindow::on_delete_event(GdkEventAny* event) { + for ( std::set ::iterator iter = filesEdited.begin(); iter != filesEdited.end();iter++ ) { + remEditorPanel(epanels[*iter]); + } + + hide (); + return true; +} + diff --git a/rtgui/editwindow.h b/rtgui/editwindow.h new file mode 100644 index 000000000..d3beb703b --- /dev/null +++ b/rtgui/editwindow.h @@ -0,0 +1,57 @@ +/* + * This file is part of RawTherapee. + * + * RawTherapee is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * RawTherapee is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with RawTherapee. If not, see . + */ +#ifndef _EDITWINDOW_ +#define _EDITWINDOW_ + +#include +#include +#include +#include + +class EditWindow : public Gtk::Window { + + private: + RTWindow* parent; + + Gtk::Notebook* mainNB; + std::set filesEdited; + std::map epanels; + + bool isFullscreen; + void toggleFullscreen (); + + public: + // Check if the system has more than one display and option is set + static bool isMultiDisplayEnabled(); + + // Should only be created once, auto-creates window on correct display + static EditWindow* getInstance(RTWindow* p); + + EditWindow (RTWindow* p); + + void addEditorPanel (EditorPanel* ep,const std::string &name); + void remEditorPanel (EditorPanel* ep); + + bool keyPressed (GdkEventKey* event); + bool on_delete_event(GdkEventAny* event); + bool on_window_state_event(GdkEventWindowState* event); + void on_mainNB_switch_page(GtkNotebookPage* page, guint page_num); + + void on_realize (); +}; + +#endif diff --git a/rtgui/filepanel.cc b/rtgui/filepanel.cc index 04dfdabe6..a365d7141 100644 --- a/rtgui/filepanel.cc +++ b/rtgui/filepanel.cc @@ -162,18 +162,16 @@ bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnectorreturnValue() && thm) { - if (options.tabbedUI){ - EditorPanel* epanel = Gtk::manage (new EditorPanel ()); - parent->addEditorPanel (epanel,Glib::path_get_basename (thm->getFileName())); - epanel->open(thm, pc->returnValue() ); - } - else{ - parent->SetEditorCurrent(); - parent->epanel->open(thm, pc->returnValue() ); - } + if (options.tabbedUI) { + EditorPanel* epanel = Gtk::manage (new EditorPanel ()); + parent->addEditorPanel (epanel,Glib::path_get_basename (thm->getFileName())); + epanel->open(thm, pc->returnValue() ); + } else { + parent->SetEditorCurrent(); + parent->epanel->open(thm, pc->returnValue() ); + } - - }else { + } else { Glib::ustring msg_ = Glib::ustring("") + M("MAIN_MSG_CANNOTLOAD") + " \"" + thm->getFileName() + "\" .\n"; Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true); msgd.run (); diff --git a/rtgui/options.cc b/rtgui/options.cc index 17f171c51..7bf2892e9 100644 --- a/rtgui/options.cc +++ b/rtgui/options.cc @@ -121,6 +121,7 @@ void Options::setDefaults () { overlayedFileNames = true; showFileNames = true; tabbedUI = false; + multiDisplayMode = 0; int babehav[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0}; baBehav = std::vector (babehav, babehav+ADDSET_PARAM_NUM); @@ -269,6 +270,7 @@ if (keyFile.has_group ("GUI")) { if (keyFile.has_key ("GUI", "FrameColor")) bgcolor = keyFile.get_integer ("GUI", "FrameColor"); if (keyFile.has_key ("GUI", "ProcessingQueueEnbled"))procQueueEnabled = keyFile.get_boolean ("GUI", "ProcessingQueueEnbled"); if (keyFile.has_key ("GUI", "ToolPanelsExpanded")) tpOpen = keyFile.get_integer_list ("GUI", "ToolPanelsExpanded"); + if (keyFile.has_key ("GUI", "MultiDisplayMode")) multiDisplayMode = keyFile.get_integer ("GUI", "MultiDisplayMode"); //if (keyFile.has_key ("GUI", "CurvePanelsExpanded")) crvOpen = keyFile.get_integer_list ("GUI", "CurvePanelsExpanded"); } @@ -400,6 +402,7 @@ int Options::saveToFile (Glib::ustring fname) { keyFile.set_boolean ("GUI", "ProcessingQueueEnbled", procQueueEnabled); Glib::ArrayHandle tpopen = tpOpen; keyFile.set_integer_list ("GUI", "ToolPanelsExpanded", tpopen); + keyFile.set_integer ("GUI", "MultiDisplayMode", multiDisplayMode); //Glib::ArrayHandle crvopen = crvOpen; //keyFile.set_integer_list ("GUI", "CurvePanelsExpanded", crvopen); @@ -460,7 +463,7 @@ void Options::load () { // out which are the parent translations. Furthermore, there must be a file for each locale () -- you cannot have // 'French (CA)' unless there is a file 'French'. - Glib::ustring defaultTranslation = argv0 + "/languages/default"; + Glib::ustring defaultTranslation = argv0 + "/languages/default"; Glib::ustring languageTranslation = ""; Glib::ustring localeTranslation = ""; diff --git a/rtgui/options.h b/rtgui/options.h index 9e190c337..59758dc5c 100644 --- a/rtgui/options.h +++ b/rtgui/options.h @@ -132,6 +132,7 @@ class Options { bool showFileNames; bool tabbedUI; int previewSizeTab,previewSizeBrowser; + int multiDisplayMode; // 0=none, 1=Edit panels on other display Options (); diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 50c7069aa..26cd99588 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -330,6 +330,7 @@ Gtk::Widget* Preferences::getGeneralPanel () { editorLayout->append_text (M("PREFERENCES_SINGLETAB")); editorLayout->append_text (M("PREFERENCES_MULTITAB")); + editorLayout->append_text (M("PREFERENCES_MULTITABDUALMON")); editorLayout->set_active (1); hbworkflow->pack_start (*flayoutlab, Gtk::PACK_SHRINK, 4); @@ -761,7 +762,9 @@ void Preferences::storePreferences () { for (Gtk::TreeIter adjs=sections->children().begin(); adjs!=sections->children().end(); adjs++) moptions.baBehav[adjs->get_value (behavColumns.addsetid)] = adjs->get_value (behavColumns.badd); - moptions.tabbedUI = (bool)editorLayout->get_active_row_number(); + int editorMode=editorLayout->get_active_row_number(); + moptions.tabbedUI = (editorMode>0); + moptions.multiDisplayMode = editorMode==2 ? 1:0; moptions.overwriteOutputFile = chOverwriteOutputFile->get_active (); } @@ -837,7 +840,11 @@ void Preferences::fillPreferences () { saveParamsCache->set_active (moptions.saveParamsCache); loadParamsPreference->set_active (moptions.paramsLoadLocation); - editorLayout->set_active(moptions.tabbedUI); + if (!moptions.tabbedUI) + editorLayout->set_active(0); + else + editorLayout->set_active(moptions.multiDisplayMode ? 2 : 1); + darkFrameDir->set_filename( moptions.rtSettings.darkFramesPath ); updateDFinfos(); diff --git a/rtgui/rtwindow.cc b/rtgui/rtwindow.cc index 211a8d801..344680cef 100644 --- a/rtgui/rtwindow.cc +++ b/rtgui/rtwindow.cc @@ -20,6 +20,7 @@ #include #include #include +#include RTWindow::RTWindow () { @@ -118,7 +119,7 @@ RTWindow::RTWindow () { add (*mainBox); show_all (); - if(options.tabbedUI) + if(options.tabbedUI || EditWindow::isMultiDisplayEnabled()) epanel->hide_all(); } @@ -151,50 +152,59 @@ void RTWindow::on_mainNB_switch_page(GtkNotebookPage* page, guint page_num) { } void RTWindow::addEditorPanel (EditorPanel* ep, const std::string &name) { + if (EditWindow::isMultiDisplayEnabled()) { + EditWindow * wndEdit = EditWindow::getInstance(this); + wndEdit->show_all(); + wndEdit->addEditorPanel(ep,name); + } else { + ep->setParent (this); - ep->setParent (this); + // construct closeable tab for the image + Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); + hb->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::FILE, Gtk::ICON_SIZE_MENU))); + hb->pack_start (*Gtk::manage (new Gtk::Label (name))); + Gtk::Button* closeb = Gtk::manage (new Gtk::Button ()); + closeb->set_image (*Gtk::manage(new Gtk::Image (Gtk::Stock::CLOSE, Gtk::ICON_SIZE_MENU))); + closeb->set_relief (Gtk::RELIEF_NONE); + closeb->set_focus_on_click (false); + // make the button as small as possible + Glib::RefPtr style = Gtk::RcStyle::create (); + style->set_xthickness (0); + style->set_ythickness (0); - // construct closeable tab for the image - Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ()); - hb->pack_start (*Gtk::manage (new Gtk::Image (Gtk::Stock::FILE, Gtk::ICON_SIZE_MENU))); - hb->pack_start (*Gtk::manage (new Gtk::Label (name))); - Gtk::Button* closeb = Gtk::manage (new Gtk::Button ()); - closeb->set_image (*Gtk::manage(new Gtk::Image (Gtk::Stock::CLOSE, Gtk::ICON_SIZE_MENU))); - closeb->set_relief (Gtk::RELIEF_NONE); - closeb->set_focus_on_click (false); - // make the button as small as possible - Glib::RefPtr style = Gtk::RcStyle::create (); - style->set_xthickness (0); - style->set_ythickness (0); + closeb->modify_style (style); + closeb->signal_clicked().connect( sigc::bind (sigc::mem_fun(*this, &RTWindow::remEditorPanel) , ep)); + hb->pack_end (*closeb); + hb->set_spacing (2); + hb->show_all (); - closeb->modify_style (style); - closeb->signal_clicked().connect( sigc::bind (sigc::mem_fun(*this, &RTWindow::remEditorPanel) , ep)); - hb->pack_end (*closeb); - hb->set_spacing (2); - hb->show_all (); + mainNB->append_page (*ep, *hb); + //ep->setAspect (); + mainNB->set_current_page (mainNB->page_num (*ep)); + mainNB->set_tab_reorderable (*ep, true); - mainNB->append_page (*ep, *hb); - //ep->setAspect (); - mainNB->set_current_page (mainNB->page_num (*ep)); - mainNB->set_tab_reorderable (*ep, true); - - epanels[ name ] = ep; - filesEdited.insert ( name ); - fpanel->refreshEditedState (filesEdited); + epanels[ name ] = ep; + filesEdited.insert ( name ); + fpanel->refreshEditedState (filesEdited); + } } void RTWindow::remEditorPanel (EditorPanel* ep) { + if (EditWindow::isMultiDisplayEnabled()) { + EditWindow * wndEdit = EditWindow::getInstance(this); + wndEdit->remEditorPanel(ep); + } else { + //ep->saveOptions (); + epanels.erase (ep->getShortName()); + filesEdited.erase (ep->getShortName ()); + fpanel->refreshEditedState (filesEdited); - //ep->saveOptions (); - epanels.erase (ep->getFileName()); - filesEdited.erase (ep->getFileName ()); - fpanel->refreshEditedState (filesEdited); + mainNB->remove_page (*ep); - mainNB->remove_page (*ep); - - if (mainNB->get_current_page () == mainNB->page_num (*bpanel)) - mainNB->set_current_page (mainNB->page_num (*fpanel)); - // TODO: ask what to do: close & apply, close & apply selection, close & revert, cancel + if (mainNB->get_current_page () == mainNB->page_num (*bpanel)) + mainNB->set_current_page (mainNB->page_num (*fpanel)); + // TODO: ask what to do: close & apply, close & apply selection, close & revert, cancel + } } bool RTWindow::keyPressed (GdkEventKey* event) { @@ -359,15 +369,15 @@ void RTWindow::MoveFileBrowserToEditor() bool RTWindow::on_expose_event_epanel(GdkEventExpose* event) { - if(!options.tabbedUI) + if(!options.tabbedUI && !EditWindow::isMultiDisplayEnabled()) MoveFileBrowserToEditor(); - return false; // Gtk::VBox::on_expose_event(event); + return false; // Gtk::VBox::on_expose_event(event); } bool RTWindow::on_expose_event_fpanel(GdkEventExpose* event) { - if(!options.tabbedUI) + if(!options.tabbedUI && !EditWindow::isMultiDisplayEnabled()) MoveFileBrowserToMain(); return false; // Gtk::HPaned::on_expose_event(event); } diff --git a/rtgui/rtwindow.h b/rtgui/rtwindow.h index eee579758..59d9f6def 100644 --- a/rtgui/rtwindow.h +++ b/rtgui/rtwindow.h @@ -30,7 +30,6 @@ class RTWindow : public Gtk::Window, public rtengine::ProgressListener{ private: Gtk::Notebook* mainNB; - FilePanel* fpanel; BatchQueuePanel* bpanel; std::set filesEdited; std::map epanels; @@ -66,7 +65,10 @@ class RTWindow : public Gtk::Window, public rtengine::ProgressListener{ void setProgressState (int state); void error (Glib::ustring descr); rtengine::ProgressListener* getProgressListener () { return pldBridge; } + EditorPanel* epanel; + FilePanel* fpanel; + void SetEditorCurrent(); void SetMainCurrent(); void MoveFileBrowserToEditor();