New dual monitor editor layout, plus memory leak fix; cmake req. (see issue #348)

This commit is contained in:
Oliver Duis
2010-11-22 15:17:01 +01:00
parent eee3ca5cd7
commit e3dbe759a3
11 changed files with 324 additions and 55 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

187
rtgui/editwindow.cc Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#include <editwindow.h>
#include <options.h>
#include <preferences.h>
#include <cursormanager.h>
#include <gtk\gtkwidget.h>
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<Glib::Error> 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<Gtk::RcStyle> 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 <Glib::ustring>::iterator iter = filesEdited.begin(); iter != filesEdited.end();iter++ ) {
remEditorPanel(epanels[*iter]);
}
hide ();
return true;
}

57
rtgui/editwindow.h Normal file
View File

@@ -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 <http://www.gnu.org/licenses/>.
*/
#ifndef _EDITWINDOW_
#define _EDITWINDOW_
#include <gtkmm.h>
#include <filepanel.h>
#include <editorpanel.h>
#include <set>
class EditWindow : public Gtk::Window {
private:
RTWindow* parent;
Gtk::Notebook* mainNB;
std::set<Glib::ustring> filesEdited;
std::map<Glib::ustring, EditorPanel*> 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

View File

@@ -162,18 +162,16 @@ bool FilePanel::imageLoaded( Thumbnail* thm, ProgressConnector<rtengine::Initial
if (pc->returnValue() && 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("<b>") + M("MAIN_MSG_CANNOTLOAD") + " \"" + thm->getFileName() + "\" .\n</b>";
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
msgd.run ();

View File

@@ -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<int> (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<int> tpopen = tpOpen;
keyFile.set_integer_list ("GUI", "ToolPanelsExpanded", tpopen);
keyFile.set_integer ("GUI", "MultiDisplayMode", multiDisplayMode);
//Glib::ArrayHandle<int> 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 <Language> for each locale <Language> (<LC>) -- 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 = "";

View File

@@ -132,6 +132,7 @@ class Options {
bool showFileNames;
bool tabbedUI;
int previewSizeTab,previewSizeBrowser;
int multiDisplayMode; // 0=none, 1=Edit panels on other display
Options ();

View File

@@ -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();

View File

@@ -20,6 +20,7 @@
#include <options.h>
#include <preferences.h>
#include <cursormanager.h>
#include <editwindow.h>
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<Gtk::RcStyle> 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<Gtk::RcStyle> 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);
}

View File

@@ -30,7 +30,6 @@ class RTWindow : public Gtk::Window, public rtengine::ProgressListener{
private:
Gtk::Notebook* mainNB;
FilePanel* fpanel;
BatchQueuePanel* bpanel;
std::set<Glib::ustring> filesEdited;
std::map<Glib::ustring, EditorPanel*> 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();