Fixed type in English translations for false color suppression, as patched by Eric Mountain
This commit is contained in:
52
rtgui/CMakeLists.txt
Executable file
52
rtgui/CMakeLists.txt
Executable file
@@ -0,0 +1,52 @@
|
||||
|
||||
set (BASESOURCEFILES
|
||||
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
|
||||
clipboard.cc thumbimageupdater.cc bqentryupdater.cc
|
||||
coarsepanel.cc cacorrection.cc colorshift.cc hlrec.cc chmixer.cc
|
||||
colorboost.cc resize.cc icmpanel.cc crop.cc shadowshighlights.cc
|
||||
colordenoise.cc
|
||||
exifpanel.cc
|
||||
sharpening.cc
|
||||
whitebalance.cc vignetting.cc rotate.cc distortion.cc
|
||||
crophandler.cc curveeditor.cc dirbrowser.cc
|
||||
filecatalog.cc
|
||||
histogrampanel.cc history.cc imagearea.cc
|
||||
imageareapanel.cc iptcpanel.cc lcurve.cc lumadenoise.cc main.cc
|
||||
multilangmgr.cc mycurve.cc options.cc
|
||||
preferences.cc profilepanel.cc safegtk.cc saveasdlg.cc
|
||||
saveformatpanel.cc splash.cc
|
||||
thumbnail.cc tonecurve.cc toolbar.cc
|
||||
guiutils.cc zoompanel.cc toolpanelcoord.cc
|
||||
thumbbrowserentrybase.cc batchqueueentry.cc
|
||||
batchqueue.cc lwbutton.cc lwbuttonset.cc
|
||||
batchqueuebuttonset.cc browserfilter.cc exiffiltersettings.cc
|
||||
profilestore.cc partialpastedlg.cc)
|
||||
|
||||
if (WIN32)
|
||||
set (EXTRA_SRC windirmonitor.cc myicon.o)
|
||||
include_directories ( ../rtengine ${CMAKE_CURRENT_BINARY_DIR} . ../rtexif ${EXTRA_INCDIR} ${GLIB2_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS}
|
||||
${GTK_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${GIOMM_INCLUDE_DIRS})
|
||||
link_directories (. ../rtexif ${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS}
|
||||
${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS} ${GIO_LIBRARY_DIRS} ${GIOMM_LIBRARY_DIRS})
|
||||
#set_target_properties (rth PROPERTIES LINK_FLAGS "-mwindows")
|
||||
else (WIN32)
|
||||
include_directories (${CMAKE_CURRENT_SOURCE_DIR}/../rtengine ${CMAKE_CURRENT_BINARY_DIR} . ${CMAKE_CURRENT_SOURCE_DIR}/../rtexif ${EXTRA_INCDIR} ${GLIB2_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS}
|
||||
${GTK_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${GIOMM_INCLUDE_DIRS} ${IPTCDATA_INCLUDE_DIRS} ${LCMS_INCLUDE_DIRS} ${GTHREAD_INCLUDE_DIRS} ${GOBJECT_INCLUDE_DIRS} )
|
||||
link_directories (${CMAKE_CURRENT_SOURCE_DIR}/../rtexif ${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS}
|
||||
${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS} ${GIO_LIBRARY_DIRS} ${GIOMM_LIBRARY_DIRS} ${IPTCDATA_LIBRARY_DIRS} ${LCMS_LIBRARY_DIRS} ${GTHREAD_LIBRARY_DIRS} ${GOBJECT_LIBRARY_DIRS})
|
||||
# create config.h which defines where data are stored
|
||||
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
endif (WIN32)
|
||||
|
||||
add_executable (rth ${EXTRA_SRC} ${BASESOURCEFILES})
|
||||
|
||||
set_target_properties (rth PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" OUTPUT_NAME rt)
|
||||
#target_link_libraries (rth rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${EXTRA_LIB} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES}
|
||||
# ${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${GTK_LIBRARIES} ${GTKMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${IPTCDATA_LIBRARIES})
|
||||
target_link_libraries (rth rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES}
|
||||
${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${GTK_LIBRARIES} ${GTKMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${IPTCDATA_LIBRARIES})
|
||||
install (TARGETS rth DESTINATION ${BINDIR})
|
||||
|
||||
BIN
rtgui/RT.ico
Executable file
BIN
rtgui/RT.ico
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 125 KiB |
28
rtgui/addsetids.h
Normal file
28
rtgui/addsetids.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef _ADDSETIDS_
|
||||
#define _ADDSETIDS_
|
||||
|
||||
#define ADDSET_TC_EXPCOMP 0
|
||||
#define ADDSET_TC_BRIGHTNESS 1
|
||||
#define ADDSET_TC_BLACKLEVEL 2
|
||||
#define ADDSET_TC_CONTRAST 3
|
||||
#define ADDSET_SH_HIGHLIGHTS 4
|
||||
#define ADDSET_SH_SHADOWS 5
|
||||
#define ADDSET_SH_LOCALCONTRAST 6
|
||||
#define ADDSET_LC_BRIGHTNESS 7
|
||||
#define ADDSET_LC_CONTRAST 8
|
||||
#define ADDSET_SHARP_AMOUNT 9
|
||||
#define ADDSET_LD_EDGETOLERANCE 10
|
||||
#define ADDSET_WB_TEMPERATURE 11
|
||||
#define ADDSET_WB_GREEN 12
|
||||
#define ADDSET_CBOOST_AMOUNT 13
|
||||
#define ADDSET_CS_BLUEYELLOW 14
|
||||
#define ADDSET_CS_GREENMAGENTA 15
|
||||
#define ADDSET_ROTATE_DEGREE 16
|
||||
#define ADDSET_DIST_AMOUNT 17
|
||||
#define ADDSET_CA_BLUE 18
|
||||
#define ADDSET_CA_RED 19
|
||||
#define ADDSET_VIGN_AMOUNT 20
|
||||
|
||||
#define ADDSET_PARAM_NUM 21
|
||||
|
||||
#endif
|
||||
274
rtgui/adjuster.cc
Executable file
274
rtgui/adjuster.cc
Executable file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <adjuster.h>
|
||||
#include <sigc++/class_slot.h>
|
||||
#include <math.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <rtengine.h>
|
||||
|
||||
extern Glib::ustring argv0;
|
||||
|
||||
int Adjuster::delay = 1000;
|
||||
|
||||
Adjuster::Adjuster (Glib::ustring vlabel, double vmin, double vmax, double vstep, double vdefault, bool editedcb) {
|
||||
|
||||
adjusterListener = NULL;
|
||||
afterReset = false;
|
||||
|
||||
set_border_width (2);
|
||||
|
||||
hbox = Gtk::manage (new Gtk::HBox ());
|
||||
|
||||
label = Gtk::manage (new Gtk::Label (vlabel, Gtk::ALIGN_LEFT));
|
||||
|
||||
if (editedcb) {
|
||||
editedCheckBox = new Gtk::CheckButton ();
|
||||
editedChange = editedCheckBox->signal_toggled().connect( sigc::mem_fun(*this, &Adjuster::editedToggled) );
|
||||
hbox->pack_start (*editedCheckBox);
|
||||
}
|
||||
else
|
||||
editedCheckBox = NULL;
|
||||
|
||||
hbox->pack_start (*label);
|
||||
|
||||
reset = Gtk::manage (new Gtk::Button ());
|
||||
reset->add (*Gtk::manage (new Gtk::Image (argv0+"/images/undo.png")));
|
||||
reset->set_relief (Gtk::RELIEF_NONE);
|
||||
reset->set_border_width (0);
|
||||
reset->set_tooltip_text (M("ADJUSTER_RESET_TO_DEFAULT"));
|
||||
|
||||
hbox->pack_end (*reset, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
spin = Gtk::manage (new Gtk::SpinButton ());
|
||||
spin->set_size_request (70, -1);
|
||||
|
||||
hbox->pack_end (*spin, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
reset->set_size_request (-1, spin->get_height());
|
||||
|
||||
slider = Gtk::manage (new Gtk::HScale ());
|
||||
slider->set_draw_value (false);
|
||||
|
||||
pack_start (*hbox, false, false);
|
||||
pack_start (*slider, false, false);
|
||||
|
||||
setLimits (vmin, vmax, vstep, vdefault);
|
||||
|
||||
defaultVal = shapeValue (vdefault);
|
||||
editedState = defEditedState = Irrelevant;
|
||||
|
||||
sliderChange = slider->signal_value_changed().connect( sigc::mem_fun(*this, &Adjuster::sliderChanged) );
|
||||
spinChange = spin->signal_value_changed().connect ( sigc::mem_fun(*this, &Adjuster::spinChanged), true);
|
||||
reset->signal_clicked().connect( sigc::mem_fun(*this, &Adjuster::resetPressed) );
|
||||
slider->set_update_policy (Gtk::UPDATE_CONTINUOUS);
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
Adjuster::~Adjuster () {
|
||||
|
||||
sliderChange.block (true);
|
||||
spinChange.block (true);
|
||||
delayConnection.block (true);
|
||||
adjusterListener = NULL;
|
||||
}
|
||||
|
||||
void Adjuster::setDefault (double def) {
|
||||
|
||||
defaultVal = shapeValue (def);
|
||||
}
|
||||
|
||||
void Adjuster::setDefaultEditedState (EditedState eState) {
|
||||
|
||||
defEditedState = eState;
|
||||
}
|
||||
|
||||
void Adjuster::resetPressed () {
|
||||
|
||||
if (editedState!=Irrelevant) {
|
||||
editedState = defEditedState;
|
||||
if (editedCheckBox) {
|
||||
editedChange.block (true);
|
||||
editedCheckBox->set_active (defEditedState==Edited);
|
||||
editedChange.block (false);
|
||||
}
|
||||
refreshLabelStyle ();
|
||||
}
|
||||
afterReset = true;
|
||||
slider->set_value (defaultVal);
|
||||
}
|
||||
|
||||
double Adjuster::shapeValue (double a) {
|
||||
|
||||
return round(a*pow(double(10), digits)) / pow(double(10), digits);
|
||||
}
|
||||
|
||||
void Adjuster::setLimits (double vmin, double vmax, double vstep, double vdefault) {
|
||||
|
||||
sliderChange.block (true);
|
||||
spinChange.block (true);
|
||||
for (digits=0; fabs(vstep*pow(double(10),digits)-floor(vstep*pow(double(10),digits)))>0.000000000001; digits++);
|
||||
spin->set_digits (digits);
|
||||
spin->set_increments (vstep, 2.0*vstep);
|
||||
spin->set_range (vmin, vmax);
|
||||
spin->set_value (shapeValue(vdefault));
|
||||
slider->set_digits (digits);
|
||||
slider->set_increments (vstep, 2.0*vstep);
|
||||
slider->set_range (vmin, vmax);
|
||||
slider->set_value (shapeValue(vdefault));
|
||||
defaultVal = shapeValue (vdefault);
|
||||
sliderChange.block (false);
|
||||
spinChange.block (false);
|
||||
}
|
||||
|
||||
void Adjuster::setAdjusterListener (AdjusterListener* alistener) {
|
||||
|
||||
adjusterListener = alistener;
|
||||
}
|
||||
|
||||
void Adjuster::spinChanged () {
|
||||
|
||||
sliderChange.block (true);
|
||||
slider->set_value (spin->get_value ());
|
||||
sliderChange.block (false);
|
||||
|
||||
if (delay==0) {
|
||||
if (adjusterListener!=NULL)
|
||||
adjusterListener->adjusterChanged (this, spin->get_value ());
|
||||
}
|
||||
else
|
||||
Glib::signal_idle().connect (sigc::mem_fun(*this, &Adjuster::notifyListener));
|
||||
|
||||
if (editedState==UnEdited) {
|
||||
editedState = Edited;
|
||||
if (editedCheckBox) {
|
||||
editedChange.block (true);
|
||||
editedCheckBox->set_active (true);
|
||||
editedChange.block (false);
|
||||
}
|
||||
refreshLabelStyle ();
|
||||
}
|
||||
afterReset = false;
|
||||
}
|
||||
|
||||
void Adjuster::sliderChanged () {
|
||||
|
||||
if (delayConnection.connected())
|
||||
delayConnection.disconnect ();
|
||||
|
||||
spinChange.block (true);
|
||||
spin->set_value (slider->get_value ());
|
||||
spinChange.block (false);
|
||||
|
||||
if (delay==0) {
|
||||
if (adjusterListener)
|
||||
adjusterListener->adjusterChanged (this, spin->get_value ());
|
||||
}
|
||||
else
|
||||
delayConnection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &Adjuster::notifyListener), delay);
|
||||
|
||||
if (!afterReset && editedState==UnEdited) {
|
||||
editedState = Edited;
|
||||
if (editedCheckBox) {
|
||||
editedChange.block (true);
|
||||
editedCheckBox->set_active (true);
|
||||
editedChange.block (false);
|
||||
}
|
||||
refreshLabelStyle ();
|
||||
}
|
||||
afterReset = false;
|
||||
}
|
||||
|
||||
void Adjuster::setValue (double a) {
|
||||
|
||||
spinChange.block (true);
|
||||
sliderChange.block (true);
|
||||
spin->set_value (shapeValue (a));
|
||||
slider->set_value (shapeValue (a));
|
||||
sliderChange.block (false);
|
||||
spinChange.block (false);
|
||||
afterReset = false;
|
||||
}
|
||||
|
||||
double Adjuster::getValue () {
|
||||
|
||||
return spin->get_value ();
|
||||
}
|
||||
|
||||
bool Adjuster::notifyListener () {
|
||||
|
||||
gdk_threads_enter();
|
||||
|
||||
if (adjusterListener!=NULL)
|
||||
adjusterListener->adjusterChanged (this, spin->get_value ());
|
||||
gdk_threads_leave();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Adjuster::setEnabled (bool enabled) {
|
||||
|
||||
spin->set_sensitive (enabled);
|
||||
slider->set_sensitive (enabled);
|
||||
}
|
||||
void Adjuster::setEditedState (EditedState eState) {
|
||||
|
||||
if (editedState!=eState) {
|
||||
if (editedCheckBox) {
|
||||
editedChange.block (true);
|
||||
editedCheckBox->set_active (eState==Edited);
|
||||
editedChange.block (false);
|
||||
}
|
||||
editedState = eState;
|
||||
refreshLabelStyle ();
|
||||
}
|
||||
}
|
||||
|
||||
EditedState Adjuster::getEditedState () {
|
||||
|
||||
if (editedState!=Irrelevant && editedCheckBox)
|
||||
editedState = editedCheckBox->get_active () ? Edited : UnEdited;
|
||||
return editedState;
|
||||
}
|
||||
|
||||
void Adjuster::showEditedCB () {
|
||||
|
||||
if (!editedCheckBox) {
|
||||
editedCheckBox = new Gtk::CheckButton ();
|
||||
hbox->pack_start (*editedCheckBox, Gtk::PACK_SHRINK, 2);
|
||||
hbox->reorder_child (*editedCheckBox, 0);
|
||||
editedChange = editedCheckBox->signal_toggled().connect( sigc::mem_fun(*this, &Adjuster::editedToggled) );
|
||||
}
|
||||
}
|
||||
|
||||
void Adjuster::refreshLabelStyle () {
|
||||
|
||||
/* Glib::RefPtr<Gtk::Style> style = label->get_style ();
|
||||
Pango::FontDescription fd = style->get_font ();
|
||||
fd.set_weight (editedState==Edited ? Pango::WEIGHT_BOLD : Pango::WEIGHT_NORMAL);
|
||||
style->set_font (fd);
|
||||
label->set_style (style);
|
||||
label->queue_draw ();*/
|
||||
}
|
||||
|
||||
void Adjuster::editedToggled () {
|
||||
|
||||
if (adjusterListener)
|
||||
adjusterListener->adjusterChanged (this, spin->get_value ());
|
||||
}
|
||||
83
rtgui/adjuster.h
Executable file
83
rtgui/adjuster.h
Executable file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _ADJUSTER_H_
|
||||
#define _ADJUSTER_H_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <editedstate.h>
|
||||
|
||||
class Adjuster;
|
||||
class AdjusterListener {
|
||||
|
||||
public:
|
||||
virtual void adjusterChanged (Adjuster* a, double newval) {}
|
||||
};
|
||||
|
||||
|
||||
class Adjuster : public Gtk::VBox {
|
||||
|
||||
protected:
|
||||
Gtk::HBox* hbox;
|
||||
Gtk::Label* label;
|
||||
Gtk::HScale* slider;
|
||||
Gtk::SpinButton* spin;
|
||||
Gtk::Button* reset;
|
||||
AdjusterListener* adjusterListener;
|
||||
sigc::connection delayConnection;
|
||||
sigc::connection spinChange;
|
||||
sigc::connection sliderChange;
|
||||
sigc::connection editedChange;
|
||||
bool listenerReady;
|
||||
double defaultVal;
|
||||
EditedState editedState;
|
||||
EditedState defEditedState;
|
||||
int digits;
|
||||
Gtk::CheckButton* editedCheckBox;
|
||||
bool afterReset;
|
||||
|
||||
double shapeValue (double a);
|
||||
void refreshLabelStyle ();
|
||||
|
||||
public:
|
||||
|
||||
static int delay;
|
||||
|
||||
Adjuster (Glib::ustring label, double vmin, double vmax, double vstep, double vdefault, bool editedCheckBox=false);
|
||||
virtual ~Adjuster ();
|
||||
void setAdjusterListener (AdjusterListener* alistener);
|
||||
|
||||
double getValue ();
|
||||
void setValue (double a);
|
||||
void setLimits (double vmin, double vmax, double vstep, double vdefault);
|
||||
void setEnabled (bool enabled);
|
||||
void setDefault (double def);
|
||||
void setEditedState (EditedState eState);
|
||||
EditedState getEditedState ();
|
||||
void setDefaultEditedState (EditedState eState);
|
||||
void showEditedCB ();
|
||||
|
||||
|
||||
void spinChanged ();
|
||||
void sliderChanged ();
|
||||
bool notifyListener ();
|
||||
void resetPressed ();
|
||||
void editedToggled ();
|
||||
};
|
||||
|
||||
#endif
|
||||
403
rtgui/batchqueue.cc
Executable file
403
rtgui/batchqueue.cc
Executable file
@@ -0,0 +1,403 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <batchqueue.h>
|
||||
#include <glibmm.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <filecatalog.h>
|
||||
#include <batchqueuebuttonset.h>
|
||||
#include <guiutils.h>
|
||||
|
||||
using namespace rtengine;
|
||||
|
||||
BatchQueue::BatchQueue () : processing(NULL), listener(NULL) {
|
||||
|
||||
int p = 0;
|
||||
pmenu = new Gtk::Menu ();
|
||||
pmenu->attach (*(cancel = new Gtk::MenuItem (M("FILEBROWSER_POPUPCANCELJOB"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(head = new Gtk::MenuItem (M("FILEBROWSER_POPUPMOVEHEAD"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(tail = new Gtk::MenuItem (M("FILEBROWSER_POPUPMOVEEND"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(selall = new Gtk::MenuItem (M("FILEBROWSER_POPUPSELECTALL"))), 0, 1, p, p+1); p++;
|
||||
pmenu->show_all ();
|
||||
|
||||
cancel->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::cancelItems), &selected));
|
||||
head->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::headItems), &selected));
|
||||
tail->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &BatchQueue::tailItems), &selected));
|
||||
selall->signal_activate().connect (sigc::mem_fun(*this, &BatchQueue::selectAll));
|
||||
}
|
||||
|
||||
void BatchQueue::rightClicked (ThumbBrowserEntryBase* entry) {
|
||||
|
||||
pmenu->popup (3, 0);
|
||||
}
|
||||
|
||||
void BatchQueue::addEntry (BatchQueueEntry* entry, bool head) {
|
||||
|
||||
entry->setParent (this);
|
||||
entry->resize (options.thumbSize);
|
||||
|
||||
entry->selected = false;
|
||||
if (!head)
|
||||
fd.push_back (entry);
|
||||
else {
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator pos;
|
||||
for (pos=fd.begin(); pos!=fd.end(); pos++)
|
||||
if (!(*pos)->processing) {
|
||||
fd.insert (pos, entry);
|
||||
break;
|
||||
}
|
||||
if (pos==fd.end())
|
||||
fd.push_back (entry);
|
||||
}
|
||||
|
||||
if (entry->thumbnail)
|
||||
entry->thumbnail->imageEnqueued ();
|
||||
|
||||
BatchQueueButtonSet* bqbs = new BatchQueueButtonSet (entry);
|
||||
bqbs->setButtonListener (this);
|
||||
entry->addButtonSet (bqbs);
|
||||
|
||||
arrangeFiles ();
|
||||
queue_draw ();
|
||||
notifyListener ();
|
||||
}
|
||||
|
||||
int deleteitem (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
delete (BatchQueueEntry*)data;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BatchQueue::cancelItems (std::vector<ThumbBrowserEntryBase*>* items) {
|
||||
|
||||
for (int i=0; i<items->size(); i++) {
|
||||
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
|
||||
if (entry->processing)
|
||||
continue;
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry);
|
||||
if (pos!=fd.end()) {
|
||||
fd.erase (pos);
|
||||
rtengine::ProcessingJob::destroy (entry->job);
|
||||
if (entry->thumbnail)
|
||||
entry->thumbnail->imageRemovedFromQueue ();
|
||||
g_idle_add (deleteitem, entry);
|
||||
}
|
||||
}
|
||||
for (int i=0; i<fd.size(); i++)
|
||||
fd[i]->selected = false;
|
||||
lastClicked = NULL;
|
||||
selected.clear ();
|
||||
redraw ();
|
||||
notifyListener ();
|
||||
}
|
||||
|
||||
void BatchQueue::headItems (std::vector<ThumbBrowserEntryBase*>* items) {
|
||||
|
||||
for (int i=items->size()-1; i>=0; i--) {
|
||||
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
|
||||
if (entry->processing)
|
||||
continue;
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry);
|
||||
if (pos!=fd.end() && pos!=fd.begin()) {
|
||||
fd.erase (pos);
|
||||
// find the first item that is not under processing
|
||||
for (pos=fd.begin(); pos!=fd.end(); pos++)
|
||||
if (!(*pos)->processing) {
|
||||
fd.insert (pos, entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
redraw ();
|
||||
}
|
||||
|
||||
void BatchQueue::tailItems (std::vector<ThumbBrowserEntryBase*>* items) {
|
||||
|
||||
for (int i=0; i<items->size(); i++) {
|
||||
BatchQueueEntry* entry = (BatchQueueEntry*)(*items)[i];
|
||||
if (entry->processing)
|
||||
continue;
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (fd.begin(), fd.end(), entry);
|
||||
if (pos!=fd.end()) {
|
||||
fd.erase (pos);
|
||||
fd.push_back (entry);
|
||||
}
|
||||
}
|
||||
redraw ();
|
||||
}
|
||||
|
||||
void BatchQueue::selectAll () {
|
||||
|
||||
lastClicked = NULL;
|
||||
selected.clear ();
|
||||
for (int i=0; i<fd.size(); i++) {
|
||||
if (fd[i]->processing)
|
||||
continue;
|
||||
fd[i]->selected = true;
|
||||
selected.push_back (fd[i]);
|
||||
}
|
||||
queue_draw ();
|
||||
}
|
||||
void BatchQueue::startProcessing () {
|
||||
|
||||
if (!processing && fd.size()>0) {
|
||||
BatchQueueEntry* next = (BatchQueueEntry*)fd[0];
|
||||
// tag it as processing
|
||||
next->processing = true;
|
||||
processing = next;
|
||||
// remove from selection
|
||||
if (processing->selected) {
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (selected.begin(), selected.end(), processing);
|
||||
if (pos!=selected.end())
|
||||
selected.erase (pos);
|
||||
processing->selected = false;
|
||||
}
|
||||
// remove button set
|
||||
next->removeButtonSet ();
|
||||
// start batch processing
|
||||
rtengine::startBatchProcessing (next->job, this);
|
||||
queue_draw ();
|
||||
}
|
||||
}
|
||||
|
||||
rtengine::ProcessingJob* BatchQueue::imageReady (rtengine::IImage16* img) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
// save image img
|
||||
Glib::ustring fname;
|
||||
SaveFormat saveFormat;
|
||||
if (processing->outFileName=="") { // auto file name
|
||||
fname = obtainFileName (processing->filename);
|
||||
saveFormat = options.saveFormat;
|
||||
}
|
||||
else { // use the save-as filename with automatic completion for uniqueness
|
||||
fname = autoCompleteFileName (removeExtension(processing->outFileName), getExtension(processing->outFileName));
|
||||
saveFormat = processing->saveFormat;
|
||||
}
|
||||
printf ("fname=%s, %s\n", fname.c_str(), removeExtension(fname).c_str());
|
||||
if (img && fname!="") {
|
||||
int err = 0;
|
||||
if (saveFormat.format=="tif")
|
||||
err = img->saveAsTIFF (fname, saveFormat.tiffBits);
|
||||
else if (saveFormat.format=="png")
|
||||
err = img->saveAsPNG (fname, saveFormat.pngCompression, saveFormat.pngBits);
|
||||
else if (saveFormat.format=="jpg")
|
||||
err = img->saveAsJPEG (fname, saveFormat.jpegQuality);
|
||||
img->free ();
|
||||
if (!err && saveFormat.saveParams)
|
||||
processing->params.save (removeExtension(fname) + ".pp2");
|
||||
if (processing->thumbnail) {
|
||||
processing->thumbnail->imageDeveloped ();
|
||||
processing->thumbnail->imageRemovedFromQueue ();
|
||||
if (listener)
|
||||
listener->imageProcessingReady (processing->filename);
|
||||
}
|
||||
}
|
||||
|
||||
// delete from the queue
|
||||
delete processing;
|
||||
processing = NULL;
|
||||
fd.erase (fd.begin());
|
||||
// return next job
|
||||
if (fd.size()==0) {
|
||||
if (listener)
|
||||
listener->queueEmpty ();
|
||||
}
|
||||
else if (listener && listener->canStartNext ()) {
|
||||
BatchQueueEntry* next = (BatchQueueEntry*)fd[0];
|
||||
// tag it as selected
|
||||
next->processing = true;
|
||||
processing = next;
|
||||
// remove from selection
|
||||
if (processing->selected) {
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator pos = std::find (selected.begin(), selected.end(), processing);
|
||||
if (pos!=selected.end())
|
||||
selected.erase (pos);
|
||||
processing->selected = false;
|
||||
}
|
||||
// remove button set
|
||||
next->removeButtonSet ();
|
||||
}
|
||||
redraw ();
|
||||
notifyListener ();
|
||||
gdk_threads_leave ();
|
||||
return processing ? processing->job : NULL;
|
||||
}
|
||||
|
||||
Glib::ustring BatchQueue::obtainFileName (const Glib::ustring& origFileName) {
|
||||
|
||||
std::vector<Glib::ustring> pa;
|
||||
std::vector<Glib::ustring> da;
|
||||
|
||||
for (int i=0; i<origFileName.size(); i++) {
|
||||
while ((i<origFileName.size()) && (origFileName[i]=='\\' || origFileName[i]=='/'))
|
||||
i++;
|
||||
if (i>=origFileName.size())
|
||||
break;
|
||||
Glib::ustring tok = "";
|
||||
while ((i<origFileName.size()) && !(origFileName[i]=='\\' || origFileName[i]=='/'))
|
||||
tok = tok + origFileName[i++];
|
||||
da.push_back (tok);
|
||||
}
|
||||
|
||||
if (origFileName[0]=='/' || origFileName[0]=='\\')
|
||||
pa.push_back ("/" + da[0]);
|
||||
else
|
||||
pa.push_back (da[0]);
|
||||
|
||||
for (int i=1; i<da.size(); i++)
|
||||
pa.push_back (pa[i-1] + "/" + da[i]);
|
||||
|
||||
// for (int i=0; i<da.size(); i++)
|
||||
// printf ("da: %s\n", da[i].c_str());
|
||||
// for (int i=0; i<pa.size(); i++)
|
||||
// printf ("pa: %s\n", pa[i].c_str());
|
||||
|
||||
// extracting filebase
|
||||
Glib::ustring filename;
|
||||
|
||||
int extpos = origFileName.size()-1;
|
||||
for (; extpos>=0 && origFileName[extpos]!='.'; extpos--);
|
||||
for (int k=extpos-1; k>=0 && origFileName[k]!='/' && origFileName[k]!='\\'; k--)
|
||||
filename = origFileName[k] + filename;
|
||||
|
||||
// printf ("%d, |%s|\n", extpos, filename.c_str());
|
||||
|
||||
// constructing full output path
|
||||
// printf ("path=|%s|\n", options.savePath.c_str());
|
||||
|
||||
Glib::ustring path="";
|
||||
if (options.saveUsePathTemplate) {
|
||||
int ix=0;
|
||||
while (options.savePathTemplate[ix]!=0) {
|
||||
if (options.savePathTemplate[ix]=='%') {
|
||||
ix++;
|
||||
if (options.savePathTemplate[ix]=='p') {
|
||||
ix++;
|
||||
int i = options.savePathTemplate[ix]-'0';
|
||||
if (i<pa.size())
|
||||
path = path + pa[pa.size()-i-1] + '/';
|
||||
ix++;
|
||||
}
|
||||
else if (options.savePathTemplate[ix]=='d') {
|
||||
ix++;
|
||||
int i = options.savePathTemplate[ix]-'0';
|
||||
if (i<da.size())
|
||||
path = path + da[da.size()-i-1] + '/';
|
||||
ix++;
|
||||
}
|
||||
else if (options.savePathTemplate[ix]=='f') {
|
||||
path = path + filename;
|
||||
}
|
||||
}
|
||||
else
|
||||
path = path + options.savePathTemplate[ix];
|
||||
ix++;
|
||||
}
|
||||
}
|
||||
else
|
||||
path = Glib::build_filename (options.savePathFolder, filename);
|
||||
|
||||
return autoCompleteFileName (path, options.saveFormat.format);
|
||||
}
|
||||
|
||||
Glib::ustring BatchQueue::autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format) {
|
||||
|
||||
// separate filename and the path to the destination directory
|
||||
Glib::ustring dstdir = Glib::path_get_dirname (fileName);
|
||||
Glib::ustring dstfname = Glib::path_get_basename (fileName);
|
||||
|
||||
// create directory, if does not exist
|
||||
if (g_mkdir_with_parents (dstdir.c_str(), 0755) )
|
||||
return "";
|
||||
|
||||
for (int tries=0; tries<100; tries++) {
|
||||
Glib::ustring fname;
|
||||
if (tries==0)
|
||||
fname = Glib::ustring::compose ("%1.%2", Glib::build_filename (dstdir, dstfname), format);
|
||||
else
|
||||
fname = Glib::ustring::compose ("%1-%2.%3", Glib::build_filename (dstdir, dstfname), tries, format);
|
||||
|
||||
if (!Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
|
||||
return fname;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int bqredraw (void* p) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
((BatchQueue*)p)->redraw();
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BatchQueue::setProgress (double p) {
|
||||
|
||||
if (processing)
|
||||
processing->progress = p;
|
||||
|
||||
g_idle_add (bqredraw, this);
|
||||
}
|
||||
|
||||
void BatchQueue::buttonPressed (LWButton* button, int actionCode, void* actionData) {
|
||||
|
||||
std::vector<ThumbBrowserEntryBase*> bqe;
|
||||
bqe.push_back ((BatchQueueEntry*)actionData);
|
||||
|
||||
if (actionCode==10) // cancel
|
||||
cancelItems (&bqe);
|
||||
else if (actionCode==8) // to head
|
||||
headItems (&bqe);
|
||||
else if (actionCode==9) // to tail
|
||||
tailItems (&bqe);
|
||||
}
|
||||
|
||||
struct NLParams {
|
||||
BatchQueueListener* listener;
|
||||
int qsize;
|
||||
};
|
||||
|
||||
int bqnotifylistener (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
NLParams* params = (NLParams*)data;
|
||||
params->listener->queueSizeChanged (params->qsize);
|
||||
delete params;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BatchQueue::notifyListener () {
|
||||
|
||||
if (listener) {
|
||||
NLParams* params = new NLParams;
|
||||
params->listener = listener;
|
||||
params->qsize = fd.size();
|
||||
g_idle_add (bqnotifylistener, params);
|
||||
}
|
||||
}
|
||||
|
||||
void BatchQueue::redrawNeeded (LWButton* button) {
|
||||
|
||||
queue_draw ();
|
||||
}
|
||||
84
rtgui/batchqueue.h
Executable file
84
rtgui/batchqueue.h
Executable file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _BATCHQUEUE_
|
||||
#define _BATCHQUEUE_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <batchqueueentry.h>
|
||||
#include <rtengine.h>
|
||||
#include <options.h>
|
||||
#include <lwbuttonset.h>
|
||||
#include <thumbbrowserbase.h>
|
||||
|
||||
class BatchQueueListener {
|
||||
|
||||
public:
|
||||
virtual void queueSizeChanged (int qsize) =0;
|
||||
virtual void imageProcessingReady (Glib::ustring fname) =0;
|
||||
virtual void queueEmpty () =0;
|
||||
virtual bool canStartNext () =0;
|
||||
};
|
||||
|
||||
class FileCatalog;
|
||||
class BatchQueue : public ThumbBrowserBase,
|
||||
public rtengine::BatchProcessingListener,
|
||||
public LWButtonListener {
|
||||
|
||||
protected:
|
||||
|
||||
BatchQueueEntry* processing;
|
||||
|
||||
Glib::ustring nameTemplate;
|
||||
|
||||
Gtk::MenuItem* cancel;
|
||||
Gtk::MenuItem* head;
|
||||
Gtk::MenuItem* tail;
|
||||
Gtk::MenuItem* selall;
|
||||
Gtk::Menu* pmenu;
|
||||
|
||||
BatchQueueListener* listener;
|
||||
|
||||
Glib::ustring obtainFileName (const Glib::ustring& origFileName);
|
||||
Glib::ustring autoCompleteFileName (const Glib::ustring& fileName, const Glib::ustring& format);
|
||||
|
||||
public:
|
||||
BatchQueue ();
|
||||
|
||||
void addEntry (BatchQueueEntry* entry, bool head=false);
|
||||
|
||||
void cancelItems (std::vector<ThumbBrowserEntryBase*>* items);
|
||||
void headItems (std::vector<ThumbBrowserEntryBase*>* items);
|
||||
void tailItems (std::vector<ThumbBrowserEntryBase*>* items);
|
||||
void selectAll ();
|
||||
|
||||
void startProcessing ();
|
||||
|
||||
bool hasJobs () { return fd.size()>0; }
|
||||
|
||||
rtengine::ProcessingJob* imageReady (rtengine::IImage16* img);
|
||||
void setProgress (double p);
|
||||
void rightClicked (ThumbBrowserEntryBase* entry);
|
||||
void buttonPressed (LWButton* button, int actionCode, void* actionData);
|
||||
void redrawNeeded (LWButton* button);
|
||||
|
||||
void setBatchQueueListener (BatchQueueListener* l) { listener = l; }
|
||||
void notifyListener ();
|
||||
};
|
||||
|
||||
#endif
|
||||
42
rtgui/batchqueuebuttonset.cc
Executable file
42
rtgui/batchqueuebuttonset.cc
Executable file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <batchqueuebuttonset.h>
|
||||
#include <multilangmgr.h>
|
||||
|
||||
extern Glib::ustring argv0;
|
||||
|
||||
bool BatchQueueButtonSet::iconsLoaded = false;
|
||||
|
||||
Cairo::RefPtr<Cairo::ImageSurface> BatchQueueButtonSet::cancelIcon;
|
||||
Cairo::RefPtr<Cairo::ImageSurface> BatchQueueButtonSet::headIcon;
|
||||
Cairo::RefPtr<Cairo::ImageSurface> BatchQueueButtonSet::tailIcon;
|
||||
|
||||
BatchQueueButtonSet::BatchQueueButtonSet (BatchQueueEntry* myEntry) {
|
||||
|
||||
if (!iconsLoaded) {
|
||||
cancelIcon = Cairo::ImageSurface::create_from_png (argv0+"/images/deltags.png");
|
||||
headIcon = Cairo::ImageSurface::create_from_png (argv0+"/images/head.png");
|
||||
tailIcon = Cairo::ImageSurface::create_from_png (argv0+"/images/tail.png");
|
||||
iconsLoaded = true;
|
||||
}
|
||||
|
||||
add (new LWButton (headIcon, 8, myEntry, LWButton::Left, LWButton::Center, M("FILEBROWSER_POPUPMOVEHEAD")));
|
||||
add (new LWButton (tailIcon, 9, myEntry, LWButton::Left, LWButton::Center, M("FILEBROWSER_POPUPMOVEEND")));
|
||||
add (new LWButton (cancelIcon, 10, myEntry, LWButton::Right, LWButton::Center, M("FILEBROWSER_POPUPCANCELJOB")));
|
||||
}
|
||||
38
rtgui/batchqueuebuttonset.h
Executable file
38
rtgui/batchqueuebuttonset.h
Executable file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _BATCHQUEUEBUTTONSET_
|
||||
#define _BATCHQUEUEBUTTONSET_
|
||||
|
||||
#include <lwbuttonset.h>
|
||||
#include <gtkmm.h>
|
||||
|
||||
class BatchQueueEntry;
|
||||
class BatchQueueButtonSet : public LWButtonSet {
|
||||
|
||||
static bool iconsLoaded;
|
||||
|
||||
public:
|
||||
static Cairo::RefPtr<Cairo::ImageSurface> cancelIcon;
|
||||
static Cairo::RefPtr<Cairo::ImageSurface> headIcon;
|
||||
static Cairo::RefPtr<Cairo::ImageSurface> tailIcon;
|
||||
|
||||
BatchQueueButtonSet (BatchQueueEntry* myEntry);
|
||||
};
|
||||
|
||||
#endif
|
||||
156
rtgui/batchqueueentry.cc
Executable file
156
rtgui/batchqueueentry.cc
Executable file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <batchqueueentry.h>
|
||||
#include <thumbbrowserbase.h>
|
||||
|
||||
BatchQueueEntry::BatchQueueEntry (rtengine::ProcessingJob* pjob, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, guint8* previmg, int prevw, int prevh, Thumbnail* thumbnail)
|
||||
: job(pjob), ThumbBrowserEntryBase(fname),
|
||||
opreview(previmg), origpw(prevw), origph(prevh), progress(0), thumbnail(thumbnail),
|
||||
outFileName("") {
|
||||
|
||||
params = pparams;
|
||||
|
||||
bqih = new BatchQueueEntryIdleHelper;
|
||||
bqih->bqentry = this;
|
||||
bqih->destroyed = false;
|
||||
bqih->pending = 0;
|
||||
|
||||
if (thumbnail)
|
||||
thumbnail->increaseRef ();
|
||||
}
|
||||
|
||||
BatchQueueEntry::~BatchQueueEntry () {
|
||||
|
||||
batchQueueEntryUpdater.removeJobs (this);
|
||||
delete [] opreview;
|
||||
if (thumbnail)
|
||||
thumbnail->decreaseRef ();
|
||||
|
||||
if (bqih->pending)
|
||||
bqih->destroyed = true;
|
||||
else
|
||||
delete bqih;
|
||||
}
|
||||
|
||||
void BatchQueueEntry::refreshThumbnailImage () {
|
||||
|
||||
if (!opreview)
|
||||
return;
|
||||
|
||||
batchQueueEntryUpdater.add (opreview, origpw, origph, preh, this);
|
||||
batchQueueEntryUpdater.process ();
|
||||
}
|
||||
|
||||
void BatchQueueEntry::calcThumbnailSize () {
|
||||
|
||||
prew = preh * origpw / origph;
|
||||
}
|
||||
|
||||
|
||||
void BatchQueueEntry::drawProgressBar (Glib::RefPtr<Gdk::Window> win, Glib::RefPtr<Gdk::GC> gc, const Gdk::Color& foregr, const Gdk::Color& backgr, int x, int w, int y, int h) {
|
||||
|
||||
if (processing) {
|
||||
Cairo::RefPtr<Cairo::Context> cr = win->create_cairo_context();
|
||||
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||
double px = x + w/6.0;
|
||||
double pw = w*2.0/3.0;
|
||||
double py = y + h/4.0;
|
||||
double ph = h/2.0;
|
||||
cr->move_to (px, py);
|
||||
cr->line_to (px+pw, py);
|
||||
cr->set_line_width (ph);
|
||||
cr->set_line_cap (Cairo::LINE_CAP_ROUND);
|
||||
cr->set_source_rgb (foregr.get_red_p(), foregr.get_green_p(), foregr.get_blue_p());
|
||||
cr->stroke ();
|
||||
|
||||
cr->move_to (px, py);
|
||||
cr->line_to (px+pw, py);
|
||||
cr->set_line_width (ph*3.0/4.0);
|
||||
cr->set_source_rgb (backgr.get_red_p(), backgr.get_green_p(), backgr.get_blue_p());
|
||||
cr->stroke ();
|
||||
|
||||
cr->move_to (px, py);
|
||||
cr->line_to (px+pw*progress, py);
|
||||
cr->set_line_width (ph/2.0);
|
||||
cr->set_source_rgb (foregr.get_red_p(), foregr.get_green_p(), foregr.get_blue_p());
|
||||
cr->stroke ();
|
||||
}
|
||||
}
|
||||
|
||||
void BatchQueueEntry::removeButtonSet () {
|
||||
|
||||
delete buttonSet;
|
||||
buttonSet = NULL;
|
||||
}
|
||||
struct bqupdate {
|
||||
BatchQueueEntryIdleHelper* bqih;
|
||||
guint8* img;
|
||||
int w,h;
|
||||
};
|
||||
|
||||
int bqeupdate (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
bqupdate* params = (bqupdate*)data;
|
||||
|
||||
BatchQueueEntryIdleHelper* bqih = params->bqih;
|
||||
|
||||
if (bqih->destroyed) {
|
||||
if (bqih->pending == 1)
|
||||
delete bqih;
|
||||
else
|
||||
bqih->pending--;
|
||||
delete [] params->img;
|
||||
delete params;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bqih->bqentry->_updateImage (params->img, params->w, params->h);
|
||||
bqih->pending--;
|
||||
|
||||
gdk_threads_leave ();
|
||||
delete params;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BatchQueueEntry::updateImage (guint8* img, int w, int h) {
|
||||
|
||||
bqih->pending++;
|
||||
|
||||
bqupdate* param = new bqupdate ();
|
||||
param->bqih = bqih;
|
||||
param->img = img;
|
||||
param->w = w;
|
||||
param->h = h;
|
||||
g_idle_add (bqeupdate, param);
|
||||
}
|
||||
|
||||
void BatchQueueEntry::_updateImage (guint8* img, int w, int h) {
|
||||
|
||||
if (preh == h) {
|
||||
prew = w;
|
||||
preview = new guint8 [prew*preh*3];
|
||||
memcpy (preview, img, prew*preh*3);
|
||||
if (parent)
|
||||
parent->redrawNeeded (this);
|
||||
}
|
||||
delete [] img;
|
||||
}
|
||||
|
||||
66
rtgui/batchqueueentry.h
Executable file
66
rtgui/batchqueueentry.h
Executable file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _BATCHQUEUEENTRY_
|
||||
#define _BATCHQUEUEENTRY_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <rtengine.h>
|
||||
#include <thumbbrowserentrybase.h>
|
||||
#include <thumbnail.h>
|
||||
#include <bqentryupdater.h>
|
||||
|
||||
class BatchQueueEntry;
|
||||
struct BatchQueueEntryIdleHelper {
|
||||
BatchQueueEntry* bqentry;
|
||||
bool destroyed;
|
||||
int pending;
|
||||
};
|
||||
|
||||
class BatchQueueEntry : public ThumbBrowserEntryBase, public BQEntryUpdateListener {
|
||||
|
||||
guint8* opreview;
|
||||
int origpw, origph;
|
||||
BatchQueueEntryIdleHelper* bqih;
|
||||
|
||||
public:
|
||||
Thumbnail* thumbnail;
|
||||
rtengine::ProcessingJob* job;
|
||||
rtengine::procparams::ProcParams params;
|
||||
double progress;
|
||||
Glib::ustring outFileName;
|
||||
SaveFormat saveFormat;
|
||||
|
||||
BatchQueueEntry (rtengine::ProcessingJob* job, const rtengine::procparams::ProcParams& pparams, Glib::ustring fname, guint8* previmg, int prevw, int prevh, Thumbnail* thumbnail=NULL);
|
||||
~BatchQueueEntry ();
|
||||
|
||||
void refreshThumbnailImage ();
|
||||
void calcThumbnailSize ();
|
||||
|
||||
void drawProgressBar (Glib::RefPtr<Gdk::Window> win, Glib::RefPtr<Gdk::GC> gc, const Gdk::Color& foregr, const Gdk::Color& backgr, int x, int w, int y, int h);
|
||||
|
||||
void removeButtonSet ();
|
||||
|
||||
// bqentryupdatelistener interface
|
||||
void updateImage (guint8* img, int w, int h);
|
||||
void _updateImage (guint8* img, int w, int h); // inside gtk thread
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
241
rtgui/batchqueuepanel.cc
Executable file
241
rtgui/batchqueuepanel.cc
Executable file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <batchqueuepanel.h>
|
||||
#include <options.h>
|
||||
#include <preferences.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <rtwindow.h>
|
||||
|
||||
BatchQueuePanel::BatchQueuePanel () {
|
||||
|
||||
batchQueue = new BatchQueue();
|
||||
|
||||
// construct batch queue panel with the extra "start" and "stop" button
|
||||
Gtk::VBox* batchQueueButtonBox = Gtk::manage (new Gtk::VBox);
|
||||
start = Gtk::manage (new Gtk::ToggleButton (M("FILEBROWSER_STARTPROCESSING")));
|
||||
stop = Gtk::manage (new Gtk::ToggleButton (M("FILEBROWSER_STOPPROCESSING")));
|
||||
autoStart = Gtk::manage (new Gtk::CheckButton ("Auto start"));
|
||||
start->set_tooltip_text (M("FILEBROWSER_STARTPROCESSINGHINT"));
|
||||
stop->set_tooltip_text (M("FILEBROWSER_STOPPROCESSINGHINT"));
|
||||
autoStart->set_tooltip_text ("Start processing automatically when a new job arrives");
|
||||
start->set_active (false);
|
||||
stop->set_active (true);
|
||||
autoStart->set_active (options.procQueueEnabled);
|
||||
|
||||
start->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-media-play"), Gtk::ICON_SIZE_BUTTON)));
|
||||
startConnection = start->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::startBatchProc));
|
||||
stop->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-media-stop"), Gtk::ICON_SIZE_BUTTON)));
|
||||
stopConnection = stop->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::stopBatchProc));
|
||||
batchQueueButtonBox->pack_start (*start, Gtk::PACK_SHRINK, 4);
|
||||
batchQueueButtonBox->pack_start (*stop, Gtk::PACK_SHRINK, 4);
|
||||
batchQueueButtonBox->pack_start (*autoStart, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
// Output directory selection
|
||||
fdir = Gtk::manage (new Gtk::Frame (M("PREFERENCES_OUTDIR")));
|
||||
Gtk::VBox* odvb = Gtk::manage (new Gtk::VBox ());
|
||||
odvb->set_border_width (4);
|
||||
Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ());
|
||||
useTemplate = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRTEMPLATE")+":"));
|
||||
hb2->pack_start (*useTemplate, Gtk::PACK_SHRINK,4);
|
||||
outdirTemplate = Gtk::manage (new Gtk::Entry ());
|
||||
hb2->pack_start (*outdirTemplate);
|
||||
odvb->pack_start (*hb2, Gtk::PACK_SHRINK, 4);
|
||||
outdirTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT"));
|
||||
useTemplate->set_tooltip_markup (M("PREFERENCES_OUTDIRTEMPLATEHINT"));
|
||||
Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ());
|
||||
useFolder = Gtk::manage (new Gtk::RadioButton (M("PREFERENCES_OUTDIRFOLDER")+":"));
|
||||
hb3->pack_start (*useFolder, Gtk::PACK_SHRINK,4);
|
||||
outdirFolder = Gtk::manage (new Gtk::FileChooserButton (M("PREFERENCES_OUTDIRFOLDER"), Gtk::FILE_CHOOSER_ACTION_SELECT_FOLDER));
|
||||
hb3->pack_start (*outdirFolder);
|
||||
odvb->pack_start (*hb3, Gtk::PACK_SHRINK, 4);
|
||||
outdirFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT"));
|
||||
useFolder->set_tooltip_markup (M("PREFERENCES_OUTDIRFOLDERHINT"));
|
||||
Gtk::RadioButton::Group g = useTemplate->get_group();
|
||||
useFolder->set_group (g);
|
||||
fdir->add (*odvb);
|
||||
|
||||
// Output file format selection
|
||||
fformat = Gtk::manage (new Gtk::Frame (M("PREFERENCES_FILEFORMAT")));
|
||||
saveFormatPanel = Gtk::manage (new SaveFormatPanel ());
|
||||
fformat->add (*saveFormatPanel);
|
||||
|
||||
saveFormatPanel->init (options.saveFormat);
|
||||
outdirTemplate->set_text (options.savePathTemplate);
|
||||
if (Glib::file_test (options.savePathFolder, Glib::FILE_TEST_IS_DIR))
|
||||
outdirFolder->set_filename (options.savePathFolder);
|
||||
useTemplate->set_active (options.saveUsePathTemplate);
|
||||
useFolder->set_active (!options.saveUsePathTemplate);
|
||||
|
||||
// setup signal handlers
|
||||
outdirTemplate->signal_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions));
|
||||
outdirFolder->signal_current_folder_changed().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions));
|
||||
useTemplate->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions));
|
||||
useFolder->signal_toggled().connect (sigc::mem_fun(*this, &BatchQueuePanel::saveOptions));
|
||||
saveFormatPanel->setListener (this);
|
||||
|
||||
// setup button bar
|
||||
topBox = Gtk::manage (new Gtk::HBox ());
|
||||
pack_start (*topBox, Gtk::PACK_SHRINK);
|
||||
|
||||
topBox->pack_start (*batchQueueButtonBox, Gtk::PACK_SHRINK, 4);
|
||||
topBox->pack_start (*fdir);
|
||||
topBox->pack_start (*fformat, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
// add middle browser area
|
||||
Gtk::HBox* hBox = Gtk::manage (new Gtk::HBox ());
|
||||
pack_start (*batchQueue);
|
||||
|
||||
// lower box with thumbnail zoom
|
||||
bottomBox = Gtk::manage (new Gtk::HBox ());
|
||||
pack_start (*bottomBox, Gtk::PACK_SHRINK);
|
||||
|
||||
// change thumbnail arrangement button
|
||||
hAlignIcon = new Gtk::Image (argv0+"/images/horizontals.png");
|
||||
vAlignIcon = new Gtk::Image (argv0+"/images/verticals.png");
|
||||
hAlignIcon->show ();
|
||||
vAlignIcon->show ();
|
||||
chAlign = Gtk::manage (new Gtk::Button ());
|
||||
chAlign->show ();
|
||||
bottomBox->pack_end (*chAlign, Gtk::PACK_SHRINK);
|
||||
chAlign->set_image (*hAlignIcon);
|
||||
chAlign->set_relief (Gtk::RELIEF_NONE);
|
||||
chAlign->signal_pressed().connect (sigc::mem_fun(*this, &BatchQueuePanel::arrangementButtonPressed));
|
||||
chAlign->set_tooltip_text (M("FILEBROWSER_ARRANGEMENTHINT"));
|
||||
bottomBox->pack_end (*Gtk::manage (new Gtk::VSeparator), Gtk::PACK_SHRINK, 4);
|
||||
if (options.fbArrangement==1)
|
||||
chAlign->set_image (*vAlignIcon);
|
||||
else
|
||||
chAlign->set_image (*hAlignIcon);
|
||||
arrangementButtonPressed ();
|
||||
|
||||
// thumbnail zoom
|
||||
Gtk::HBox* zoomBox = Gtk::manage (new Gtk::HBox ());
|
||||
zoomBox->pack_start (*Gtk::manage (new Gtk::VSeparator), Gtk::PACK_SHRINK, 4);
|
||||
Gtk::Label* zoomLabel = Gtk::manage (new Gtk::Label (Glib::ustring("<b>")+M("FILEBROWSER_THUMBSIZE")+":</b>"));
|
||||
zoomLabel->set_use_markup (true);
|
||||
zoomBox->pack_start (*zoomLabel, Gtk::PACK_SHRINK, 4);
|
||||
zoomInButton = Gtk::manage (new Gtk::Button ());
|
||||
zoomInButton->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-zoom-in"), Gtk::ICON_SIZE_SMALL_TOOLBAR)));
|
||||
zoomInButton->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomIn));
|
||||
zoomInButton->set_relief (Gtk::RELIEF_NONE);
|
||||
zoomInButton->set_tooltip_text (M("FILEBROWSER_ZOOMINHINT"));
|
||||
zoomBox->pack_end (*zoomInButton, Gtk::PACK_SHRINK);
|
||||
zoomOutButton = Gtk::manage (new Gtk::Button ());
|
||||
zoomOutButton->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-zoom-out"), Gtk::ICON_SIZE_SMALL_TOOLBAR)));
|
||||
zoomOutButton->signal_pressed().connect (sigc::mem_fun(*batchQueue, &BatchQueue::zoomOut));
|
||||
zoomOutButton->set_relief (Gtk::RELIEF_NONE);
|
||||
zoomOutButton->set_tooltip_text (M("FILEBROWSER_ZOOMOUTHINT"));
|
||||
zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK);
|
||||
bottomBox->pack_end (*zoomBox, Gtk::PACK_SHRINK);
|
||||
|
||||
|
||||
batchQueue->setBatchQueueListener (this);
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
void BatchQueuePanel::arrangementButtonPressed () {
|
||||
|
||||
if (chAlign->get_image()==hAlignIcon) {
|
||||
chAlign->set_image (*vAlignIcon);
|
||||
batchQueue->setArrangement (BatchQueue::TB_Vertical);
|
||||
}
|
||||
else {
|
||||
chAlign->set_image (*hAlignIcon);
|
||||
batchQueue->setArrangement (BatchQueue::TB_Horizontal);
|
||||
}
|
||||
}
|
||||
|
||||
void BatchQueuePanel::queueSizeChanged (int qsize) {
|
||||
|
||||
// TODO: write it somewhere
|
||||
}
|
||||
|
||||
void BatchQueuePanel::imageProcessingReady (Glib::ustring fname) {
|
||||
|
||||
parent->imageDeveloped (fname);
|
||||
}
|
||||
|
||||
void BatchQueuePanel::startBatchProc () {
|
||||
|
||||
stopConnection.block (true);
|
||||
startConnection.block (true);
|
||||
stop->set_active (false);
|
||||
start->set_active (true);
|
||||
stopConnection.block (false);
|
||||
startConnection.block (false);
|
||||
|
||||
if (batchQueue->hasJobs()) {
|
||||
fdir->set_sensitive (false);
|
||||
fformat->set_sensitive (false);
|
||||
batchQueue->startProcessing ();
|
||||
}
|
||||
else
|
||||
stopBatchProc ();
|
||||
}
|
||||
|
||||
void BatchQueuePanel::stopBatchProc () {
|
||||
|
||||
stopConnection.block (true);
|
||||
startConnection.block (true);
|
||||
stop->set_active (true);
|
||||
start->set_active (false);
|
||||
stopConnection.block (false);
|
||||
startConnection.block (false);
|
||||
}
|
||||
|
||||
void BatchQueuePanel::addBatchQueueJob (BatchQueueEntry* bqe, bool head) {
|
||||
|
||||
batchQueue->addEntry (bqe, head);
|
||||
|
||||
if (stop->get_active () && autoStart->get_active ())
|
||||
startBatchProc ();
|
||||
}
|
||||
|
||||
void BatchQueuePanel::queueEmpty () {
|
||||
|
||||
stopBatchProc ();
|
||||
fdir->set_sensitive (true);
|
||||
fformat->set_sensitive (true);
|
||||
}
|
||||
|
||||
bool BatchQueuePanel::canStartNext () {
|
||||
|
||||
if (start->get_active ())
|
||||
return true;
|
||||
else {
|
||||
fdir->set_sensitive (true);
|
||||
fformat->set_sensitive (true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void BatchQueuePanel::saveOptions () {
|
||||
|
||||
options.saveFormat = saveFormatPanel->getFormat ();
|
||||
options.savePathTemplate = outdirTemplate->get_text();
|
||||
options.savePathFolder = outdirFolder->get_filename();
|
||||
options.saveUsePathTemplate = useTemplate->get_active();
|
||||
options.procQueueEnabled = autoStart->get_active ();
|
||||
}
|
||||
|
||||
void BatchQueuePanel::formatChanged () {
|
||||
|
||||
saveOptions ();
|
||||
}
|
||||
78
rtgui/batchqueuepanel.h
Executable file
78
rtgui/batchqueuepanel.h
Executable file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _BATCHQUEUEPANEL_
|
||||
#define _BATCHQUEUEPANEL_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <batchqueue.h>
|
||||
#include <saveformatpanel.h>
|
||||
|
||||
class RTWindow;
|
||||
class BatchQueuePanel : public Gtk::VBox,
|
||||
public BatchQueueListener,
|
||||
public FormatChangeListener {
|
||||
|
||||
Gtk::Button* zoomInButton;
|
||||
Gtk::Button* zoomOutButton;
|
||||
Gtk::ToggleButton* start;
|
||||
Gtk::ToggleButton* stop;
|
||||
Gtk::CheckButton* autoStart;
|
||||
sigc::connection startConnection;
|
||||
sigc::connection stopConnection;
|
||||
|
||||
Gtk::Entry* outdirTemplate;
|
||||
Gtk::FileChooserButton* outdirFolder;
|
||||
Gtk::RadioButton* useTemplate;
|
||||
Gtk::RadioButton* useFolder;
|
||||
SaveFormatPanel* saveFormatPanel;
|
||||
Gtk::Frame *fdir, *fformat;
|
||||
|
||||
Gtk::Image* hAlignIcon;
|
||||
Gtk::Image* vAlignIcon;
|
||||
Gtk::Button* chAlign;
|
||||
|
||||
RTWindow* parent;
|
||||
BatchQueue* batchQueue;
|
||||
Gtk::HBox* bottomBox;
|
||||
Gtk::HBox* topBox;
|
||||
|
||||
public:
|
||||
|
||||
BatchQueuePanel ();
|
||||
|
||||
void setParent (RTWindow* p) { parent = p; }
|
||||
void arrangementButtonPressed ();
|
||||
|
||||
void addBatchQueueJob (BatchQueueEntry* bqe, bool head=false);
|
||||
|
||||
// batchqueuelistener interface
|
||||
void queueSizeChanged (int qsize);
|
||||
void imageProcessingReady (Glib::ustring fname);
|
||||
void queueEmpty ();
|
||||
bool canStartNext ();
|
||||
|
||||
void startBatchProc ();
|
||||
void stopBatchProc ();
|
||||
|
||||
void saveOptions ();
|
||||
void formatChanged ();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
299
rtgui/batchtoolpanelcoord.cc
Executable file
299
rtgui/batchtoolpanelcoord.cc
Executable file
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <multilangmgr.h>
|
||||
#include <batchtoolpanelcoord.h>
|
||||
#include <options.h>
|
||||
#include <filepanel.h>
|
||||
#include <procparamchangers.h>
|
||||
#include <addsetids.h>
|
||||
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
BatchToolPanelCoordinator::BatchToolPanelCoordinator (FilePanel* parent) : ToolPanelCoordinator(), parent(parent) {
|
||||
|
||||
// remove exif panel and iptc panel
|
||||
std::vector<ToolPanel*>::iterator epi = std::find (toolPanels.begin(), toolPanels.end(), exifpanel);
|
||||
if (epi!=toolPanels.end())
|
||||
toolPanels.erase (epi);
|
||||
std::vector<ToolPanel*>::iterator ipi = std::find (toolPanels.begin(), toolPanels.end(), iptcpanel);
|
||||
if (ipi!=toolPanels.end())
|
||||
toolPanels.erase (ipi);
|
||||
toolPanelNotebook->remove_page (*metadataPanel);
|
||||
|
||||
for (int i=0; i<toolPanels.size(); i++)
|
||||
toolPanels[i]->setBatchMode (true);
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::selectionChanged (const std::vector<Thumbnail*>& selected) {
|
||||
|
||||
if (selected!=this->selected) {
|
||||
closeSession ();
|
||||
this->selected = selected;
|
||||
selFileNames.clear ();
|
||||
for (int i=0; i<selected.size(); i++)
|
||||
selFileNames.push_back (selected[i]->getFileName ());
|
||||
initSession ();
|
||||
}
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::closeSession (bool save) {
|
||||
|
||||
pparamsEdited.set (false);
|
||||
|
||||
for (int i=0; i<selected.size(); i++)
|
||||
selected[i]->removeThumbnailListener (this);
|
||||
|
||||
if (somethingChanged && save) {
|
||||
|
||||
// read new values from the gui
|
||||
for (int i=0; i<toolPanels.size(); i++)
|
||||
toolPanels[i]->write (&pparams, &pparamsEdited);
|
||||
|
||||
// combine with initial parameters and set
|
||||
ProcParams newParams;
|
||||
for (int i=0; i<selected.size(); i++) {
|
||||
newParams = initialPP[i];
|
||||
pparamsEdited.combine (newParams, pparams);
|
||||
selected[i]->setProcParams (newParams, BATCHEDITOR, true);
|
||||
}
|
||||
}
|
||||
for (int i=0; i<paramcListeners.size(); i++)
|
||||
paramcListeners[i]->clearParamChanges ();
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::initSession () {
|
||||
|
||||
somethingChanged = false;
|
||||
|
||||
initialPP.resize (selected.size());
|
||||
for (int i=0; i<selected.size(); i++) {
|
||||
initialPP[i] = selected[i]->getProcParams ();
|
||||
selected[i]->applyAutoExp (initialPP[i]);
|
||||
selected[i]->addThumbnailListener (this);
|
||||
}
|
||||
|
||||
pparamsEdited.initFrom (initialPP);
|
||||
|
||||
/* curve->setAdjusterBehavior (false, false, false, false);
|
||||
whitebalance->setAdjusterBehavior (false, false);
|
||||
vignetting->setAdjusterBehavior (false);
|
||||
rotate->setAdjusterBehavior (false);
|
||||
distortion->setAdjusterBehavior (false);
|
||||
cacorrection->setAdjusterBehavior (false, false);
|
||||
colorshift->setAdjusterBehavior (false, false);
|
||||
colorboost->setAdjusterBehavior (false);
|
||||
lumadenoise->setAdjusterBehavior (false);
|
||||
sharpening->setAdjusterBehavior (false);
|
||||
shadowshighlights->setAdjusterBehavior (false, false, false);
|
||||
*/
|
||||
crop->setDimensions (100000, 100000);
|
||||
|
||||
/* if (selected.size()>0) {
|
||||
pparams = selected[0]->getProcParams ();
|
||||
for (int i=0; i<toolPanels.size(); i++) {
|
||||
toolPanels[i]->setDefaults (&pparams, &pparamsEdited);
|
||||
toolPanels[i]->read (&pparams, &pparamsEdited);
|
||||
}
|
||||
for (int i=0; i<paramcListeners.size(); i++)
|
||||
paramcListeners[i]->procParamsChanged (&pparams, rtengine::EvPhotoLoaded, "batch processing", &pparamsEdited);
|
||||
}
|
||||
*/
|
||||
|
||||
if (selected.size()>0) {
|
||||
|
||||
pparams = selected[0]->getProcParams ();
|
||||
coarse->initBatchBehavior ();
|
||||
|
||||
curve->setAdjusterBehavior (options.baBehav[ADDSET_TC_EXPCOMP], options.baBehav[ADDSET_TC_BRIGHTNESS], options.baBehav[ADDSET_TC_BLACKLEVEL], options.baBehav[ADDSET_TC_CONTRAST]);
|
||||
lcurve->setAdjusterBehavior (options.baBehav[ADDSET_LC_BRIGHTNESS], options.baBehav[ADDSET_LC_CONTRAST]);
|
||||
whitebalance->setAdjusterBehavior (options.baBehav[ADDSET_WB_TEMPERATURE], options.baBehav[ADDSET_WB_GREEN]);
|
||||
vignetting->setAdjusterBehavior (options.baBehav[ADDSET_VIGN_AMOUNT]);
|
||||
rotate->setAdjusterBehavior (options.baBehav[ADDSET_ROTATE_DEGREE]);
|
||||
distortion->setAdjusterBehavior (options.baBehav[ADDSET_DIST_AMOUNT]);
|
||||
cacorrection->setAdjusterBehavior (options.baBehav[ADDSET_CA_RED], options.baBehav[ADDSET_CA_BLUE]);
|
||||
colorshift->setAdjusterBehavior (options.baBehav[ADDSET_CS_BLUEYELLOW], options.baBehav[ADDSET_CS_GREENMAGENTA]);
|
||||
colorboost->setAdjusterBehavior (options.baBehav[ADDSET_CBOOST_AMOUNT]);
|
||||
lumadenoise->setAdjusterBehavior (options.baBehav[ADDSET_LD_EDGETOLERANCE]);
|
||||
sharpening->setAdjusterBehavior (options.baBehav[ADDSET_SHARP_AMOUNT]);
|
||||
shadowshighlights->setAdjusterBehavior (options.baBehav[ADDSET_SH_HIGHLIGHTS], options.baBehav[ADDSET_SH_SHADOWS], options.baBehav[ADDSET_SH_LOCALCONTRAST]);
|
||||
|
||||
if (options.baBehav[ADDSET_TC_EXPCOMP]) pparams.toneCurve.expcomp = 0;
|
||||
if (options.baBehav[ADDSET_TC_BRIGHTNESS]) pparams.toneCurve.brightness = 0;
|
||||
if (options.baBehav[ADDSET_TC_BLACKLEVEL]) pparams.toneCurve.black = 0;
|
||||
if (options.baBehav[ADDSET_TC_CONTRAST]) pparams.toneCurve.contrast = 0;
|
||||
|
||||
if (options.baBehav[ADDSET_SH_HIGHLIGHTS]) pparams.sh.highlights = 0;
|
||||
if (options.baBehav[ADDSET_SH_SHADOWS]) pparams.sh.shadows = 0;
|
||||
if (options.baBehav[ADDSET_SH_LOCALCONTRAST]) pparams.sh.localcontrast = 0;
|
||||
|
||||
if (options.baBehav[ADDSET_LC_BRIGHTNESS]) pparams.lumaCurve.brightness = 0;
|
||||
if (options.baBehav[ADDSET_LC_CONTRAST]) pparams.lumaCurve.contrast = 0;
|
||||
|
||||
if (options.baBehav[ADDSET_SHARP_AMOUNT]) pparams.sharpening.amount = 0;
|
||||
if (options.baBehav[ADDSET_LD_EDGETOLERANCE]) pparams.lumaDenoise.edgetolerance = 0;
|
||||
|
||||
if (options.baBehav[ADDSET_WB_TEMPERATURE]) pparams.wb.temperature = 0;
|
||||
if (options.baBehav[ADDSET_WB_GREEN]) pparams.wb.green = 0;
|
||||
|
||||
if (options.baBehav[ADDSET_CBOOST_AMOUNT]) pparams.colorBoost.amount = 0;
|
||||
|
||||
if (options.baBehav[ADDSET_CS_BLUEYELLOW]) pparams.colorShift.a = 0;
|
||||
if (options.baBehav[ADDSET_CS_GREENMAGENTA]) pparams.colorShift.b = 0;
|
||||
|
||||
if (options.baBehav[ADDSET_ROTATE_DEGREE]) pparams.rotate.degree = 0;
|
||||
if (options.baBehav[ADDSET_DIST_AMOUNT]) pparams.distortion.amount = 0;
|
||||
if (options.baBehav[ADDSET_CA_RED]) pparams.cacorrection.red = 0;
|
||||
if (options.baBehav[ADDSET_CA_BLUE]) pparams.cacorrection.blue = 0;
|
||||
if (options.baBehav[ADDSET_VIGN_AMOUNT]) pparams.vignetting.amount = 0;
|
||||
|
||||
for (int i=0; i<toolPanels.size(); i++) {
|
||||
toolPanels[i]->setDefaults (&pparams, &pparamsEdited);
|
||||
toolPanels[i]->read (&pparams, &pparamsEdited);
|
||||
}
|
||||
for (int i=0; i<paramcListeners.size(); i++)
|
||||
paramcListeners[i]->procParamsChanged (&pparams, rtengine::EvPhotoLoaded, "batch processing", &pparamsEdited);
|
||||
}
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr) {
|
||||
|
||||
if (selected.size()==0)
|
||||
return;
|
||||
|
||||
somethingChanged = true;
|
||||
|
||||
pparamsEdited.set (false);
|
||||
// read new values from the gui
|
||||
for (int i=0; i<toolPanels.size(); i++)
|
||||
toolPanels[i]->write (&pparams, &pparamsEdited);
|
||||
|
||||
if (event==rtengine::EvAutoExp || event==rtengine::EvClip)
|
||||
for (int i=0; i<selected.size(); i++) {
|
||||
initialPP[i].toneCurve.autoexp = pparams.toneCurve.autoexp;
|
||||
initialPP[i].toneCurve.clip = pparams.toneCurve.clip;
|
||||
selected[i]->applyAutoExp (initialPP[i]);
|
||||
}
|
||||
|
||||
// combine with initial parameters and set
|
||||
ProcParams newParams;
|
||||
for (int i=0; i<selected.size(); i++) {
|
||||
newParams = initialPP[i];
|
||||
pparamsEdited.combine (newParams, pparams);
|
||||
selected[i]->setProcParams (newParams, BATCHEDITOR, false);
|
||||
}
|
||||
|
||||
for (int i=0; i<paramcListeners.size(); i++)
|
||||
paramcListeners[i]->procParamsChanged (&pparams, event, descr, &pparamsEdited);
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::getAutoWB (double& temp, double& green) {
|
||||
|
||||
if (selected.size()>0)
|
||||
selected[0]->getAutoWB (temp, green);
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::getCamWB (double& temp, double& green) {
|
||||
|
||||
if (selected.size()>0)
|
||||
selected[0]->getCamWB (temp, green);
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::optionsChanged () {
|
||||
|
||||
closeSession ();
|
||||
initSession ();
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::procParamsChanged (Thumbnail* thm, int whoChangedIt) {
|
||||
|
||||
if (whoChangedIt!=BATCHEDITOR) {
|
||||
closeSession (false);
|
||||
initSession ();
|
||||
}
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::profileChange (const ProcParams *nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited) {
|
||||
|
||||
pparams = *nparams;
|
||||
if (paramsEdited)
|
||||
pparamsEdited = *paramsEdited;
|
||||
|
||||
for (int i=0; i<toolPanels.size(); i++)
|
||||
toolPanels[i]->read (&pparams, &pparamsEdited);
|
||||
|
||||
somethingChanged = true;
|
||||
|
||||
// read new values from the gui
|
||||
for (int i=0; i<toolPanels.size(); i++)
|
||||
toolPanels[i]->write (&pparams, &pparamsEdited);
|
||||
|
||||
// combine with initial parameters and set
|
||||
ProcParams newParams;
|
||||
for (int i=0; i<selected.size(); i++) {
|
||||
newParams = initialPP[i];
|
||||
pparamsEdited.combine (newParams, pparams);
|
||||
selected[i]->setProcParams (newParams, BATCHEDITOR, false);
|
||||
}
|
||||
|
||||
for (int i=0; i<paramcListeners.size(); i++)
|
||||
paramcListeners[i]->procParamsChanged (&pparams, event, descr, &pparamsEdited);
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::cropSelectionReady () {
|
||||
|
||||
toolBar->setTool (TMHand);
|
||||
}
|
||||
|
||||
CropGUIListener* BatchToolPanelCoordinator::startCropEditing (Thumbnail* thm) {
|
||||
|
||||
if (thm) {
|
||||
int w, h;
|
||||
thm->getFinalSize (thm->getProcParams (), w, h);
|
||||
crop->setDimensions (w, h);
|
||||
}
|
||||
return crop;
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::rotateSelectionReady (double rotate_deg, Thumbnail* thm) {
|
||||
|
||||
toolBar->setTool (TMHand);
|
||||
if (rotate_deg!=0.0)
|
||||
rotate->straighten (rotate_deg);
|
||||
}
|
||||
|
||||
void BatchToolPanelCoordinator::spotWBselected (int x, int y, Thumbnail* thm) {
|
||||
|
||||
// toolBar->setTool (TOOL_HAND);
|
||||
if (x>0 && y>0 && thm) {
|
||||
for (int i=0; i<selected.size(); i++)
|
||||
if (selected[i]==thm) {
|
||||
double temp;
|
||||
double green;
|
||||
thm->getSpotWB (x, y, whitebalance->getSize(), temp, green);
|
||||
double otemp = initialPP[i].wb.temperature;
|
||||
double ogreen = initialPP[i].wb.green;
|
||||
if (options.baBehav[12])
|
||||
temp = temp - otemp;
|
||||
if (options.baBehav[13])
|
||||
green = green - ogreen;
|
||||
whitebalance->setWB (temp, green);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
76
rtgui/batchtoolpanelcoord.h
Executable file
76
rtgui/batchtoolpanelcoord.h
Executable file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 __BATCHTOOLPANELCCORD__
|
||||
#define __BATCHTOOLPANELCCORD__
|
||||
|
||||
#include <thumbnail.h>
|
||||
#include <toolpanelcoord.h>
|
||||
#include <fileselectionchangelistener.h>
|
||||
#include <rtengine.h>
|
||||
#include <paramsedited.h>
|
||||
#include <thumbnaillistener.h>
|
||||
|
||||
class FilePanel;
|
||||
class BatchToolPanelCoordinator :
|
||||
public ToolPanelCoordinator,
|
||||
public FileSelectionChangeListener,
|
||||
public ThumbnailListener
|
||||
{
|
||||
protected:
|
||||
rtengine::procparams::ProcParams pparams;
|
||||
ParamsEdited pparamsEdited;
|
||||
std::vector<Thumbnail*> selected;
|
||||
std::vector<Glib::ustring> selFileNames;
|
||||
std::vector<rtengine::procparams::ProcParams> initialPP;
|
||||
bool somethingChanged;
|
||||
FilePanel* parent;
|
||||
|
||||
void closeSession (bool save=true);
|
||||
void initSession ();
|
||||
|
||||
public:
|
||||
|
||||
BatchToolPanelCoordinator (FilePanel* parent);
|
||||
|
||||
// FileSelectionChangeListener interface
|
||||
void selectionChanged (const std::vector<Thumbnail*>& selected);
|
||||
|
||||
// toolpanellistener interface
|
||||
void panelChanged (rtengine::ProcEvent event, const Glib::ustring& descr);
|
||||
|
||||
// profilechangelistener interface
|
||||
void profileChange (const rtengine::procparams::ProcParams* nparams, rtengine::ProcEvent event, const Glib::ustring& descr, const ParamsEdited* paramsEdited=NULL);
|
||||
|
||||
// wbprovider interface
|
||||
void getAutoWB (double& temp, double& green);
|
||||
void getCamWB (double& temp, double& green);
|
||||
|
||||
// thumbnaillistener interface
|
||||
void procParamsChanged (Thumbnail* thm, int whoChangedIt);
|
||||
|
||||
// imageareatoollistener interface
|
||||
void spotWBselected (int x, int y, Thumbnail* thm=NULL);
|
||||
void cropSelectionReady ();
|
||||
void rotateSelectionReady (double rotate_deg, Thumbnail* thm=NULL);
|
||||
CropGUIListener* startCropEditing (Thumbnail* thm=NULL);
|
||||
|
||||
void optionsChanged ();
|
||||
};
|
||||
|
||||
#endif
|
||||
137
rtgui/bqentryupdater.cc
Executable file
137
rtgui/bqentryupdater.cc
Executable file
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <bqentryupdater.h>
|
||||
#include <gtkmm.h>
|
||||
#include <guiutils.h>
|
||||
|
||||
BatchQueueEntryUpdater batchQueueEntryUpdater;
|
||||
|
||||
BatchQueueEntryUpdater::BatchQueueEntryUpdater ()
|
||||
: tostop(false), stopped(true), qMutex(NULL) {
|
||||
}
|
||||
|
||||
void BatchQueueEntryUpdater::add (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener) {
|
||||
|
||||
if (!qMutex)
|
||||
qMutex = new Glib::Mutex ();
|
||||
|
||||
qMutex->lock ();
|
||||
// look up if an older version is in the queue
|
||||
std::list<Job>::iterator i;
|
||||
for (i=jqueue.begin(); i!=jqueue.end(); i++)
|
||||
if (i->oimg==oimg && i->listener==listener) {
|
||||
i->ow = ow;
|
||||
i->oh = oh;
|
||||
i->newh = newh;
|
||||
i->listener = listener;
|
||||
break;
|
||||
}
|
||||
// not found, create and append new job
|
||||
if (i==jqueue.end ()) {
|
||||
Job j;
|
||||
j.oimg = oimg;
|
||||
j.ow = ow;
|
||||
j.oh = oh;
|
||||
j.newh = newh;
|
||||
j.listener = listener;
|
||||
jqueue.push_back (j);
|
||||
}
|
||||
qMutex->unlock ();
|
||||
}
|
||||
|
||||
void BatchQueueEntryUpdater::process () {
|
||||
|
||||
if (stopped)
|
||||
#undef THREAD_PRIORITY_NORMAL
|
||||
thread = Glib::Thread::create(sigc::mem_fun(*this, &BatchQueueEntryUpdater::process_), (unsigned long int)0, true, true, Glib::THREAD_PRIORITY_NORMAL);
|
||||
}
|
||||
|
||||
void BatchQueueEntryUpdater::process_ () {
|
||||
|
||||
stopped = false;
|
||||
tostop = false;
|
||||
|
||||
// TODO: process visible jobs first
|
||||
while (!tostop && !jqueue.empty ()) {
|
||||
qMutex->lock ();
|
||||
Job current = jqueue.front ();
|
||||
jqueue.pop_front ();
|
||||
qMutex->unlock ();
|
||||
if (current.listener) {
|
||||
int neww = current.newh * current.ow / current.oh;
|
||||
guint8* img = new guint8 [current.newh*neww*3];
|
||||
thumbInterp (current.oimg, current.ow, current.oh, img, neww, current.newh);
|
||||
current.listener->updateImage (img, neww, current.newh);
|
||||
}
|
||||
}
|
||||
stopped = true;
|
||||
}
|
||||
|
||||
void BatchQueueEntryUpdater::stop () {
|
||||
|
||||
if (stopped) {
|
||||
tostop = true;
|
||||
return; }
|
||||
|
||||
gdk_threads_leave();
|
||||
tostop = true;
|
||||
Glib::Thread::self()->yield();
|
||||
if (!stopped)
|
||||
thread->join ();
|
||||
gdk_threads_enter();
|
||||
}
|
||||
|
||||
void BatchQueueEntryUpdater::removeJobs () {
|
||||
|
||||
if (!qMutex)
|
||||
return;
|
||||
|
||||
qMutex->lock ();
|
||||
while (!jqueue.empty())
|
||||
jqueue.pop_front ();
|
||||
qMutex->unlock ();
|
||||
}
|
||||
|
||||
void BatchQueueEntryUpdater::removeJobs (BQEntryUpdateListener* listener) {
|
||||
|
||||
if (!qMutex)
|
||||
return;
|
||||
|
||||
qMutex->lock ();
|
||||
bool ready = false;
|
||||
while (!ready) {
|
||||
ready = true;
|
||||
std::list<Job>::iterator i;
|
||||
for (i=jqueue.begin(); i!=jqueue.end(); i++)
|
||||
if (i->listener == listener) {
|
||||
jqueue.erase (i);
|
||||
ready = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
qMutex->unlock ();
|
||||
}
|
||||
|
||||
void BatchQueueEntryUpdater::terminate () {
|
||||
|
||||
stop ();
|
||||
removeJobs ();
|
||||
}
|
||||
|
||||
|
||||
62
rtgui/bqentryupdater.h
Executable file
62
rtgui/bqentryupdater.h
Executable file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _BQENTRYUPDATER_
|
||||
#define _BQENTRYUPDATER_
|
||||
|
||||
#include <glibmm.h>
|
||||
#include <rtengine.h>
|
||||
#include <thumbnail.h>
|
||||
|
||||
class BQEntryUpdateListener {
|
||||
|
||||
public:
|
||||
virtual void updateImage (guint8* img, int w, int h) {}
|
||||
};
|
||||
|
||||
class BatchQueueEntryUpdater {
|
||||
|
||||
struct Job {
|
||||
guint8* oimg;
|
||||
int ow, oh, newh;
|
||||
BQEntryUpdateListener* listener;
|
||||
};
|
||||
|
||||
protected:
|
||||
bool tostop;
|
||||
bool stopped;
|
||||
std::list<Job> jqueue;
|
||||
Glib::Thread* thread;
|
||||
Glib::Mutex* qMutex;
|
||||
|
||||
public:
|
||||
BatchQueueEntryUpdater ();
|
||||
|
||||
void add (guint8* oimg, int ow, int oh, int newh, BQEntryUpdateListener* listener);
|
||||
void process ();
|
||||
void stop ();
|
||||
void removeJobs ();
|
||||
void removeJobs (BQEntryUpdateListener* listener);
|
||||
void terminate ();
|
||||
|
||||
void process_ ();
|
||||
};
|
||||
|
||||
extern BatchQueueEntryUpdater batchQueueEntryUpdater;
|
||||
|
||||
#endif
|
||||
26
rtgui/browserfilter.cc
Executable file
26
rtgui/browserfilter.cc
Executable file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <browserfilter.h>
|
||||
|
||||
BrowserFilter::BrowserFilter () : exifFilterEnabled (false) {
|
||||
|
||||
showTrash = true;
|
||||
for (int i=0; i<6; i++)
|
||||
showRanked[i] = true;
|
||||
}
|
||||
37
rtgui/browserfilter.h
Executable file
37
rtgui/browserfilter.h
Executable file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _BROWSERFILTER_
|
||||
#define _BROWSERFILTER_
|
||||
|
||||
#include <exiffiltersettings.h>
|
||||
|
||||
class BrowserFilter {
|
||||
|
||||
public:
|
||||
bool showRanked[6];
|
||||
bool showTrash;
|
||||
bool showNotTrash;
|
||||
|
||||
bool exifFilterEnabled;
|
||||
ExifFilterSettings exifFilter;
|
||||
|
||||
BrowserFilter ();
|
||||
};
|
||||
|
||||
#endif
|
||||
139
rtgui/cacheimagedata.cc
Executable file
139
rtgui/cacheimagedata.cc
Executable file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <cacheimagedata.h>
|
||||
#include <vector>
|
||||
#include <glib/gstdio.h>
|
||||
#include <safekeyfile.h>
|
||||
|
||||
CacheImageData::CacheImageData ()
|
||||
: md5(""), supported(false), format(FT_Invalid), rank(0), inTrash(false), recentlySaved(false),
|
||||
timeValid(false), exifValid(false) {
|
||||
}
|
||||
|
||||
int CacheImageData::load (const Glib::ustring& fname) {
|
||||
|
||||
rtengine::SafeKeyFile keyFile;
|
||||
|
||||
try {
|
||||
if (!keyFile.load_from_file (fname))
|
||||
return 1;
|
||||
|
||||
if (keyFile.has_group ("General")) {
|
||||
if (keyFile.has_key ("General", "MD5")) md5 = keyFile.get_string ("General", "MD5");
|
||||
if (keyFile.has_key ("General", "Version")) version = keyFile.get_integer ("General", "Version");
|
||||
if (keyFile.has_key ("General", "Supported")) supported = keyFile.get_boolean ("General", "Supported");
|
||||
if (keyFile.has_key ("General", "Format")) format = (ThFileType)keyFile.get_integer ("General", "Format");
|
||||
if (keyFile.has_key ("General", "Rank")) rank = keyFile.get_integer ("General", "Rank");
|
||||
if (keyFile.has_key ("General", "InTrash")) inTrash = keyFile.get_boolean ("General", "InTrash");
|
||||
if (keyFile.has_key ("General", "RecentlySaved")) recentlySaved = keyFile.get_boolean ("General", "RecentlySaved");
|
||||
}
|
||||
|
||||
timeValid = keyFile.has_group ("DateTime");
|
||||
|
||||
if (timeValid) {
|
||||
if (keyFile.has_key ("DateTime", "Year")) year = keyFile.get_integer ("DateTime", "Year");
|
||||
if (keyFile.has_key ("DateTime", "Month")) month = keyFile.get_integer ("DateTime", "Month");
|
||||
if (keyFile.has_key ("DateTime", "Day")) day = keyFile.get_integer ("DateTime", "Day");
|
||||
if (keyFile.has_key ("DateTime", "Hour")) hour = keyFile.get_integer ("DateTime", "Hour");
|
||||
if (keyFile.has_key ("DateTime", "Min")) min = keyFile.get_integer ("DateTime", "Min");
|
||||
if (keyFile.has_key ("DateTime", "Sec")) sec = keyFile.get_integer ("DateTime", "Sec");
|
||||
if (keyFile.has_key ("DateTime", "MSec")) msec = keyFile.get_integer ("DateTime", "MSec");
|
||||
}
|
||||
|
||||
exifValid = false;
|
||||
|
||||
if (keyFile.has_group ("ExifInfo")) {
|
||||
exifValid = true;
|
||||
if (keyFile.has_key ("ExifInfo", "Valid")) exifValid = keyFile.get_boolean ("ExifInfo", "Valid");
|
||||
|
||||
if (exifValid) {
|
||||
if (keyFile.has_key ("ExifInfo", "FNumber")) fnumber = keyFile.get_double ("ExifInfo", "FNumber");
|
||||
if (keyFile.has_key ("ExifInfo", "Shutter")) shutter = keyFile.get_double ("ExifInfo", "Shutter");
|
||||
if (keyFile.has_key ("ExifInfo", "FocalLen")) focalLen = keyFile.get_double ("ExifInfo", "FocalLen");
|
||||
if (keyFile.has_key ("ExifInfo", "ISO")) iso = keyFile.get_integer ("ExifInfo", "ISO");
|
||||
}
|
||||
if (keyFile.has_key ("ExifInfo", "Lens")) lens = keyFile.get_string ("ExifInfo", "Lens");
|
||||
if (keyFile.has_key ("ExifInfo", "Camera")) camera = keyFile.get_string ("ExifInfo", "Camera");
|
||||
}
|
||||
|
||||
if (format==FT_Raw && keyFile.has_group ("ExtraRawInfo")) {
|
||||
if (keyFile.has_key ("ExtraRawInfo", "ThumbImageType")) thumbImgType = keyFile.get_integer ("ExtraRawInfo", "ThumbImageType");
|
||||
if (keyFile.has_key ("ExtraRawInfo", "ThumbImageOffset")) thumbOffset = keyFile.get_integer ("ExtraRawInfo", "ThumbImageOffset");
|
||||
}
|
||||
else {
|
||||
rotate = 0;
|
||||
thumbImgType = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
catch (Glib::Error) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int CacheImageData::save (const Glib::ustring& fname) {
|
||||
|
||||
rtengine::SafeKeyFile keyFile;
|
||||
|
||||
try {
|
||||
keyFile.load_from_file (fname);
|
||||
} catch (...) {}
|
||||
|
||||
keyFile.set_string ("General", "MD5", md5);
|
||||
keyFile.set_integer ("General", "Version", options.version);
|
||||
keyFile.set_boolean ("General", "Supported", supported);
|
||||
keyFile.set_integer ("General", "Format", format);
|
||||
keyFile.set_integer ("General", "Rank", rank);
|
||||
keyFile.set_boolean ("General", "InTrash", inTrash);
|
||||
keyFile.set_boolean ("General", "RecentlySaved", recentlySaved);
|
||||
|
||||
if (timeValid) {
|
||||
keyFile.set_integer ("DateTime", "Year", year);
|
||||
keyFile.set_integer ("DateTime", "Month", month);
|
||||
keyFile.set_integer ("DateTime", "Day", day);
|
||||
keyFile.set_integer ("DateTime", "Hour", hour);
|
||||
keyFile.set_integer ("DateTime", "Min", min);
|
||||
keyFile.set_integer ("DateTime", "Sec", sec);
|
||||
keyFile.set_integer ("DateTime", "MSec", msec);
|
||||
}
|
||||
|
||||
keyFile.set_boolean ("ExifInfo", "Valid", exifValid);
|
||||
if (exifValid) {
|
||||
keyFile.set_double ("ExifInfo", "FNumber", fnumber);
|
||||
keyFile.set_double ("ExifInfo", "Shutter", shutter);
|
||||
keyFile.set_double ("ExifInfo", "FocalLen", focalLen);
|
||||
keyFile.set_integer ("ExifInfo", "ISO", iso);
|
||||
}
|
||||
keyFile.set_string ("ExifInfo", "Lens", lens);
|
||||
keyFile.set_string ("ExifInfo", "Camera", camera);
|
||||
|
||||
if (format==FT_Raw) {
|
||||
keyFile.set_integer ("ExtraRawInfo", "ThumbImageType", thumbImgType);
|
||||
keyFile.set_integer ("ExtraRawInfo", "ThumbImageOffset", thumbOffset);
|
||||
}
|
||||
|
||||
FILE *f = g_fopen (fname.c_str(), "wt");
|
||||
if (!f)
|
||||
return 1;
|
||||
else {
|
||||
fprintf (f, "%s", keyFile.to_data().c_str());
|
||||
fclose (f);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
67
rtgui/cacheimagedata.h
Executable file
67
rtgui/cacheimagedata.h
Executable file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _CACHEIMAGEDATA_
|
||||
#define _CACHEIMAGEDATA_
|
||||
|
||||
#include <glibmm.h>
|
||||
#include <options.h>
|
||||
|
||||
class CacheImageData {
|
||||
|
||||
public:
|
||||
|
||||
// basic informations
|
||||
Glib::ustring md5;
|
||||
int version;
|
||||
bool supported;
|
||||
ThFileType format;
|
||||
char rank;
|
||||
bool inTrash;
|
||||
bool recentlySaved;
|
||||
|
||||
// time/date info
|
||||
bool timeValid;
|
||||
short year;
|
||||
char month;
|
||||
char day;
|
||||
char hour;
|
||||
char min;
|
||||
char sec;
|
||||
char msec;
|
||||
|
||||
// exif info
|
||||
bool exifValid;
|
||||
double fnumber;
|
||||
double shutter;
|
||||
double focalLen;
|
||||
unsigned iso;
|
||||
Glib::ustring lens;
|
||||
Glib::ustring camera;
|
||||
|
||||
// additional info on raw images
|
||||
int rotate;
|
||||
int thumbImgType;
|
||||
int thumbOffset;
|
||||
|
||||
CacheImageData ();
|
||||
|
||||
int load (const Glib::ustring& fname);
|
||||
int save (const Glib::ustring& fname);
|
||||
};
|
||||
#endif
|
||||
253
rtgui/cachemanager.cc
Executable file
253
rtgui/cachemanager.cc
Executable file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <cachemanager.h>
|
||||
#include <options.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <giomm.h>
|
||||
#include <guiutils.h>
|
||||
#include <procparamchangers.h>
|
||||
#include <safegtk.h>
|
||||
|
||||
CacheManager cacheMgr;
|
||||
|
||||
void CacheManager::init () {
|
||||
|
||||
openEntries.clear ();
|
||||
baseDir = options.cacheBaseDir;
|
||||
|
||||
if (!Glib::file_test (baseDir, Glib::FILE_TEST_IS_DIR))
|
||||
g_mkdir_with_parents (baseDir.c_str(), 511);
|
||||
if (!Glib::file_test (Glib::build_filename (baseDir, "profiles"), Glib::FILE_TEST_IS_DIR))
|
||||
g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "profiles")).c_str(), 511);
|
||||
if (!Glib::file_test (Glib::build_filename (baseDir, "images"), Glib::FILE_TEST_IS_DIR))
|
||||
g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "images")).c_str(), 511);
|
||||
if (!Glib::file_test (Glib::build_filename (baseDir, "aehistograms"), Glib::FILE_TEST_IS_DIR))
|
||||
g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "aehistograms")).c_str(), 511);
|
||||
if (!Glib::file_test (Glib::build_filename (baseDir, "embprofiles"), Glib::FILE_TEST_IS_DIR))
|
||||
g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "embprofiles")).c_str(), 511);
|
||||
if (!Glib::file_test (Glib::build_filename (baseDir, "data"), Glib::FILE_TEST_IS_DIR))
|
||||
g_mkdir_with_parents (Glib::ustring(Glib::build_filename (baseDir, "data")).c_str(), 511);
|
||||
}
|
||||
|
||||
Thumbnail* CacheManager::getEntry (const Glib::ustring& fname) {
|
||||
|
||||
Thumbnail* res = NULL;
|
||||
|
||||
std::map<std::string, Thumbnail*>::iterator r = openEntries.find (fname);
|
||||
// if it is open, return it
|
||||
if (r!=openEntries.end()) {
|
||||
r->second->increaseRef ();
|
||||
return r->second;
|
||||
}
|
||||
|
||||
// compute the md5
|
||||
std::string md5 = getMD5 (fname);
|
||||
if (md5=="")
|
||||
return NULL;
|
||||
|
||||
// build path name
|
||||
Glib::ustring cfname = getCacheFileName ("data", fname, md5) + ".txt";
|
||||
|
||||
// let's see if we have it in the cache
|
||||
if (Glib::file_test (cfname, Glib::FILE_TEST_EXISTS)) {
|
||||
CacheImageData* cfs = new CacheImageData ();
|
||||
int e = cfs->load (cfname);
|
||||
if (!e && cfs->supported==true)
|
||||
res = new Thumbnail (this, fname, cfs);
|
||||
if (res && !res->isSupported ()) {
|
||||
delete res;
|
||||
res = NULL;
|
||||
}
|
||||
delete cfs;
|
||||
}
|
||||
// if not, create a new one
|
||||
if (!res) {
|
||||
res = new Thumbnail (this, fname, md5);
|
||||
if (!res->isSupported ()) {
|
||||
delete res;
|
||||
res = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (res)
|
||||
openEntries[fname] = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void CacheManager::deleteEntry (const Glib::ustring& fname) {
|
||||
|
||||
// check if it is opened
|
||||
std::map<std::string, Thumbnail*>::iterator r = openEntries.find (fname);
|
||||
// if it is open, dont delete it
|
||||
if (r!=openEntries.end()) {
|
||||
std::string md5 = r->second->getMD5 ();
|
||||
r->second->decreaseRef ();
|
||||
// if in the editor, the thumbnail still exists. If not, delete it:
|
||||
r = openEntries.find (fname);
|
||||
if (r==openEntries.end() && md5!="") {
|
||||
::g_remove ((getCacheFileName ("data", fname, md5) + ".txt").c_str());
|
||||
::g_remove ((getCacheFileName ("profiles", fname, md5) + ".pp2").c_str());
|
||||
::g_remove ((getCacheFileName ("images", fname, md5) + ".cust").c_str());
|
||||
::g_remove ((getCacheFileName ("images", fname, md5) + ".jpg").c_str());
|
||||
::g_remove ((getCacheFileName ("aehistograms", fname, md5)).c_str());
|
||||
::g_remove ((getCacheFileName ("embprofiles", fname, md5) + ".icc").c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
std::string md5 = getMD5 (fname);
|
||||
if (md5!="") {
|
||||
::g_remove ((getCacheFileName ("data", fname, md5) + ".txt").c_str());
|
||||
::g_remove ((getCacheFileName ("profiles", fname, md5) + ".pp2").c_str());
|
||||
::g_remove ((getCacheFileName ("images", fname, md5) + ".cust").c_str());
|
||||
::g_remove ((getCacheFileName ("images", fname, md5) + ".jpg").c_str());
|
||||
::g_remove ((getCacheFileName ("aehistograms", fname, md5)).c_str());
|
||||
::g_remove ((getCacheFileName ("embprofiles", fname, md5) + ".icc").c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CacheManager::renameEntry (const std::string& oldfilename, const std::string& oldmd5, const std::string& newfilename) {
|
||||
|
||||
std::string newmd5 = getMD5 (newfilename);
|
||||
|
||||
::g_rename ((getCacheFileName ("profiles", oldfilename, oldmd5) + ".pp2").c_str(), (getCacheFileName ("profiles", newfilename, newmd5) + ".pp2").c_str());
|
||||
::g_rename ((getCacheFileName ("images", oldfilename, oldmd5) + ".cust").c_str(), (getCacheFileName ("images", newfilename, newmd5) + ".cust").c_str());
|
||||
::g_rename ((getCacheFileName ("images", oldfilename, oldmd5) + ".jpg").c_str(), (getCacheFileName ("images", newfilename, newmd5) + ".jpg").c_str());
|
||||
::g_rename ((getCacheFileName ("aehistograms", oldfilename, oldmd5)).c_str(), (getCacheFileName ("aehistograms", newfilename, newmd5)).c_str());
|
||||
::g_rename ((getCacheFileName ("embprofiles", oldfilename, oldmd5) + ".icc").c_str(), (getCacheFileName ("embprofiles", newfilename, newmd5) + ".icc").c_str());
|
||||
::g_rename ((getCacheFileName ("data", oldfilename, oldmd5) + ".txt").c_str(), (getCacheFileName ("data", newfilename, newmd5) + ".txt").c_str());
|
||||
|
||||
// check if it is opened
|
||||
std::map<std::string, Thumbnail*>::iterator r = openEntries.find (oldfilename);
|
||||
// if it is open, update md5
|
||||
if (r!=openEntries.end()) {
|
||||
Thumbnail* t = r->second;
|
||||
openEntries.erase (r);
|
||||
t->setFileName (newfilename);
|
||||
openEntries[newfilename] = t;
|
||||
t->updateCache ();
|
||||
t->reSaveThumbnail ();
|
||||
}
|
||||
}
|
||||
|
||||
void CacheManager::closeThumbnail (Thumbnail* t) {
|
||||
|
||||
t->updateCache ();
|
||||
std::map<std::string, Thumbnail*>::iterator r = openEntries.find (t->getFileName());
|
||||
if (r!=openEntries.end())
|
||||
openEntries.erase (r);
|
||||
delete t;
|
||||
}
|
||||
|
||||
void CacheManager::closeCache () {
|
||||
|
||||
applyCacheSizeLimitation ();
|
||||
}
|
||||
|
||||
void CacheManager::clearAll () {
|
||||
|
||||
deleteDir ("images");
|
||||
deleteDir ("aehistograms");
|
||||
deleteDir ("embprofiles");
|
||||
deleteDir ("profiles");
|
||||
deleteDir ("data");
|
||||
|
||||
// re-generate thumbnail images and clear profiles of open thumbnails
|
||||
std::map<std::string, Thumbnail*>::iterator i;
|
||||
for (i=openEntries.begin(); i!=openEntries.end(); i++) {
|
||||
i->second->clearProcParams (CACHEMGR);
|
||||
i->second->generateThumbnailImage ();
|
||||
i->second->updateCache ();
|
||||
}
|
||||
}
|
||||
void CacheManager::clearThumbImages () {
|
||||
|
||||
deleteDir ("images");
|
||||
deleteDir ("aehistograms");
|
||||
deleteDir ("embprofiles");
|
||||
|
||||
// re-generate thumbnail images of open thumbnails
|
||||
std::map<std::string, Thumbnail*>::iterator i;
|
||||
for (i=openEntries.begin(); i!=openEntries.end(); i++)
|
||||
i->second->generateThumbnailImage ();
|
||||
}
|
||||
|
||||
void CacheManager::clearProfiles () {
|
||||
|
||||
deleteDir ("profiles");
|
||||
// clear profiles of open thumbnails
|
||||
std::map<std::string, Thumbnail*>::iterator i;
|
||||
for (i=openEntries.begin(); i!=openEntries.end(); i++)
|
||||
i->second->clearProcParams (CACHEMGR);
|
||||
}
|
||||
|
||||
void CacheManager::deleteDir (const Glib::ustring& dirName) {
|
||||
|
||||
try {
|
||||
Glib::Dir* dir = new Glib::Dir (Glib::build_filename (baseDir, dirName));
|
||||
for (Glib::DirIterator i = dir->begin(); i!=dir->end(); ++i)
|
||||
::g_remove (Glib::build_filename (Glib::build_filename (baseDir, dirName), *i).c_str());
|
||||
delete dir;
|
||||
}
|
||||
catch (const Glib::FileError& fe) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string CacheManager::getMD5 (const Glib::ustring& fname) {
|
||||
|
||||
Glib::RefPtr<Gio::File> file = Gio::File::create_for_path (fname);
|
||||
if (file) {
|
||||
Glib::RefPtr<Gio::FileInfo> info = safe_query_file_info (file);
|
||||
if (info)
|
||||
return Glib::Checksum::compute_checksum (Glib::Checksum::CHECKSUM_MD5, Glib::ustring::compose ("%1%2", fname, info->get_size()));
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
Glib::ustring CacheManager::getCacheFileName (const Glib::ustring& subdir, const Glib::ustring& fname, const Glib::ustring& md5) {
|
||||
|
||||
Glib::ustring cfn = Glib::build_filename (baseDir, subdir);
|
||||
Glib::ustring cname = Glib::path_get_basename (fname) + "." + md5;
|
||||
return Glib::build_filename (cfn, cname);
|
||||
}
|
||||
|
||||
void CacheManager::applyCacheSizeLimitation () {
|
||||
|
||||
std::vector<FileMTimeInfo> flist;
|
||||
Glib::ustring dataDir = Glib::build_filename (baseDir, "data");
|
||||
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (dataDir);
|
||||
|
||||
safe_build_file_list (dir, flist);
|
||||
|
||||
if (flist.size() > options.maxCacheEntries) {
|
||||
std::sort (flist.begin(), flist.end());
|
||||
while (flist.size() > options.maxCacheEntries) {
|
||||
::g_remove ((Glib::build_filename (Glib::build_filename (baseDir, "data"), flist.front().fname) + ".txt").c_str());
|
||||
::g_remove ((Glib::build_filename (Glib::build_filename (baseDir, "images"), flist.front().fname) + ".cust").c_str());
|
||||
::g_remove ((Glib::build_filename (Glib::build_filename (baseDir, "images"), flist.front().fname) + ".jpg").c_str());
|
||||
::g_remove ((Glib::build_filename (Glib::build_filename (baseDir, "aehistograms"), flist.front().fname)).c_str());
|
||||
::g_remove ((Glib::build_filename (Glib::build_filename (baseDir, "embprofiles"), flist.front().fname) + ".icc").c_str());
|
||||
// ::g_remove ((Glib::build_filename (Glib::build_filename (baseDir, "profiles"), flist.front().fname) + ".pp2").c_str());
|
||||
flist.erase (flist.begin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
64
rtgui/cachemanager.h
Executable file
64
rtgui/cachemanager.h
Executable file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _CACHEMANAGER_
|
||||
#define _CACHEMANAGER_
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <glibmm.h>
|
||||
#include <thumbnail.h>
|
||||
#include <stdio.h>
|
||||
|
||||
class Thumbnail;
|
||||
|
||||
class CacheManager {
|
||||
|
||||
std::map<std::string, Thumbnail*> openEntries;
|
||||
Glib::ustring baseDir;
|
||||
|
||||
void deleteDir (const Glib::ustring& dirName);
|
||||
|
||||
public:
|
||||
CacheManager () {}
|
||||
|
||||
void init ();
|
||||
Thumbnail* getEntry (const Glib::ustring& fname);
|
||||
void deleteEntry (const Glib::ustring& fname);
|
||||
void renameEntry (const std::string& oldfilename, const std::string& oldmd5, const std::string& newfilename);
|
||||
|
||||
void closeThumbnail (Thumbnail* t);
|
||||
|
||||
const Glib::ustring& getBaseDir () { return baseDir; }
|
||||
void closeCache ();
|
||||
|
||||
static std::string getMD5 (const Glib::ustring& fname);
|
||||
|
||||
void clearAll ();
|
||||
void clearThumbImages ();
|
||||
void clearProfiles ();
|
||||
|
||||
void applyCacheSizeLimitation ();
|
||||
|
||||
Glib::ustring getCacheFileName (const Glib::ustring& subdir, const Glib::ustring& fname, const Glib::ustring& md5);
|
||||
};
|
||||
|
||||
extern CacheManager cacheMgr;
|
||||
|
||||
#endif
|
||||
|
||||
103
rtgui/cacorrection.cc
Executable file
103
rtgui/cacorrection.cc
Executable file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <cacorrection.h>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
CACorrection::CACorrection () : valaAdd(false), valbAdd(false) {
|
||||
|
||||
red = Gtk::manage (new Adjuster (M("TP_CACORRECTION_RED"), -0.005, 0.005, 0.0001, 0));
|
||||
red->setAdjusterListener (this);
|
||||
|
||||
blue = Gtk::manage (new Adjuster (M("TP_CACORRECTION_BLUE"), -0.005, 0.005, 0.0001, 0));
|
||||
blue->setAdjusterListener (this);
|
||||
|
||||
pack_start (*red);
|
||||
pack_start (*blue);
|
||||
|
||||
show_all();
|
||||
}
|
||||
|
||||
void CACorrection::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
if (pedited) {
|
||||
red->setEditedState (pedited->cacorrection.red ? Edited : UnEdited);
|
||||
blue->setEditedState (pedited->cacorrection.blue ? Edited : UnEdited);
|
||||
}
|
||||
|
||||
red->setValue (pp->cacorrection.red);
|
||||
blue->setValue (pp->cacorrection.blue);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void CACorrection::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
pp->cacorrection.red = red->getValue ();
|
||||
pp->cacorrection.blue = blue->getValue ();
|
||||
|
||||
if (pedited) {
|
||||
pedited->cacorrection.red = red->getEditedState ();
|
||||
pedited->cacorrection.blue = blue->getEditedState ();
|
||||
}
|
||||
}
|
||||
|
||||
void CACorrection::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
|
||||
|
||||
red->setDefault (defParams->cacorrection.red);
|
||||
blue->setDefault (defParams->cacorrection.blue);
|
||||
|
||||
if (pedited) {
|
||||
red->setDefaultEditedState (pedited->cacorrection.red ? Edited : UnEdited);
|
||||
blue->setDefaultEditedState (pedited->cacorrection.blue ? Edited : UnEdited);
|
||||
}
|
||||
else {
|
||||
red->setDefaultEditedState (Irrelevant);
|
||||
blue->setDefaultEditedState (Irrelevant);
|
||||
}
|
||||
}
|
||||
|
||||
void CACorrection::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
if (listener)
|
||||
listener->panelChanged (EvCACorr, Glib::ustring::compose ("%1=%3\n%2=%4", M("TP_CACORRECTION_RED"), M("TP_CACORRECTION_BLUE"), Glib::ustring::format (std::setw(5), std::fixed, std::setprecision(4), red->getValue()), Glib::ustring::format (std::setw(5), std::fixed, std::setprecision(4), blue->getValue())));
|
||||
}
|
||||
|
||||
void CACorrection::setAdjusterBehavior (bool baadd, bool bbadd) {
|
||||
|
||||
if (!valaAdd && baadd || valaAdd && !baadd)
|
||||
red->setLimits (-0.005, 0.005, 0.0001, 0);
|
||||
|
||||
if (!valbAdd && bbadd || valbAdd && !bbadd)
|
||||
blue->setLimits (-0.005, 0.005, 0.0001, 0);
|
||||
|
||||
valaAdd = baadd;
|
||||
valbAdd = bbadd;
|
||||
}
|
||||
|
||||
void CACorrection::setBatchMode (bool batchMode) {
|
||||
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
red->showEditedCB ();
|
||||
blue->showEditedCB ();
|
||||
}
|
||||
46
rtgui/cacorrection.h
Executable file
46
rtgui/cacorrection.h
Executable file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _CACORRECTION_H_
|
||||
#define _CACORRECTION_H_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <adjuster.h>
|
||||
#include <toolpanel.h>
|
||||
|
||||
class CACorrection : public Gtk::VBox, public AdjusterListener, public ToolPanel {
|
||||
|
||||
protected:
|
||||
Adjuster* red;
|
||||
Adjuster* blue;
|
||||
bool valaAdd, valbAdd;
|
||||
|
||||
public:
|
||||
|
||||
CACorrection ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
|
||||
void setBatchMode (bool batchMode);
|
||||
|
||||
void adjusterChanged (Adjuster* a, double newval);
|
||||
void setAdjusterBehavior (bool baadd, bool bbadd);
|
||||
};
|
||||
|
||||
#endif
|
||||
151
rtgui/chmixer.cc
Executable file
151
rtgui/chmixer.cc
Executable file
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <chmixer.h>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
ChMixer::ChMixer () {
|
||||
|
||||
Gtk::Label* rlabel = Gtk::manage (new Gtk::Label ());
|
||||
rlabel->set_markup (Glib::ustring("<span foreground=\"red\"><b>") + M("TP_CHMIXER_RED") + Glib::ustring(":</b></span>"));
|
||||
|
||||
red[0] = Gtk::manage (new Adjuster (M("TP_CHMIXER_RED"), -200, 200, 1, 100));
|
||||
red[1] = Gtk::manage (new Adjuster (M("TP_CHMIXER_GREEN"), -200, 200, 1, 0));
|
||||
red[2] = Gtk::manage (new Adjuster (M("TP_CHMIXER_BLUE"), -200, 200, 1, 0));
|
||||
|
||||
Gtk::HSeparator* rsep = Gtk::manage (new Gtk::HSeparator ());
|
||||
|
||||
pack_start (*rlabel);
|
||||
for (int i=0; i<3; i++)
|
||||
pack_start (*red[i]);
|
||||
pack_start (*rsep);
|
||||
|
||||
Gtk::Label* glabel = Gtk::manage (new Gtk::Label ());
|
||||
glabel->set_markup (Glib::ustring("<span foreground=\"darkgreen\"><b>") + M("TP_CHMIXER_GREEN") + Glib::ustring(":</b></span>"));
|
||||
|
||||
green[0] = Gtk::manage (new Adjuster (M("TP_CHMIXER_RED"), -200, 200, 1, 0));
|
||||
green[1] = Gtk::manage (new Adjuster (M("TP_CHMIXER_GREEN"), -200, 200, 1, 100));
|
||||
green[2] = Gtk::manage (new Adjuster (M("TP_CHMIXER_BLUE"), -200, 200, 1, 0));
|
||||
|
||||
Gtk::HSeparator* gsep = Gtk::manage (new Gtk::HSeparator ());
|
||||
|
||||
pack_start (*glabel);
|
||||
for (int i=0; i<3; i++)
|
||||
pack_start (*green[i]);
|
||||
pack_start (*gsep);
|
||||
|
||||
Gtk::Label* blabel = Gtk::manage (new Gtk::Label ());
|
||||
blabel->set_markup (Glib::ustring("<span foreground=\"blue\"><b>") + M("TP_CHMIXER_BLUE") + Glib::ustring(":</b></span>"));
|
||||
|
||||
blue[0] = Gtk::manage (new Adjuster (M("TP_CHMIXER_RED"), -200, 200, 1, 0));
|
||||
blue[1] = Gtk::manage (new Adjuster (M("TP_CHMIXER_GREEN"), -200, 200, 1, 0));
|
||||
blue[2] = Gtk::manage (new Adjuster (M("TP_CHMIXER_BLUE"), -200, 200, 1, 100));
|
||||
|
||||
for (int i=0; i<3; i++) {
|
||||
red[i]->setAdjusterListener (this);
|
||||
green[i]->setAdjusterListener (this);
|
||||
blue[i]->setAdjusterListener (this);
|
||||
}
|
||||
|
||||
pack_start (*blabel);
|
||||
for (int i=0; i<3; i++)
|
||||
pack_start (*blue[i]);
|
||||
|
||||
show_all();
|
||||
}
|
||||
|
||||
void ChMixer::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
if (pedited)
|
||||
for (int i=0; i<3; i++) {
|
||||
red[i]->setEditedState (pedited->chmixer.red[i] ? Edited : UnEdited);
|
||||
green[i]->setEditedState (pedited->chmixer.green[i] ? Edited : UnEdited);
|
||||
blue[i]->setEditedState (pedited->chmixer.blue[i] ? Edited : UnEdited);
|
||||
}
|
||||
|
||||
for (int i=0; i<3; i++) {
|
||||
red[i]->setValue (pp->chmixer.red[i]);
|
||||
green[i]->setValue (pp->chmixer.green[i]);
|
||||
blue[i]->setValue (pp->chmixer.blue[i]);
|
||||
}
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void ChMixer::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
for (int i=0; i<3; i++) {
|
||||
pp->chmixer.red[i] = (int) red[i]->getValue ();
|
||||
pp->chmixer.green[i] = (int) green[i]->getValue ();
|
||||
pp->chmixer.blue[i] = (int) blue[i]->getValue ();
|
||||
}
|
||||
|
||||
if (pedited)
|
||||
for (int i=0; i<3; i++) {
|
||||
pedited->chmixer.red[i] = red[i]->getEditedState ();
|
||||
pedited->chmixer.green[i] = green[i]->getEditedState ();
|
||||
pedited->chmixer.blue[i] = blue[i]->getEditedState ();
|
||||
}
|
||||
}
|
||||
|
||||
void ChMixer::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
|
||||
|
||||
for (int i=0; i<3; i++) {
|
||||
red[i]->setDefault (defParams->chmixer.red[i]);
|
||||
green[i]->setDefault (defParams->chmixer.green[i]);
|
||||
blue[i]->setDefault (defParams->chmixer.blue[i]);
|
||||
}
|
||||
|
||||
if (pedited)
|
||||
for (int i=0; i<3; i++) {
|
||||
red[i]->setDefaultEditedState (pedited->chmixer.red[i] ? Edited : UnEdited);
|
||||
green[i]->setDefaultEditedState (pedited->chmixer.green[i] ? Edited : UnEdited);
|
||||
blue[i]->setDefaultEditedState (pedited->chmixer.blue[i] ? Edited : UnEdited);
|
||||
}
|
||||
else
|
||||
for (int i=0; i<3; i++) {
|
||||
red[i]->setDefaultEditedState (Irrelevant);
|
||||
green[i]->setDefaultEditedState (Irrelevant);
|
||||
blue[i]->setDefaultEditedState (Irrelevant);
|
||||
}
|
||||
}
|
||||
|
||||
void ChMixer::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
if (listener) {
|
||||
Glib::ustring descr = Glib::ustring::compose ("R=%1,%2,%3\nG=%4,%5,%6\nB=%7,%8,%9",
|
||||
(int)red[0]->getValue(), (int)red[1]->getValue(), (int)red[2]->getValue(),
|
||||
(int)green[0]->getValue(), (int)green[1]->getValue(), (int)green[2]->getValue(),
|
||||
(int)blue[0]->getValue(), (int)blue[1]->getValue(), (int)blue[2]->getValue());
|
||||
listener->panelChanged (EvChMixer, descr);
|
||||
}
|
||||
}
|
||||
|
||||
void ChMixer::setBatchMode (bool batchMode) {
|
||||
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
for (int i=0; i<3; i++) {
|
||||
red[i]->showEditedCB ();
|
||||
green[i]->showEditedCB ();
|
||||
blue[i]->showEditedCB ();
|
||||
}
|
||||
}
|
||||
45
rtgui/chmixer.h
Executable file
45
rtgui/chmixer.h
Executable file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _CHMIXER_H_
|
||||
#define _CHMIXER_H_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <adjuster.h>
|
||||
#include <toolpanel.h>
|
||||
|
||||
class ChMixer : public Gtk::VBox, public AdjusterListener, public ToolPanel {
|
||||
|
||||
protected:
|
||||
Adjuster *red[3];
|
||||
Adjuster *green[3];
|
||||
Adjuster *blue[3];
|
||||
|
||||
public:
|
||||
|
||||
ChMixer ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
|
||||
void setBatchMode (bool batchMode);
|
||||
|
||||
void adjusterChanged (Adjuster* a, double newval);
|
||||
};
|
||||
|
||||
#endif
|
||||
21
rtgui/clipboard.cc
Executable file
21
rtgui/clipboard.cc
Executable file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <clipboard.h>
|
||||
|
||||
Clipboard clipboard;
|
||||
44
rtgui/clipboard.h
Executable file
44
rtgui/clipboard.h
Executable file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _CLIPBOARD_
|
||||
#define _CLIPBOARD_
|
||||
|
||||
#include <vector>
|
||||
#include <rtengine.h>
|
||||
|
||||
class Clipboard {
|
||||
|
||||
bool _hasIPTC;
|
||||
std::vector<rtengine::procparams::IPTCPair> iptc;
|
||||
bool _hasProcParams;
|
||||
rtengine::procparams::ProcParams procParams;
|
||||
|
||||
public:
|
||||
void setIPTC (const std::vector<rtengine::procparams::IPTCPair>& iptcc) { iptc = iptcc; _hasIPTC = true;}
|
||||
const std::vector<rtengine::procparams::IPTCPair>& getIPTC () { return iptc; }
|
||||
bool hasIPTC () { return _hasIPTC; }
|
||||
|
||||
void setProcParams (const rtengine::procparams::ProcParams& pparams) { procParams = pparams; _hasProcParams = true; }
|
||||
const rtengine::procparams::ProcParams& getProcParams () { return procParams; }
|
||||
bool hasProcParams () { return _hasProcParams; }
|
||||
};
|
||||
|
||||
extern Clipboard clipboard;
|
||||
|
||||
#endif
|
||||
148
rtgui/coarsepanel.cc
Executable file
148
rtgui/coarsepanel.cc
Executable file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <coarsepanel.h>
|
||||
|
||||
extern Glib::ustring argv0;
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
CoarsePanel::CoarsePanel () : ToolPanel () {
|
||||
|
||||
degree = 0;
|
||||
|
||||
Gtk::Image* rotateli = Gtk::manage (new Gtk::Image (argv0+"/images/stock-rotate-270-16.png"));
|
||||
rotate_left = Gtk::manage (new Gtk::Button ());
|
||||
rotate_left->add (*rotateli);
|
||||
rotate_left->set_relief(Gtk::RELIEF_NONE);
|
||||
pack_start (*rotate_left);
|
||||
|
||||
Gtk::Image* rotateri = Gtk::manage (new Gtk::Image (argv0+"/images/stock-rotate-90-16.png"));
|
||||
rotate_right = Gtk::manage (new Gtk::Button ());
|
||||
rotate_right->add (*rotateri);
|
||||
rotate_right->set_relief(Gtk::RELIEF_NONE);
|
||||
pack_start (*rotate_right);
|
||||
|
||||
Gtk::Image* fliphi = Gtk::manage (new Gtk::Image (argv0+"/images/stock-flip-horizontal-16.png"));
|
||||
hflip = Gtk::manage (new Gtk::ToggleButton ());
|
||||
hflip->add (*fliphi);
|
||||
hflip->set_relief(Gtk::RELIEF_NONE);
|
||||
pack_start (*hflip);
|
||||
|
||||
Gtk::Image* flipvi = Gtk::manage (new Gtk::Image (argv0+"/images/stock-flip-vertical-16.png"));
|
||||
vflip = Gtk::manage (new Gtk::ToggleButton ());
|
||||
vflip->add (*flipvi);
|
||||
vflip->set_relief(Gtk::RELIEF_NONE);
|
||||
pack_start (*vflip);
|
||||
|
||||
rotate_left->set_tooltip_text (M("TP_COARSETRAF_TOOLTIP_ROTLEFT"));
|
||||
rotate_right->set_tooltip_text (M("TP_COARSETRAF_TOOLTIP_ROTRIGHT"));
|
||||
vflip->set_tooltip_text (M("TP_COARSETRAF_TOOLTIP_VFLIP"));
|
||||
hflip->set_tooltip_text (M("TP_COARSETRAF_TOOLTIP_HFLIP"));
|
||||
|
||||
rotate_left->signal_pressed().connect( sigc::mem_fun(*this, &CoarsePanel::rotateLeft) );
|
||||
rotate_right->signal_pressed().connect( sigc::mem_fun(*this, &CoarsePanel::rotateRight) );
|
||||
hflip->signal_toggled().connect( sigc::mem_fun(*this, &CoarsePanel::flipHorizontal) );
|
||||
vflip->signal_toggled().connect( sigc::mem_fun(*this, &CoarsePanel::flipVertical) );
|
||||
|
||||
show_all_children ();
|
||||
}
|
||||
|
||||
void CoarsePanel::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
if (pedited) {
|
||||
degree = 0;
|
||||
hflip->set_active (pedited->coarse.hflip ? pp->coarse.hflip : false);
|
||||
vflip->set_active (pedited->coarse.vflip ? pp->coarse.vflip : false);
|
||||
oldhflip = pp->coarse.hflip;
|
||||
oldvflip = pp->coarse.vflip;
|
||||
}
|
||||
else {
|
||||
degree = pp->coarse.rotate;
|
||||
hflip->set_active (pp->coarse.hflip);
|
||||
vflip->set_active (pp->coarse.vflip);
|
||||
}
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void CoarsePanel::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
pp->coarse.rotate = degree;
|
||||
|
||||
if (pedited) {
|
||||
pedited->coarse.rotate = degree!=0;
|
||||
pedited->coarse.hflip = oldhflip != hflip->get_active ();
|
||||
pedited->coarse.vflip = oldvflip != vflip->get_active ();
|
||||
pp->coarse.hflip = oldhflip != hflip->get_active ();
|
||||
pp->coarse.vflip = oldvflip != vflip->get_active ();
|
||||
}
|
||||
else {
|
||||
pp->coarse.hflip = hflip->get_active ();
|
||||
pp->coarse.vflip = vflip->get_active ();
|
||||
}
|
||||
}
|
||||
|
||||
void CoarsePanel::initBatchBehavior () {
|
||||
|
||||
disableListener ();
|
||||
|
||||
degree = 0;
|
||||
hflip->set_active (false);
|
||||
vflip->set_active (false);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void CoarsePanel::rotateLeft () {
|
||||
|
||||
degree = (degree + 270) % 360;
|
||||
if (listener)
|
||||
listener->panelChanged (EvCTRotate, Glib::ustring::format (degree));
|
||||
}
|
||||
|
||||
void CoarsePanel::rotateRight () {
|
||||
|
||||
degree = (degree + 90) % 360;
|
||||
if (listener)
|
||||
listener->panelChanged (EvCTRotate, Glib::ustring::format (degree));
|
||||
}
|
||||
|
||||
void CoarsePanel::flipHorizontal () {
|
||||
|
||||
if (listener) {
|
||||
if (hflip->get_active ())
|
||||
listener->panelChanged (EvCTHFlip, M("GENERAL_ENABLED"));
|
||||
else
|
||||
listener->panelChanged (EvCTHFlip, M("GENERAL_DISABLED"));
|
||||
}
|
||||
}
|
||||
|
||||
void CoarsePanel::flipVertical () {
|
||||
|
||||
if (listener) {
|
||||
if (vflip->get_active ())
|
||||
listener->panelChanged (EvCTVFlip, M("GENERAL_ENABLED"));
|
||||
else
|
||||
listener->panelChanged (EvCTVFlip, M("GENERAL_DISABLED"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
49
rtgui/coarsepanel.h
Executable file
49
rtgui/coarsepanel.h
Executable file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 __COARSEPANEL__
|
||||
#define __COARSEPANEL__
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <toolpanel.h>
|
||||
|
||||
class CoarsePanel : public Gtk::HBox, public ToolPanel {
|
||||
|
||||
protected:
|
||||
Gtk::Button* rotate_left;
|
||||
Gtk::Button* rotate_right;
|
||||
Gtk::ToggleButton* hflip;
|
||||
Gtk::ToggleButton* vflip;
|
||||
int degree;
|
||||
bool oldhflip, oldvflip;
|
||||
|
||||
public:
|
||||
|
||||
CoarsePanel ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void initBatchBehavior ();
|
||||
|
||||
void rotateLeft ();
|
||||
void rotateRight ();
|
||||
void flipHorizontal ();
|
||||
void flipVertical ();
|
||||
};
|
||||
|
||||
#endif
|
||||
191
rtgui/colorboost.cc
Executable file
191
rtgui/colorboost.cc
Executable file
@@ -0,0 +1,191 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <colorboost.h>
|
||||
#include <iomanip>
|
||||
#include <guiutils.h>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
ColorBoost::ColorBoost () : ToolPanel(), cbAdd(false) {
|
||||
|
||||
colorboost = new Adjuster (M("TP_COLORBOOST_AMOUNT"), -100, 300, 1, 0);
|
||||
|
||||
pack_start (*colorboost);
|
||||
pack_start (*Gtk::manage (new Gtk::HSeparator()));
|
||||
|
||||
avoidclip = Gtk::manage (new Gtk::CheckButton (M("TP_COLORBOOST_AVOIDCOLORCLIP")));
|
||||
|
||||
pack_start (*avoidclip);
|
||||
pack_start (*Gtk::manage (new Gtk::HSeparator()));
|
||||
|
||||
enablelimiter = Gtk::manage (new Gtk::CheckButton (M("TP_COLORBOOST_ENABLESATLIMITER")));
|
||||
pack_start (*enablelimiter);
|
||||
|
||||
saturationlimiter = new Adjuster (M("TP_COLORBOOST_SATLIMIT"), 0, 200, 0.1, 100);
|
||||
saturationlimiter->show ();
|
||||
saturationlimiter->reference ();
|
||||
|
||||
colorboost->setAdjusterListener (this);
|
||||
saturationlimiter->setAdjusterListener (this);
|
||||
acconn = avoidclip->signal_toggled().connect( sigc::mem_fun(*this, &ColorBoost::avoidclip_toggled) );
|
||||
elconn = enablelimiter->signal_toggled().connect( sigc::mem_fun(*this, &ColorBoost::enablelimiter_toggled) );
|
||||
|
||||
show_all_children ();
|
||||
}
|
||||
|
||||
ColorBoost::~ColorBoost () {
|
||||
|
||||
delete saturationlimiter;
|
||||
}
|
||||
|
||||
void ColorBoost::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
if (pedited) {
|
||||
colorboost->setEditedState (pedited->colorBoost.amount ? Edited : UnEdited);
|
||||
saturationlimiter->setEditedState (pedited->colorBoost.saturationlimit ? Edited : UnEdited);
|
||||
avoidclip->set_inconsistent (!pedited->colorBoost.avoidclip);
|
||||
enablelimiter->set_inconsistent (!pedited->colorBoost.enable_saturationlimiter);
|
||||
}
|
||||
|
||||
colorboost->setValue (pp->colorBoost.amount);
|
||||
saturationlimiter->setValue (pp->colorBoost.saturationlimit);
|
||||
acconn.block (true);
|
||||
avoidclip->set_active (pp->colorBoost.avoidclip);
|
||||
acconn.block (false);
|
||||
elconn.block (true);
|
||||
enablelimiter->set_active (pp->colorBoost.enable_saturationlimiter);
|
||||
elconn.block (false);
|
||||
|
||||
removeIfThere (this, saturationlimiter, false);
|
||||
if (enablelimiter->get_active () || enablelimiter->get_inconsistent())
|
||||
pack_start (*saturationlimiter);
|
||||
|
||||
lastACVal = pp->colorBoost.avoidclip;
|
||||
lastELVal = pp->colorBoost.enable_saturationlimiter;
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void ColorBoost::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
pp->colorBoost.amount = (int)colorboost->getValue();
|
||||
pp->colorBoost.avoidclip = avoidclip->get_active ();
|
||||
pp->colorBoost.enable_saturationlimiter = enablelimiter->get_active ();
|
||||
pp->colorBoost.saturationlimit = saturationlimiter->getValue ();
|
||||
|
||||
if (pedited) {
|
||||
pedited->colorBoost.amount = colorboost->getEditedState ();
|
||||
pedited->colorBoost.avoidclip = !avoidclip->get_inconsistent();
|
||||
pedited->colorBoost.enable_saturationlimiter = !enablelimiter->get_inconsistent();
|
||||
pedited->colorBoost.saturationlimit = saturationlimiter->getEditedState ();
|
||||
}
|
||||
}
|
||||
|
||||
void ColorBoost::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
|
||||
|
||||
colorboost->setDefault (defParams->colorBoost.amount);
|
||||
saturationlimiter->setDefault (defParams->colorBoost.saturationlimit);
|
||||
|
||||
if (pedited) {
|
||||
colorboost->setDefaultEditedState (pedited->colorBoost.amount ? Edited : UnEdited);
|
||||
saturationlimiter->setDefaultEditedState (pedited->colorBoost.saturationlimit ? Edited : UnEdited);
|
||||
}
|
||||
else {
|
||||
colorboost->setDefaultEditedState (Irrelevant);
|
||||
saturationlimiter->setDefaultEditedState (Irrelevant);
|
||||
}
|
||||
}
|
||||
|
||||
void ColorBoost::avoidclip_toggled () {
|
||||
|
||||
if (batchMode) {
|
||||
if (avoidclip->get_inconsistent()) {
|
||||
avoidclip->set_inconsistent (false);
|
||||
acconn.block (true);
|
||||
avoidclip->set_active (false);
|
||||
acconn.block (false);
|
||||
}
|
||||
else if (lastACVal)
|
||||
avoidclip->set_inconsistent (true);
|
||||
|
||||
lastACVal = avoidclip->get_active ();
|
||||
}
|
||||
|
||||
if (listener) {
|
||||
if (avoidclip->get_active ())
|
||||
listener->panelChanged (EvCBAvoidClip, M("GENERAL_ENABLED"));
|
||||
else
|
||||
listener->panelChanged (EvCBAvoidClip, M("GENERAL_DISABLED"));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorBoost::enablelimiter_toggled () {
|
||||
|
||||
if (batchMode) {
|
||||
if (enablelimiter->get_inconsistent()) {
|
||||
enablelimiter->set_inconsistent (false);
|
||||
elconn.block (true);
|
||||
enablelimiter->set_active (false);
|
||||
elconn.block (false);
|
||||
}
|
||||
else if (lastELVal)
|
||||
enablelimiter->set_inconsistent (true);
|
||||
|
||||
lastELVal = enablelimiter->get_active ();
|
||||
}
|
||||
|
||||
removeIfThere (this, saturationlimiter, false);
|
||||
if (enablelimiter->get_active () || enablelimiter->get_inconsistent())
|
||||
pack_start (*saturationlimiter);
|
||||
|
||||
if (listener) {
|
||||
if (enablelimiter->get_active ())
|
||||
listener->panelChanged (EvCBSatLimiter, M("GENERAL_ENABLED"));
|
||||
else
|
||||
listener->panelChanged (EvCBSatLimiter, M("GENERAL_DISABLED"));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorBoost::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
if (listener) {
|
||||
if (a!=saturationlimiter)
|
||||
listener->panelChanged (EvCBBoost, Glib::ustring::format ((int)a->getValue()));
|
||||
else
|
||||
listener->panelChanged (EvCBSatLimit, Glib::ustring::format (std::setw(2), std::fixed, std::setprecision(1), a->getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorBoost::setAdjusterBehavior (bool bcbadd) {
|
||||
|
||||
if (!cbAdd && bcbadd || cbAdd && !bcbadd)
|
||||
colorboost->setLimits (-100, 100, 1, 0);
|
||||
|
||||
cbAdd = bcbadd;
|
||||
}
|
||||
|
||||
void ColorBoost::setBatchMode (bool batchMode) {
|
||||
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
colorboost->showEditedCB ();
|
||||
saturationlimiter->showEditedCB ();
|
||||
}
|
||||
53
rtgui/colorboost.h
Executable file
53
rtgui/colorboost.h
Executable file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _COLORBOOST_H_
|
||||
#define _COLORBOOST_H_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <adjuster.h>
|
||||
#include <toolpanel.h>
|
||||
|
||||
class ColorBoost : public Gtk::VBox, public AdjusterListener, public ToolPanel {
|
||||
|
||||
protected:
|
||||
Adjuster* colorboost;
|
||||
Gtk::CheckButton* avoidclip;
|
||||
Gtk::CheckButton* enablelimiter;
|
||||
Adjuster* saturationlimiter;
|
||||
bool cbAdd;
|
||||
sigc::connection acconn, elconn;
|
||||
bool lastACVal, lastELVal;
|
||||
|
||||
public:
|
||||
|
||||
ColorBoost ();
|
||||
virtual ~ColorBoost ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
|
||||
void setBatchMode (bool batchMode);
|
||||
|
||||
void adjusterChanged (Adjuster* a, double newval);
|
||||
void avoidclip_toggled ();
|
||||
void enablelimiter_toggled ();
|
||||
void setAdjusterBehavior (bool bcbadd);
|
||||
};
|
||||
|
||||
#endif
|
||||
120
rtgui/colordenoise.cc
Executable file
120
rtgui/colordenoise.cc
Executable file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <colordenoise.h>
|
||||
#include <math.h>
|
||||
#include <iomanip>
|
||||
#include <guiutils.h>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
ColorDenoise::ColorDenoise () : ToolPanel() {
|
||||
|
||||
enabled = Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLED")));
|
||||
enabled->set_active (false);
|
||||
|
||||
amount = Gtk::manage (new Adjuster ("Amount", 1, 100, 1, 30));
|
||||
|
||||
pack_start (*enabled);
|
||||
pack_start (*Gtk::manage (new Gtk::HSeparator()));
|
||||
pack_start (*amount);
|
||||
|
||||
enaConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &ColorDenoise::enabledChanged) );
|
||||
amount->setAdjusterListener (this);
|
||||
|
||||
show_all_children ();
|
||||
}
|
||||
|
||||
void ColorDenoise::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
if (pedited) {
|
||||
amount->setEditedState (pedited->colorDenoise.amount ? Edited : UnEdited);
|
||||
enabled->set_inconsistent (!pedited->colorDenoise.enabled);
|
||||
}
|
||||
|
||||
enaConn.block (true);
|
||||
enabled->set_active (pp->colorDenoise.enabled);
|
||||
enaConn.block (false);
|
||||
|
||||
lastEnabled = pp->colorDenoise.enabled;
|
||||
|
||||
amount->setValue (pp->colorDenoise.amount);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void ColorDenoise::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
pp->colorDenoise.amount = amount->getValue ();
|
||||
pp->colorDenoise.enabled = enabled->get_active();
|
||||
|
||||
if (pedited) {
|
||||
pedited->colorDenoise.amount = amount->getEditedState ();
|
||||
pedited->colorDenoise.enabled = !enabled->get_inconsistent();
|
||||
}
|
||||
}
|
||||
|
||||
void ColorDenoise::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
|
||||
|
||||
amount->setDefault (defParams->colorDenoise.amount);
|
||||
|
||||
if (pedited)
|
||||
amount->setDefaultEditedState (pedited->colorDenoise.amount ? Edited : UnEdited);
|
||||
else
|
||||
amount->setDefaultEditedState (Irrelevant);
|
||||
}
|
||||
|
||||
void ColorDenoise::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
if (listener && enabled->get_active()) {
|
||||
|
||||
listener->panelChanged (EvCDNRadius, Glib::ustring::format (std::setw(2), std::fixed, std::setprecision(1), a->getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorDenoise::enabledChanged () {
|
||||
|
||||
if (batchMode) {
|
||||
if (enabled->get_inconsistent()) {
|
||||
enabled->set_inconsistent (false);
|
||||
enaConn.block (true);
|
||||
enabled->set_active (false);
|
||||
enaConn.block (false);
|
||||
}
|
||||
else if (lastEnabled)
|
||||
enabled->set_inconsistent (true);
|
||||
|
||||
lastEnabled = enabled->get_active ();
|
||||
}
|
||||
|
||||
if (listener) {
|
||||
if (enabled->get_active ())
|
||||
listener->panelChanged (EvCDNEnabled, M("GENERAL_ENABLED"));
|
||||
else
|
||||
listener->panelChanged (EvCDNEnabled, M("GENERAL_DISABLED"));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorDenoise::setBatchMode (bool batchMode) {
|
||||
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
amount->showEditedCB ();
|
||||
}
|
||||
47
rtgui/colordenoise.h
Executable file
47
rtgui/colordenoise.h
Executable file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _COLORDENOISE_H_
|
||||
#define _COLORDENOISE_H_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <adjuster.h>
|
||||
#include <toolpanel.h>
|
||||
|
||||
class ColorDenoise : public Gtk::VBox, public AdjusterListener, public ToolPanel {
|
||||
|
||||
protected:
|
||||
Adjuster* amount;
|
||||
Gtk::CheckButton* enabled;
|
||||
bool lastEnabled;
|
||||
sigc::connection enaConn;
|
||||
|
||||
public:
|
||||
|
||||
ColorDenoise ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
|
||||
void setBatchMode (bool batchMode);
|
||||
|
||||
void adjusterChanged (Adjuster* a, double newval);
|
||||
void enabledChanged ();
|
||||
};
|
||||
|
||||
#endif
|
||||
108
rtgui/colorshift.cc
Executable file
108
rtgui/colorshift.cc
Executable file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <colorshift.h>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
ColorShift::ColorShift () : ToolPanel(), aAdd(false), bAdd(false) {
|
||||
|
||||
ashift = Gtk::manage (new Adjuster (M("TP_COLORSHIFT_GREENMAGENTA"), -25, 25, 0.1, 0));
|
||||
pack_start (*ashift);
|
||||
|
||||
bshift = Gtk::manage (new Adjuster (M("TP_COLORSHIFT_BLUEYELLOW"), -25, 25, 0.1, 0));
|
||||
pack_start (*bshift);
|
||||
|
||||
ashift->setAdjusterListener (this);
|
||||
bshift->setAdjusterListener (this);
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
void ColorShift::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
if (pedited) {
|
||||
ashift->setEditedState (pedited->colorShift.a ? Edited : UnEdited);
|
||||
bshift->setEditedState (pedited->colorShift.b ? Edited : UnEdited);
|
||||
}
|
||||
|
||||
ashift->setValue (pp->colorShift.a);
|
||||
bshift->setValue (pp->colorShift.b);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void ColorShift::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
pp->colorShift.a = ashift->getValue ();
|
||||
pp->colorShift.b = bshift->getValue ();
|
||||
|
||||
if (pedited) {
|
||||
pedited->colorShift.a = ashift->getEditedState ();
|
||||
pedited->colorShift.b = bshift->getEditedState ();
|
||||
}
|
||||
}
|
||||
|
||||
void ColorShift::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
|
||||
|
||||
ashift->setDefault (defParams->colorShift.a);
|
||||
bshift->setDefault (defParams->colorShift.b);
|
||||
|
||||
if (pedited) {
|
||||
ashift->setDefaultEditedState (pedited->colorShift.a ? Edited : UnEdited);
|
||||
bshift->setDefaultEditedState (pedited->colorShift.b ? Edited : UnEdited);
|
||||
}
|
||||
else {
|
||||
ashift->setDefaultEditedState (Irrelevant);
|
||||
bshift->setDefaultEditedState (Irrelevant);
|
||||
}
|
||||
}
|
||||
|
||||
void ColorShift::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
if (!listener)
|
||||
return;
|
||||
|
||||
if (a==ashift)
|
||||
listener->panelChanged (EvCShiftA, Glib::ustring::format (std::setw(2), std::fixed, std::setprecision(1), a->getValue()));
|
||||
else if (a==bshift)
|
||||
listener->panelChanged (EvCShiftB, Glib::ustring::format (std::setw(2), std::fixed, std::setprecision(1), a->getValue()));
|
||||
}
|
||||
|
||||
void ColorShift::setAdjusterBehavior (bool baadd, bool bbadd) {
|
||||
|
||||
if (!aAdd && baadd || aAdd && !baadd)
|
||||
ashift->setLimits (-25, 25, 0.1, 0);
|
||||
|
||||
if (!bAdd && bbadd || bAdd && !bbadd)
|
||||
bshift->setLimits (-25, 25, 0.1, 0);
|
||||
|
||||
aAdd = baadd;
|
||||
bAdd = bbadd;
|
||||
}
|
||||
|
||||
void ColorShift::setBatchMode (bool batchMode) {
|
||||
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
ashift->showEditedCB ();
|
||||
bshift->showEditedCB ();
|
||||
}
|
||||
46
rtgui/colorshift.h
Executable file
46
rtgui/colorshift.h
Executable file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _COLORSHIFT_H_
|
||||
#define _COLORSHIFT_H_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <adjuster.h>
|
||||
#include <toolpanel.h>
|
||||
|
||||
class ColorShift : public Gtk::VBox, public AdjusterListener, public ToolPanel {
|
||||
|
||||
protected:
|
||||
Adjuster* ashift;
|
||||
Adjuster* bshift;
|
||||
bool aAdd, bAdd;
|
||||
|
||||
public:
|
||||
|
||||
ColorShift ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
|
||||
void setBatchMode (bool batchMode);
|
||||
|
||||
void adjusterChanged (Adjuster* a, double newval);
|
||||
void setAdjusterBehavior (bool baadd, bool bbadd);
|
||||
};
|
||||
|
||||
#endif
|
||||
25
rtgui/config.h.in
Normal file
25
rtgui/config.h.in
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2010 Lukas Jirkovsky <l.jirkovsky@gmail.com>
|
||||
*
|
||||
* 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 __CONFIG_H__
|
||||
#define __CONFIG_H__
|
||||
|
||||
#define DATA_SEARCH_PATH "${DATADIR}"
|
||||
|
||||
#endif
|
||||
200
rtgui/createicon.cc
Executable file
200
rtgui/createicon.cc
Executable file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <png.h>
|
||||
|
||||
void png_read_data(png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||
png_size_t check;
|
||||
|
||||
/* fread() returns 0 on error, so it is OK to store this in a png_size_t
|
||||
* instead of an int, which is what fread() actually returns.
|
||||
*/
|
||||
check = (png_size_t)fread(data, (png_size_t)1, length, (FILE *)png_ptr->io_ptr);
|
||||
|
||||
if (check != length)
|
||||
{
|
||||
png_error(png_ptr, "Read Error");
|
||||
}
|
||||
}
|
||||
|
||||
void png_write_data(png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||
png_uint_32 check;
|
||||
|
||||
check = fwrite(data, 1, length, (FILE *)(png_ptr->io_ptr));
|
||||
if (check != length)
|
||||
{
|
||||
png_error(png_ptr, "Write Error");
|
||||
}
|
||||
}
|
||||
|
||||
void png_flush(png_structp png_ptr) {
|
||||
FILE *io_ptr;
|
||||
io_ptr = (FILE *)CVT_PTR((png_ptr->io_ptr));
|
||||
if (io_ptr != NULL)
|
||||
fflush(io_ptr);
|
||||
}
|
||||
|
||||
|
||||
unsigned char* loadPNG (char* fname, int& w, int& h) {
|
||||
|
||||
FILE *file = fopen (fname,"rb");
|
||||
|
||||
unsigned char header[8];
|
||||
fread (header, 1, 8, file);
|
||||
|
||||
png_structp png = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0);
|
||||
png_infop info = png_create_info_struct (png);
|
||||
png_infop end_info = png_create_info_struct (png);
|
||||
if (setjmp (png_jmpbuf(png))) {
|
||||
png_destroy_read_struct (&png, &info, &end_info);
|
||||
fclose (file);
|
||||
return NULL;
|
||||
}
|
||||
//set up png read
|
||||
png_set_read_fn (png, file, png_read_data);
|
||||
png_set_sig_bytes (png,8);
|
||||
|
||||
png_read_info(png,info);
|
||||
|
||||
unsigned long width,height;
|
||||
int bit_depth,color_type,interlace_type,compression_type,filter_method;
|
||||
png_get_IHDR(png,info,&width,&height,&bit_depth,&color_type,&interlace_type,
|
||||
&compression_type, &filter_method);
|
||||
|
||||
//converting to 32bpp format
|
||||
if (color_type==PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png);
|
||||
|
||||
if (color_type==PNG_COLOR_TYPE_GRAY || color_type==PNG_COLOR_TYPE_GRAY_ALPHA)
|
||||
png_set_gray_to_rgb(png);
|
||||
|
||||
if (png_get_valid(png,info,PNG_INFO_tRNS)) png_set_tRNS_to_alpha(png);
|
||||
|
||||
if (interlace_type!=PNG_INTERLACE_NONE) {
|
||||
png_destroy_read_struct (&png, &info, &end_info);
|
||||
fclose (file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA)
|
||||
png_set_strip_alpha(png);
|
||||
|
||||
//setting gamma
|
||||
double gamma;
|
||||
if (png_get_gAMA(png,info,&gamma))
|
||||
png_set_gamma(png, 2.0, gamma);
|
||||
else
|
||||
png_set_gamma(png,2.0, 0.45455);
|
||||
|
||||
int bps = 8;
|
||||
|
||||
//updating png info struct
|
||||
png_read_update_info(png,info);
|
||||
png_get_IHDR(png,info,&width,&height,&bit_depth,&color_type,&interlace_type,
|
||||
&compression_type, &filter_method);
|
||||
|
||||
if (color_type & PNG_COLOR_MASK_ALPHA)
|
||||
png_set_strip_alpha(png);
|
||||
|
||||
png_read_update_info(png,info);
|
||||
png_get_IHDR(png,info,&width,&height,&bit_depth,&color_type,&interlace_type,
|
||||
&compression_type, &filter_method);
|
||||
|
||||
|
||||
unsigned char* data = new unsigned char[width*height*3];
|
||||
int rowlen = width*3;
|
||||
unsigned char *row = new unsigned char [rowlen];
|
||||
|
||||
for (unsigned int i=0;i<height;i++) {
|
||||
|
||||
png_read_row (png, (png_byte*)row, NULL);
|
||||
memcpy (data+3*i*width, row, 3*width);
|
||||
}
|
||||
|
||||
png_read_end (png, 0);
|
||||
png_destroy_read_struct (&png, &info, &end_info);
|
||||
|
||||
delete [] row;
|
||||
fclose(file);
|
||||
|
||||
w = width;
|
||||
h = height;
|
||||
return data;
|
||||
}
|
||||
|
||||
void savePNG (char* fname, unsigned char* data1, unsigned char* data2, int w, int h) {
|
||||
|
||||
FILE* file = fopen(fname,"wb");
|
||||
|
||||
png_structp png = png_create_write_struct (PNG_LIBPNG_VER_STRING,0,0,0);
|
||||
png_infop info = png_create_info_struct(png);
|
||||
|
||||
if (setjmp(png_jmpbuf(png))) {
|
||||
png_destroy_write_struct (&png,&info);
|
||||
fclose(file);
|
||||
return;
|
||||
}
|
||||
|
||||
png_set_write_fn (png, file, png_write_data, png_flush);
|
||||
png_set_compression_level(png,6);
|
||||
|
||||
int width = w;
|
||||
int height = h;
|
||||
int bps = 8;
|
||||
|
||||
png_set_IHDR(png, info, width, height, bps, PNG_COLOR_TYPE_RGB_ALPHA,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_BASE);
|
||||
|
||||
|
||||
int rowlen = width*4;
|
||||
unsigned char *row = new unsigned char [rowlen];
|
||||
|
||||
png_write_info(png,info);
|
||||
for (unsigned int i=0;i<height;i++) {
|
||||
for (int j=0; j<width; j++) {
|
||||
int ofs = 3*(width*i+j);
|
||||
unsigned char alpha = data2[ofs] - data1[ofs];
|
||||
if (i==8 && j==8)
|
||||
printf ("alpha=%d pix=%d\n",(int)alpha, (int)(data1[ofs+0] / (1.0 - alpha/255.0)));
|
||||
if (alpha<255) {
|
||||
row[4*j+0] = data1[ofs+0] / (1.0 - alpha/255.0);
|
||||
row[4*j+1] = data1[ofs+1] / (1.0 - alpha/255.0);
|
||||
row[4*j+2] = data1[ofs+2] / (1.0 - alpha/255.0);
|
||||
}
|
||||
else {
|
||||
|
||||
}
|
||||
row[4*j+3] = 255-alpha;
|
||||
}
|
||||
png_write_row (png, (png_byte*)row);
|
||||
}
|
||||
|
||||
png_write_end(png,info);
|
||||
png_destroy_write_struct(&png,&info);
|
||||
|
||||
delete [] row;
|
||||
fclose (file);
|
||||
}
|
||||
|
||||
int main (int argc, char* argv[]) {
|
||||
|
||||
int w, h;
|
||||
unsigned char* data1 = loadPNG (argv[1], w, h);
|
||||
unsigned char* data2 = loadPNG (argv[2], w, h);
|
||||
savePNG (argv[3], data1, data2, w, h);
|
||||
|
||||
}
|
||||
973
rtgui/crop.cc
Executable file
973
rtgui/crop.cc
Executable file
@@ -0,0 +1,973 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <crop.h>
|
||||
#include <options.h>
|
||||
#include <guiutils.h>
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
extern Glib::ustring argv0;
|
||||
extern Options options;
|
||||
|
||||
class RefreshSpinHelper {
|
||||
|
||||
public:
|
||||
Crop* crop;
|
||||
bool notify;
|
||||
RefreshSpinHelper (Crop* _crop, bool _notify)
|
||||
: crop(_crop), notify(_notify) {}
|
||||
};
|
||||
|
||||
Crop::Crop () {
|
||||
|
||||
clistener = NULL;
|
||||
|
||||
maxw = 3000;
|
||||
maxh = 2000;
|
||||
|
||||
enabled = Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLED")));
|
||||
enabled->set_active (false);
|
||||
pack_start(*enabled);
|
||||
|
||||
pack_start(*Gtk::manage (new Gtk::HSeparator()));
|
||||
|
||||
Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ());
|
||||
|
||||
hb1->pack_start (*Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("TP_CROP_X") +": ")));
|
||||
x = Gtk::manage (new Gtk::SpinButton ());
|
||||
x->set_size_request (60, -1);
|
||||
hb1->pack_start (*x);
|
||||
|
||||
hb1->pack_start (*Gtk::manage (new Gtk::Label (Glib::ustring(" ") + M("TP_CROP_Y") + ": ")));
|
||||
y = Gtk::manage (new Gtk::SpinButton ());
|
||||
y->set_size_request (60, -1);
|
||||
hb1->pack_start (*y);
|
||||
|
||||
pack_start (*hb1, Gtk::PACK_SHRINK, 2);
|
||||
|
||||
Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ());
|
||||
|
||||
hb2->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_W") + ": ")));
|
||||
w = Gtk::manage (new Gtk::SpinButton ());
|
||||
w->set_size_request (60, -1);
|
||||
hb2->pack_start (*w);
|
||||
|
||||
hb2->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_H") + ": ")));
|
||||
h = Gtk::manage (new Gtk::SpinButton ());
|
||||
h->set_size_request (60, -1);
|
||||
hb2->pack_start (*h);
|
||||
|
||||
pack_start (*hb2, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
selectCrop = Gtk::manage (new Gtk::Button (M("TP_CROP_SELECTCROP")));
|
||||
selectCrop->set_image (*Gtk::manage (new Gtk::Image (argv0+"/images/crop16.png")));
|
||||
|
||||
pack_start (*selectCrop, Gtk::PACK_SHRINK, 2);
|
||||
|
||||
Gtk::HBox* hb3 = Gtk::manage (new Gtk::HBox ());
|
||||
|
||||
fixr = Gtk::manage (new Gtk::CheckButton (M("TP_CROP_FIXRATIO")));
|
||||
fixr->set_active (1);
|
||||
|
||||
hb3->pack_start (*fixr, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
ratio = Gtk::manage (new Gtk::ComboBoxText ());
|
||||
hb3->pack_start (*ratio, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
orientation = Gtk::manage (new Gtk::ComboBoxText ());
|
||||
hb3->pack_start (*orientation);
|
||||
|
||||
pack_start (*hb3, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
Gtk::HBox* hb31 = Gtk::manage (new Gtk::HBox ());
|
||||
|
||||
hb31->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_GUIDETYPE"))), Gtk::PACK_SHRINK, 4);
|
||||
guide = Gtk::manage (new Gtk::ComboBoxText ());
|
||||
hb31->pack_start (*guide);
|
||||
|
||||
pack_start (*hb31, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
dpibox = Gtk::manage (new Gtk::VBox());
|
||||
dpibox->pack_start (*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_SHRINK, 2);
|
||||
|
||||
Gtk::HBox* hb4 = Gtk::manage (new Gtk::HBox ());
|
||||
hb4->pack_start (*Gtk::manage (new Gtk::Label (M("TP_CROP_DPI"))));
|
||||
dpi = Gtk::manage (new Gtk::SpinButton ());
|
||||
dpi->set_size_request (60, -1);
|
||||
hb4->pack_start (*dpi);
|
||||
|
||||
dpibox->pack_start (*hb4, Gtk::PACK_SHRINK, 2);
|
||||
|
||||
sizecm = Gtk::manage (new Gtk::Label (M("GENERAL_NA") + " cm x " + M("GENERAL_NA") + " cm"));
|
||||
sizein = Gtk::manage (new Gtk::Label (M("GENERAL_NA") + " in x " + M("GENERAL_NA") + " in"));
|
||||
|
||||
dpibox->pack_start (*sizecm, Gtk::PACK_SHRINK, 1);
|
||||
dpibox->pack_start (*sizein, Gtk::PACK_SHRINK, 1);
|
||||
|
||||
pack_start (*dpibox, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
dpi->set_value (300);
|
||||
|
||||
ratio->append_text ("3:2");
|
||||
ratio->append_text ("4:3");
|
||||
ratio->append_text ("16:9");
|
||||
ratio->append_text ("16:10");
|
||||
ratio->append_text ("5:4");
|
||||
ratio->append_text ("2:1");
|
||||
ratio->append_text ("1:1");
|
||||
ratio->append_text ("DIN");
|
||||
ratio->set_active (0);
|
||||
|
||||
orientation->append_text (M("GENERAL_LANDSCAPE"));
|
||||
orientation->append_text (M("GENERAL_PORTRAIT"));
|
||||
orientation->set_active (0);
|
||||
|
||||
guide->append_text (M("TP_CROP_GTNONE"));
|
||||
guide->append_text (M("TP_CROP_GTRULETHIRDS"));
|
||||
guide->append_text (M("TP_CROP_GTDIAGONALS"));
|
||||
guide->append_text (M("TP_CROP_GTHARMMEANS1"));
|
||||
guide->append_text (M("TP_CROP_GTHARMMEANS2"));
|
||||
guide->append_text (M("TP_CROP_GTHARMMEANS3"));
|
||||
guide->append_text (M("TP_CROP_GTHARMMEANS4"));
|
||||
guide->set_active (0);
|
||||
|
||||
w->set_range (0, maxw);
|
||||
h->set_range (0, maxh);
|
||||
x->set_range (0, maxw);
|
||||
y->set_range (0, maxh);
|
||||
|
||||
x->set_digits (0);
|
||||
x->set_increments (1,100);
|
||||
x->set_value (0);
|
||||
|
||||
y->set_digits (0);
|
||||
y->set_increments (1,100);
|
||||
y->set_value (0);
|
||||
|
||||
w->set_digits (0);
|
||||
w->set_increments (1,100);
|
||||
w->set_value (200);
|
||||
|
||||
h->set_digits (0);
|
||||
h->set_increments (1,100);
|
||||
h->set_value (200);
|
||||
|
||||
dpi->set_digits (0);
|
||||
dpi->set_increments (1,100);
|
||||
dpi->set_range (50, 12000);
|
||||
dpi->set_value (300);
|
||||
|
||||
xconn = x->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::positionChanged), true);
|
||||
yconn = y->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::positionChanged), true);
|
||||
wconn = w->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::widthChanged), true);
|
||||
hconn = h->signal_value_changed().connect ( sigc::mem_fun(*this, &Crop::heightChanged), true);
|
||||
econn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &Crop::enabledChanged) );
|
||||
fconn = fixr->signal_toggled().connect( sigc::mem_fun(*this, &Crop::ratioChanged) );
|
||||
rconn = ratio->signal_changed().connect( sigc::mem_fun(*this, &Crop::ratioChanged) );
|
||||
oconn = orientation->signal_changed().connect( sigc::mem_fun(*this, &Crop::ratioChanged) );
|
||||
gconn = guide->signal_changed().connect( sigc::mem_fun(*this, &Crop::notifyListener) );
|
||||
selectCrop->signal_pressed().connect( sigc::mem_fun(*this, &Crop::selectPressed) );
|
||||
dpi->signal_value_changed().connect( sigc::mem_fun(*this, &Crop::refreshSize) );
|
||||
|
||||
nx = ny = nw = nh = 0;
|
||||
nsx = nsy = nsw = nsh = 0;
|
||||
lastScale = 1.0;
|
||||
lastRotationDeg = 0;
|
||||
show_all ();
|
||||
}
|
||||
|
||||
void Crop::writeOptions () {
|
||||
|
||||
options.cropDPI = (int)dpi->get_value ();
|
||||
}
|
||||
|
||||
void Crop::readOptions () {
|
||||
|
||||
disableListener ();
|
||||
|
||||
dpi->set_value (options.cropDPI);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void Crop::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
xconn.block (true);
|
||||
yconn.block (true);
|
||||
wconn.block (true);
|
||||
hconn.block (true);
|
||||
rconn.block (true);
|
||||
fconn.block (true);
|
||||
oconn.block (true);
|
||||
gconn.block (true);
|
||||
enabled->set_active (pp->crop.enabled);
|
||||
|
||||
// check if the new values are larger than the maximum
|
||||
double tmp, maxw, maxh;
|
||||
w->get_range (tmp, maxw);
|
||||
h->get_range (tmp, maxh);
|
||||
if (pp->crop.x + pp->crop.w > maxw || pp->crop.y + pp->crop.h > maxh)
|
||||
setDimensions (pp->crop.x + pp->crop.w, pp->crop.y + pp->crop.h);
|
||||
|
||||
ratio->set_active_text (pp->crop.ratio);
|
||||
fixr->set_active (pp->crop.fixratio);
|
||||
|
||||
if (pp->crop.orientation == "Landscape")
|
||||
orientation->set_active (0);
|
||||
else if (pp->crop.orientation == "Portrait")
|
||||
orientation->set_active (1);
|
||||
|
||||
if (pp->crop.guide == "None")
|
||||
guide->set_active (0);
|
||||
else if (pp->crop.guide == "Rule of thirds")
|
||||
guide->set_active (1);
|
||||
else if (pp->crop.guide == "Rule of diagonals")
|
||||
guide->set_active (2);
|
||||
else if (pp->crop.guide == "Harmonic means 1")
|
||||
guide->set_active (3);
|
||||
else if (pp->crop.guide == "Harmonic means 2")
|
||||
guide->set_active (4);
|
||||
else if (pp->crop.guide == "Harmonic means 3")
|
||||
guide->set_active (5);
|
||||
else if (pp->crop.guide == "Harmonic means 4")
|
||||
guide->set_active (6);
|
||||
|
||||
x->set_value (pp->crop.x);
|
||||
y->set_value (pp->crop.y);
|
||||
w->set_value (pp->crop.w);
|
||||
h->set_value (pp->crop.h);
|
||||
|
||||
nx = pp->crop.x;
|
||||
ny = pp->crop.y;
|
||||
nw = pp->crop.w;
|
||||
nh = pp->crop.h;
|
||||
|
||||
if (pp->resize.enabled)
|
||||
lastScale = pp->resize.scale;
|
||||
else
|
||||
lastScale = 1.0;
|
||||
nsx = nx / lastScale;
|
||||
nsy = ny / lastScale;
|
||||
nsw = nw / lastScale;
|
||||
nsh = nh / lastScale;
|
||||
lastRotationDeg = pp->coarse.rotate;
|
||||
|
||||
wDirty = false;
|
||||
hDirty = false;
|
||||
xDirty = false;
|
||||
yDirty = false;
|
||||
|
||||
if (pedited) {
|
||||
wDirty = pedited->crop.w;
|
||||
hDirty = pedited->crop.h;
|
||||
xDirty = pedited->crop.x;
|
||||
yDirty = pedited->crop.y;
|
||||
if (!pedited->crop.ratio)
|
||||
ratio->set_active (8);
|
||||
if (!pedited->crop.orientation)
|
||||
orientation->set_active (2);
|
||||
if (!pedited->crop.guide)
|
||||
guide->set_active (7);
|
||||
enabled->set_inconsistent (!pedited->crop.enabled);
|
||||
fixr->set_inconsistent (!pedited->crop.fixratio);
|
||||
}
|
||||
|
||||
lastEnabled = pp->crop.enabled;
|
||||
lastAspect = pp->crop.fixratio;
|
||||
|
||||
xconn.block (false);
|
||||
yconn.block (false);
|
||||
wconn.block (false);
|
||||
hconn.block (false);
|
||||
rconn.block (false);
|
||||
fconn.block (false);
|
||||
oconn.block (false);
|
||||
gconn.block (false);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void Crop::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
pp->crop.enabled = enabled->get_active ();
|
||||
pp->crop.x = nx;
|
||||
pp->crop.y = ny;
|
||||
pp->crop.w = nw;
|
||||
pp->crop.h = nh;
|
||||
pp->crop.fixratio = fixr->get_active ();
|
||||
pp->crop.ratio = ratio->get_active_text ();
|
||||
|
||||
if (orientation->get_active_row_number()==0)
|
||||
pp->crop.orientation = "Landscape";
|
||||
else if (orientation->get_active_row_number()==1)
|
||||
pp->crop.orientation = "Portrait";
|
||||
|
||||
if (guide->get_active_row_number()==0)
|
||||
pp->crop.guide = "None";
|
||||
else if (guide->get_active_row_number()==1)
|
||||
pp->crop.guide = "Rule of thirds";
|
||||
else if (guide->get_active_row_number()==2)
|
||||
pp->crop.guide = "Rule of diagonals";
|
||||
else if (guide->get_active_row_number()==3)
|
||||
pp->crop.guide = "Harmonic means 1";
|
||||
else if (guide->get_active_row_number()==4)
|
||||
pp->crop.guide = "Harmonic means 2";
|
||||
else if (guide->get_active_row_number()==5)
|
||||
pp->crop.guide = "Harmonic means 3";
|
||||
else if (guide->get_active_row_number()==6)
|
||||
pp->crop.guide = "Harmonic means 4";
|
||||
|
||||
if (pedited) {
|
||||
pedited->crop.enabled = !enabled->get_inconsistent();
|
||||
pedited->crop.ratio = ratio->get_active_row_number() != 8;
|
||||
pedited->crop.orientation = orientation->get_active_row_number() != 2;
|
||||
pedited->crop.guide = guide->get_active_row_number() != 7;
|
||||
pedited->crop.fixratio = !fixr->get_inconsistent();
|
||||
pedited->crop.w = wDirty;
|
||||
pedited->crop.h = hDirty;
|
||||
pedited->crop.x = xDirty;
|
||||
pedited->crop.y = yDirty;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Crop::selectPressed () {
|
||||
|
||||
if (clistener)
|
||||
clistener->cropSelectRequested ();
|
||||
}
|
||||
|
||||
void Crop::notifyListener () {
|
||||
|
||||
if (listener && enabled->get_active ())
|
||||
listener->panelChanged (EvCrop, Glib::ustring::compose ("%1=%2, %3=%4\n%5=%6, %7=%8", M("TP_CROP_X"), nx, M("TP_CROP_Y"), ny, M("TP_CROP_W"), nw, M("TP_CROP_H"), nh));
|
||||
}
|
||||
|
||||
void Crop::enabledChanged () {
|
||||
|
||||
if (batchMode) {
|
||||
if (enabled->get_inconsistent()) {
|
||||
enabled->set_inconsistent (false);
|
||||
econn.block (true);
|
||||
enabled->set_active (false);
|
||||
econn.block (false);
|
||||
}
|
||||
else if (lastEnabled)
|
||||
enabled->set_inconsistent (true);
|
||||
|
||||
lastEnabled = enabled->get_active ();
|
||||
}
|
||||
|
||||
if (listener) {
|
||||
if (enabled->get_active ())
|
||||
listener->panelChanged (EvCrop, Glib::ustring::compose ("%1=%2, %3=%4\n%5=%6, %7=%8", M("TP_CROP_X"), nx, M("TP_CROP_Y"), ny, M("TP_CROP_W"), nw, M("TP_CROP_H"), nh));
|
||||
else
|
||||
listener->panelChanged (EvCrop, M("GENERAL_DISABLED"));
|
||||
}
|
||||
}
|
||||
|
||||
int notifylistener (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
((Crop*)data)->notifyListener ();
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int refreshspins (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
RefreshSpinHelper* rsh = (RefreshSpinHelper*) data;
|
||||
rsh->crop->refreshSpins (rsh->notify);
|
||||
delete rsh;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Crop::resizeScaleChanged (double rsc) {
|
||||
|
||||
lastScale = rsc;
|
||||
|
||||
nx = (int)round (nsx * rsc);
|
||||
ny = (int)round (nsy * rsc);
|
||||
nw = (int)round (nsw * rsc);
|
||||
nh = (int)round (nsh * rsc);
|
||||
|
||||
if (nx+nw > maxw || ny+nh > maxh)
|
||||
setDimensions (nx+nw, ny+nh);
|
||||
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, false));
|
||||
}
|
||||
|
||||
void Crop::hFlipCrop () {
|
||||
|
||||
nx = maxw - nx - nw;
|
||||
nsx = nx / lastScale;
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, false));
|
||||
}
|
||||
|
||||
void Crop::vFlipCrop () {
|
||||
|
||||
ny = maxh - ny - nh;
|
||||
nsy = ny / lastScale;
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, false));
|
||||
}
|
||||
|
||||
void Crop::rotateCrop (int deg) {
|
||||
|
||||
int tmp;
|
||||
switch ((360+deg-lastRotationDeg)%360) {
|
||||
case 90:
|
||||
tmp = nx;
|
||||
nx = maxh - ny - nh;
|
||||
ny = tmp;
|
||||
tmp = nw;
|
||||
nw = nh;
|
||||
nh = tmp;
|
||||
break;
|
||||
case 270:
|
||||
tmp = ny;
|
||||
ny = maxw - nx - nw;
|
||||
nx = tmp;
|
||||
tmp = nw;
|
||||
nw = nh;
|
||||
nh = tmp;
|
||||
break;
|
||||
case 180:
|
||||
nx = maxw - nx - nw;
|
||||
ny = maxh - ny - nh;
|
||||
break;
|
||||
}
|
||||
nsx = nx / lastScale;
|
||||
nsy = ny / lastScale;
|
||||
nsw = nw / lastScale;
|
||||
nsh = nh / lastScale;
|
||||
|
||||
lastRotationDeg = deg;
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, false));
|
||||
}
|
||||
|
||||
void Crop::positionChanged () {
|
||||
|
||||
xDirty = true;
|
||||
yDirty = true;
|
||||
|
||||
int X = (int)x->get_value ();
|
||||
int Y = (int)y->get_value ();
|
||||
int W = nw;
|
||||
int H = nh;
|
||||
cropMoved (X, Y, W, H);
|
||||
g_idle_add (notifylistener, this);
|
||||
}
|
||||
|
||||
void Crop::widthChanged () {
|
||||
|
||||
wDirty = true;
|
||||
|
||||
int X = nx;
|
||||
int Y = ny;
|
||||
int W = (int)w->get_value ();
|
||||
int H = nh;
|
||||
cropWidth2Resized (X, Y, W, H);
|
||||
g_idle_add (notifylistener, this);
|
||||
}
|
||||
|
||||
void Crop::heightChanged () {
|
||||
|
||||
hDirty = true;
|
||||
|
||||
int X = nx;
|
||||
int Y = ny;
|
||||
int W = nw;
|
||||
int H = (int)h->get_value ();
|
||||
cropHeight2Resized (X, Y, W, H);
|
||||
g_idle_add (notifylistener, this);
|
||||
}
|
||||
|
||||
|
||||
void Crop::ratioChanged () {
|
||||
|
||||
if (batchMode && lastAspect != fixr->get_active ()) {
|
||||
if (fixr->get_inconsistent()) {
|
||||
fixr->set_inconsistent (false);
|
||||
fconn.block (true);
|
||||
fixr->set_active (false);
|
||||
fconn.block (false);
|
||||
}
|
||||
else if (lastAspect)
|
||||
fixr->set_inconsistent (true);
|
||||
|
||||
lastAspect = fixr->get_active ();
|
||||
}
|
||||
|
||||
|
||||
if (fixr->get_active() && !fixr->get_inconsistent()) {
|
||||
|
||||
// int W = w->get_value ();
|
||||
// int H = h->get_value ();
|
||||
int W = nw;
|
||||
int H = nh;
|
||||
int X = nx;
|
||||
int Y = ny;
|
||||
if (W>=H)
|
||||
cropWidth2Resized (X, Y, W, H);
|
||||
else
|
||||
cropHeight2Resized (X, Y, W, H);
|
||||
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, true));
|
||||
}
|
||||
}
|
||||
|
||||
void Crop::refreshSize () {
|
||||
|
||||
if (!batchMode) {
|
||||
|
||||
std::ostringstream ostrin;
|
||||
ostrin.precision (3);
|
||||
// ostrin << h->get_value()/dpi->get_value() << " in x " << w->get_value()/dpi->get_value() << " in";;
|
||||
ostrin << nh/dpi->get_value() << " in x " << nw/dpi->get_value() << " in";;
|
||||
|
||||
sizein->set_text (ostrin.str ());
|
||||
|
||||
std::ostringstream ostrcm;
|
||||
ostrcm.precision (3);
|
||||
// ostrcm << h->get_value()/dpi->get_value()*2.54 << " cm x " << w->get_value()/dpi->get_value()*2.54 << " cm";;
|
||||
ostrcm << nh/dpi->get_value()*2.54 << " cm x " << nw/dpi->get_value()*2.54 << " cm";;
|
||||
|
||||
sizecm->set_text (ostrcm.str ());
|
||||
}
|
||||
}
|
||||
|
||||
void Crop::setDimensions (int mw, int mh) {
|
||||
|
||||
maxw = mw;
|
||||
maxh = mh;
|
||||
|
||||
xconn.block (true);
|
||||
yconn.block (true);
|
||||
wconn.block (true);
|
||||
hconn.block (true);
|
||||
|
||||
w->set_range (0, maxw);
|
||||
h->set_range (0, maxh);
|
||||
x->set_range (0, maxw);
|
||||
y->set_range (0, maxh);
|
||||
|
||||
xconn.block (false);
|
||||
yconn.block (false);
|
||||
wconn.block (false);
|
||||
hconn.block (false);
|
||||
|
||||
if (enabled->get_active()==false) {
|
||||
nx = 0;
|
||||
ny = 0;
|
||||
nw = mw;
|
||||
nh = mh;
|
||||
|
||||
nsx = nx / lastScale;
|
||||
nsy = ny / lastScale;
|
||||
nsw = nw / lastScale;
|
||||
nsh = nh / lastScale;
|
||||
refreshSpins ();
|
||||
}
|
||||
refreshSize ();
|
||||
}
|
||||
|
||||
struct setdimparams {
|
||||
Crop* crop;
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
int setdim (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
setdimparams* params = (setdimparams*)data;
|
||||
params->crop->setDimensions (params->x, params->y);
|
||||
delete params;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Crop::sizeChanged (int x, int y, int ow, int oh) {
|
||||
|
||||
setdimparams* params = new setdimparams;
|
||||
params->x = x;
|
||||
params->y = y;
|
||||
params->crop = this;
|
||||
g_idle_add (setdim, params);
|
||||
}
|
||||
|
||||
bool Crop::refreshSpins (bool notify) {
|
||||
|
||||
xconn.block (true);
|
||||
yconn.block (true);
|
||||
wconn.block (true);
|
||||
hconn.block (true);
|
||||
|
||||
x->set_value (nx);
|
||||
y->set_value (ny);
|
||||
w->set_value (nw);
|
||||
h->set_value (nh);
|
||||
|
||||
xDirty = true;
|
||||
yDirty = true;
|
||||
wDirty = true;
|
||||
hDirty = true;
|
||||
|
||||
xconn.block (false);
|
||||
yconn.block (false);
|
||||
wconn.block (false);
|
||||
hconn.block (false);
|
||||
|
||||
refreshSize ();
|
||||
if (notify)
|
||||
notifyListener ();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Crop::cropMoved (int &X, int &Y, int &W, int &H) {
|
||||
|
||||
// W = w->get_value ();
|
||||
// H = h->get_value ();
|
||||
W = nw;
|
||||
H = nh;
|
||||
|
||||
if (X+W>maxw)
|
||||
X = maxw-W;
|
||||
if (Y+H>maxh)
|
||||
Y = maxh-H;
|
||||
if (X<0)
|
||||
X = 0;
|
||||
if (Y<0)
|
||||
Y = 0;
|
||||
|
||||
nx = X;
|
||||
ny = Y;
|
||||
nw = W;
|
||||
nh = H;
|
||||
|
||||
nsx = nx / lastScale;
|
||||
nsy = ny / lastScale;
|
||||
nsw = nw / lastScale;
|
||||
nsh = nh / lastScale;
|
||||
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, false));
|
||||
// Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins));
|
||||
}
|
||||
|
||||
void Crop::cropWidth1Resized (int &X, int &Y, int &W, int &H) {
|
||||
|
||||
if (W<0)
|
||||
W = 0;
|
||||
if (H<0)
|
||||
H = 0;
|
||||
|
||||
if (X<0) {
|
||||
W += X;
|
||||
X = 0;
|
||||
}
|
||||
if (fixr->get_active()) {
|
||||
double r = getRatio();
|
||||
int W2max = (int)round(r*(maxh-Y));
|
||||
if (W>W2max) {
|
||||
X += W - W2max;
|
||||
W = W2max;
|
||||
}
|
||||
H = (int)round(W / r);
|
||||
}
|
||||
|
||||
nx = X;
|
||||
ny = Y;
|
||||
nw = W;
|
||||
nh = H;
|
||||
|
||||
nsx = nx / lastScale;
|
||||
nsy = ny / lastScale;
|
||||
nsw = nw / lastScale;
|
||||
nsh = nh / lastScale;
|
||||
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, false));
|
||||
// Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins));
|
||||
}
|
||||
|
||||
void Crop::cropWidth2Resized (int &X, int &Y, int &W, int &H) {
|
||||
|
||||
// X = x->get_value ();
|
||||
// Y = y->get_value ();
|
||||
X = nx;
|
||||
Y = ny;
|
||||
|
||||
if (W<0)
|
||||
W = 0;
|
||||
if (H<0)
|
||||
H = 0;
|
||||
|
||||
if (W>maxw-X)
|
||||
W = maxw-X;
|
||||
|
||||
if (fixr->get_active()) {
|
||||
double r = getRatio();
|
||||
int W2max = (int)round(r*(maxh-Y));
|
||||
if (W>W2max)
|
||||
W = W2max;
|
||||
H = (int)round(W / r);
|
||||
}
|
||||
|
||||
nx = X;
|
||||
ny = Y;
|
||||
nw = W;
|
||||
nh = H;
|
||||
|
||||
nsx = nx / lastScale;
|
||||
nsy = ny / lastScale;
|
||||
nsw = nw / lastScale;
|
||||
nsh = nh / lastScale;
|
||||
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, false));
|
||||
// Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins));
|
||||
}
|
||||
|
||||
void Crop::cropHeight1Resized (int &X, int &Y, int &W, int &H) {
|
||||
|
||||
if (W<0)
|
||||
W = 0;
|
||||
if (H<0)
|
||||
H = 0;
|
||||
|
||||
if (Y<0) {
|
||||
H += Y;
|
||||
Y = 0;
|
||||
}
|
||||
|
||||
if (fixr->get_active()) {
|
||||
double r = getRatio();
|
||||
int H2max = (int)round((maxw-X) / r);
|
||||
if (H>H2max) {
|
||||
Y += H - H2max;
|
||||
H = H2max;
|
||||
}
|
||||
W = (int)round(H * r);
|
||||
}
|
||||
|
||||
nx = X;
|
||||
ny = Y;
|
||||
nw = W;
|
||||
nh = H;
|
||||
|
||||
nsx = nx / lastScale;
|
||||
nsy = ny / lastScale;
|
||||
nsw = nw / lastScale;
|
||||
nsh = nh / lastScale;
|
||||
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, false));
|
||||
// Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins));
|
||||
}
|
||||
|
||||
void Crop::cropHeight2Resized (int &X, int &Y, int &W, int &H) {
|
||||
|
||||
// X = x->get_value ();
|
||||
// Y = y->get_value ();
|
||||
X = nx;
|
||||
Y = ny;
|
||||
|
||||
if (W<0)
|
||||
W = 0;
|
||||
if (H<0)
|
||||
H = 0;
|
||||
int H1max = maxh-Y;
|
||||
if (H>H1max)
|
||||
H = H1max;
|
||||
if (fixr->get_active()) {
|
||||
double r = getRatio ();
|
||||
int H2max = (int)round ((maxw-X) / r);
|
||||
if (H>H2max)
|
||||
H = H2max;
|
||||
W = (int)round(H * r);
|
||||
}
|
||||
|
||||
nx = X;
|
||||
ny = Y;
|
||||
nw = W;
|
||||
nh = H;
|
||||
|
||||
nsx = nx / lastScale;
|
||||
nsy = ny / lastScale;
|
||||
nsw = nw / lastScale;
|
||||
nsh = nh / lastScale;
|
||||
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, false));
|
||||
// Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins));
|
||||
}
|
||||
|
||||
void Crop::cropInit (int &x, int &y, int &w, int &h) {
|
||||
|
||||
nx = x;
|
||||
ny = y;
|
||||
nw = 1;
|
||||
nh = 1;
|
||||
|
||||
nsx = nx / lastScale;
|
||||
nsy = ny / lastScale;
|
||||
nsw = nw / lastScale;
|
||||
nsh = nh / lastScale;
|
||||
|
||||
w = 1; h = 1;
|
||||
|
||||
econn.block (true);
|
||||
enabled->set_active (1);
|
||||
econn.block (false);
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, false));
|
||||
// Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins));
|
||||
}
|
||||
|
||||
void Crop::cropResized (int &x, int &y, int& x2, int& y2) {
|
||||
|
||||
if (x2<0)
|
||||
x2 = 0;
|
||||
if (y2<0)
|
||||
y2 = 0;
|
||||
if (x2>=maxw)
|
||||
x2 = maxw-1;
|
||||
if (y2>=maxh)
|
||||
y2 = maxh-1;
|
||||
|
||||
int X, Y;
|
||||
int W;
|
||||
if (x<x2) {
|
||||
W = x2 - x + 1;
|
||||
X = x;
|
||||
}
|
||||
else {
|
||||
W = x - x2 + 1;
|
||||
X = x2;
|
||||
}
|
||||
int H;
|
||||
if (y<y2) {
|
||||
H = y2 - y + 1;
|
||||
Y = y;
|
||||
}
|
||||
else {
|
||||
H = y - y2 + 1;
|
||||
Y = y2;
|
||||
}
|
||||
|
||||
if (W>maxw)
|
||||
W = maxw;
|
||||
if (H>maxh)
|
||||
H = maxh;
|
||||
|
||||
if (fixr->get_active()) {
|
||||
double r = getRatio ();
|
||||
if (y<=y2) {
|
||||
int W2max = (int)round ((maxh-Y) * r);
|
||||
if (W>W2max)
|
||||
W = W2max;
|
||||
}
|
||||
else {
|
||||
int W2max = (int)round (y * r);
|
||||
if (W>W2max)
|
||||
W = W2max;
|
||||
}
|
||||
H = (int)round(W / r);
|
||||
if (x<x2)
|
||||
x2 = x + W - 1;
|
||||
else
|
||||
x2 = x - W + 1;
|
||||
if (y<y2)
|
||||
y2 = y + H - 1;
|
||||
else
|
||||
y2 = y - H + 1;
|
||||
}
|
||||
|
||||
if (x<x2) {
|
||||
W = x2 - x + 1;
|
||||
X = x;
|
||||
}
|
||||
else {
|
||||
W = x - x2 + 1;
|
||||
X = x2;
|
||||
}
|
||||
if (y<y2) {
|
||||
H = y2 - y + 1;
|
||||
Y = y;
|
||||
}
|
||||
else {
|
||||
H = y - y2 + 1;
|
||||
Y = y2;
|
||||
}
|
||||
|
||||
nx = X;
|
||||
ny = Y;
|
||||
nw = W;
|
||||
nh = H;
|
||||
|
||||
nsx = nx / lastScale;
|
||||
nsy = ny / lastScale;
|
||||
nsw = nw / lastScale;
|
||||
nsh = nh / lastScale;
|
||||
|
||||
g_idle_add (refreshspins, new RefreshSpinHelper (this, false));
|
||||
// Glib::signal_idle().connect (sigc::mem_fun(*this, &Crop::refreshSpins));
|
||||
}
|
||||
|
||||
void Crop::cropManipReady () {
|
||||
|
||||
g_idle_add (notifylistener, this);
|
||||
}
|
||||
|
||||
double Crop::getRatio () {
|
||||
|
||||
double r = -1.0;
|
||||
if (fixr->get_active()==false)
|
||||
return r;
|
||||
if (ratio->get_active_row_number()==0)
|
||||
r = 3.0/2.0;
|
||||
else if (ratio->get_active_row_number()==1)
|
||||
r = 4.0/3.0;
|
||||
else if (ratio->get_active_row_number()==2)
|
||||
r = 16.0/9.0;
|
||||
else if (ratio->get_active_row_number()==3)
|
||||
r = 16.0/10.0;
|
||||
else if (ratio->get_active_row_number()==4)
|
||||
r = 5.0/4.0;
|
||||
else if (ratio->get_active_row_number()==5)
|
||||
r = 2.0/1.0;
|
||||
else if (ratio->get_active_row_number()==6)
|
||||
r = 1.0/1.0;
|
||||
else if (ratio->get_active_row_number()==7)
|
||||
r = 1.414;
|
||||
if (orientation->get_active_row_number()==0)
|
||||
return r;
|
||||
else
|
||||
return 1.0 / r;
|
||||
}
|
||||
|
||||
void Crop::setBatchMode (bool batchMode) {
|
||||
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
|
||||
ratio->append_text ("(Unchanged)");
|
||||
orientation->append_text ("(Unchanged)");
|
||||
guide->append_text ("(Unchanged)");
|
||||
removeIfThere (this, dpibox);
|
||||
}
|
||||
100
rtgui/crop.h
Executable file
100
rtgui/crop.h
Executable file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _CROP_H_
|
||||
#define _CROP_H_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <cropguilistener.h>
|
||||
#include <toolpanel.h>
|
||||
|
||||
class CropPanelListener {
|
||||
|
||||
public:
|
||||
virtual void cropSelectRequested () {}
|
||||
};
|
||||
|
||||
|
||||
class Crop : public Gtk::VBox, public CropGUIListener, public ToolPanel, public rtengine::SizeListener {
|
||||
|
||||
protected:
|
||||
Gtk::CheckButton* enabled;
|
||||
Gtk::CheckButton* fixr;
|
||||
Gtk::ComboBoxText* ratio;
|
||||
Gtk::ComboBoxText* orientation;
|
||||
Gtk::ComboBoxText* guide;
|
||||
Gtk::Button* selectCrop;
|
||||
CropPanelListener* clistener;
|
||||
int opt;
|
||||
Gtk::SpinButton* x;
|
||||
Gtk::SpinButton* y;
|
||||
Gtk::SpinButton* w;
|
||||
Gtk::SpinButton* h;
|
||||
Gtk::SpinButton* dpi;
|
||||
Gtk::Label* sizecm;
|
||||
Gtk::Label* sizein;
|
||||
Gtk::VBox* dpibox;
|
||||
int maxw, maxh;
|
||||
int nx, ny, nw, nh;
|
||||
double nsx, nsy, nsw, nsh, lastScale;
|
||||
int lastRotationDeg;
|
||||
sigc::connection xconn, yconn, wconn, hconn, econn, fconn, rconn, oconn, gconn;
|
||||
bool wDirty, hDirty, xDirty, yDirty, lastEnabled, lastAspect;
|
||||
|
||||
public:
|
||||
|
||||
Crop ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setBatchMode (bool batchMode);
|
||||
|
||||
void ratioChanged ();
|
||||
void refreshSize ();
|
||||
void selectPressed ();
|
||||
void setDimensions (int mw, int mh);
|
||||
void enabledChanged ();
|
||||
void positionChanged ();
|
||||
void widthChanged ();
|
||||
void heightChanged ();
|
||||
bool refreshSpins (bool notify=false);
|
||||
void notifyListener ();
|
||||
void sizeChanged (int w, int h, int ow, int oh);
|
||||
|
||||
void readOptions ();
|
||||
void writeOptions ();
|
||||
|
||||
void cropMoved (int &x, int &y, int &w, int &h);
|
||||
void cropWidth1Resized (int &x, int &y, int &w, int &h);
|
||||
void cropWidth2Resized (int &x, int &y, int &w, int &h);
|
||||
void cropHeight1Resized (int &x, int &y, int &w, int &h);
|
||||
void cropHeight2Resized (int &x, int &y, int &w, int &h);
|
||||
void cropInit (int &x, int &y, int &w, int &h);
|
||||
void cropResized (int &x, int &y, int& x2, int& y2);
|
||||
void cropManipReady ();
|
||||
double getRatio ();
|
||||
|
||||
void setCropPanelListener (CropPanelListener* cl) { clistener = cl; }
|
||||
|
||||
void resizeScaleChanged (double rsc);
|
||||
void hFlipCrop ();
|
||||
void vFlipCrop ();
|
||||
void rotateCrop (int deg);
|
||||
};
|
||||
|
||||
#endif
|
||||
36
rtgui/cropguilistener.h
Executable file
36
rtgui/cropguilistener.h
Executable file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 __CROPGUILISTENER__
|
||||
#define __CROPGUILISTENER__
|
||||
|
||||
class CropGUIListener {
|
||||
|
||||
public:
|
||||
virtual void cropMoved (int &x, int &y, int &w, int &h) =0;
|
||||
virtual void cropWidth1Resized (int &x, int &y, int &w, int &h) =0;
|
||||
virtual void cropWidth2Resized (int &x, int &y, int &w, int &h) =0;
|
||||
virtual void cropHeight1Resized (int &x, int &y, int &w, int &h) =0;
|
||||
virtual void cropHeight2Resized (int &x, int &y, int &w, int &h) =0;
|
||||
virtual void cropInit (int &x, int &y, int &w, int &h) =0;
|
||||
virtual void cropResized (int &x, int &y, int& x2, int& y2) =0;
|
||||
virtual void cropManipReady () =0;
|
||||
virtual double getRatio () =0;
|
||||
};
|
||||
|
||||
#endif
|
||||
329
rtgui/crophandler.cc
Executable file
329
rtgui/crophandler.cc
Executable file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <crophandler.h>
|
||||
#undef THREAD_PRIORITY_NORMAL
|
||||
|
||||
using namespace rtengine;
|
||||
|
||||
CropHandler::CropHandler ()
|
||||
: crop(NULL), listener(NULL), cropimg(NULL), ipc(NULL),
|
||||
cx(0), cy(0), cw(0), ch(0),
|
||||
cropX(0), cropY(0), cropW(0), cropH(0),
|
||||
zoom(1000), enabled(false) {
|
||||
|
||||
chi = new CropHandlerIdleHelper;
|
||||
chi->destroyed = false;
|
||||
chi->pending = 0;
|
||||
chi->cropHandler = this;
|
||||
}
|
||||
|
||||
CropHandler::~CropHandler () {
|
||||
|
||||
if (ipc)
|
||||
ipc->delSizeListener (this);
|
||||
|
||||
setEnabled (false);
|
||||
if (crop)
|
||||
crop->destroy ();
|
||||
cimg.lock ();
|
||||
if (chi->pending)
|
||||
chi->destroyed = true;
|
||||
else
|
||||
delete chi;
|
||||
cimg.unlock ();
|
||||
}
|
||||
|
||||
void CropHandler::newImage (StagedImageProcessor* ipc_) {
|
||||
|
||||
ipc = ipc_;
|
||||
cx = 0;
|
||||
cy = 0;
|
||||
|
||||
if (!ipc)
|
||||
return;
|
||||
|
||||
crop = ipc->createCrop ();
|
||||
ipc->setSizeListener (this);
|
||||
crop->setListener (enabled ? this : NULL);
|
||||
initial = true;
|
||||
}
|
||||
|
||||
void CropHandler::sizeChanged (int x, int y, int ow, int oh) { // the ipc notifies it to keep track size changes like rotation
|
||||
|
||||
compDim ();
|
||||
|
||||
// this should be put into an idle source!!!
|
||||
/* if (listener)
|
||||
listener->cropWindowChanged ();
|
||||
*/
|
||||
}
|
||||
|
||||
double CropHandler::getFitZoom () {
|
||||
|
||||
if (ipc) {
|
||||
double z1 = (double) wh / ipc->getFullHeight ();
|
||||
double z2 = (double) ww / ipc->getFullWidth ();
|
||||
return z1<z2 ? z1 : z2;
|
||||
}
|
||||
else
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
void CropHandler::setZoom (int z, int centerx, int centery) {
|
||||
|
||||
int x = cx + cw / 2;
|
||||
int y = cy + ch / 2;
|
||||
|
||||
if (centerx>=0)
|
||||
x = centerx;
|
||||
if (centery>=0)
|
||||
y = centery;
|
||||
|
||||
zoom = z;
|
||||
if (zoom>=1000) {
|
||||
cw = ww * 1000 / zoom;
|
||||
ch = wh * 1000 / zoom;
|
||||
}
|
||||
else {
|
||||
cw = ww * zoom;
|
||||
ch = wh * zoom;
|
||||
}
|
||||
cx = x - cw / 2;
|
||||
cy = y - ch / 2;
|
||||
|
||||
compDim ();
|
||||
if (enabled)
|
||||
update ();
|
||||
}
|
||||
|
||||
|
||||
void CropHandler::setWSize (int w, int h) {
|
||||
|
||||
ww = w;
|
||||
wh = h;
|
||||
if (zoom>=1000) {
|
||||
cw = ww * 1000 / zoom;
|
||||
ch = wh * 1000 / zoom;
|
||||
}
|
||||
else {
|
||||
cw = ww * zoom;
|
||||
ch = wh * zoom;
|
||||
}
|
||||
|
||||
compDim ();
|
||||
if (enabled)
|
||||
update ();
|
||||
}
|
||||
|
||||
void CropHandler::getWSize (int& w, int &h) {
|
||||
|
||||
w = ww;
|
||||
h = wh;
|
||||
}
|
||||
|
||||
void CropHandler::setPosition (int x, int y, bool update_) {
|
||||
|
||||
cx = x;
|
||||
cy = y;
|
||||
|
||||
compDim ();
|
||||
if (enabled && update_)
|
||||
update ();
|
||||
}
|
||||
|
||||
void CropHandler::getPosition (int& x, int& y) {
|
||||
|
||||
x = cropX;
|
||||
y = cropY;
|
||||
}
|
||||
|
||||
|
||||
int createpixbufs (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
|
||||
CropHandlerIdleHelper* chi = (CropHandlerIdleHelper*) data;
|
||||
if (chi->destroyed) {
|
||||
if (chi->pending == 1)
|
||||
delete chi;
|
||||
else
|
||||
chi->pending--;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CropHandler* ch = chi->cropHandler;
|
||||
|
||||
ch->cimg.lock ();
|
||||
ch->cropPixbuf.clear ();
|
||||
|
||||
if (!ch->enabled) {
|
||||
delete [] ch->cropimg;
|
||||
ch->cropimg = NULL;
|
||||
ch->cimg.unlock ();
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ch->cropimg) {
|
||||
if (ch->cix==ch->cropX && ch->ciy==ch->cropY && ch->ciw==ch->cropW && ch->cih==ch->cropH && ch->cis==(ch->zoom>=1000?1:ch->zoom)) {
|
||||
// calculate final image size
|
||||
int czoom = ch->zoom<1000 ? 1000 : ch->zoom;
|
||||
int imw = ch->cropimg_width * czoom / 1000;
|
||||
int imh = ch->cropimg_height * czoom / 1000;
|
||||
if (imw>ch->ww)
|
||||
imw = ch->ww;
|
||||
if (imh>ch->wh)
|
||||
imh = ch->wh;
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> tmpPixbuf = Gdk::Pixbuf::create_from_data (ch->cropimg, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, ch->cropimg_height, 3*ch->cropimg_width);
|
||||
ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
|
||||
tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom/1000.0, czoom/1000.0, Gdk::INTERP_NEAREST);
|
||||
tmpPixbuf.clear ();
|
||||
}
|
||||
delete [] ch->cropimg;
|
||||
ch->cropimg = NULL;
|
||||
}
|
||||
ch->cimg.unlock ();
|
||||
if (ch->listener) {
|
||||
ch->listener->cropImageUpdated ();
|
||||
if (ch->initial) {
|
||||
ch->listener->initialImageArrived ();
|
||||
ch->initial = false;
|
||||
}
|
||||
}
|
||||
|
||||
chi->pending--;
|
||||
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CropHandler::setDetailedCrop (IImage8* im, rtengine::procparams::CropParams cp, int ax, int ay, int aw, int ah, int askip) {
|
||||
|
||||
if (!enabled)
|
||||
return;
|
||||
|
||||
cimg.lock ();
|
||||
|
||||
cropParams = cp;
|
||||
|
||||
cropPixbuf.clear ();
|
||||
if (cropimg)
|
||||
delete [] cropimg;
|
||||
cropimg = NULL;
|
||||
|
||||
if (ax==cropX && ay==cropY && aw==cropW && ah==cropH && askip==(zoom>=1000?1:zoom)) {
|
||||
cropimg_width = im->getWidth ();
|
||||
cropimg_height = im->getHeight ();
|
||||
cropimg = new unsigned char [3*cropimg_width*cropimg_height];
|
||||
memcpy (cropimg, im->getData(), 3*cropimg_width*cropimg_height);
|
||||
cix = ax;
|
||||
ciy = ay;
|
||||
ciw = aw;
|
||||
cih = ah;
|
||||
cis = askip;
|
||||
chi->pending++;
|
||||
g_idle_add (createpixbufs, chi);
|
||||
}
|
||||
cimg.unlock ();
|
||||
}
|
||||
|
||||
bool CropHandler::getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip) {
|
||||
|
||||
cwx = cropX;
|
||||
cwy = cropY;
|
||||
cww = cropW;
|
||||
cwh = cropH;
|
||||
|
||||
// hack: if called before first size allocation the size will be 0
|
||||
if (cww<10)
|
||||
cww = 10;
|
||||
if (cwh<32)
|
||||
cwh = 32;
|
||||
|
||||
cskip = zoom>=1000 ? 1 : zoom;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CropHandler::update () {
|
||||
|
||||
if (crop) {
|
||||
// crop->setWindow (cropX, cropY, cropW, cropH, zoom>=1000 ? 1 : zoom); --> we use the "getWindow" hook instead of setting the size before
|
||||
crop->setListener (this);
|
||||
cropPixbuf.clear ();
|
||||
Glib::Thread::create(sigc::mem_fun(*crop, &DetailedCrop::fullUpdate), 0, false, true, Glib::THREAD_PRIORITY_NORMAL);
|
||||
}
|
||||
}
|
||||
|
||||
void CropHandler::setEnabled (bool e) {
|
||||
|
||||
enabled = e;
|
||||
if (!enabled) {
|
||||
if (crop)
|
||||
crop->setListener (NULL);
|
||||
cimg.lock ();
|
||||
delete [] cropimg;
|
||||
cropimg = NULL;
|
||||
cropPixbuf.clear ();
|
||||
cimg.unlock ();
|
||||
}
|
||||
else
|
||||
update ();
|
||||
}
|
||||
|
||||
bool CropHandler::getEnabled () {
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void CropHandler::getSize (int& w, int& h) {
|
||||
|
||||
w = cropW;
|
||||
h = cropH;
|
||||
}
|
||||
|
||||
void CropHandler::compDim () {
|
||||
|
||||
cropX = cx;
|
||||
cropY = cy;
|
||||
cropW = cw;
|
||||
cropH = ch;
|
||||
|
||||
cutRectToImgBounds (cropX, cropY, cropW, cropH);
|
||||
}
|
||||
|
||||
void CropHandler::cutRectToImgBounds (int& x, int& y, int& w, int& h) {
|
||||
|
||||
if (ipc) {
|
||||
if (w > ipc->getFullWidth())
|
||||
w = ipc->getFullWidth();
|
||||
if (h > ipc->getFullHeight())
|
||||
h = ipc->getFullHeight();
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
if (x + w >= ipc->getFullWidth())
|
||||
x = ipc->getFullWidth() - w;
|
||||
if (y + h >= ipc->getFullHeight())
|
||||
y = ipc->getFullHeight() - h;
|
||||
}
|
||||
}
|
||||
94
rtgui/crophandler.h
Executable file
94
rtgui/crophandler.h
Executable file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 __CROPHANDLER__
|
||||
#define __CROPHANDLER__
|
||||
|
||||
#include <rtengine.h>
|
||||
#include <gtkmm.h>
|
||||
|
||||
class CropHandlerListener {
|
||||
|
||||
public:
|
||||
virtual void cropImageUpdated () {}
|
||||
virtual void cropWindowChanged () {}
|
||||
virtual void initialImageArrived () {}
|
||||
};
|
||||
|
||||
class CropHandler;
|
||||
struct CropHandlerIdleHelper {
|
||||
CropHandler* cropHandler;
|
||||
bool destroyed;
|
||||
int pending;
|
||||
};
|
||||
|
||||
class CropHandler : public rtengine::DetailedCropListener, public rtengine::SizeListener {
|
||||
|
||||
friend int createpixbufs (void* data);
|
||||
|
||||
protected:
|
||||
int zoom;
|
||||
int ww, wh; // size of the crop view on the screen
|
||||
int cx, cy, cw, ch; // position and size of the requested crop
|
||||
int cropX, cropY, cropW, cropH; // position and size of the crop corresponding to cropPixbuf
|
||||
bool enabled;
|
||||
unsigned char* cropimg;
|
||||
int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis;
|
||||
bool initial;
|
||||
|
||||
rtengine::StagedImageProcessor* ipc;
|
||||
rtengine::DetailedCrop* crop;
|
||||
|
||||
CropHandlerListener* listener;
|
||||
CropHandlerIdleHelper* chi;
|
||||
|
||||
void update ();
|
||||
void compDim ();
|
||||
public:
|
||||
|
||||
rtengine::procparams::CropParams cropParams;
|
||||
Glib::RefPtr<Gdk::Pixbuf> cropPixbuf;
|
||||
Glib::Mutex cimg;
|
||||
|
||||
CropHandler ();
|
||||
~CropHandler ();
|
||||
|
||||
void setCropHandlerListener (CropHandlerListener* l) { listener = l; }
|
||||
|
||||
void newImage (rtengine::StagedImageProcessor* ipc_);
|
||||
void setZoom (int z, int centerx=-1, int centery=-1);
|
||||
double getFitZoom ();
|
||||
void setWSize (int w, int h);
|
||||
void getWSize (int& w, int &h);
|
||||
void setPosition (int x, int y, bool update=true);
|
||||
void getPosition (int& x, int& y);
|
||||
void getSize (int& w, int& h);
|
||||
|
||||
void setEnabled (bool e);
|
||||
bool getEnabled ();
|
||||
|
||||
// DetailedCropListener interface
|
||||
void setDetailedCrop (rtengine::IImage8* im, rtengine::procparams::CropParams cp, int cx, int cy, int cw, int ch, int skip);
|
||||
bool getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip);
|
||||
// SizeListener interface
|
||||
void sizeChanged (int w, int h, int ow, int oh);
|
||||
|
||||
void cutRectToImgBounds (int& x, int& y, int& w, int& h);
|
||||
};
|
||||
|
||||
#endif
|
||||
1030
rtgui/cropwindow.cc
Executable file
1030
rtgui/cropwindow.cc
Executable file
File diff suppressed because it is too large
Load Diff
146
rtgui/cropwindow.h
Executable file
146
rtgui/cropwindow.h
Executable file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _CROPWINDOW_
|
||||
#define _CROPWINDOW_
|
||||
|
||||
#include <rtengine.h>
|
||||
#include <gtkmm.h>
|
||||
#include <lwbutton.h>
|
||||
#include <lwbuttonset.h>
|
||||
#include <editenums.h>
|
||||
#include <crophandler.h>
|
||||
#include <list>
|
||||
#include <cropguilistener.h>
|
||||
#include <pointermotionlistener.h>
|
||||
|
||||
class CropWindow;
|
||||
class CropWindowListener {
|
||||
|
||||
public:
|
||||
virtual void cropPositionChanged (CropWindow*) {}
|
||||
virtual void cropWindowSizeChanged (CropWindow*) {}
|
||||
virtual void cropZoomChanged (CropWindow*) {}
|
||||
virtual void initialImageArrived (CropWindow*) {}
|
||||
};
|
||||
|
||||
class ImageArea;
|
||||
class CropWindow : public LWButtonListener, public CropHandlerListener {
|
||||
|
||||
// state management
|
||||
ImgEditState state; // current state of user (see enum State)
|
||||
int action_x, action_y, press_x, press_y;
|
||||
double rot_deg;
|
||||
bool onResizeArea;
|
||||
bool deleted;
|
||||
bool fitZoomEnabled;
|
||||
bool fitZoom;
|
||||
|
||||
// decoration
|
||||
Cairo::RefPtr<Cairo::ImageSurface> resizeSurface;
|
||||
LWButton *bZoomIn, *bZoomOut, *bZoom100, *bZoomFit, *bClose;
|
||||
LWButtonSet buttonSet;
|
||||
Glib::ustring cropLabel;
|
||||
int backColor;
|
||||
bool decorated;
|
||||
|
||||
// sizes, positions
|
||||
int titleHeight, sideBorderWidth, lowerBorderWidth, upperBorderWidth, sepWidth, minWidth;
|
||||
int imgAreaX, imgAreaY, imgAreaW, imgAreaH;
|
||||
int imgX, imgY, imgW, imgH;
|
||||
int xpos, ypos, width, height;
|
||||
|
||||
// image handling
|
||||
CropHandler cropHandler;
|
||||
ImageArea* iarea;
|
||||
int cropZoom; // *1000
|
||||
|
||||
// crop gui listener
|
||||
CropGUIListener* cropgl;
|
||||
PointerMotionListener* pmlistener;
|
||||
std::list<CropWindowListener*> listeners;
|
||||
|
||||
CropWindow* observedCropWin;
|
||||
|
||||
bool onArea (CursorArea a, int x, int y);
|
||||
void updateCursor (int x, int y);
|
||||
void drawDecoration (Cairo::RefPtr<Cairo::Context> cr);
|
||||
void drawStraightenGuide (Cairo::RefPtr<Cairo::Context> cr);
|
||||
void drawSpotWBRectangle (Cairo::RefPtr<Cairo::Context> cr);
|
||||
void drawObservedFrame (Cairo::RefPtr<Cairo::Context> cr);
|
||||
void translateCoord (int phyx, int phyy, int& imgx, int& imgy);
|
||||
void changeZoom (int zoom, bool notify=true, int centerx=-1, int centery=-1);
|
||||
void getObservedFrameArea(int& x, int& y, int& w, int& h);
|
||||
|
||||
public:
|
||||
CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_);
|
||||
~CropWindow ();
|
||||
|
||||
void setDecorated (bool decorated) { this->decorated = decorated; }
|
||||
void setFitZoomEnabled (bool fze) { fitZoomEnabled = fze; }
|
||||
void setObservedCropWin (CropWindow* cw) { observedCropWin = cw; }
|
||||
|
||||
void setPosition (int x, int y);
|
||||
void getPosition (int& x, int& y);
|
||||
void setSize (int w, int h, bool norefresh=false);
|
||||
void getSize (int& w, int& h);
|
||||
|
||||
// zoomlistener interface
|
||||
void zoomIn ();
|
||||
void zoomOut ();
|
||||
void zoom11 ();
|
||||
void zoomFit ();
|
||||
double getZoom ();
|
||||
void setZoom (double zoom);
|
||||
|
||||
bool isInside (int x, int y);
|
||||
|
||||
void buttonPress (int button, int num, int state, int x, int y);
|
||||
void buttonRelease (int button, int num, int state, int x, int y);
|
||||
void pointerMoved (int x, int y);
|
||||
|
||||
void expose (Cairo::RefPtr<Cairo::Context> cr);
|
||||
|
||||
// interface lwbuttonlistener
|
||||
void buttonPressed (LWButton* button, int actionCode, void* actionData);
|
||||
void redrawNeeded (LWButton* button);
|
||||
|
||||
// crop handling
|
||||
void getCropRectangle (int& x, int& y, int& w, int& h);
|
||||
void getCropPosition (int& x, int& y);
|
||||
void setCropPosition (int x, int y);
|
||||
void getCropSize (int& w, int& h);
|
||||
|
||||
// listeners
|
||||
void setCropGUIListener (CropGUIListener* cgl) { cropgl = cgl; }
|
||||
void setPointerMotionListener (PointerMotionListener* pml) { pmlistener = pml; }
|
||||
|
||||
// crop window listeners
|
||||
void addCropWindowListener (CropWindowListener* l) { listeners.push_back (l); }
|
||||
void delCropWindowListener (CropWindowListener* l);
|
||||
|
||||
// crophandlerlistener interface
|
||||
void cropImageUpdated ();
|
||||
void cropWindowChanged ();
|
||||
void initialImageArrived ();
|
||||
|
||||
void remoteMove (int deltaX, int deltaY);
|
||||
void remoteMoveReady ();
|
||||
};
|
||||
|
||||
#endif
|
||||
72
rtgui/cursormanager.cc
Executable file
72
rtgui/cursormanager.cc
Executable file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <cursormanager.h>
|
||||
#include <options.h>
|
||||
#include <safegtk.h>
|
||||
|
||||
CursorManager cursorManager;
|
||||
|
||||
void CursorManager::init (Glib::RefPtr<Gdk::Window> mainWin) {
|
||||
|
||||
cResizeWidth = new Gdk::Cursor (Gdk::SB_H_DOUBLE_ARROW);
|
||||
cResizeHeight = new Gdk::Cursor (Gdk::SB_V_DOUBLE_ARROW);
|
||||
cResizeDiag = new Gdk::Cursor (Gdk::BOTTOM_RIGHT_CORNER);
|
||||
cCropMove = new Gdk::Cursor (Gdk::FLEUR);
|
||||
cCropMoving = new Gdk::Cursor (Gdk::HAND2);
|
||||
cCropSelection = new Gdk::Cursor (Gdk::CROSSHAIR);
|
||||
#ifdef _WIN32
|
||||
cNormal = new Gdk::Cursor (Gdk::LAST_CURSOR);
|
||||
#else
|
||||
cNormal = new Gdk::Cursor (Gdk::ARROW);
|
||||
#endif
|
||||
Glib::RefPtr<Gdk::Pixbuf> hand = safe_create_from_file(argv0+"/images/openhand22.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> close_hand = safe_create_from_file(argv0+"/images/closedhand22.png");
|
||||
Glib::RefPtr<Gdk::Pixbuf> wbpick = safe_create_from_file(argv0+"/images/wbpicker16.png");
|
||||
cHand = hand ? new Gdk::Cursor (cNormal->get_display(), hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2);
|
||||
cClosedHand = close_hand ? new Gdk::Cursor (cNormal->get_display(), close_hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2);
|
||||
cWB = wbpick ? new Gdk::Cursor (cNormal->get_display(), wbpick, 1, 12) : new Gdk::Cursor (Gdk::ARROW);
|
||||
|
||||
mainWindow = mainWin;
|
||||
}
|
||||
|
||||
void CursorManager::setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape shape) {
|
||||
|
||||
if (shape==CSArrow)
|
||||
window->set_cursor (*cNormal);
|
||||
else if (shape==CSOpenHand)
|
||||
window->set_cursor (*cHand);
|
||||
else if (shape==CSClosedHand)
|
||||
window->set_cursor (*cClosedHand);
|
||||
else if (shape==CSMove)
|
||||
window->set_cursor (*cCropMove);
|
||||
else if (shape==CSResizeWidth)
|
||||
window->set_cursor (*cResizeWidth);
|
||||
else if (shape==CSResizeHeight)
|
||||
window->set_cursor (*cResizeHeight);
|
||||
else if (shape==CSResizeDiagonal)
|
||||
window->set_cursor (*cResizeDiag);
|
||||
else if (shape==CSSpotWB)
|
||||
window->set_cursor (*cWB);
|
||||
else if (shape==CSCropSelect)
|
||||
window->set_cursor (*cCropSelection);
|
||||
else if (shape==CSStraighten)
|
||||
window->set_cursor (*cCropSelection);
|
||||
}
|
||||
|
||||
|
||||
49
rtgui/cursormanager.h
Executable file
49
rtgui/cursormanager.h
Executable file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _CURSORMANAGER_
|
||||
#define _CURSORMANAGER_
|
||||
|
||||
#include <gtkmm.h>
|
||||
|
||||
enum CursorShape {CSArrow, CSOpenHand, CSClosedHand, CSMove, CSResizeWidth, CSResizeHeight, CSResizeDiagonal, CSSpotWB, CSCropSelect, CSStraighten};
|
||||
|
||||
class CursorManager {
|
||||
|
||||
protected:
|
||||
Gdk::Cursor* cResizeWidth;
|
||||
Gdk::Cursor* cResizeHeight;
|
||||
Gdk::Cursor* cResizeDiag;
|
||||
Gdk::Cursor* cCropMove;
|
||||
Gdk::Cursor* cCropMoving;
|
||||
Gdk::Cursor* cNormal;
|
||||
Gdk::Cursor* cCropSelection;
|
||||
Gdk::Cursor* cHand;
|
||||
Gdk::Cursor* cClosedHand;
|
||||
Gdk::Cursor* cWB;
|
||||
Glib::RefPtr<Gdk::Window> mainWindow;
|
||||
|
||||
public:
|
||||
void init (Glib::RefPtr<Gdk::Window> mainWin);
|
||||
void setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape shape);
|
||||
};
|
||||
|
||||
extern CursorManager cursorManager;
|
||||
|
||||
#endif
|
||||
|
||||
393
rtgui/curveeditor.cc
Executable file
393
rtgui/curveeditor.cc
Executable file
@@ -0,0 +1,393 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <curveeditor.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <guiutils.h>
|
||||
#include <multilangmgr.h>
|
||||
|
||||
CurveEditor::CurveEditor () : cl(NULL), activeParamControl(-1), realized(false), curveTypeIx(-1) {
|
||||
|
||||
Gtk::HBox* tsbox = Gtk::manage (new Gtk::HBox ());
|
||||
Gtk::Label* tslab = Gtk::manage (new Gtk::Label ("Type:"));
|
||||
curveType = Gtk::manage (new Gtk::ComboBoxText ());
|
||||
|
||||
tsbox->pack_start (*tslab, Gtk::PACK_SHRINK, 8);
|
||||
tsbox->pack_start (*curveType);
|
||||
|
||||
pack_start (*tsbox);
|
||||
|
||||
curveType->append_text ("Linear");
|
||||
curveType->append_text ("Parametric");
|
||||
curveType->append_text ("Custom");
|
||||
curveType->set_active (0);
|
||||
|
||||
// custom curve
|
||||
customCurveBox = new Gtk::VBox ();
|
||||
customCurve = Gtk::manage (new MyCurve ());
|
||||
Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
af->add (*customCurve);
|
||||
customCurve->set_size_request (-1, 200);
|
||||
customCurve->setType (Spline);
|
||||
customCurveBox->pack_start (*af, Gtk::PACK_EXPAND_WIDGET);
|
||||
|
||||
Gtk::HBox* bbox = Gtk::manage (new Gtk::HBox ());
|
||||
save = Gtk::manage (new Gtk::Button ());
|
||||
save->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
|
||||
load = Gtk::manage (new Gtk::Button ());
|
||||
load->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-open"), Gtk::ICON_SIZE_BUTTON)));
|
||||
|
||||
bbox->pack_end (*save, Gtk::PACK_EXPAND_WIDGET, 4);
|
||||
bbox->pack_end (*load, Gtk::PACK_EXPAND_WIDGET, 4);
|
||||
|
||||
customCurveBox->pack_end (*bbox, Gtk::PACK_SHRINK, 2);
|
||||
customCurveBox->show_all ();
|
||||
|
||||
save->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::savePressed) );
|
||||
load->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::loadPressed) );
|
||||
save->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
|
||||
load->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
|
||||
|
||||
// parametric curve
|
||||
paramCurveBox = new Gtk::VBox ();
|
||||
paramCurve = Gtk::manage (new MyCurve ());
|
||||
Gtk::Table* ctab = Gtk::manage (new Gtk::Table (2,1));
|
||||
Gtk::AspectFrame* afp = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
afp->add (*paramCurve);
|
||||
paramCurve->set_size_request (200, 200);
|
||||
paramCurve->setType (Parametric);
|
||||
shcSelector = Gtk::manage (new SHCSelector ());
|
||||
shcSelector->set_size_request (200, 20);
|
||||
|
||||
ctab->attach (*afp, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
|
||||
ctab->attach (*shcSelector, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, 2, 2);
|
||||
|
||||
Gtk::HBox* tmpb = Gtk::manage (new Gtk::HBox ());
|
||||
tmpb->pack_start (*ctab, true, false);
|
||||
|
||||
paramCurveBox->pack_start (*tmpb, true, true);
|
||||
|
||||
highlights = Gtk::manage (new Adjuster ("Highlights", -100, 100, 1, 0));
|
||||
lights = Gtk::manage (new Adjuster ("Lights", -100, 100, 1, 0));
|
||||
darks = Gtk::manage (new Adjuster ("Darks", -100, 100, 1, 0));
|
||||
shadows = Gtk::manage (new Adjuster ("Shadows", -100, 100, 1, 0));
|
||||
|
||||
Gtk::EventBox* evhighlights = Gtk::manage (new Gtk::EventBox ());
|
||||
Gtk::EventBox* evlights = Gtk::manage (new Gtk::EventBox ());
|
||||
Gtk::EventBox* evdarks = Gtk::manage (new Gtk::EventBox ());
|
||||
Gtk::EventBox* evshadows = Gtk::manage (new Gtk::EventBox ());
|
||||
|
||||
evhighlights->add (*highlights);
|
||||
evlights->add (*lights);
|
||||
evdarks->add (*darks);
|
||||
evshadows->add (*shadows);
|
||||
|
||||
paramCurveBox->pack_start (*Gtk::manage (new Gtk::HSeparator ()));
|
||||
paramCurveBox->pack_start (*evhighlights);
|
||||
paramCurveBox->pack_start (*evlights);
|
||||
paramCurveBox->pack_start (*evdarks);
|
||||
paramCurveBox->pack_start (*evshadows);
|
||||
paramCurveBox->show_all ();
|
||||
|
||||
customCurveBox->reference ();
|
||||
paramCurveBox->reference ();
|
||||
|
||||
customCurve->setCurveListener (this);
|
||||
paramCurve->setCurveListener (this);
|
||||
shcSelector->setSHCListener (this);
|
||||
|
||||
highlights->setAdjusterListener (this);
|
||||
lights->setAdjusterListener (this);
|
||||
darks->setAdjusterListener (this);
|
||||
shadows->setAdjusterListener (this);
|
||||
|
||||
evhighlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
evlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
evdarks->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
evshadows->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
typeconn = curveType->signal_changed().connect (sigc::mem_fun(*this, &CurveEditor::typeSelectionChanged) );
|
||||
evhighlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 4));
|
||||
evlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 5));
|
||||
evdarks->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 6));
|
||||
evshadows->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 7));
|
||||
evhighlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 4));
|
||||
evlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 5));
|
||||
evdarks->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 6));
|
||||
evshadows->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 7));
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
CurveEditor::~CurveEditor () {
|
||||
|
||||
delete customCurveBox;
|
||||
delete paramCurveBox;
|
||||
}
|
||||
|
||||
void CurveEditor::savePressed () {
|
||||
|
||||
Gtk::FileChooserDialog dialog(M("CURVEEDITOR_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE);
|
||||
// if (options.multiUser)
|
||||
// dialog.set_current_folder (Options::rtdir + "/" + options.profilePath);
|
||||
// else
|
||||
// dialog.set_current_folder (argv0 + "/" + options.profilePath);
|
||||
|
||||
dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
|
||||
dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_OK);
|
||||
|
||||
Gtk::FileFilter filter_pp;
|
||||
filter_pp.set_name(M("CURVEEDITOR_FILEDLGFILTERCURVE"));
|
||||
filter_pp.add_pattern("*.rtc");
|
||||
dialog.add_filter(filter_pp);
|
||||
|
||||
Gtk::FileFilter filter_any;
|
||||
filter_any.set_name(M("CURVEEDITOR_FILEDLGFILTERANY"));
|
||||
filter_any.add_pattern("*");
|
||||
dialog.add_filter(filter_any);
|
||||
|
||||
dialog.set_do_overwrite_confirmation (true);
|
||||
|
||||
int result = dialog.run();
|
||||
|
||||
if (result==Gtk::RESPONSE_OK) {
|
||||
|
||||
std::string fname = dialog.get_filename();
|
||||
|
||||
if (getExtension (fname)!="rtc")
|
||||
fname = fname + ".rtc";
|
||||
|
||||
if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
|
||||
Glib::ustring msg_ = Glib::ustring("<b>") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + "</b>";
|
||||
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
|
||||
int response = msgd.run ();
|
||||
if (response==Gtk::RESPONSE_NO)
|
||||
return;
|
||||
}
|
||||
|
||||
std::ofstream f (fname.c_str());
|
||||
std::vector<double> p = customCurve->getPoints ();
|
||||
int ix = 0;
|
||||
if (p[ix++]<0)
|
||||
f << "Linear\n";
|
||||
else
|
||||
f << "Spline\n";
|
||||
for (int i=0; i<p.size()/2; i++, ix+=2)
|
||||
f << p[ix] << ' ' << p[ix+1] << std::endl;
|
||||
f.close ();
|
||||
}
|
||||
}
|
||||
|
||||
void CurveEditor::loadPressed () {
|
||||
|
||||
Gtk::FileChooserDialog dialog(M("CURVEEDITOR_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN);
|
||||
|
||||
dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
|
||||
dialog.add_button(Gtk::StockID("gtk-open"), Gtk::RESPONSE_OK);
|
||||
|
||||
Gtk::FileFilter filter_pp;
|
||||
filter_pp.set_name(M("CURVEEDITOR_FILEDLGFILTERCURVE"));
|
||||
filter_pp.add_pattern("*.rtc");
|
||||
dialog.add_filter(filter_pp);
|
||||
|
||||
Gtk::FileFilter filter_any;
|
||||
filter_any.set_name(M("CURVEEDITOR_FILEDLGFILTERANY"));
|
||||
filter_any.add_pattern("*");
|
||||
dialog.add_filter(filter_any);
|
||||
|
||||
int result = dialog.run();
|
||||
|
||||
if (result==Gtk::RESPONSE_OK) {
|
||||
std::ifstream f (dialog.get_filename().c_str());
|
||||
if (f) {
|
||||
std::vector<double> p;
|
||||
std::string s;
|
||||
f >> s;
|
||||
if (s=="Linear")
|
||||
p.push_back (-1);
|
||||
else if (s=="Spline")
|
||||
p.push_back (1);
|
||||
else return;
|
||||
double x;
|
||||
while (f) {
|
||||
f >> x;
|
||||
if (f)
|
||||
p.push_back (x);
|
||||
}
|
||||
customCurve->setPoints (p);
|
||||
customCurve->queue_draw ();
|
||||
customCurve->notifyListener ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CurveEditor::on_realize () {
|
||||
|
||||
Gtk::VBox::on_realize();
|
||||
realized = true;
|
||||
setCurve (tmpCurve);
|
||||
}
|
||||
|
||||
void CurveEditor::setCurve (const std::vector<double>& c) {
|
||||
|
||||
tmpCurve = c;
|
||||
|
||||
if (realized && curveType->get_active_row_number()<3) { // if it is not realized or "unchanged" is selected, just store the curve (prev line) and do not change gui
|
||||
|
||||
typeconn.block(true);
|
||||
if (c.size()==0 || c[0]==0) {
|
||||
curveType->set_active (0);
|
||||
curveTypeIx = 0;
|
||||
}
|
||||
else if (c[0]==1) {
|
||||
curveType->set_active (2);
|
||||
curveTypeIx = 2;
|
||||
customCurve->setPoints (c);
|
||||
}
|
||||
else if (c[0]==2) {
|
||||
curveType->set_active (1);
|
||||
curveTypeIx = 1;
|
||||
paramCurve->setPoints (c);
|
||||
shcSelector->setPositions (c[1], c[2], c[3]);
|
||||
highlights->setValue (c[4]);
|
||||
lights->setValue (c[5]);
|
||||
darks->setValue (c[6]);
|
||||
shadows->setValue (c[7]);
|
||||
}
|
||||
removeIfThere (this, customCurveBox, false);
|
||||
removeIfThere (this, paramCurveBox, false);
|
||||
|
||||
if (curveType->get_active_row_number()==1)
|
||||
pack_start (*paramCurveBox);
|
||||
else if (curveType->get_active_row_number()==2)
|
||||
pack_start (*customCurveBox);
|
||||
|
||||
typeconn.block(false);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<double> CurveEditor::getCurve () {
|
||||
|
||||
if (!realized || curveType->get_active_row_number()==3)
|
||||
return tmpCurve;
|
||||
|
||||
if (curveTypeIx<=0) {
|
||||
std::vector<double> lcurve (1);
|
||||
lcurve[0] = 0.0;
|
||||
return lcurve;
|
||||
}
|
||||
else if (curveTypeIx==1) {
|
||||
std::vector<double> lcurve (8);
|
||||
lcurve[0] = 2.0;
|
||||
shcSelector->getPositions (lcurve[1], lcurve[2], lcurve[3]);
|
||||
lcurve[4] = highlights->getValue ();
|
||||
lcurve[5] = lights->getValue ();
|
||||
lcurve[6] = darks->getValue ();
|
||||
lcurve[7] = shadows->getValue ();
|
||||
return lcurve;
|
||||
}
|
||||
else if (curveTypeIx==2)
|
||||
return customCurve->getPoints ();
|
||||
}
|
||||
|
||||
void CurveEditor::typeSelectionChanged () {
|
||||
|
||||
removeIfThere (this, customCurveBox, false);
|
||||
removeIfThere (this, paramCurveBox, false);
|
||||
|
||||
if (curveType->get_active_row_number()==1)
|
||||
pack_start (*paramCurveBox);
|
||||
else if (curveType->get_active_row_number()==2)
|
||||
pack_start (*customCurveBox);
|
||||
|
||||
if (curveType->get_active_row_number()<3)
|
||||
curveTypeIx = curveType->get_active_row_number();
|
||||
|
||||
curveChanged ();
|
||||
}
|
||||
|
||||
void CurveEditor::curveChanged () {
|
||||
|
||||
if (cl)
|
||||
cl->curveChanged ();
|
||||
}
|
||||
|
||||
void CurveEditor::shcChanged () {
|
||||
|
||||
paramCurve->setPoints (getCurve());
|
||||
if (cl)
|
||||
cl->curveChanged ();
|
||||
}
|
||||
|
||||
void CurveEditor::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
paramCurve->setPoints (getCurve());
|
||||
if (cl)
|
||||
cl->curveChanged ();
|
||||
}
|
||||
|
||||
bool CurveEditor::adjusterEntered (GdkEventCrossing* ev, int ac) {
|
||||
|
||||
if (ev->detail != GDK_NOTIFY_INFERIOR) {
|
||||
activeParamControl = ac;
|
||||
paramCurve->setActiveParam (activeParamControl);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CurveEditor::adjusterLeft (GdkEventCrossing* ev, int ac) {
|
||||
|
||||
if (ev->detail != GDK_NOTIFY_INFERIOR) {
|
||||
activeParamControl = -1;
|
||||
paramCurve->setActiveParam (activeParamControl);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CurveEditor::setBatchMode (bool batchMode) {
|
||||
|
||||
curveType->append_text ("(Unchanged)");
|
||||
}
|
||||
|
||||
bool CurveEditor::isUnChanged () {
|
||||
|
||||
return curveType->get_active_row_number()==3;
|
||||
}
|
||||
|
||||
void CurveEditor::setUnChanged (bool uc) {
|
||||
|
||||
if (uc) {
|
||||
typeconn.block(true);
|
||||
removeIfThere (this, customCurveBox, false);
|
||||
removeIfThere (this, paramCurveBox, false);
|
||||
curveType->set_active (3);
|
||||
typeconn.block(false);
|
||||
}
|
||||
else {
|
||||
typeconn.block(true);
|
||||
curveType->set_active (-1); // hack: if it remains 3 (unchanged), then setcurve does not switch selection in the combo
|
||||
setCurve (getCurve ());
|
||||
typeconn.block(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CurveEditor::updateBackgroundHistogram (unsigned int* hist) {
|
||||
|
||||
paramCurve->updateBackgroundHistogram (hist);
|
||||
customCurve->updateBackgroundHistogram (hist);
|
||||
}
|
||||
79
rtgui/curveeditor.h
Executable file
79
rtgui/curveeditor.h
Executable file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _CURVEEDITOR_
|
||||
#define _CURVEEDITOR_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <mycurve.h>
|
||||
#include <shcselector.h>
|
||||
#include <adjuster.h>
|
||||
|
||||
class CurveEditor : public Gtk::VBox, public CurveListener, public SHCListener, public AdjusterListener {
|
||||
|
||||
Gtk::ComboBoxText* curveType;
|
||||
Gtk::VBox* paramCurveBox;
|
||||
Gtk::VBox* customCurveBox;
|
||||
|
||||
MyCurve* customCurve;
|
||||
MyCurve* paramCurve;
|
||||
SHCSelector* shcSelector;
|
||||
|
||||
Adjuster* highlights;
|
||||
Adjuster* lights;
|
||||
Adjuster* darks;
|
||||
Adjuster* shadows;
|
||||
|
||||
Gtk::Button* save;
|
||||
Gtk::Button* load;
|
||||
|
||||
CurveListener* cl;
|
||||
|
||||
bool realized;
|
||||
std::vector<double> tmpCurve;
|
||||
int curveTypeIx;
|
||||
|
||||
int activeParamControl;
|
||||
|
||||
sigc::connection typeconn;
|
||||
|
||||
public:
|
||||
|
||||
CurveEditor ();
|
||||
virtual ~CurveEditor ();
|
||||
void setBatchMode (bool batchMode);
|
||||
bool isUnChanged ();
|
||||
void setUnChanged (bool uc);
|
||||
|
||||
void on_realize ();
|
||||
void setCurveListener (CurveListener* l) { cl = l; }
|
||||
void savePressed ();
|
||||
void loadPressed ();
|
||||
void typeSelectionChanged ();
|
||||
void setCurve (const std::vector<double>& c);
|
||||
std::vector<double> getCurve ();
|
||||
void curveChanged ();
|
||||
void shcChanged ();
|
||||
void adjusterChanged (Adjuster* a, double newval);
|
||||
bool adjusterEntered (GdkEventCrossing* ev, int ac);
|
||||
bool adjusterLeft (GdkEventCrossing* ev, int ac);
|
||||
void updateBackgroundHistogram (unsigned int* hist);
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
28
rtgui/curvelistener.h
Normal file
28
rtgui/curvelistener.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _CURVELISTENER_
|
||||
#define _CURVELISTENER_
|
||||
|
||||
class CurveListener {
|
||||
|
||||
public:
|
||||
virtual void curveChanged () {}
|
||||
};
|
||||
|
||||
#endif
|
||||
367
rtgui/dirbrowser.cc
Executable file
367
rtgui/dirbrowser.cc
Executable file
@@ -0,0 +1,367 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <dirbrowser.h>
|
||||
#ifdef WIN32
|
||||
#define _WIN32_WINNT 0x0600
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#include <options.h>
|
||||
#include <safegtk.h>
|
||||
|
||||
#define CHECKTIME 5000
|
||||
extern Glib::ustring argv0;
|
||||
|
||||
DirBrowser::DirBrowser () {
|
||||
|
||||
dirtree = new Gtk::TreeView();
|
||||
scrolledwindow4 = new Gtk::ScrolledWindow();
|
||||
|
||||
// dirtree->set_flags(Gtk::CAN_FOCUS);
|
||||
dirtree->set_headers_visible(false);
|
||||
dirtree->set_rules_hint(false);
|
||||
dirtree->set_reorderable(false);
|
||||
dirtree->set_enable_search(false);
|
||||
scrolledwindow4->set_flags(Gtk::CAN_FOCUS);
|
||||
scrolledwindow4->set_border_width(2);
|
||||
scrolledwindow4->set_shadow_type(Gtk::SHADOW_NONE);
|
||||
scrolledwindow4->set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS);
|
||||
scrolledwindow4->property_window_placement().set_value(Gtk::CORNER_TOP_LEFT);
|
||||
scrolledwindow4->add(*dirtree);
|
||||
|
||||
pack_start (*scrolledwindow4);
|
||||
dirtree->show ();
|
||||
scrolledwindow4->show ();
|
||||
}
|
||||
|
||||
void DirBrowser::fillDirTree () {
|
||||
|
||||
openfolder = safe_create_from_file (argv0+"/images/folder_open.png");
|
||||
closedfolder = safe_create_from_file (argv0+"/images/folder.png");
|
||||
icdrom = safe_create_from_file (argv0+"/images/cdrom.png");
|
||||
ifloppy = safe_create_from_file (argv0+"/images/floppy.png");
|
||||
ihdd = safe_create_from_file (argv0+"/images/hdd.png");
|
||||
iremovable = safe_create_from_file (argv0+"/images/usbpendrive.png");
|
||||
inetwork = safe_create_from_file (argv0+"/images/network.png");
|
||||
|
||||
//Create the Tree model:
|
||||
dirTreeModel = Gtk::TreeStore::create(dtColumns);
|
||||
dirtree->set_model (dirTreeModel);
|
||||
|
||||
fillRoot ();
|
||||
|
||||
Gtk::CellRendererPixbuf* render_pb = new Gtk::CellRendererPixbuf ();
|
||||
tvc.pack_start (*render_pb, false);
|
||||
tvc.add_attribute(*render_pb, "pixbuf-expander-closed", 1);
|
||||
tvc.add_attribute(*render_pb, "pixbuf", 1);
|
||||
tvc.add_attribute(*render_pb, "pixbuf-expander-open", 0);
|
||||
tvc.pack_start (crt);
|
||||
tvc.add_attribute(crt, "text", 2);
|
||||
|
||||
crt.property_ypad() = 0;
|
||||
render_pb->property_ypad() = 0;
|
||||
|
||||
dirtree->append_column(tvc);
|
||||
|
||||
dirtree->signal_row_expanded().connect(sigc::mem_fun(*this, &DirBrowser::row_expanded));
|
||||
dirtree->signal_row_activated().connect(sigc::mem_fun(*this, &DirBrowser::row_activated));
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
void DirBrowser::addRoot (char letter) {
|
||||
|
||||
char volume[4];
|
||||
volume[0] = letter;
|
||||
strcpy (volume+1, ":\\");
|
||||
|
||||
Gtk::TreeModel::iterator root = dirTreeModel->append();
|
||||
root->set_value (dtColumns.filename, Glib::ustring(volume));
|
||||
root->set_value (dtColumns.dirname, Glib::ustring(volume));
|
||||
|
||||
int type = GetDriveType (volume);
|
||||
if (type==DRIVE_CDROM) {
|
||||
root->set_value (0, icdrom);
|
||||
root->set_value (1, icdrom);
|
||||
}
|
||||
else if (type==DRIVE_REMOVABLE) {
|
||||
if (letter-'A'<2) {
|
||||
root->set_value (0, ifloppy);
|
||||
root->set_value (1, ifloppy);
|
||||
}
|
||||
else {
|
||||
root->set_value (0, iremovable);
|
||||
root->set_value (1, iremovable);
|
||||
}
|
||||
}
|
||||
else if (type==DRIVE_REMOTE) {
|
||||
root->set_value (0, inetwork);
|
||||
root->set_value (1, inetwork);
|
||||
}
|
||||
else if (type==DRIVE_FIXED) {
|
||||
root->set_value (0, ihdd);
|
||||
root->set_value (1, ihdd);
|
||||
}
|
||||
|
||||
Gtk::TreeModel::iterator child = dirTreeModel->append (root->children());
|
||||
child->set_value (dtColumns.filename, Glib::ustring("foo"));
|
||||
}
|
||||
|
||||
void DirBrowser::updateDirTreeRoot () {
|
||||
|
||||
for (Gtk::TreeModel::iterator i=dirTreeModel->children().begin(); i!=dirTreeModel->children().end(); i++)
|
||||
updateDirTree (i);
|
||||
}
|
||||
|
||||
void DirBrowser::updateDirTree (const Gtk::TreeModel::iterator& iter) {
|
||||
|
||||
if (dirtree->row_expanded (dirTreeModel->get_path (iter))) {
|
||||
updateDir (iter);
|
||||
for (Gtk::TreeModel::iterator i=iter->children().begin(); i!=iter->children().end(); i++)
|
||||
updateDirTree (i);
|
||||
}
|
||||
}
|
||||
|
||||
void DirBrowser::updateVolumes () {
|
||||
|
||||
int nvolumes = GetLogicalDrives ();
|
||||
if (nvolumes!=volumes) {
|
||||
for (int i=0; i<32; i++)
|
||||
if (((volumes >> i) & 1) && !((nvolumes >> i) & 1)) { // volume i has been deleted
|
||||
for (Gtk::TreeModel::iterator iter = dirTreeModel->children().begin(); iter!=dirTreeModel->children().end(); iter++)
|
||||
if (iter->get_value (dtColumns.filename).c_str()[0]-'A' == i) {
|
||||
dirTreeModel->erase (iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!((volumes >> i) & 1) && ((nvolumes >> i) & 1))
|
||||
addRoot ('A'+i); // volume i has been added
|
||||
volumes = nvolumes;
|
||||
}
|
||||
}
|
||||
|
||||
int _updateVolumes (void* br) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
((DirBrowser*)br)->updateVolumes ();
|
||||
gdk_threads_leave ();
|
||||
return 1;
|
||||
}
|
||||
int _updateDirTree (void* br) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
((DirBrowser*)br)->updateDirTreeRoot ();
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DirBrowser::winDirChanged () {
|
||||
|
||||
g_idle_add (_updateDirTree, this);
|
||||
}
|
||||
#endif
|
||||
|
||||
void DirBrowser::fillRoot () {
|
||||
|
||||
#ifdef WIN32
|
||||
volumes = GetLogicalDrives ();
|
||||
for (int i=0; i<32; i++)
|
||||
if ((volumes >> i) & 1)
|
||||
addRoot ('A'+i);
|
||||
// since sigc++ is not thread safe, we have to use the glib function
|
||||
g_timeout_add (CHECKTIME, _updateVolumes, this);
|
||||
#else
|
||||
Gtk::TreeModel::Row rootRow = *(dirTreeModel->append());
|
||||
rootRow[dtColumns.filename] = "/";
|
||||
rootRow[dtColumns.dirname] = "/";
|
||||
Gtk::TreeModel::Row childRow = *(dirTreeModel->append(rootRow.children()));
|
||||
childRow[dtColumns.filename] = "foo";
|
||||
#endif
|
||||
}
|
||||
|
||||
void DirBrowser::row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path) {
|
||||
|
||||
expandSuccess = false;
|
||||
|
||||
int todel = iter->children().size();
|
||||
|
||||
std::vector<Glib::ustring> subDirs;
|
||||
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname));
|
||||
|
||||
safe_build_subdir_list (dir, subDirs, options.fbShowHidden);
|
||||
|
||||
if (subDirs.size() == 0)
|
||||
dirtree->collapse_row (path);
|
||||
else {
|
||||
|
||||
std::sort (subDirs.begin(), subDirs.end());
|
||||
for (int i=0; i<subDirs.size(); i++)
|
||||
addDir (iter, subDirs[i]);
|
||||
|
||||
for (int i=0; i<todel; i++)
|
||||
dirTreeModel->erase (iter->children().begin());
|
||||
expandSuccess = true;
|
||||
}
|
||||
#ifdef _WIN32
|
||||
Glib::RefPtr<WinDirMonitor> monitor = Glib::RefPtr<WinDirMonitor>(new WinDirMonitor (iter->get_value (dtColumns.dirname), this));
|
||||
iter->set_value (dtColumns.monitor, monitor);
|
||||
#elif defined __APPLE__
|
||||
printf("TODO fix dir->monitor_directory () for OSX\n");
|
||||
#else
|
||||
Glib::RefPtr<Gio::FileMonitor> monitor = dir->monitor_directory ();
|
||||
iter->set_value (dtColumns.monitor, monitor);
|
||||
monitor->signal_changed().connect (sigc::bind(sigc::mem_fun(*this, &DirBrowser::file_changed), iter, dir->get_parse_name()));
|
||||
#endif
|
||||
}
|
||||
|
||||
void DirBrowser::updateDir (const Gtk::TreeModel::iterator& iter) {
|
||||
|
||||
// first test if some files are deleted
|
||||
bool change = true;
|
||||
while (change) {
|
||||
change = false;
|
||||
for (Gtk::TreeModel::iterator it=iter->children().begin(); it!=iter->children().end(); it++)
|
||||
if (!Glib::file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_EXISTS)
|
||||
|| !Glib::file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_IS_DIR)) {
|
||||
dirTreeModel->erase (it);
|
||||
change = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// test if new files are created
|
||||
std::vector<Glib::ustring> subDirs;
|
||||
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname));
|
||||
safe_build_subdir_list (dir, subDirs, options.fbShowHidden);
|
||||
|
||||
for (int i=0; i<subDirs.size(); i++) {
|
||||
bool found = false;
|
||||
for (Gtk::TreeModel::iterator it=iter->children().begin(); it!=iter->children().end() && !found ; it++)
|
||||
found = (it->get_value (dtColumns.filename)==subDirs[i]);
|
||||
|
||||
if (!found)
|
||||
addDir (iter, subDirs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void DirBrowser::addDir (const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirname) {
|
||||
|
||||
Gtk::TreeModel::iterator child = dirTreeModel->append(iter->children());
|
||||
child->set_value (dtColumns.filename, dirname);
|
||||
child->set_value (0, openfolder);
|
||||
child->set_value (1, closedfolder);
|
||||
Glib::ustring fullname = Glib::build_filename (iter->get_value (dtColumns.dirname), dirname);
|
||||
child->set_value (dtColumns.dirname, fullname);
|
||||
Glib::RefPtr<Gio::File> f = Gio::File::create_for_path (fullname);
|
||||
Gtk::TreeModel::iterator fooRow = dirTreeModel->append(child->children());
|
||||
fooRow->set_value (dtColumns.filename, Glib::ustring("foo"));
|
||||
}
|
||||
|
||||
void DirBrowser::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column) {
|
||||
|
||||
Glib::ustring dname = dirTreeModel->get_iter (path)->get_value (dtColumns.dirname);
|
||||
if (Glib::file_test (dname, Glib::FILE_TEST_IS_DIR))
|
||||
for (int i=0; i<dllisteners.size(); i++)
|
||||
dllisteners[i]->dirSelected (dname);
|
||||
}
|
||||
|
||||
Gtk::TreePath DirBrowser::expandToDir (const Glib::ustring& absDirPath) {
|
||||
|
||||
Gtk::TreeModel::Path path;
|
||||
path.append_index(0);
|
||||
|
||||
int end = 0;
|
||||
int beg = 0;
|
||||
char* dcpy = strdup (absDirPath.c_str());
|
||||
char* dir = strtok (dcpy, "/\\");
|
||||
int count = 0;
|
||||
expandSuccess = true;
|
||||
|
||||
#ifndef _WIN32
|
||||
Gtk::TreeModel::iterator j = dirTreeModel->get_iter (path);
|
||||
path.up ();
|
||||
path.append_index (0);
|
||||
row_expanded(j, path);
|
||||
path.append_index (0);
|
||||
#endif
|
||||
|
||||
while (dir) {
|
||||
Glib::ustring dirstr = dir;
|
||||
#ifdef _WIN32
|
||||
if (count==0)
|
||||
dirstr = dirstr + "\\";
|
||||
#endif
|
||||
Gtk::TreeModel::iterator i = dirTreeModel->get_iter (path);
|
||||
int ix = 0;
|
||||
while (i && expandSuccess) {
|
||||
Gtk::TreeModel::Row crow = *i;
|
||||
Glib::ustring str =crow[dtColumns.filename];
|
||||
#ifdef _WIN32
|
||||
if (str.casefold()==dirstr.casefold()) {
|
||||
#else
|
||||
if (str==dirstr) {
|
||||
#endif
|
||||
path.up ();
|
||||
path.append_index (ix);
|
||||
row_expanded(i, path);
|
||||
path.append_index (0);
|
||||
break;
|
||||
}
|
||||
ix++;
|
||||
i++;
|
||||
}
|
||||
count++;
|
||||
dir = strtok(NULL, "/\\");
|
||||
}
|
||||
|
||||
free(dcpy);
|
||||
|
||||
path.up ();
|
||||
dirtree->expand_to_path (path);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
void DirBrowser::open (const Glib::ustring& dirname, const Glib::ustring& fileName) {
|
||||
|
||||
dirtree->collapse_all ();
|
||||
|
||||
Glib::ustring absDirPath = Gio::File::create_for_path(dirname)->get_parse_name ();
|
||||
Gtk::TreePath path = expandToDir (absDirPath);
|
||||
|
||||
if (expandSuccess) {
|
||||
dirtree->scroll_to_row (path);
|
||||
dirtree->get_selection()->select (path);
|
||||
for (int i=0; i<dllisteners.size(); i++)
|
||||
dllisteners[i]->dirSelected (absDirPath, Glib::build_filename (absDirPath, fileName));
|
||||
}
|
||||
}
|
||||
|
||||
void DirBrowser::file_changed (const Glib::RefPtr<Gio::File>& file, const Glib::RefPtr<Gio::File>& other_file, Gio::FileMonitorEvent event_type, const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirName) {
|
||||
|
||||
if (!file || !Glib::file_test (dirName, Glib::FILE_TEST_IS_DIR) || event_type==Gio::FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED)
|
||||
return;
|
||||
|
||||
gdk_threads_enter();
|
||||
updateDir (iter);
|
||||
gdk_threads_leave();
|
||||
}
|
||||
|
||||
void DirBrowser::selectDir (Glib::ustring dir) {
|
||||
|
||||
open (dir, "");
|
||||
}
|
||||
|
||||
103
rtgui/dirbrowser.h
Executable file
103
rtgui/dirbrowser.h
Executable file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _DIRBROWSER_
|
||||
#define _DIRBROWSER_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <giomm.h>
|
||||
#ifdef _WIN32
|
||||
#include <windirmonitor.h>
|
||||
#endif
|
||||
#include <dirselectionlistener.h>
|
||||
#include <dirbrowserremoteinterface.h>
|
||||
|
||||
class DirBrowser : public Gtk::VBox, public DirBrowserRemoteInterface
|
||||
#ifdef _WIN32
|
||||
, public WinDirChangeListener
|
||||
#endif
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
Glib::RefPtr<Gtk::TreeStore> dirTreeModel;
|
||||
|
||||
struct DirTreeColumns : public Gtk::TreeModelColumnRecord {
|
||||
public:
|
||||
Gtk::TreeModelColumn<Glib::ustring> filename;
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > icon1;
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > icon2;
|
||||
Gtk::TreeModelColumn<Glib::ustring> dirname;
|
||||
#ifdef _WIN32
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<WinDirMonitor> > monitor;
|
||||
#else
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<Gio::FileMonitor> > monitor;
|
||||
#endif
|
||||
|
||||
DirTreeColumns() { add(icon1); add(icon2); add(filename); add(dirname); add(monitor); }
|
||||
};
|
||||
|
||||
Gtk::TreeViewColumn tvc;
|
||||
Gtk::CellRendererText crt;
|
||||
Gtk::CellRendererPixbuf crb;
|
||||
DirTreeColumns dtColumns;
|
||||
|
||||
Gtk::TreeView *dirtree;
|
||||
Gtk::ScrolledWindow *scrolledwindow4;
|
||||
std::vector<DirSelectionListener*> dllisteners;
|
||||
|
||||
void fillRoot ();
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> openfolder;
|
||||
Glib::RefPtr<Gdk::Pixbuf> closedfolder;
|
||||
Glib::RefPtr<Gdk::Pixbuf> icdrom;
|
||||
Glib::RefPtr<Gdk::Pixbuf> ifloppy;
|
||||
Glib::RefPtr<Gdk::Pixbuf> ihdd;
|
||||
Glib::RefPtr<Gdk::Pixbuf> inetwork;
|
||||
Glib::RefPtr<Gdk::Pixbuf> iremovable;
|
||||
|
||||
bool expandSuccess;
|
||||
|
||||
#ifdef WIN32
|
||||
int volumes;
|
||||
public:
|
||||
void updateVolumes ();
|
||||
void updateDirTree (const Gtk::TreeModel::iterator& iter);
|
||||
void updateDirTreeRoot ();
|
||||
void winDirChanged ();
|
||||
private:
|
||||
void addRoot (char letter);
|
||||
#endif
|
||||
void addDir (const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirname);
|
||||
Gtk::TreePath expandToDir (const Glib::ustring& dirName);
|
||||
void updateDir (const Gtk::TreeModel::iterator& iter);
|
||||
void notifyListeners ();
|
||||
|
||||
public:
|
||||
DirBrowser ();
|
||||
|
||||
void fillDirTree ();
|
||||
void row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path);
|
||||
void row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
|
||||
void file_changed (const Glib::RefPtr<Gio::File>& file, const Glib::RefPtr<Gio::File>& other_file, Gio::FileMonitorEvent event_type, const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirName);
|
||||
void open (const Glib::ustring& dirName, const Glib::ustring& fileName=""); // goes to dir "dirName" and selects file "fileName"
|
||||
void addDirSelectionListener (DirSelectionListener* l) { dllisteners.push_back (l); }
|
||||
void selectDir (Glib::ustring dir);
|
||||
};
|
||||
|
||||
#endif
|
||||
31
rtgui/dirbrowserremoteinterface.h
Executable file
31
rtgui/dirbrowserremoteinterface.h
Executable file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _DIRBROWSERREMOTEINTERFACE_
|
||||
#define _DIRBROWSERREMOTEINTERFACE_
|
||||
|
||||
#include <glibmm.h>
|
||||
|
||||
class DirBrowserRemoteInterface {
|
||||
|
||||
public:
|
||||
virtual void selectDir (Glib::ustring dir) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
30
rtgui/dirselectionlistener.h
Executable file
30
rtgui/dirselectionlistener.h
Executable file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _DIRSELECTIONLISTENER_
|
||||
#define _DIRSELECTIONLISTENER_
|
||||
|
||||
#include <glibmm.h>
|
||||
|
||||
class DirSelectionListener {
|
||||
|
||||
public:
|
||||
virtual void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile="") {}
|
||||
};
|
||||
|
||||
#endif
|
||||
83
rtgui/distortion.cc
Executable file
83
rtgui/distortion.cc
Executable file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <distortion.h>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
Distortion::Distortion () {
|
||||
|
||||
distor = Gtk::manage (new Adjuster (M("TP_DISTORTION_AMOUNT"), -0.5, 0.5, 0.001, 0));
|
||||
distor->setAdjusterListener (this);
|
||||
distor->show();
|
||||
pack_start (*distor);
|
||||
distAdd = false;
|
||||
}
|
||||
|
||||
void Distortion::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
if (pedited)
|
||||
distor->setEditedState (pedited->distortion.amount ? Edited : UnEdited);
|
||||
|
||||
distor->setValue (pp->distortion.amount);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void Distortion::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
pp->distortion.amount = distor->getValue ();
|
||||
|
||||
if (pedited)
|
||||
pedited->distortion.amount = distor->getEditedState ();
|
||||
}
|
||||
|
||||
void Distortion::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
|
||||
|
||||
distor->setDefault (defParams->distortion.amount);
|
||||
|
||||
if (pedited)
|
||||
distor->setDefaultEditedState (pedited->distortion.amount ? Edited : UnEdited);
|
||||
else
|
||||
distor->setDefaultEditedState (Irrelevant);
|
||||
}
|
||||
|
||||
void Distortion::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
if (listener)
|
||||
listener->panelChanged (EvDISTAmount, Glib::ustring::format (std::setw(4), std::fixed, std::setprecision(3), a->getValue()));
|
||||
}
|
||||
|
||||
void Distortion::setAdjusterBehavior (bool bvadd) {
|
||||
|
||||
if (!distAdd && bvadd || distAdd && !bvadd)
|
||||
distor->setLimits (-0.5, 0.5, 0.001, 0);
|
||||
|
||||
distAdd = bvadd;
|
||||
}
|
||||
|
||||
void Distortion::setBatchMode (bool batchMode) {
|
||||
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
distor->showEditedCB ();
|
||||
}
|
||||
|
||||
45
rtgui/distortion.h
Executable file
45
rtgui/distortion.h
Executable file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _DISTORTION_H_
|
||||
#define _DISTORTION_H_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <adjuster.h>
|
||||
#include <toolpanel.h>
|
||||
|
||||
class Distortion : public Gtk::VBox, public AdjusterListener, public ToolPanel {
|
||||
|
||||
protected:
|
||||
Adjuster* distor;
|
||||
bool distAdd;
|
||||
|
||||
public:
|
||||
|
||||
Distortion ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
|
||||
void setBatchMode (bool batchMode);
|
||||
|
||||
void adjusterChanged (Adjuster* a, double newval);
|
||||
void setAdjusterBehavior (bool bvadd);
|
||||
};
|
||||
|
||||
#endif
|
||||
25
rtgui/editedstate.h
Executable file
25
rtgui/editedstate.h
Executable file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _EDITEDSTATE_
|
||||
#define _EDITEDSTATE_
|
||||
|
||||
enum EditedState { UnEdited=0, Edited=1, Irrelevant=2 };
|
||||
|
||||
#endif
|
||||
|
||||
25
rtgui/editenums.h
Executable file
25
rtgui/editenums.h
Executable file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _EDITENUMS_
|
||||
#define _EDITENUMS_
|
||||
|
||||
enum ImgEditState {SNormal, SCropMove, SHandMove, SResizeW1, SResizeW2, SResizeH1, SResizeH2, SCropSelecting, SRotateSelecting, SCropWinMove, SCropFrameMove, SCropImgMove, SCropWinResize, SObservedMove};
|
||||
enum CursorArea {CropWinButtons, CropToolBar, CropImage, CropBorder, CropTop, CropBottom, CropLeft, CropRight, CropInside, CropResize, CropObserved};
|
||||
|
||||
#endif
|
||||
792
rtgui/editorpanel.cc
Executable file
792
rtgui/editorpanel.cc
Executable file
@@ -0,0 +1,792 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <editorpanel.h>
|
||||
#include <options.h>
|
||||
#include <progressdialog.h>
|
||||
#include <rtwindow.h>
|
||||
#include <guiutils.h>
|
||||
#include <procparamchangers.h>
|
||||
#include <safegtk.h>
|
||||
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
EditorPanel::EditorPanel (Thumbnail* tmb, rtengine::InitialImage* isrc) : parent(NULL), beforeIarea(NULL), beforePreviewHandler(NULL), beforeIpc(NULL) {
|
||||
|
||||
epih = new EditorPanelIdleHelper;
|
||||
epih->epanel = this;
|
||||
epih->destroyed = false;
|
||||
epih->pending = 0;
|
||||
|
||||
// construct toolpanelcoordinator
|
||||
tpc = new ToolPanelCoordinator ();
|
||||
|
||||
// build GUI
|
||||
// build left side panel
|
||||
leftbox = Gtk::manage (new Gtk::VBox ());
|
||||
leftbox->set_border_width (4);
|
||||
|
||||
histogramPanel = Gtk::manage (new HistogramPanel ());
|
||||
histogramPanel->set_size_request (-1, 150);
|
||||
// leftbox->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
profilep = Gtk::manage (new ProfilePanel ());
|
||||
Gtk::Frame* ppframe = Gtk::manage (new Gtk::Frame ());
|
||||
ppframe->add (*profilep);
|
||||
ppframe->set_label (M("PROFILEPANEL_LABEL"));
|
||||
// leftbox->pack_start (*ppframe, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
navigator = Gtk::manage (new Navigator ());
|
||||
navigator->previewWindow->set_size_request (-1, 150);
|
||||
leftbox->pack_start (*navigator, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
history = Gtk::manage (new History ());
|
||||
leftbox->pack_start (*history);
|
||||
|
||||
leftbox->show_all ();
|
||||
|
||||
// build the middle of the screen
|
||||
Gtk::VBox* editbox = Gtk::manage (new Gtk::VBox ());
|
||||
|
||||
info = Gtk::manage (new Gtk::ToggleButton ());
|
||||
Gtk::Image* infoimg = Gtk::manage (new Gtk::Image (argv0+"/images/info.png"));
|
||||
info->add (*infoimg);
|
||||
info->set_relief(Gtk::RELIEF_NONE);
|
||||
info->set_tooltip_text (M("MAIN_TOOLTIP_QINFO"));
|
||||
|
||||
beforeAfter = Gtk::manage (new Gtk::ToggleButton ("B|A"));
|
||||
beforeAfter->set_tooltip_text ("Toggle before/after view");
|
||||
|
||||
|
||||
Gtk::VSeparator* vsept = Gtk::manage (new Gtk::VSeparator ());
|
||||
Gtk::VSeparator* vsepz = Gtk::manage (new Gtk::VSeparator ());
|
||||
Gtk::VSeparator* vsepi = Gtk::manage (new Gtk::VSeparator ());
|
||||
Gtk::VSeparator* vseph = Gtk::manage (new Gtk::VSeparator ());
|
||||
|
||||
hidehp = Gtk::manage (new Gtk::ToggleButton ());
|
||||
Gtk::Label* hidehpLabel = Gtk::manage (new Gtk::Label ());
|
||||
hidehpLabel->set_markup ("<b>H</b>");
|
||||
Gtk::Image* hpimg = Gtk::manage (new Gtk::Image (argv0+"/images/left.png"));
|
||||
Gtk::HBox* hidehpBox = Gtk::manage (new Gtk::HBox ());
|
||||
hidehpBox->pack_start (*hpimg, Gtk::PACK_SHRINK, 2);
|
||||
hidehpBox->pack_start (*hidehpLabel, Gtk::PACK_SHRINK, 2);
|
||||
hidehp->add (*hidehpBox);
|
||||
hidehp->set_relief(Gtk::RELIEF_NONE);
|
||||
hidehp->set_active (options.showHistory);
|
||||
hidehp->set_tooltip_text (M("MAIN_TOOLTIP_HIDEHP"));
|
||||
|
||||
Gtk::VSeparator* vsepcl = Gtk::manage (new Gtk::VSeparator ());
|
||||
Gtk::VSeparator* vsepz2 = Gtk::manage (new Gtk::VSeparator ());
|
||||
|
||||
iarea = new ImageAreaPanel ();
|
||||
|
||||
Gtk::HBox* toolBarPanel = Gtk::manage (new Gtk::HBox ());
|
||||
toolBarPanel->pack_start (*hidehp, Gtk::PACK_SHRINK, 1);
|
||||
toolBarPanel->pack_start (*vseph, Gtk::PACK_SHRINK, 2);
|
||||
toolBarPanel->pack_start (*info, Gtk::PACK_SHRINK, 1);
|
||||
toolBarPanel->pack_start (*beforeAfter, Gtk::PACK_SHRINK, 1);
|
||||
toolBarPanel->pack_start (*vsepi, Gtk::PACK_SHRINK, 2);
|
||||
toolBarPanel->pack_start (*tpc->getToolBar(), Gtk::PACK_SHRINK, 1);
|
||||
toolBarPanel->pack_start (*vsept, Gtk::PACK_SHRINK, 2);
|
||||
toolBarPanel->pack_end (*tpc->coarse, Gtk::PACK_SHRINK, 4);
|
||||
toolBarPanel->pack_end (*vsepcl, Gtk::PACK_SHRINK, 4);
|
||||
toolBarPanel->pack_end (*iarea->imageArea->indClippedPanel, Gtk::PACK_SHRINK, 0);
|
||||
toolBarPanel->pack_end (*vsepz, Gtk::PACK_SHRINK, 2);
|
||||
|
||||
afterBox = Gtk::manage (new Gtk::VBox ());
|
||||
afterBox->pack_start (*iarea);
|
||||
|
||||
beforeAfterBox = Gtk::manage (new Gtk::HBox());
|
||||
beforeAfterBox->pack_start (*afterBox);
|
||||
|
||||
editbox->pack_start (*toolBarPanel, Gtk::PACK_SHRINK);
|
||||
editbox->pack_start (*beforeAfterBox);
|
||||
|
||||
// build right side panel
|
||||
vboxright = Gtk::manage (new Gtk::VBox (false, 0));
|
||||
vboxright->set_border_width (4);
|
||||
vboxright->pack_start (*histogramPanel, Gtk::PACK_SHRINK, 4);
|
||||
vboxright->pack_start (*ppframe, Gtk::PACK_SHRINK, 4);
|
||||
// main notebook
|
||||
vboxright->pack_start (*tpc->toolPanelNotebook);
|
||||
|
||||
// buttons & status
|
||||
Gtk::HBox* iops = Gtk::manage (new Gtk::HBox ());
|
||||
saveimgas = Gtk::manage (new Gtk::Button (M("MAIN_BUTTON_SAVE")));
|
||||
saveimgas->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
|
||||
queueimg = Gtk::manage (new Gtk::Button ("Put to queue"));
|
||||
queueimg->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-execute"), Gtk::ICON_SIZE_BUTTON)));
|
||||
sendtogimp = Gtk::manage (new Gtk::Button (M("MAIN_BUTTON_SENDTOEDITOR")));
|
||||
sendtogimp->set_image (*Gtk::manage(new Gtk::Image (argv0+"/images/gimp.png")));
|
||||
iops->pack_start (*saveimgas, Gtk::PACK_SHRINK);
|
||||
iops->pack_start (*queueimg, Gtk::PACK_SHRINK);
|
||||
iops->pack_start (*sendtogimp, Gtk::PACK_SHRINK);
|
||||
|
||||
statusBox = Gtk::manage (new Gtk::HBox ());
|
||||
progressLabel = Gtk::manage (new Gtk::Label(""));
|
||||
statusBox->pack_start (*progressLabel);
|
||||
red = new Gtk::Image (argv0+"/images/red.png");
|
||||
green = new Gtk::Image (argv0+"/images/green.png");
|
||||
red->show ();
|
||||
green->show ();
|
||||
statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4);
|
||||
iops->pack_start(*statusBox, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
iops->pack_end (*iarea->imageArea->zoomPanel, Gtk::PACK_SHRINK, 1);
|
||||
iops->pack_end (*vsepz2, Gtk::PACK_SHRINK, 2);
|
||||
|
||||
|
||||
editbox->pack_start (*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_SHRINK, 4);
|
||||
editbox->pack_start (*iops, Gtk::PACK_SHRINK, 4);
|
||||
editbox->show_all ();
|
||||
|
||||
// build screen
|
||||
hpanedl = Gtk::manage (new Gtk::HPaned());
|
||||
hpanedr = Gtk::manage (new Gtk::HPaned());
|
||||
leftbox->reference ();
|
||||
vboxright->reference ();
|
||||
if (options.showHistory) {
|
||||
hpanedl->pack1(*leftbox, false, true);
|
||||
hpanedl->set_position (options.historyPanelWidth);
|
||||
}
|
||||
|
||||
Gtk::Frame* vbfr = Gtk::manage (new Gtk::Frame ());
|
||||
vbfr->add (*editbox);
|
||||
hpanedl->pack2(*vbfr, true, true);
|
||||
|
||||
hpanedr->pack1(*hpanedl, true, true);
|
||||
hpanedr->pack2(*vboxright, false, true);
|
||||
|
||||
pack_start (*hpanedr);
|
||||
show_all ();
|
||||
|
||||
// save as dialog
|
||||
if (Glib::file_test (options.lastSaveAsPath, Glib::FILE_TEST_IS_DIR))
|
||||
saveAsDialog = new SaveAsDialog (options.lastSaveAsPath);
|
||||
else
|
||||
saveAsDialog = new SaveAsDialog (Glib::get_user_special_dir (G_USER_DIRECTORY_PICTURES));
|
||||
|
||||
|
||||
// connect listeners
|
||||
profilep->setProfileChangeListener (tpc);
|
||||
history->setProfileChangeListener (tpc);
|
||||
history->setHistoryBeforeLineListener (this);
|
||||
tpc->addPParamsChangeListener (profilep);
|
||||
tpc->addPParamsChangeListener (history);
|
||||
tpc->addPParamsChangeListener (this);
|
||||
iarea->imageArea->setCropGUIListener (tpc->getCropGUIListener());
|
||||
iarea->imageArea->setPointerMotionListener (navigator);
|
||||
iarea->imageArea->setImageAreaToolListener (tpc);
|
||||
|
||||
// initialize components
|
||||
info->set_active (options.showInfo);
|
||||
tpc->readOptions ();
|
||||
|
||||
// connect event handlers
|
||||
info->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::info_toggled) );
|
||||
beforeAfter->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::beforeAfterToggled) );
|
||||
hidehp->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::hideHistoryActivated) );
|
||||
saveimgas->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::saveAsPressed) );
|
||||
queueimg->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::queueImgPressed) );
|
||||
sendtogimp->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::sendToGimpPressed) );
|
||||
|
||||
// open image
|
||||
open (tmb, isrc);
|
||||
}
|
||||
|
||||
bool EditorPanel::beforeClosing () {
|
||||
|
||||
options.toolPanelWidth = vboxright->get_width ();
|
||||
return true;
|
||||
}
|
||||
|
||||
EditorPanel::~EditorPanel () {
|
||||
|
||||
history->setHistoryBeforeLineListener (NULL);
|
||||
// the order is important!
|
||||
delete iarea;
|
||||
delete beforeIarea;
|
||||
|
||||
if (ipc)
|
||||
ipc->setPreviewImageListener (NULL);
|
||||
if (beforeIpc)
|
||||
beforeIpc->setPreviewImageListener (NULL);
|
||||
|
||||
delete previewHandler;
|
||||
delete beforePreviewHandler;
|
||||
|
||||
if (ipc)
|
||||
close ();
|
||||
|
||||
if (epih->pending)
|
||||
epih->destroyed = true;
|
||||
else
|
||||
delete epih;
|
||||
|
||||
delete tpc;
|
||||
|
||||
delete red;
|
||||
delete green;
|
||||
delete leftbox;
|
||||
delete vboxright;
|
||||
|
||||
delete saveAsDialog;
|
||||
}
|
||||
|
||||
void EditorPanel::on_realize () {
|
||||
|
||||
Gtk::VBox::on_realize ();
|
||||
vboxright->set_size_request (options.toolPanelWidth, -1);
|
||||
}
|
||||
|
||||
rtengine::InitialImage* EditorPanel::loadImage (Thumbnail* tmb) {
|
||||
|
||||
// try to load the image
|
||||
Glib::ustring filename = tmb->getFileName ();
|
||||
int error;
|
||||
// InitialImage* isrc = InitialImage::load (filename, tmb->getType()==FT_Raw, error, this);
|
||||
ProgressDialog<rtengine::InitialImage*>* pdload = new ProgressDialog<rtengine::InitialImage*> (M("PROGRESSDLG_LOADING"));
|
||||
rtengine::InitialImage* isrc;
|
||||
pdload->setFunc (sigc::bind(sigc::ptr_fun(&rtengine::InitialImage::load), filename, tmb->getType()==FT_Raw, &error, pdload->getProgressListener()), &isrc);
|
||||
pdload->start ();
|
||||
delete pdload;
|
||||
|
||||
if (error)
|
||||
return NULL;
|
||||
else
|
||||
return isrc;
|
||||
}
|
||||
|
||||
void EditorPanel::open (Thumbnail* tmb, rtengine::InitialImage* isrc) {
|
||||
|
||||
// initialize everything
|
||||
openThm = tmb;
|
||||
openThm->increaseRef ();
|
||||
|
||||
previewHandler = new PreviewHandler ();
|
||||
|
||||
this->isrc = isrc;
|
||||
ipc = rtengine::StagedImageProcessor::create (isrc);
|
||||
ipc->setProgressListener (this);
|
||||
ipc->setPreviewImageListener (previewHandler);
|
||||
ipc->setPreviewScale (10);
|
||||
tpc->initImage (ipc, tmb->getType()==FT_Raw);
|
||||
ipc->setHistogramListener (this);
|
||||
|
||||
// iarea->fitZoom (); // tell to the editorPanel that the next image has to be fitted to the screen
|
||||
iarea->imageArea->setPreviewHandler (previewHandler);
|
||||
iarea->imageArea->setImProcCoordinator (ipc);
|
||||
navigator->previewWindow->setPreviewHandler (previewHandler);
|
||||
navigator->previewWindow->setImageArea (iarea->imageArea);
|
||||
|
||||
// try to load the last saved parameters from the cache or from the pp2 file
|
||||
ProcParams* ldprof = NULL;
|
||||
if (openThm->hasProcParams()) {
|
||||
ldprof = new ProcParams ();
|
||||
*ldprof = openThm->getProcParams ();
|
||||
}
|
||||
|
||||
// initialize profile
|
||||
if (openThm->getType()!=FT_Raw)
|
||||
profilep->initProfile (options.defProfImg, ldprof, NULL);
|
||||
else
|
||||
profilep->initProfile (options.defProfRaw, ldprof, NULL);
|
||||
|
||||
openThm->addThumbnailListener (this);
|
||||
info_toggled ();
|
||||
}
|
||||
|
||||
void EditorPanel::close () {
|
||||
|
||||
saveProfile ();
|
||||
|
||||
// close image processor and the current thumbnail
|
||||
tpc->closeImage (); // this call stops image processing
|
||||
tpc->writeOptions ();
|
||||
|
||||
if (ipc)
|
||||
rtengine::StagedImageProcessor::destroy (ipc);
|
||||
if (beforeIpc)
|
||||
rtengine::StagedImageProcessor::destroy (beforeIpc);
|
||||
|
||||
openThm->removeThumbnailListener (this);
|
||||
openThm->decreaseRef ();
|
||||
}
|
||||
|
||||
void EditorPanel::saveProfile () {
|
||||
|
||||
ProcParams params;
|
||||
ipc->getParams (¶ms);
|
||||
|
||||
if (options.saveParamsFile)
|
||||
params.save (openThm->getFileName() + ".pp2");
|
||||
if (openThm && options.saveParamsCache)
|
||||
openThm->setProcParams (params, EDITOR);
|
||||
}
|
||||
|
||||
Glib::ustring EditorPanel::getShortName () {
|
||||
|
||||
return Glib::path_get_basename (openThm->getFileName ());
|
||||
}
|
||||
|
||||
Glib::ustring EditorPanel::getFileName () {
|
||||
|
||||
return openThm->getFileName ();
|
||||
}
|
||||
|
||||
// TODO!!!
|
||||
void EditorPanel::procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) {
|
||||
|
||||
// if (ev!=EvPhotoLoaded)
|
||||
// saveLabel->set_markup (Glib::ustring("<span foreground=\"#AA0000\" weight=\"bold\">") + M("MAIN_BUTTON_SAVE") + "</span>");
|
||||
}
|
||||
|
||||
struct spsparams {
|
||||
bool state;
|
||||
EditorPanelIdleHelper* epih;
|
||||
};
|
||||
|
||||
int setprocstate (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
spsparams* p = (spsparams*)data;
|
||||
|
||||
if (p->epih->destroyed) {
|
||||
if (p->epih->pending == 1)
|
||||
delete p->epih;
|
||||
else
|
||||
p->epih->pending--;
|
||||
delete p;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
p->epih->epanel->refreshProcessingState (p->state);
|
||||
p->epih->pending--;
|
||||
delete p;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EditorPanel::setProgressState (int state) {
|
||||
|
||||
epih->pending++;
|
||||
|
||||
spsparams* p = new spsparams;
|
||||
p->state = state;
|
||||
p->epih = epih;
|
||||
g_idle_add (setprocstate, p);
|
||||
}
|
||||
|
||||
void EditorPanel::refreshProcessingState (bool state) {
|
||||
|
||||
// Set proc params of thumbnail. It saves it into the cache and updates the file browser.
|
||||
if (ipc && openThm && !state && tpc->getChangedState()) {
|
||||
rtengine::procparams::ProcParams pparams;
|
||||
ipc->getParams (&pparams);
|
||||
openThm->setProcParams (pparams, EDITOR, false);
|
||||
}
|
||||
|
||||
// change state of the led
|
||||
std::vector<Widget*> children = (std::vector<Widget*>) statusBox->get_children();
|
||||
if (children.size()>=1) {
|
||||
Gtk::Widget* wlast = children[children.size()-1];
|
||||
if (wlast)
|
||||
statusBox->remove (*wlast);
|
||||
}
|
||||
if (state)
|
||||
statusBox->pack_end (*red, Gtk::PACK_SHRINK, 4);
|
||||
else
|
||||
statusBox->pack_end (*green, Gtk::PACK_SHRINK, 4);
|
||||
}
|
||||
|
||||
struct errparams {
|
||||
Glib::ustring descr;
|
||||
EditorPanelIdleHelper* epih;
|
||||
};
|
||||
|
||||
void EditorPanel::displayError (Glib::ustring descr) {
|
||||
|
||||
if (parent) {
|
||||
Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, descr, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||
msgd->set_title (M("MAIN_MSG_CANNOTSAVE"));
|
||||
msgd->run ();
|
||||
delete msgd;
|
||||
}
|
||||
}
|
||||
|
||||
int disperror (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
errparams* p = (errparams*)data;
|
||||
|
||||
if (p->epih->destroyed) {
|
||||
if (p->epih->pending == 1)
|
||||
delete p->epih;
|
||||
else
|
||||
p->epih->pending--;
|
||||
delete p;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
p->epih->epanel->displayError (p->descr);
|
||||
p->epih->pending--;
|
||||
delete p;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EditorPanel::error (Glib::ustring descr) {
|
||||
|
||||
epih->pending++;
|
||||
errparams* p = new errparams;
|
||||
p->descr = descr;
|
||||
p->epih = epih;
|
||||
g_idle_add (disperror, p);
|
||||
}
|
||||
|
||||
void EditorPanel::info_toggled () {
|
||||
|
||||
Glib::ustring infoString;
|
||||
|
||||
const rtengine::ImageMetaData* idata = ipc->getInitialImage()->getMetaData();
|
||||
if (idata && idata->hasExif())
|
||||
infoString = Glib::ustring::compose ("%1 %2\nF/%3 %4 sec\n%5: %6\n%7: %8 mm\n",
|
||||
Glib::ustring(idata->getMake()), Glib::ustring(idata->getModel()),
|
||||
Glib::ustring(idata->apertureToString(idata->getFNumber())), Glib::ustring(idata->shutterToString(idata->getShutterSpeed())),
|
||||
M("QINFO_ISO"), idata->getISOSpeed(),
|
||||
M("QINFO_FOCALLENGTH"), idata->getFocalLen())
|
||||
+ Glib::ustring::compose ("%1: %2", M("QINFO_LENS"), Glib::ustring(idata->getLens()));
|
||||
else
|
||||
infoString = M("QINFO_NOEXIF");
|
||||
|
||||
iarea->imageArea->setInfoText (infoString);
|
||||
iarea->imageArea->infoEnabled (info->get_active ());
|
||||
}
|
||||
|
||||
void EditorPanel::hideHistoryActivated () {
|
||||
|
||||
removeIfThere (hpanedl, leftbox, false);
|
||||
if (hidehp->get_active())
|
||||
hpanedl->pack1 (*leftbox, false, true);
|
||||
}
|
||||
|
||||
bool EditorPanel::handleShortcutKey (GdkEventKey* event) {
|
||||
|
||||
if (event->keyval==GDK_H || event->keyval==GDK_h) {
|
||||
hidehp->set_active (!hidehp->get_active());
|
||||
return true;
|
||||
}
|
||||
else if ((event->keyval==GDK_Z || event->keyval==GDK_z) && event->state & GDK_CONTROL_MASK && !(event->state & GDK_SHIFT_MASK)) {
|
||||
history->undo ();
|
||||
return true;
|
||||
}
|
||||
else if ((event->keyval==GDK_Z || event->keyval==GDK_z) && event->state & GDK_CONTROL_MASK && event->state & GDK_SHIFT_MASK) {
|
||||
history->redo ();
|
||||
return true;
|
||||
}
|
||||
else if (event->keyval==GDK_w || event->keyval==GDK_W) {
|
||||
tpc->getToolBar()->wb_pressed ();
|
||||
return true;
|
||||
}
|
||||
else if (event->keyval==GDK_c || event->keyval==GDK_C) {
|
||||
tpc->getToolBar()->crop_pressed ();
|
||||
return true;
|
||||
}
|
||||
else if (event->keyval==GDK_s || event->keyval==GDK_S) {
|
||||
tpc->getToolBar()->stra_pressed ();
|
||||
return true;
|
||||
}
|
||||
else if (event->keyval==GDK_n || event->keyval==GDK_N) {
|
||||
tpc->getToolBar()->hand_pressed ();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) {
|
||||
|
||||
if (whoChangedIt!=EDITOR)
|
||||
tpc->profileChange (&openThm->getProcParams(), rtengine::EvProfileChangeNotification, "Profile Changed in Browser");
|
||||
}
|
||||
|
||||
rtengine::IImage16* EditorPanel::processImage () {
|
||||
|
||||
rtengine::procparams::ProcParams pparams;
|
||||
ipc->getParams (&pparams);
|
||||
rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
|
||||
int err = 0;
|
||||
ProgressDialog<rtengine::IImage16*>* pdproc = new ProgressDialog<rtengine::IImage16*> (M("PROGRESSDLG_PROCESSING"));
|
||||
rtengine::IImage16* img;
|
||||
pdproc->setFunc (sigc::bind(sigc::ptr_fun(&rtengine::processImage), job, err, pdproc->getProgressListener()), &img);
|
||||
pdproc->start ();
|
||||
delete pdproc;
|
||||
return img;
|
||||
}
|
||||
|
||||
BatchQueueEntry* EditorPanel::createBatchQueueEntry () {
|
||||
|
||||
rtengine::procparams::ProcParams pparams;
|
||||
ipc->getParams (&pparams);
|
||||
rtengine::ProcessingJob* job = rtengine::ProcessingJob::create (ipc->getInitialImage(), pparams);
|
||||
int prevh = options.maxThumbnailHeight;
|
||||
int prevw = prevh;
|
||||
guint8* prev = NULL;//(guint8*) previewHandler->getImagePreview (prevw, prevh);
|
||||
return new BatchQueueEntry (job, pparams, openThm->getFileName(), prev, prevw, prevh, openThm);
|
||||
}
|
||||
|
||||
int EditorPanel::saveImage (rtengine::IImage16* img, Glib::ustring& fname, SaveFormat sf, bool findNewNameIfNeeded) {
|
||||
|
||||
Glib::ustring fileName = Glib::ustring::compose ("%1.%2", fname, sf.format);
|
||||
if (findNewNameIfNeeded) {
|
||||
int tries = 1;
|
||||
while (Glib::file_test (fileName, Glib::FILE_TEST_EXISTS) && tries<1000) {
|
||||
fileName = Glib::ustring::compose("%1-%2.%3", fname, tries, sf.format);
|
||||
tries++;
|
||||
}
|
||||
if (tries==1000)
|
||||
return -1000;
|
||||
}
|
||||
|
||||
ProgressDialog<int>* pdsave = new ProgressDialog<int> (M("PROGRESSDLG_SAVING"));
|
||||
img->setSaveProgressListener (pdsave->getProgressListener());
|
||||
|
||||
int err;
|
||||
if (sf.format=="tif")
|
||||
pdsave->setFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsTIFF), fileName, sf.tiffBits), &err);
|
||||
else if (sf.format=="png")
|
||||
pdsave->setFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsPNG), fileName, sf.pngCompression, sf.pngBits), &err);
|
||||
else if (sf.format=="jpg")
|
||||
pdsave->setFunc (sigc::bind(sigc::mem_fun(img, &rtengine::IImage16::saveAsJPEG), fileName, sf.jpegQuality), &err);
|
||||
pdsave->start ();
|
||||
delete pdsave;
|
||||
|
||||
fname = fileName;
|
||||
return err;
|
||||
}
|
||||
|
||||
void EditorPanel::saveAsPressed () {
|
||||
|
||||
// obtaining short name without extension
|
||||
saveAsDialog->setInitialFileName (removeExtension (Glib::path_get_basename (openThm->getFileName())));
|
||||
saveAsDialog->run ();
|
||||
Glib::ustring fname = saveAsDialog->getFileName ();
|
||||
if (fname=="")
|
||||
return;
|
||||
|
||||
SaveFormat sf = saveAsDialog->getFormat ();
|
||||
if (getExtension (fname)!=sf.format)
|
||||
fname = fname + "." + sf.format;
|
||||
|
||||
if (saveAsDialog->getImmediately ()) {
|
||||
// check if it exists
|
||||
if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
|
||||
Glib::ustring msg_ = Glib::ustring("<b>") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + "</b>";
|
||||
Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
|
||||
int response = msgd.run ();
|
||||
if (response==Gtk::RESPONSE_NO)
|
||||
return;
|
||||
}
|
||||
// save image
|
||||
rtengine::IImage16* img = processImage ();
|
||||
int err = 0;
|
||||
if (img) {
|
||||
fname = removeExtension (fname);
|
||||
err = saveImage (img, fname, sf, false);
|
||||
img->free ();
|
||||
if (!err) {
|
||||
openThm->imageDeveloped ();
|
||||
// save processing parameters, if needed
|
||||
if (sf.saveParams) {
|
||||
rtengine::procparams::ProcParams pparams;
|
||||
ipc->getParams (&pparams);
|
||||
pparams.save (removeExtension (fname) + ".out.pp2");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!img || err) {
|
||||
Glib::ustring msg_ = Glib::ustring("<b>") + fname + ": Error during image saving\n</b>";
|
||||
Gtk::MessageDialog msgd (*parent, msg_, true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||
msgd.run ();
|
||||
}
|
||||
}
|
||||
else {
|
||||
BatchQueueEntry* bqe = createBatchQueueEntry ();
|
||||
bqe->outFileName = fname;
|
||||
bqe->saveFormat = saveAsDialog->getFormat ();
|
||||
parent->addBatchQueueJob (bqe, saveAsDialog->getToHeadOfQueue ());
|
||||
}
|
||||
// ask parent to redraw file browser
|
||||
// ... or does it automatically when the tab is switched to it
|
||||
}
|
||||
|
||||
void EditorPanel::queueImgPressed () {
|
||||
|
||||
saveProfile ();
|
||||
parent->addBatchQueueJob (createBatchQueueEntry ());
|
||||
}
|
||||
|
||||
void EditorPanel::sendToGimpPressed () {
|
||||
|
||||
// develop image
|
||||
rtengine::IImage16* img = processImage ();
|
||||
if (img) {
|
||||
// get file name base
|
||||
Glib::ustring shortname = removeExtension (Glib::path_get_basename (openThm->getFileName()));
|
||||
Glib::ustring dirname = Glib::get_tmp_dir ();
|
||||
Glib::ustring filename = Glib::build_filename (dirname, shortname);
|
||||
|
||||
SaveFormat sf;
|
||||
sf.format = "tif";
|
||||
sf.tiffBits = 16;
|
||||
int err = saveImage (img, filename, sf, true);
|
||||
img->free ();
|
||||
if (!err) {
|
||||
bool success=false;
|
||||
Glib::ustring cmdLine;
|
||||
// start gimp
|
||||
if (options.editorToSendTo==1) {
|
||||
#ifdef _WIN32
|
||||
cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), "gimp-win-remote") + "\" gimp-2.4.exe" + " \"" + filename + "\"";
|
||||
#else
|
||||
cmdLine = Glib::ustring("gimp-remote ") + " \"" + filename + "\"";
|
||||
#endif
|
||||
success = safe_spawn_command_line_async (cmdLine);
|
||||
if (!success){
|
||||
#ifdef _WIN32
|
||||
int ver = 12;
|
||||
while (!success && ver) {
|
||||
cmdLine = Glib::ustring("\"") + Glib::build_filename (Glib::build_filename(options.gimpDir,"bin"), Glib::ustring::compose("gimp-2.%1.exe",ver)) + "\" \"" + filename + "\"";
|
||||
ver--;
|
||||
success = safe_spawn_command_line_async (cmdLine);
|
||||
}
|
||||
#elif defined __APPLE__
|
||||
cmdLine = Glib::ustring("gimp ") + " \"" + filename + "\"";
|
||||
success = safe_spawn_command_line_async (cmdLine);
|
||||
#else
|
||||
cmdLine = Glib::ustring("gimp ") + " \"" + filename + "\"";
|
||||
success = safe_spawn_command_line_async (cmdLine);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (options.editorToSendTo==2) {
|
||||
#ifdef __APPLE__
|
||||
cmdLine = Glib::ustring("open -a \'") + Glib::build_filename(options.psDir,"Photoshop.app\' ") + "\'" + filename + "\'";
|
||||
#else
|
||||
cmdLine = Glib::ustring("\"") + Glib::build_filename(options.psDir,"Photoshop.exe") + "\" \"" + filename + "\"";
|
||||
#endif
|
||||
success = safe_spawn_command_line_async (cmdLine);
|
||||
}
|
||||
else if (options.editorToSendTo==3) {
|
||||
#ifdef __APPLE__
|
||||
cmdLine = Glib::ustring("") + options.customEditorProg + filename;
|
||||
#else
|
||||
cmdLine = Glib::ustring("\"") + options.customEditorProg + "\" \"" + filename + "\"";
|
||||
#endif
|
||||
success = safe_spawn_command_line_async (cmdLine);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
Gtk::MessageDialog* msgd = new Gtk::MessageDialog (*parent, M("MAIN_MSG_CANNOTSTARTEDITOR"), false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
|
||||
msgd->set_secondary_text (M("MAIN_MSG_CANNOTSTARTEDITOR_SECONDARY"));
|
||||
msgd->set_title (M("MAIN_BUTTON_SENDTOEDITOR"));
|
||||
msgd->run ();
|
||||
delete msgd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorPanel::saveOptions () {
|
||||
|
||||
options.historyPanelWidth = hpanedl->get_position ();
|
||||
options.toolPanelWidth = vboxright->get_width ();
|
||||
}
|
||||
|
||||
void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) {
|
||||
|
||||
if (beforeIpc) {
|
||||
ProcParams* pparams = beforeIpc->getParamsForUpdate (rtengine::EvProfileChanged);
|
||||
*pparams = params;
|
||||
beforeIpc->paramsUpdateReady ();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorPanel::beforeAfterToggled () {
|
||||
|
||||
removeIfThere (beforeAfterBox, beforeBox, false);
|
||||
removeIfThere (afterBox, afterLabel, false);
|
||||
|
||||
if (beforeIarea) {
|
||||
if (beforeIpc)
|
||||
beforeIpc->stopProcessing ();
|
||||
iarea->setBeforeAfterViews (NULL, iarea);
|
||||
delete beforeIarea;
|
||||
beforeIarea = NULL;
|
||||
if (beforeIpc)
|
||||
beforeIpc->setPreviewImageListener (NULL);
|
||||
delete beforePreviewHandler;
|
||||
beforePreviewHandler = NULL;
|
||||
if (beforeIpc)
|
||||
rtengine::StagedImageProcessor::destroy (beforeIpc);
|
||||
beforeIpc = NULL;
|
||||
}
|
||||
|
||||
if (beforeAfter->get_active ()) {
|
||||
|
||||
beforeIarea = new ImageAreaPanel ();
|
||||
|
||||
beforeLabel = Gtk::manage (new Gtk::Label ());
|
||||
beforeLabel->set_markup ("<b>Before:</b>");
|
||||
beforeBox = Gtk::manage (new Gtk::VBox ());
|
||||
beforeBox->pack_start (*beforeLabel, Gtk::PACK_SHRINK, 2);
|
||||
beforeBox->pack_start (*beforeIarea);
|
||||
|
||||
afterLabel = Gtk::manage (new Gtk::Label ());
|
||||
afterLabel->set_markup ("<b>After:</b>");
|
||||
afterBox->pack_start (*afterLabel, Gtk::PACK_SHRINK, 2);
|
||||
afterBox->reorder_child (*afterLabel, 0);
|
||||
|
||||
beforeAfterBox->pack_start (*beforeBox);
|
||||
beforeAfterBox->reorder_child (*beforeBox, 0);
|
||||
beforeAfterBox->show_all ();
|
||||
|
||||
beforePreviewHandler = new PreviewHandler ();
|
||||
isrc->increaseRef ();
|
||||
beforeIpc = rtengine::StagedImageProcessor::create (isrc);
|
||||
beforeIpc->setPreviewScale (10);
|
||||
beforeIpc->setPreviewImageListener (beforePreviewHandler);
|
||||
beforeIarea->imageArea->setPreviewHandler (beforePreviewHandler);
|
||||
beforeIarea->imageArea->setImProcCoordinator (beforeIpc);
|
||||
|
||||
iarea->setBeforeAfterViews (beforeIarea, iarea);
|
||||
beforeIarea->setBeforeAfterViews (beforeIarea, iarea);
|
||||
|
||||
rtengine::procparams::ProcParams params;
|
||||
if (history->getBeforeLineParams (params))
|
||||
historyBeforeLineChanged (params);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorPanel::histogramChanged (unsigned int* rh, unsigned int* gh, unsigned int* bh, unsigned int* lh, unsigned int* bcrgb, unsigned int* bcl) {
|
||||
|
||||
histogramPanel->histogramChanged (rh, gh, bh, lh);
|
||||
tpc->updateCurveBackgroundHistogram (bcrgb, bcl);
|
||||
}
|
||||
145
rtgui/editorpanel.h
Executable file
145
rtgui/editorpanel.h
Executable file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _EDITORPANEL_
|
||||
#define _EDITORPANEL_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <imageareapanel.h>
|
||||
#include <toolpanelcoord.h>
|
||||
#include <profilepanel.h>
|
||||
#include <rtengine.h>
|
||||
#include <history.h>
|
||||
#include <histogrampanel.h>
|
||||
#include <thumbnail.h>
|
||||
#include <saveasdlg.h>
|
||||
#include <batchqueueentry.h>
|
||||
#include <thumbnaillistener.h>
|
||||
#include <navigator.h>
|
||||
|
||||
class EditorPanel;
|
||||
struct EditorPanelIdleHelper {
|
||||
EditorPanel* epanel;
|
||||
bool destroyed;
|
||||
int pending;
|
||||
};
|
||||
|
||||
class RTWindow;
|
||||
class EditorPanel : public Gtk::VBox,
|
||||
public PParamsChangeListener,
|
||||
public rtengine::ProgressListener,
|
||||
public ThumbnailListener,
|
||||
public HistoryBeforeLineListener,
|
||||
public rtengine::HistogramListener {
|
||||
|
||||
protected:
|
||||
Gtk::Label *progressLabel;
|
||||
Gtk::ToggleButton* info;
|
||||
Gtk::ToggleButton* hidehp;
|
||||
Gtk::ToggleButton* beforeAfter;
|
||||
Gtk::HPaned* hpanedl;
|
||||
Gtk::HPaned* hpanedr;
|
||||
Gtk::HBox* statusBox;
|
||||
Gtk::Image* red;
|
||||
Gtk::Image* green;
|
||||
Gtk::VBox* leftbox, *vboxright;
|
||||
|
||||
Gtk::Button* queueimg;
|
||||
Gtk::Button* saveimgas;
|
||||
Gtk::Button* sendtogimp;
|
||||
|
||||
ImageAreaPanel* iarea;
|
||||
PreviewHandler* previewHandler;
|
||||
PreviewHandler* beforePreviewHandler; // for the before-after view
|
||||
Navigator* navigator;
|
||||
ImageAreaPanel* beforeIarea; // for the before-after view
|
||||
Gtk::VBox* beforeBox;
|
||||
Gtk::VBox* afterBox;
|
||||
Gtk::Label* beforeLabel;
|
||||
Gtk::Label* afterLabel;
|
||||
Gtk::HBox* beforeAfterBox;
|
||||
|
||||
ProfilePanel* profilep;
|
||||
History* history;
|
||||
HistogramPanel* histogramPanel;
|
||||
ToolPanelCoordinator* tpc;
|
||||
RTWindow* parent;
|
||||
SaveAsDialog* saveAsDialog;
|
||||
|
||||
Thumbnail* openThm;
|
||||
rtengine::InitialImage* isrc;
|
||||
rtengine::StagedImageProcessor* ipc;
|
||||
rtengine::StagedImageProcessor* beforeIpc; // for the before-after view
|
||||
|
||||
EditorPanelIdleHelper* epih;
|
||||
|
||||
void open (Thumbnail* tmb, rtengine::InitialImage* isrc);
|
||||
void close ();
|
||||
|
||||
rtengine::IImage16* processImage ();
|
||||
BatchQueueEntry* createBatchQueueEntry ();
|
||||
int saveImage (rtengine::IImage16* img, Glib::ustring& fname, SaveFormat sf, bool findNewNameIfNeeded);
|
||||
|
||||
public:
|
||||
|
||||
static rtengine::InitialImage* loadImage (Thumbnail* tmb);
|
||||
|
||||
EditorPanel (Thumbnail* tmb, rtengine::InitialImage* isrc);
|
||||
virtual ~EditorPanel ();
|
||||
|
||||
bool beforeClosing ();
|
||||
void on_realize ();
|
||||
|
||||
void setParent (RTWindow* p) { parent = p; }
|
||||
|
||||
// progresslistener interface
|
||||
void setProgressState (int state);
|
||||
void error (Glib::ustring descr);
|
||||
void refreshProcessingState (bool state); // this is called by setProcessingState in the gtk thread
|
||||
void displayError (Glib::ustring descr); // this is called by error in the gtk thread
|
||||
|
||||
// PParamsChangeListener interface
|
||||
void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited=NULL);
|
||||
|
||||
// thumbnaillistener interface
|
||||
void procParamsChanged (Thumbnail* thm, int whoChangedIt);
|
||||
|
||||
// HistoryBeforeLineListener
|
||||
void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params);
|
||||
|
||||
// HistogramListener
|
||||
void histogramChanged (unsigned int* rh, unsigned int* gh, unsigned int* bh, unsigned int* lh, unsigned int* bcrgb, unsigned int* bcl);
|
||||
|
||||
// event handlers
|
||||
void info_toggled ();
|
||||
void hideHistoryActivated ();
|
||||
void beforeAfterToggled ();
|
||||
void saveAsPressed ();
|
||||
void queueImgPressed ();
|
||||
void sendToGimpPressed ();
|
||||
|
||||
void saveProfile ();
|
||||
Glib::ustring getShortName ();
|
||||
Glib::ustring getFileName ();
|
||||
bool handleShortcutKey (GdkEventKey* event);
|
||||
|
||||
void saveOptions ();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
44
rtgui/exiffiltersettings.cc
Executable file
44
rtgui/exiffiltersettings.cc
Executable file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <exiffiltersettings.h>
|
||||
|
||||
ExifFilterSettings::ExifFilterSettings () {
|
||||
|
||||
clear ();
|
||||
}
|
||||
|
||||
void ExifFilterSettings::clear () {
|
||||
fnumberFrom = 100;
|
||||
fnumberTo = 0;
|
||||
shutterFrom = 100;
|
||||
shutterTo = 0;
|
||||
isoFrom = 100000000;
|
||||
isoTo = 0;
|
||||
focalFrom = 1e8;
|
||||
focalTo = 0;
|
||||
lenses.clear ();
|
||||
cameras.clear ();
|
||||
|
||||
filterFNumber = false;
|
||||
filterShutter = false;
|
||||
filterFocalLen = false;
|
||||
filterISO = false;
|
||||
filterCamera = false;
|
||||
filterLens = false;
|
||||
}
|
||||
51
rtgui/exiffiltersettings.h
Executable file
51
rtgui/exiffiltersettings.h
Executable file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _EXIFFILTERSETTINGS_
|
||||
#define _EXIFFILTERSETTINGS_
|
||||
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
class ExifFilterSettings {
|
||||
|
||||
public:
|
||||
std::set<std::string> cameras;
|
||||
std::set<std::string> lenses;
|
||||
double fnumberFrom;
|
||||
double fnumberTo;
|
||||
double shutterFrom;
|
||||
double shutterTo;
|
||||
double focalFrom;
|
||||
double focalTo;
|
||||
int isoFrom;
|
||||
int isoTo;
|
||||
|
||||
bool filterFNumber;
|
||||
bool filterShutter;
|
||||
bool filterFocalLen;
|
||||
bool filterISO;
|
||||
bool filterCamera;
|
||||
bool filterLens;
|
||||
|
||||
ExifFilterSettings ();
|
||||
void clear ();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
569
rtgui/exifpanel.cc
Executable file
569
rtgui/exifpanel.cc
Executable file
@@ -0,0 +1,569 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <exifpanel.h>
|
||||
#include <safegtk.h>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
using namespace rtexif;
|
||||
extern Glib::ustring argv0;
|
||||
|
||||
ExifPanel::ExifPanel () : idata(NULL) {
|
||||
|
||||
recursiveOp = true;
|
||||
|
||||
exifTree = Gtk::manage(new Gtk::TreeView());
|
||||
scrolledWindow = Gtk::manage(new Gtk::ScrolledWindow());
|
||||
|
||||
exifTree->set_headers_visible(false);
|
||||
exifTree->set_rules_hint(false);
|
||||
exifTree->set_reorderable(false);
|
||||
exifTree->set_enable_search(true);
|
||||
exifTree->get_selection()->set_mode (Gtk::SELECTION_MULTIPLE);
|
||||
scrolledWindow->set_border_width(2);
|
||||
scrolledWindow->set_shadow_type(Gtk::SHADOW_NONE);
|
||||
scrolledWindow->set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS);
|
||||
scrolledWindow->property_window_placement().set_value(Gtk::CORNER_TOP_LEFT);
|
||||
scrolledWindow->add(*exifTree);
|
||||
|
||||
exifTreeModel = Gtk::TreeStore::create(exifColumns);
|
||||
exifTree->set_model (exifTreeModel);
|
||||
|
||||
delicon = safe_create_from_file (argv0+"/images/deltags.png");
|
||||
keepicon = safe_create_from_file (argv0+"/images/addtags.png");
|
||||
editicon = safe_create_from_file (argv0+"/images/logoicon16.png");
|
||||
|
||||
Gtk::TreeView::Column *viewcol = Gtk::manage(new Gtk::TreeView::Column ("Field Name"));
|
||||
Gtk::CellRendererPixbuf* render_pb = Gtk::manage(new Gtk::CellRendererPixbuf ());
|
||||
Gtk::CellRendererText *render_txt = Gtk::manage(new Gtk::CellRendererText());
|
||||
viewcol->pack_start (*render_pb, false);
|
||||
viewcol->pack_start (*render_txt, true);
|
||||
viewcol->add_attribute (*render_pb, "pixbuf", exifColumns.icon);
|
||||
viewcol->add_attribute (*render_txt, "markup", exifColumns.field);
|
||||
|
||||
render_pb->property_ypad() = 0;
|
||||
render_txt->property_ypad() = 0;
|
||||
render_pb->property_yalign() = 0;
|
||||
render_txt->property_yalign() = 0;
|
||||
|
||||
exifTree->append_column (*viewcol);
|
||||
|
||||
Gtk::TreeView::Column *viewcolv = Gtk::manage(new Gtk::TreeView::Column ("Value"));
|
||||
Gtk::CellRendererText *render_txtv = Gtk::manage(new Gtk::CellRendererText());
|
||||
viewcolv->pack_start (*render_txtv, true);
|
||||
viewcolv->add_attribute (*render_txtv, "markup", exifColumns.value);
|
||||
|
||||
render_txtv->property_ypad() = 0;
|
||||
|
||||
exifTree->append_column (*viewcolv);
|
||||
|
||||
pack_start (*scrolledWindow);
|
||||
|
||||
Gtk::HBox* buttons1 = Gtk::manage(new Gtk::HBox ());
|
||||
Gtk::HBox* buttons2 = Gtk::manage(new Gtk::HBox ());
|
||||
|
||||
remove = Gtk::manage(new Gtk::Button (M("EXIFPANEL_REMOVE")));
|
||||
remove->set_image (*Gtk::manage(new Gtk::Image (delicon)));
|
||||
remove->set_tooltip_text (M("EXIFPANEL_REMOVEHINT"));
|
||||
buttons1->pack_start (*remove);
|
||||
|
||||
keep = Gtk::manage(new Gtk::Button (M("EXIFPANEL_KEEP")));
|
||||
keep->set_image (*Gtk::manage(new Gtk::Image (keepicon)));
|
||||
keep->set_tooltip_text (M("EXIFPANEL_KEEPHINT"));
|
||||
buttons1->pack_start (*keep);
|
||||
|
||||
add = Gtk::manage(new Gtk::Button (M("EXIFPANEL_ADDEDIT")));
|
||||
add->set_image (*Gtk::manage(new Gtk::Image (editicon)));
|
||||
add->set_tooltip_text (M("EXIFPANEL_ADDEDITHINT"));
|
||||
buttons1->pack_start (*add);
|
||||
|
||||
reset = Gtk::manage(new Gtk::Button (M("EXIFPANEL_RESET")));
|
||||
reset->set_image (*Gtk::manage(new Gtk::Image (Gtk::StockID ("gtk-undo"), Gtk::IconSize (2))));
|
||||
reset->set_tooltip_text (M("EXIFPANEL_RESETHINT"));
|
||||
buttons2->pack_start (*reset);
|
||||
|
||||
resetAll = Gtk::manage(new Gtk::Button (M("EXIFPANEL_RESETALL")));
|
||||
resetAll->set_image (*Gtk::manage(new Gtk::Image (argv0+"/images/gtk-undo-ltr.png")));
|
||||
resetAll->set_tooltip_text (M("EXIFPANEL_RESETALLHINT"));
|
||||
buttons2->pack_start (*resetAll);
|
||||
|
||||
pack_end (*buttons2, Gtk::PACK_SHRINK);
|
||||
pack_end (*buttons1, Gtk::PACK_SHRINK);
|
||||
|
||||
exifTree->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &ExifPanel::exifSelectionChanged));
|
||||
exifTree->signal_row_activated().connect(sigc::mem_fun(*this, &ExifPanel::row_activated));
|
||||
|
||||
remove->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::removePressed) );
|
||||
keep->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::keepPressed) );
|
||||
reset->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::resetPressed) );
|
||||
resetAll->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::resetAllPressed) );
|
||||
add->signal_clicked().connect( sigc::mem_fun(*this, &ExifPanel::addPressed) );
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
ExifPanel::~ExifPanel () {
|
||||
}
|
||||
|
||||
void ExifPanel::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
changeList = pp->exif;
|
||||
setImageData (idata);
|
||||
applyChangeList ();
|
||||
exifSelectionChanged ();
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void ExifPanel::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
// updateChangeList ();
|
||||
pp->exif = changeList;
|
||||
}
|
||||
|
||||
void ExifPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
|
||||
|
||||
defChangeList = defParams->exif;
|
||||
}
|
||||
|
||||
void ExifPanel::setImageData (const ImageMetaData* id) {
|
||||
|
||||
idata = id;
|
||||
exifTreeModel->clear ();
|
||||
|
||||
const std::vector<Tag*>& defTags = ExifManager::getDefaultTIFFTags (NULL);
|
||||
for (int i=0; i<defTags.size(); i++)
|
||||
if (defTags[i]->nameToString() == "ImageWidth" || defTags[i]->nameToString() == "ImageHeight" || defTags[i]->nameToString() == "BitsPerSample")
|
||||
addTag (exifTreeModel->children(), defTags[i]->nameToString(), "?", SYSTEM, false);
|
||||
else
|
||||
addTag (exifTreeModel->children(), defTags[i]->nameToString(), defTags[i]->valueToString(), SYSTEM, false);
|
||||
|
||||
if (id && id->getExifData ()) {
|
||||
// id->getExifData ()->printAll ();
|
||||
addDirectory (id->getExifData (), exifTreeModel->children());
|
||||
}
|
||||
}
|
||||
|
||||
Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, int action, bool editable) {
|
||||
|
||||
Gtk::TreeModel::Row row = *(exifTreeModel->append(root));
|
||||
row[exifColumns.action] = action;
|
||||
row[exifColumns.editable] = editable;
|
||||
row[exifColumns.edited] = false;
|
||||
row[exifColumns.field_nopango] = field;
|
||||
row[exifColumns.value_nopango] = value;
|
||||
row[exifColumns.orig_value] = value;
|
||||
|
||||
if (action==WRITE)
|
||||
row[exifColumns.icon] = keepicon;
|
||||
else if (action==DONTWRITE)
|
||||
row[exifColumns.icon] = delicon;
|
||||
|
||||
if (editable) {
|
||||
row[exifColumns.field] = Glib::ustring("<b>") + field + "</b>";
|
||||
row[exifColumns.value] = Glib::ustring("<b>") + value + "</b>";
|
||||
}
|
||||
else if (action==SYSTEM) {
|
||||
row[exifColumns.field] = Glib::ustring("<i>") + field + "</i>";
|
||||
row[exifColumns.value] = Glib::ustring("<i>") + value + "</i>";
|
||||
}
|
||||
else {
|
||||
row[exifColumns.field] = field;
|
||||
row[exifColumns.value] = value;
|
||||
}
|
||||
|
||||
return row.children();
|
||||
}
|
||||
|
||||
void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children root) {
|
||||
|
||||
for (int i=0; i<dir->getCount(); i++) {
|
||||
Tag* t = ((TagDirectory*)dir)->getTagByIndex (i);
|
||||
if (t->getAttrib() && t->getAttrib()->action==SYSTEM)
|
||||
continue;
|
||||
if (t->isDirectory())
|
||||
for (int j=0; t->getDirectory(j); j++) {
|
||||
Gtk::TreeModel::Children ch = addTag (root, t->nameToString (j), M("EXIFPANEL_SUBDIRECTORY"), t->getAttrib() ? t->getAttrib()->action : 0, t->getAttrib() && t->getAttrib()->editable);
|
||||
addDirectory (t->getDirectory(j), ch);
|
||||
}
|
||||
else
|
||||
addTag (root, t->nameToString (), t->valueToString (), t->getAttrib() ? t->getAttrib()->action : 0, t->getAttrib() && t->getAttrib()->editable);
|
||||
}
|
||||
}
|
||||
|
||||
void ExifPanel::exifSelectionChanged () {
|
||||
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = exifTree->get_selection();
|
||||
std::vector<Gtk::TreeModel::Path> sel = selection->get_selected_rows();
|
||||
if (sel.size()>1) {
|
||||
remove->set_sensitive (1);
|
||||
keep->set_sensitive (1);
|
||||
reset->set_sensitive (1);
|
||||
}
|
||||
else if (sel.size()==1) {
|
||||
Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (sel[0]);
|
||||
if (iter->get_value (exifColumns.action)==SYSTEM) {
|
||||
remove->set_sensitive (0);
|
||||
keep->set_sensitive (0);
|
||||
reset->set_sensitive (0);
|
||||
}
|
||||
else if (iter->children().size()>0) {
|
||||
remove->set_sensitive (1);
|
||||
keep->set_sensitive (1);
|
||||
reset->set_sensitive (1);
|
||||
}
|
||||
else if (iter->get_value(exifColumns.icon)==delicon) {
|
||||
remove->set_sensitive (0);
|
||||
keep->set_sensitive (1);
|
||||
reset->set_sensitive (1);
|
||||
}
|
||||
else if (iter->get_value(exifColumns.icon)==keepicon || iter->get_value(exifColumns.icon)==editicon) {
|
||||
keep->set_sensitive (0);
|
||||
remove->set_sensitive (1);
|
||||
reset->set_sensitive (1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
remove->set_sensitive (0);
|
||||
keep->set_sensitive (0);
|
||||
reset->set_sensitive (0);
|
||||
}
|
||||
}
|
||||
|
||||
void ExifPanel::delIt (Gtk::TreeModel::iterator iter) {
|
||||
|
||||
if (!iter)
|
||||
return;
|
||||
|
||||
if (iter->get_value (exifColumns.action) != SYSTEM)
|
||||
iter->set_value (exifColumns.icon, delicon);
|
||||
if (recursiveOp)
|
||||
for (Gtk::TreeModel::iterator i=iter->children().begin(); i!=iter->children().end(); i++)
|
||||
delIt (i);
|
||||
}
|
||||
|
||||
void ExifPanel::removePressed () {
|
||||
|
||||
std::vector<Gtk::TreeModel::Path> sel = exifTree->get_selection()->get_selected_rows();
|
||||
for (int i=0; i<sel.size(); i++)
|
||||
delIt (exifTreeModel->get_iter (sel[i]));
|
||||
|
||||
exifSelectionChanged ();
|
||||
updateChangeList ();
|
||||
notifyListener ();
|
||||
}
|
||||
|
||||
void ExifPanel::keepIt (Gtk::TreeModel::iterator iter) {
|
||||
|
||||
if (!iter)
|
||||
return;
|
||||
|
||||
if (iter->get_value (exifColumns.action) != SYSTEM)
|
||||
iter->set_value (exifColumns.icon, iter->get_value (exifColumns.edited) ? editicon : keepicon);
|
||||
if (recursiveOp)
|
||||
for (Gtk::TreeModel::iterator i=iter->children().begin(); i!=iter->children().end(); i++)
|
||||
keepIt (i);
|
||||
}
|
||||
|
||||
void ExifPanel::keepPressed () {
|
||||
|
||||
std::vector<Gtk::TreeModel::Path> sel = exifTree->get_selection()->get_selected_rows();
|
||||
for (int i=0; i<sel.size(); i++)
|
||||
keepIt (exifTreeModel->get_iter (sel[i]));
|
||||
|
||||
exifSelectionChanged ();
|
||||
updateChangeList ();
|
||||
notifyListener ();
|
||||
}
|
||||
|
||||
/*void ExifPanel::resetIt (Gtk::TreeModel::iterator iter) {
|
||||
|
||||
if (!iter)
|
||||
return;
|
||||
|
||||
if (iter->get_value (exifColumns.action)!=SYSTEM)
|
||||
iter->set_value (exifColumns.icon, iter->get_value (exifColumns.action) ? keepicon : delicon);
|
||||
if (iter->get_value (exifColumns.edited)) {
|
||||
iter->set_value (exifColumns.value, Glib::ustring("<b>") + iter->get_value(exifColumns.orig_value) + "</b>");
|
||||
iter->set_value (exifColumns.value_nopango, iter->get_value(exifColumns.orig_value));
|
||||
iter->set_value (exifColumns.edited, false);
|
||||
}
|
||||
if (iter->get_value (exifColumns.action)==100)
|
||||
exifTreeModel->erase (iter);
|
||||
else
|
||||
if (recursiveOp)
|
||||
for (Gtk::TreeModel::iterator i=iter->children().begin(); i!=iter->children().end(); i++)
|
||||
resetIt (i);
|
||||
}*/
|
||||
Gtk::TreeModel::iterator ExifPanel::resetIt (Gtk::TreeModel::iterator iter) {
|
||||
|
||||
if (!iter)
|
||||
return iter;
|
||||
|
||||
if (iter->get_value (exifColumns.action)!=SYSTEM)
|
||||
iter->set_value (exifColumns.icon, iter->get_value (exifColumns.action) ? keepicon : delicon);
|
||||
if (iter->get_value (exifColumns.edited)) {
|
||||
iter->set_value (exifColumns.value, Glib::ustring("<b>") + iter->get_value(exifColumns.orig_value) + "</b>");
|
||||
iter->set_value (exifColumns.value_nopango, iter->get_value(exifColumns.orig_value));
|
||||
iter->set_value (exifColumns.edited, false);
|
||||
}
|
||||
if (iter->get_value (exifColumns.action)==100) {
|
||||
return exifTreeModel->erase (iter);
|
||||
}
|
||||
else
|
||||
if (recursiveOp) {
|
||||
Gtk::TreeModel::iterator i = iter->children().begin();
|
||||
while (i && i != iter->children().end())
|
||||
i = resetIt (i);
|
||||
}
|
||||
return ++iter;
|
||||
}
|
||||
void ExifPanel::resetPressed () {
|
||||
|
||||
std::vector<Gtk::TreeModel::Path> sel = exifTree->get_selection()->get_selected_rows();
|
||||
for (int i=0; i<sel.size(); i++)
|
||||
resetIt (exifTreeModel->get_iter (sel[i]));
|
||||
|
||||
exifSelectionChanged ();
|
||||
updateChangeList ();
|
||||
notifyListener ();
|
||||
}
|
||||
|
||||
void ExifPanel::resetAllPressed () {
|
||||
|
||||
setImageData (idata);
|
||||
changeList = defChangeList;
|
||||
applyChangeList ();
|
||||
exifSelectionChanged ();
|
||||
notifyListener ();
|
||||
}
|
||||
|
||||
void ExifPanel::addPressed () {
|
||||
|
||||
Gtk::Dialog* dialog = new Gtk::Dialog (M("EXIFPANEL_ADDTAGDLG_TITLE"), *((Gtk::Window*)get_toplevel()), true, true);
|
||||
dialog->add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
|
||||
dialog->add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
|
||||
|
||||
Gtk::HBox* hb1 = new Gtk::HBox ();
|
||||
Gtk::HBox* hb2 = new Gtk::HBox ();
|
||||
|
||||
Gtk::Label* tlabel = new Gtk::Label (M("EXIFPANEL_ADDTAGDLG_SELECTTAG")+":");
|
||||
Gtk::ComboBoxText* tcombo = new Gtk::ComboBoxText ();
|
||||
|
||||
tcombo->append_text ("Artist");
|
||||
tcombo->append_text ("Copyright");
|
||||
tcombo->append_text ("ImageDescription");
|
||||
tcombo->append_text ("Exif.UserComment");
|
||||
|
||||
hb1->pack_start (*tlabel, Gtk::PACK_SHRINK, 4);
|
||||
hb1->pack_start (*tcombo);
|
||||
|
||||
Gtk::Label* vlabel = new Gtk::Label (M("EXIFPANEL_ADDTAGDLG_ENTERVALUE")+":");
|
||||
Gtk::Entry* ventry = new Gtk::Entry ();
|
||||
hb2->pack_start (*vlabel, Gtk::PACK_SHRINK, 4);
|
||||
hb2->pack_start (*ventry);
|
||||
|
||||
Glib::ustring sel = getSelection (true);
|
||||
if (sel=="")
|
||||
tcombo->set_active_text ("Exif.UserComment");
|
||||
else {
|
||||
tcombo->set_active_text (sel);
|
||||
if (tcombo->get_active ()<0) {
|
||||
tcombo->append_text (sel);
|
||||
tcombo->set_active_text (sel);
|
||||
}
|
||||
ventry->set_text (getSelectedValue ());
|
||||
}
|
||||
|
||||
ventry->set_activates_default (true);
|
||||
dialog->set_default_response (Gtk::RESPONSE_OK);
|
||||
dialog->get_vbox()->pack_start (*hb1, Gtk::PACK_SHRINK);
|
||||
dialog->get_vbox()->pack_start (*hb2, Gtk::PACK_SHRINK, 4);
|
||||
tlabel->show ();
|
||||
tcombo->show ();
|
||||
vlabel->show ();
|
||||
ventry->show ();
|
||||
hb1->show ();
|
||||
hb2->show ();
|
||||
|
||||
if (dialog->run ()== Gtk::RESPONSE_OK) {
|
||||
editTag (exifTreeModel->children(), tcombo->get_active_text(), ventry->get_text());
|
||||
updateChangeList ();
|
||||
notifyListener ();
|
||||
}
|
||||
|
||||
delete dialog;
|
||||
delete tlabel;
|
||||
delete tcombo;
|
||||
delete vlabel;
|
||||
delete ventry;
|
||||
delete hb1;
|
||||
delete hb2;
|
||||
}
|
||||
|
||||
void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value) {
|
||||
|
||||
Glib::ustring::size_type dp = name.find_first_of ('.');
|
||||
Glib::ustring fseg = name.substr (0,dp);
|
||||
// look up first segment of the path
|
||||
Gtk::TreeModel::iterator iter;
|
||||
for (iter = root.begin(); iter!=root.end(); iter++)
|
||||
if (iter->get_value (exifColumns.field_nopango) == fseg)
|
||||
break;
|
||||
|
||||
if (iter==root.end() && value!="#keep" && value!="#delete") {
|
||||
iter = exifTreeModel->append(root);
|
||||
iter->set_value (exifColumns.field_nopango, fseg);
|
||||
iter->set_value (exifColumns.action, 100);
|
||||
if (dp==Glib::ustring::npos) {
|
||||
iter->set_value (exifColumns.value, Glib::ustring("<b>") + value + "</b>");
|
||||
iter->set_value (exifColumns.value_nopango, value);
|
||||
iter->set_value (exifColumns.orig_value, value);
|
||||
iter->set_value (exifColumns.field, Glib::ustring("<b>") + fseg + "</b>");
|
||||
iter->set_value (exifColumns.edited, true);
|
||||
iter->set_value (exifColumns.editable, true);
|
||||
iter->set_value (exifColumns.icon, editicon);
|
||||
}
|
||||
else {
|
||||
iter->set_value (exifColumns.value, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY")));
|
||||
iter->set_value (exifColumns.value_nopango, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY")));
|
||||
iter->set_value (exifColumns.field, fseg);
|
||||
iter->set_value (exifColumns.icon, keepicon);
|
||||
iter->set_value (exifColumns.orig_value, Glib::ustring(M("EXIFPANEL_SUBDIRECTORY")));
|
||||
}
|
||||
}
|
||||
|
||||
if (dp==Glib::ustring::npos) {
|
||||
if (value=="#keep" && iter->get_value (exifColumns.action)!=SYSTEM)
|
||||
iter->set_value (exifColumns.icon, iter->get_value (exifColumns.edited) ? editicon : keepicon);
|
||||
else if (value=="#delete" && iter->get_value (exifColumns.action)!=SYSTEM)
|
||||
iter->set_value (exifColumns.icon, delicon);
|
||||
else {
|
||||
iter->set_value (exifColumns.value, Glib::ustring("<b>") + value + "</b>");
|
||||
iter->set_value (exifColumns.value_nopango, value);
|
||||
iter->set_value (exifColumns.edited, true);
|
||||
iter->set_value (exifColumns.icon, editicon);
|
||||
}
|
||||
}
|
||||
else
|
||||
editTag (iter->children(), name.substr (dp+1, Glib::ustring::npos), value);
|
||||
}
|
||||
|
||||
Glib::ustring ExifPanel::getSelectedValue () {
|
||||
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = exifTree->get_selection();
|
||||
std::vector<Gtk::TreeModel::Path> rows = selection->get_selected_rows();
|
||||
if (rows.size()!=1)
|
||||
return "";
|
||||
Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (rows[0]);
|
||||
if (iter)
|
||||
return iter->get_value (exifColumns.value_nopango);
|
||||
return "";
|
||||
}
|
||||
|
||||
Glib::ustring ExifPanel::getSelection (bool onlyeditable) {
|
||||
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = exifTree->get_selection();
|
||||
std::vector<Gtk::TreeModel::Path> rows = selection->get_selected_rows();
|
||||
|
||||
if (rows.size()!=1)
|
||||
return "";
|
||||
Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (rows[0]);
|
||||
|
||||
Glib::ustring ret = "";
|
||||
bool first = true;
|
||||
bool editable = false;
|
||||
while (iter) {
|
||||
if (first)
|
||||
ret = iter->get_value (exifColumns.field_nopango);
|
||||
else
|
||||
ret = iter->get_value (exifColumns.field_nopango) + "." + ret;
|
||||
editable = iter->get_value (exifColumns.editable);
|
||||
iter = iter->parent ();
|
||||
first = false;
|
||||
}
|
||||
if (!editable && onlyeditable)
|
||||
return "";
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ExifPanel::updateChangeList (Gtk::TreeModel::Children root, std::string prefix) {
|
||||
|
||||
if (prefix!="")
|
||||
prefix = prefix + ".";
|
||||
|
||||
Gtk::TreeModel::iterator iter;
|
||||
for (iter = root.begin(); iter!=root.end(); iter++) {
|
||||
if (iter->get_value (exifColumns.edited) == true) {
|
||||
ExifPair ec;
|
||||
ec.field = prefix + iter->get_value (exifColumns.field_nopango);
|
||||
ec.value = iter->get_value (exifColumns.value_nopango);
|
||||
changeList.push_back (ec);
|
||||
}
|
||||
else if (iter->get_value (exifColumns.action) == WRITE && iter->get_value (exifColumns.icon) == delicon) {
|
||||
ExifPair ec;
|
||||
ec.field = prefix + iter->get_value (exifColumns.field_nopango);
|
||||
ec.value = "#delete";
|
||||
changeList.push_back (ec);
|
||||
}
|
||||
else if (iter->get_value (exifColumns.action) == DONTWRITE && iter->get_value (exifColumns.icon) == keepicon) {
|
||||
ExifPair ec;
|
||||
ec.field = prefix + iter->get_value (exifColumns.field_nopango);
|
||||
ec.value = "#keep";
|
||||
changeList.push_back (ec);
|
||||
}
|
||||
if (iter->get_value (exifColumns.icon) == keepicon)
|
||||
updateChangeList (iter->children(), prefix + iter->get_value (exifColumns.field_nopango));
|
||||
}
|
||||
}
|
||||
|
||||
void ExifPanel::updateChangeList () {
|
||||
|
||||
changeList.clear ();
|
||||
updateChangeList (exifTreeModel->children(), "");
|
||||
}
|
||||
|
||||
void ExifPanel::applyChangeList () {
|
||||
|
||||
for (int i=0; i<changeList.size(); i++)
|
||||
editTag (exifTreeModel->children(), changeList[i].field, changeList[i].value);
|
||||
}
|
||||
|
||||
void ExifPanel::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column) {
|
||||
|
||||
Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (path);
|
||||
if (iter) {
|
||||
if (iter->children().size()>0)
|
||||
if (exifTree->row_expanded (path))
|
||||
exifTree->collapse_row (path);
|
||||
else
|
||||
exifTree->expand_row (path, false);
|
||||
else if (iter->get_value (exifColumns.editable))
|
||||
addPressed ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ExifPanel::notifyListener () {
|
||||
|
||||
if (listener)
|
||||
listener->panelChanged (EvExif, M("HISTORY_CHANGED"));
|
||||
}
|
||||
97
rtgui/exifpanel.h
Executable file
97
rtgui/exifpanel.h
Executable file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _EXIFPANEL_
|
||||
#define _EXIFPANEL_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <toolpanel.h>
|
||||
|
||||
class ExifPanel : public Gtk::VBox, public ToolPanel {
|
||||
|
||||
private:
|
||||
const rtengine::ImageMetaData* idata;
|
||||
int fullw, fullh, cx, cy, cw, ch;
|
||||
bool crenabled;
|
||||
std::vector<rtengine::procparams::ExifPair> changeList;
|
||||
std::vector<rtengine::procparams::ExifPair> defChangeList;
|
||||
bool recursiveOp;
|
||||
|
||||
class ExifColumns : public Gtk::TreeModelColumnRecord {
|
||||
public:
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > icon;
|
||||
Gtk::TreeModelColumn<Glib::ustring> field;
|
||||
Gtk::TreeModelColumn<Glib::ustring> field_nopango;
|
||||
Gtk::TreeModelColumn<Glib::ustring> value;
|
||||
Gtk::TreeModelColumn<Glib::ustring> value_nopango;
|
||||
Gtk::TreeModelColumn<Glib::ustring> orig_value;
|
||||
Gtk::TreeModelColumn<int> action; // = 0: dont write to output, =1: write to output, =2: chagned by RT (not editable/deletable), =3: new addition
|
||||
Gtk::TreeModelColumn<bool> editable;
|
||||
Gtk::TreeModelColumn<bool> edited;
|
||||
|
||||
ExifColumns() { add(field); add(value); add(icon); add(action); add(edited); add(field_nopango); add(value_nopango); add(editable); add(orig_value); }
|
||||
};
|
||||
Glib::RefPtr<Gdk::Pixbuf> delicon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> keepicon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> editicon;
|
||||
|
||||
ExifColumns exifColumns;
|
||||
Gtk::TreeView* exifTree;
|
||||
Gtk::ScrolledWindow* scrolledWindow;
|
||||
Glib::RefPtr<Gtk::TreeStore> exifTreeModel;
|
||||
|
||||
Gtk::Button* remove;
|
||||
Gtk::Button* keep;
|
||||
Gtk::Button* add;
|
||||
Gtk::Button* reset;
|
||||
Gtk::Button* resetAll;
|
||||
|
||||
Gtk::TreeModel::Children addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, int action, bool editable);
|
||||
void editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value);
|
||||
void updateChangeList (Gtk::TreeModel::Children root, std::string prefix);
|
||||
void addDirectory (const rtexif::TagDirectory* dir, Gtk::TreeModel::Children root);
|
||||
Glib::ustring getSelection (bool onlyifeditable=false);
|
||||
Glib::ustring getSelectedValue ();
|
||||
void updateChangeList ();
|
||||
void applyChangeList ();
|
||||
void keepIt (Gtk::TreeModel::iterator iter);
|
||||
void delIt (Gtk::TreeModel::iterator iter);
|
||||
Gtk::TreeModel::iterator resetIt (Gtk::TreeModel::iterator iter);
|
||||
public:
|
||||
ExifPanel ();
|
||||
virtual ~ExifPanel ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
|
||||
|
||||
void setImageData (const rtengine::ImageMetaData* id);
|
||||
|
||||
void exifSelectionChanged ();
|
||||
void removePressed ();
|
||||
void keepPressed ();
|
||||
void resetPressed ();
|
||||
void resetAllPressed ();
|
||||
void addPressed ();
|
||||
void row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
|
||||
|
||||
void notifyListener ();
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
112
rtgui/favoritbrowser.cc
Executable file
112
rtgui/favoritbrowser.cc
Executable file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <favoritbrowser.h>
|
||||
|
||||
FavoritBrowser::FavoritBrowser () : listener (NULL), lastSelectedDir ("") {
|
||||
|
||||
scrollw = Gtk::manage (new Gtk::ScrolledWindow ());
|
||||
scrollw->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||
|
||||
Gtk::Frame* frame = Gtk::manage (new Gtk::Frame ("Favorite Folders"));
|
||||
frame->add (*scrollw);
|
||||
|
||||
pack_start (*frame);
|
||||
|
||||
treeView = Gtk::manage (new Gtk::TreeView ());
|
||||
scrollw->add (*treeView);
|
||||
|
||||
favoritModel = Gtk::ListStore::create (favoritColumns);
|
||||
treeView->set_model (favoritModel);
|
||||
treeView->set_headers_visible (false);
|
||||
|
||||
Gtk::TreeView::Column *iviewcol = Gtk::manage (new Gtk::TreeView::Column ("icon"));
|
||||
Gtk::CellRendererPixbuf *iconCR = Gtk::manage (new Gtk::CellRendererPixbuf());
|
||||
iviewcol->pack_start (*iconCR, false);
|
||||
iviewcol->add_attribute (*iconCR, "gicon", 0);
|
||||
|
||||
treeView->append_column (*iviewcol);
|
||||
treeView->append_column ("text", favoritColumns.shortdir);
|
||||
|
||||
treeView->set_tooltip_column (2);
|
||||
treeView->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &FavoritBrowser::selectionChanged));
|
||||
|
||||
add = Gtk::manage (new Gtk::Button ("Add"));
|
||||
del = Gtk::manage (new Gtk::Button ("Del"));
|
||||
add->set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::ADD, Gtk::ICON_SIZE_MENU)));
|
||||
del->set_image (*Gtk::manage (new Gtk::Image (Gtk::Stock::REMOVE, Gtk::ICON_SIZE_MENU)));
|
||||
Gtk::HBox* buttonBox = Gtk::manage (new Gtk::HBox ());
|
||||
buttonBox->pack_start (*add);
|
||||
buttonBox->pack_start (*del);
|
||||
|
||||
pack_start (*buttonBox, Gtk::PACK_SHRINK, 2);
|
||||
|
||||
add->signal_clicked().connect(sigc::mem_fun(*this, &FavoritBrowser::addPressed));
|
||||
del->signal_clicked().connect(sigc::mem_fun(*this, &FavoritBrowser::delPressed));
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
void FavoritBrowser::selectionChanged () {
|
||||
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = treeView->get_selection();
|
||||
Gtk::TreeModel::iterator iter = selection->get_selected();
|
||||
if (iter && listener)
|
||||
listener->selectDir (iter->get_value (favoritColumns.fulldir));
|
||||
}
|
||||
|
||||
void FavoritBrowser::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) {
|
||||
|
||||
lastSelectedDir = dirname;
|
||||
}
|
||||
|
||||
void FavoritBrowser::addPressed () {
|
||||
|
||||
if (lastSelectedDir=="")
|
||||
return;
|
||||
|
||||
// check if the dirname is already in the list. If yes, return.
|
||||
Gtk::TreeModel::iterator iter = favoritModel->children ().begin();
|
||||
while (iter != favoritModel->children().end()) {
|
||||
if (iter->get_value (favoritColumns.fulldir) == lastSelectedDir)
|
||||
return;
|
||||
iter++;
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gio::File> hfile = Gio::File::create_for_parse_name (lastSelectedDir);
|
||||
if (hfile) {
|
||||
Glib::RefPtr<Gio::FileInfo> info = hfile->query_info ();
|
||||
if (info) {
|
||||
Gtk::TreeModel::Row newrow = *(favoritModel->append());
|
||||
newrow[favoritColumns.shortdir] = info->get_display_name ();
|
||||
newrow[favoritColumns.fulldir] = lastSelectedDir;
|
||||
newrow[favoritColumns.icon] = info->get_icon ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FavoritBrowser::delPressed () {
|
||||
|
||||
// lookup the selected item in the bookmark
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = treeView->get_selection();
|
||||
Gtk::TreeModel::iterator iter = selection->get_selected();
|
||||
|
||||
if (iter)
|
||||
favoritModel->erase (iter);
|
||||
}
|
||||
|
||||
58
rtgui/favoritbrowser.h
Executable file
58
rtgui/favoritbrowser.h
Executable file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _FAVORITBROWSER_
|
||||
#define _FAVORITBROWSER_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <dirbrowserremoteinterface.h>
|
||||
#include <dirselectionlistener.h>
|
||||
|
||||
class FavoritBrowser : public Gtk::VBox, public DirSelectionListener {
|
||||
|
||||
class FavoritColumns : public Gtk::TreeModel::ColumnRecord {
|
||||
public:
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<Gio::Icon> > icon;
|
||||
Gtk::TreeModelColumn<Glib::ustring> shortdir;
|
||||
Gtk::TreeModelColumn<Glib::ustring> fulldir;
|
||||
FavoritColumns() { add(icon); add(shortdir), add(fulldir); }
|
||||
};
|
||||
|
||||
FavoritColumns favoritColumns;
|
||||
Gtk::ScrolledWindow* scrollw;
|
||||
Gtk::TreeView* treeView;
|
||||
Glib::RefPtr<Gtk::ListStore> favoritModel;
|
||||
DirBrowserRemoteInterface* listener;
|
||||
Glib::ustring lastSelectedDir;
|
||||
Gtk::Button* add;
|
||||
Gtk::Button* del;
|
||||
public:
|
||||
|
||||
FavoritBrowser ();
|
||||
|
||||
void setDirBrowserRemoteInterface (DirBrowserRemoteInterface* l) { listener = l; }
|
||||
void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile="");
|
||||
|
||||
void addPressed ();
|
||||
void delPressed ();
|
||||
void selectionChanged ();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
581
rtgui/filebrowser.cc
Executable file
581
rtgui/filebrowser.cc
Executable file
@@ -0,0 +1,581 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <filebrowser.h>
|
||||
#include <glibmm.h>
|
||||
#include <options.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <clipboard.h>
|
||||
#include <profilestore.h>
|
||||
#include <procparamchangers.h>
|
||||
|
||||
FileBrowser::FileBrowser ()
|
||||
: tbl(NULL) {
|
||||
|
||||
fbih = new FileBrowserIdleHelper;
|
||||
fbih->fbrowser = this;
|
||||
fbih->destroyed = false;
|
||||
fbih->pending = 0;
|
||||
|
||||
profileStore.parseProfiles ();
|
||||
|
||||
signal_style_changed().connect( sigc::mem_fun(*this, &FileBrowser::styleChanged) );
|
||||
|
||||
int p = 0;
|
||||
pmenu = new Gtk::Menu ();
|
||||
pmenu->attach (*(open = new Gtk::MenuItem (M("FILEBROWSER_POPUPOPEN"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(develop = new Gtk::MenuItem (M("FILEBROWSER_POPUPPROCESS"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(rank[0] = new Gtk::MenuItem (M("FILEBROWSER_POPUPUNRANK"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(rank[1] = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK1"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(rank[2] = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK2"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(rank[3] = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK3"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(rank[4] = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK4"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(rank[5] = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK5"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(trash = new Gtk::MenuItem (M("FILEBROWSER_POPUPTRASH"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(untrash = new Gtk::MenuItem (M("FILEBROWSER_POPUPUNTRASH"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(rename = new Gtk::MenuItem (M("FILEBROWSER_POPUPRENAME"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(remove = new Gtk::MenuItem (M("FILEBROWSER_POPUPREMOVE"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(selall = new Gtk::MenuItem (M("FILEBROWSER_POPUPSELECTALL"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(copyprof = new Gtk::MenuItem (M("FILEBROWSER_COPYPROFILE"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(pasteprof = new Gtk::MenuItem (M("FILEBROWSER_PASTEPROFILE"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(partpasteprof = new Gtk::MenuItem (M("FILEBROWSER_PARTIALPASTEPROFILE"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(applyprof = new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE"))), 0, 1, p, p+1); p++;
|
||||
pmenu->attach (*(clearprof = new Gtk::MenuItem (M("FILEBROWSER_CLEARPROFILE"))), 0, 1, p, p+1); p++;
|
||||
pmenu->show_all ();
|
||||
|
||||
pmaccelgroup = Gtk::AccelGroup::create ();
|
||||
pmenu->set_accel_group (pmaccelgroup);
|
||||
selall->add_accelerator ("activate", pmenu->get_accel_group(), GDK_a, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
|
||||
trash->add_accelerator ("activate", pmenu->get_accel_group(), GDK_Delete, (Gdk::ModifierType)0, Gtk::ACCEL_VISIBLE);
|
||||
untrash->add_accelerator ("activate", pmenu->get_accel_group(), GDK_Delete, Gdk::SHIFT_MASK, Gtk::ACCEL_VISIBLE);
|
||||
develop->add_accelerator ("activate", pmenu->get_accel_group(), GDK_Q, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
|
||||
copyprof->add_accelerator ("activate", pmenu->get_accel_group(), GDK_C, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
|
||||
pasteprof->add_accelerator ("activate", pmenu->get_accel_group(), GDK_V, Gdk::CONTROL_MASK, Gtk::ACCEL_VISIBLE);
|
||||
partpasteprof->add_accelerator ("activate", pmenu->get_accel_group(), GDK_V, Gdk::CONTROL_MASK | Gdk::SHIFT_MASK, Gtk::ACCEL_VISIBLE);
|
||||
|
||||
profmenu = new Gtk::Menu ();
|
||||
|
||||
open->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), open));
|
||||
for (int i=0; i<6; i++)
|
||||
rank[i]->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), rank[i]));
|
||||
trash->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), trash));
|
||||
untrash->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), untrash));
|
||||
develop->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), develop));
|
||||
rename->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), rename));
|
||||
remove->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), remove));
|
||||
selall->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), selall));
|
||||
copyprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), copyprof));
|
||||
pasteprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), pasteprof));
|
||||
partpasteprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), partpasteprof));
|
||||
applyprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), applyprof));
|
||||
clearprof->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated), clearprof));
|
||||
}
|
||||
|
||||
void FileBrowser::rightClicked (ThumbBrowserEntryBase* entry) {
|
||||
|
||||
trash->set_sensitive (false);
|
||||
untrash->set_sensitive (false);
|
||||
for (int i=0; i<selected.size(); i++)
|
||||
if (((FileBrowserEntry*)selected[i])->thumbnail->getStage()==1) {
|
||||
untrash->set_sensitive (true);
|
||||
break;
|
||||
}
|
||||
for (int i=0; i<selected.size(); i++)
|
||||
if (((FileBrowserEntry*)selected[i])->thumbnail->getStage()==0) {
|
||||
trash->set_sensitive (true);
|
||||
break;
|
||||
}
|
||||
|
||||
pasteprof->set_sensitive (clipboard.hasProcParams());
|
||||
partpasteprof->set_sensitive (clipboard.hasProcParams());
|
||||
copyprof->set_sensitive (selected.size()==1);
|
||||
clearprof->set_sensitive (selected.size()>0);
|
||||
|
||||
int p = 0;
|
||||
Gtk::Menu* applmenu = Gtk::manage (new Gtk::Menu ());
|
||||
std::vector<Glib::ustring> profnames = profileStore.getProfileNames ();
|
||||
for (int i=0; i<profnames.size(); i++) {
|
||||
Gtk::MenuItem* mi = Gtk::manage (new Gtk::MenuItem (profnames[i]));
|
||||
applmenu->attach (*mi, 0, 1, p, p+1); p++;
|
||||
mi->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::applyMenuItemActivated), profnames[i]));
|
||||
mi->show ();
|
||||
}
|
||||
applyprof->set_submenu (*applmenu);
|
||||
|
||||
pmenu->popup (3, this->eventTime);
|
||||
}
|
||||
|
||||
void FileBrowser::doubleClicked (ThumbBrowserEntryBase* entry) {
|
||||
|
||||
if (tbl && entry) {
|
||||
std::vector<Thumbnail*> entries;
|
||||
entries.push_back (((FileBrowserEntry*)entry)->thumbnail);
|
||||
tbl->openRequested (entries);
|
||||
}
|
||||
}
|
||||
|
||||
struct addparams {
|
||||
FileBrowserIdleHelper* fbih;
|
||||
FileBrowserEntry* entry;
|
||||
};
|
||||
|
||||
int addfl (void* data) {
|
||||
|
||||
addparams* ap = (addparams*) data;
|
||||
FileBrowserIdleHelper* fbih = ap->fbih;
|
||||
|
||||
gdk_threads_enter();
|
||||
|
||||
if (fbih->destroyed) {
|
||||
if (fbih->pending == 1)
|
||||
delete fbih;
|
||||
else
|
||||
fbih->pending--;
|
||||
delete ap->entry;
|
||||
delete ap;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
ap->fbih->fbrowser->addEntry_ (ap->entry);
|
||||
delete ap;
|
||||
fbih->pending--;
|
||||
gdk_threads_leave();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileBrowser::addEntry (FileBrowserEntry* entry) {
|
||||
|
||||
fbih->pending++;
|
||||
entry->setParent (this);
|
||||
addparams* ap = new addparams;
|
||||
ap->fbih = fbih;
|
||||
ap->entry = entry;
|
||||
g_idle_add (addfl, ap);
|
||||
}
|
||||
|
||||
void FileBrowser::addEntry_ (FileBrowserEntry* entry) {
|
||||
|
||||
entry->selected = false;
|
||||
entry->drawable = false;
|
||||
entry->framed = editedFiles.find (entry->filename)!=editedFiles.end();
|
||||
|
||||
// add button set to the thumbbrowserentry
|
||||
entry->addButtonSet (new FileThumbnailButtonSet (entry));
|
||||
entry->getThumbButtonSet()->setRank (entry->thumbnail->getRank());
|
||||
entry->getThumbButtonSet()->setInTrash (entry->thumbnail->getStage()==1);
|
||||
entry->getThumbButtonSet()->setButtonListener (this);
|
||||
entry->resize (options.thumbSize);
|
||||
|
||||
// find place in abc order
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator i = fd.begin();
|
||||
while (i!=fd.end() && *entry < *((FileBrowserEntry*)*i))
|
||||
i++;
|
||||
|
||||
fd.insert (i, entry);
|
||||
|
||||
initEntry (entry);
|
||||
redraw ();
|
||||
}
|
||||
|
||||
FileBrowserEntry* FileBrowser::delEntry (const Glib::ustring& fname) {
|
||||
|
||||
for (std::vector<ThumbBrowserEntryBase*>::iterator i=fd.begin(); i!=fd.end(); i++)
|
||||
if ((*i)->filename==fname) {
|
||||
ThumbBrowserEntryBase* entry = *i;
|
||||
entry->selected = false;
|
||||
fd.erase (i);
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator j = std::find (selected.begin(), selected.end(), entry);
|
||||
if (j!=selected.end()) {
|
||||
selected.erase (j);
|
||||
notifySelectionListener ();
|
||||
}
|
||||
if (lastClicked==entry)
|
||||
lastClicked = NULL;
|
||||
redraw ();
|
||||
return (FileBrowserEntry*)entry;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FileBrowserEntry* FileBrowser::findEntry (const Glib::ustring& fname) {
|
||||
|
||||
for (std::vector<ThumbBrowserEntryBase*>::iterator i=fd.begin(); i!=fd.end(); i++)
|
||||
if ((*i)->filename==fname)
|
||||
return (FileBrowserEntry*)*i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FileBrowser::close () {
|
||||
if (fbih->pending)
|
||||
fbih->destroyed = true;
|
||||
else
|
||||
delete fbih;
|
||||
|
||||
fbih = new FileBrowserIdleHelper;
|
||||
fbih->fbrowser = this;
|
||||
fbih->destroyed = false;
|
||||
fbih->pending = 0;
|
||||
|
||||
for (int i=0; i<fd.size(); i++)
|
||||
delete fd[i];
|
||||
fd.clear ();
|
||||
selected.clear ();
|
||||
notifySelectionListener ();
|
||||
lastClicked = NULL;
|
||||
for (int i=0; i<fd.size(); i++)
|
||||
((FileBrowserEntry*)fd[i])->thumbnail->decreaseRef ();
|
||||
}
|
||||
|
||||
void FileBrowser::menuItemActivated (Gtk::MenuItem* m) {
|
||||
|
||||
std::vector<FileBrowserEntry*> mselected;
|
||||
for (int i=0; i<selected.size(); i++)
|
||||
mselected.push_back ((FileBrowserEntry*)selected[i]);
|
||||
|
||||
if (!tbl || (m!=selall && mselected.size()==0) )
|
||||
return;
|
||||
|
||||
for (int i=0; i<6; i++)
|
||||
if (m==rank[i]) {
|
||||
rankingRequested (mselected, i);
|
||||
return;
|
||||
}
|
||||
if (m==open) {
|
||||
std::vector<Thumbnail*> entries;
|
||||
for (int i=0; i<mselected.size(); i++)
|
||||
entries.push_back (mselected[i]->thumbnail);
|
||||
tbl->openRequested (entries);
|
||||
}
|
||||
else if (m==remove)
|
||||
tbl->deleteRequested (mselected);
|
||||
else if (m==trash)
|
||||
toTrashRequested (mselected);
|
||||
else if (m==untrash)
|
||||
fromTrashRequested (mselected);
|
||||
else if (m==develop)
|
||||
tbl->developRequested (mselected);
|
||||
else if (m==rename)
|
||||
tbl->renameRequested (mselected);
|
||||
else if (m==selall) {
|
||||
lastClicked = NULL;
|
||||
selected.clear ();
|
||||
for (int i=0; i<fd.size(); i++)
|
||||
if (checkFilter (fd[i])) {
|
||||
fd[i]->selected = true;
|
||||
selected.push_back (fd[i]);
|
||||
}
|
||||
queue_draw ();
|
||||
notifySelectionListener ();
|
||||
}
|
||||
else if (m==copyprof)
|
||||
copyProfile ();
|
||||
else if (m==pasteprof)
|
||||
pasteProfile ();
|
||||
else if (m==partpasteprof)
|
||||
partPasteProfile ();
|
||||
else if (m==clearprof) {
|
||||
for (int i=0; i<mselected.size(); i++)
|
||||
mselected[i]->thumbnail->clearProcParams (FILEBROWSER);
|
||||
queue_draw ();
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowser::copyProfile () {
|
||||
|
||||
if (selected.size()==1)
|
||||
clipboard.setProcParams (((FileBrowserEntry*)selected[0])->thumbnail->getProcParams());
|
||||
}
|
||||
|
||||
void FileBrowser::pasteProfile () {
|
||||
|
||||
std::vector<FileBrowserEntry*> mselected;
|
||||
for (int i=0; i<selected.size(); i++)
|
||||
mselected.push_back ((FileBrowserEntry*)selected[i]);
|
||||
|
||||
if (!tbl || mselected.size()==0)
|
||||
return;
|
||||
|
||||
for (int i=0; i<mselected.size(); i++)
|
||||
mselected[i]->thumbnail->setProcParams (clipboard.getProcParams(), FILEBROWSER);
|
||||
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
void FileBrowser::partPasteProfile () {
|
||||
|
||||
std::vector<FileBrowserEntry*> mselected;
|
||||
for (int i=0; i<selected.size(); i++)
|
||||
mselected.push_back ((FileBrowserEntry*)selected[i]);
|
||||
|
||||
if (!tbl || mselected.size()==0)
|
||||
return;
|
||||
|
||||
if (partialPasteDlg.run ()) {
|
||||
|
||||
for (int i=0; i<mselected.size(); i++) {
|
||||
rtengine::procparams::ProcParams params = mselected[i]->thumbnail->getProcParams ();
|
||||
partialPasteDlg.applyPaste (¶ms, &clipboard.getProcParams());
|
||||
mselected[i]->thumbnail->setProcParams (params, FILEBROWSER);
|
||||
}
|
||||
|
||||
queue_draw ();
|
||||
}
|
||||
partialPasteDlg.hide ();
|
||||
}
|
||||
|
||||
bool FileBrowser::keyPressed (GdkEventKey* event) {
|
||||
|
||||
if ((event->keyval==GDK_C || event->keyval==GDK_c) && event->state & GDK_CONTROL_MASK) {
|
||||
copyProfile ();
|
||||
return true;
|
||||
}
|
||||
else if ((event->keyval==GDK_V || event->keyval==GDK_v) && event->state & GDK_CONTROL_MASK && !(event->state & GDK_SHIFT_MASK)) {
|
||||
pasteProfile ();
|
||||
return true;
|
||||
}
|
||||
else if ((event->keyval==GDK_V || event->keyval==GDK_v) && event->state & GDK_CONTROL_MASK && event->state & GDK_SHIFT_MASK) {
|
||||
partPasteProfile ();
|
||||
return true;
|
||||
}
|
||||
else if (event->keyval==GDK_Delete && !(event->state & GDK_SHIFT_MASK)) {
|
||||
menuItemActivated (trash);
|
||||
return true;
|
||||
}
|
||||
else if (event->keyval==GDK_Delete && event->state & GDK_SHIFT_MASK) {
|
||||
menuItemActivated (untrash);
|
||||
return true;
|
||||
}
|
||||
else if ((event->keyval==GDK_Q || event->keyval==GDK_q) && event->state & GDK_CONTROL_MASK) {
|
||||
menuItemActivated (develop);
|
||||
return true;
|
||||
}
|
||||
else if ((event->keyval==GDK_A || event->keyval==GDK_a) && event->state & GDK_CONTROL_MASK) {
|
||||
menuItemActivated (selall);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void FileBrowser::applyMenuItemActivated (Glib::ustring ppname) {
|
||||
|
||||
rtengine::procparams::ProcParams* pparams = profileStore.getProfile (ppname);
|
||||
if (pparams && selected.size()>0) {
|
||||
for (int i=0; i<selected.size(); i++)
|
||||
((FileBrowserEntry*)selected[i])->thumbnail->setProcParams (*pparams, FILEBROWSER);
|
||||
queue_draw ();
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowser::applyFilter (const BrowserFilter& filter) {
|
||||
|
||||
this->filter = filter;
|
||||
|
||||
// remove items not complying the filter from the selection
|
||||
bool selchanged = false;
|
||||
for (int i=0; i<fd.size(); i++)
|
||||
if (fd[i]->selected && !checkFilter (fd[i])) {
|
||||
fd[i]->selected = false;
|
||||
std::vector<ThumbBrowserEntryBase*>::iterator j = std::find (selected.begin(), selected.end(), fd[i]);
|
||||
selected.erase (j);
|
||||
if (lastClicked==fd[i])
|
||||
lastClicked = NULL;
|
||||
selchanged = true;
|
||||
}
|
||||
if (selchanged)
|
||||
notifySelectionListener ();
|
||||
redraw ();
|
||||
}
|
||||
|
||||
bool FileBrowser::checkFilter (ThumbBrowserEntryBase* entryb) { // true -> entry complies filter
|
||||
|
||||
FileBrowserEntry* entry = (FileBrowserEntry*)entryb;
|
||||
// return false if basic filter settings are not satisfied
|
||||
if (filter.showRanked[entry->thumbnail->getRank()]==false || (entry->thumbnail->getStage()==1 && !filter.showTrash) || (entry->thumbnail->getStage()==0 && !filter.showNotTrash))
|
||||
return false;
|
||||
|
||||
// check exif filter
|
||||
const CacheImageData* cfs = entry->thumbnail->getCacheImageData();
|
||||
double tol = 0.01;
|
||||
double tol2 = 1e-8;
|
||||
|
||||
if (!filter.exifFilterEnabled)
|
||||
return true;
|
||||
|
||||
if (!cfs->exifValid)
|
||||
return (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(cfs->camera)>0)
|
||||
&& (!filter.exifFilter.filterLens || filter.exifFilter.lenses.count(cfs->lens)>0);
|
||||
|
||||
return
|
||||
(!filter.exifFilter.filterShutter || (rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs->shutter)) >= filter.exifFilter.shutterFrom-tol2 && rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs->shutter)) <= filter.exifFilter.shutterTo+tol2))
|
||||
&& (!filter.exifFilter.filterFNumber || (rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs->fnumber)) >= filter.exifFilter.fnumberFrom-tol2 && rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs->fnumber)) <= filter.exifFilter.fnumberTo+tol2))
|
||||
&& (!filter.exifFilter.filterFocalLen || (cfs->focalLen >= filter.exifFilter.focalFrom-tol && cfs->focalLen <= filter.exifFilter.focalTo+tol))
|
||||
&& (!filter.exifFilter.filterISO || (cfs->iso >= filter.exifFilter.isoFrom && cfs->iso <= filter.exifFilter.isoTo))
|
||||
&& (!filter.exifFilter.filterCamera || filter.exifFilter.cameras.count(cfs->camera)>0)
|
||||
&& (!filter.exifFilter.filterLens || filter.exifFilter.lenses.count(cfs->lens)>0);
|
||||
}
|
||||
|
||||
void FileBrowser::toTrashRequested (std::vector<FileBrowserEntry*> tbe) {
|
||||
|
||||
for (int i=0; i<tbe.size(); i++) {
|
||||
if (tbe[i]->thumbnail->getStage()==1)
|
||||
continue;
|
||||
tbe[i]->thumbnail->setStage (1);
|
||||
if (tbe[i]->getThumbButtonSet()) {
|
||||
tbe[i]->getThumbButtonSet()->setRank (tbe[i]->thumbnail->getRank());
|
||||
tbe[i]->getThumbButtonSet()->setInTrash (true);
|
||||
}
|
||||
}
|
||||
applyFilter (filter);
|
||||
}
|
||||
|
||||
void FileBrowser::fromTrashRequested (std::vector<FileBrowserEntry*> tbe) {
|
||||
|
||||
for (int i=0; i<tbe.size(); i++) {
|
||||
if (tbe[i]->thumbnail->getStage()==0)
|
||||
continue;
|
||||
tbe[i]->thumbnail->setStage (0);
|
||||
if (tbe[i]->getThumbButtonSet()) {
|
||||
tbe[i]->getThumbButtonSet()->setRank (tbe[i]->thumbnail->getRank());
|
||||
tbe[i]->getThumbButtonSet()->setInTrash (false);
|
||||
}
|
||||
}
|
||||
applyFilter (filter);
|
||||
}
|
||||
|
||||
void FileBrowser::rankingRequested (std::vector<FileBrowserEntry*> tbe, int rank) {
|
||||
|
||||
for (int i=0; i<tbe.size(); i++) {
|
||||
tbe[i]->thumbnail->setRank (rank);
|
||||
if (tbe[i]->getThumbButtonSet())
|
||||
tbe[i]->getThumbButtonSet()->setRank (tbe[i]->thumbnail->getRank());
|
||||
}
|
||||
applyFilter (filter);
|
||||
}
|
||||
|
||||
void FileBrowser::buttonPressed (LWButton* button, int actionCode, void* actionData) {
|
||||
|
||||
if (actionCode>=0 && actionCode<=5) { // rank
|
||||
std::vector<FileBrowserEntry*> tbe;
|
||||
tbe.push_back ((FileBrowserEntry*)actionData);
|
||||
rankingRequested (tbe, actionCode);
|
||||
}
|
||||
else if (actionCode==6 && tbl) { // to processin queue
|
||||
std::vector<FileBrowserEntry*> tbe;
|
||||
tbe.push_back ((FileBrowserEntry*)actionData);
|
||||
tbl->developRequested (tbe);
|
||||
}
|
||||
else if (actionCode==7) { // to trash / undelete
|
||||
std::vector<FileBrowserEntry*> tbe;
|
||||
FileBrowserEntry* entry = (FileBrowserEntry*)actionData;
|
||||
tbe.push_back (entry);
|
||||
if (entry->thumbnail->getStage()==0)
|
||||
toTrashRequested (tbe);
|
||||
else
|
||||
fromTrashRequested (tbe);
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowser::openNextImage () {
|
||||
|
||||
if (fd.size()>0) {
|
||||
for (int i=fd.size()-1; i>=0; i--)
|
||||
if (editedFiles.find (fd[i]->filename)!=editedFiles.end())
|
||||
if (i<fd.size()-1 && tbl) {
|
||||
std::vector<Thumbnail*> entries;
|
||||
entries.push_back (((FileBrowserEntry*)fd[i+1])->thumbnail);
|
||||
tbl->openRequested (entries);
|
||||
return;
|
||||
}
|
||||
if (tbl) {
|
||||
std::vector<Thumbnail*> entries;
|
||||
entries.push_back (((FileBrowserEntry*)fd[0])->thumbnail);
|
||||
tbl->openRequested (entries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowser::openPrevImage () {
|
||||
|
||||
if (fd.size()>0) {
|
||||
for (int i=0; i<fd.size(); i++)
|
||||
if (editedFiles.find (fd[i]->filename)!=editedFiles.end())
|
||||
if (i>0 && tbl) {
|
||||
std::vector<Thumbnail*> entries;
|
||||
entries.push_back (((FileBrowserEntry*)fd[i-1])->thumbnail);
|
||||
tbl->openRequested (entries);
|
||||
return;
|
||||
}
|
||||
if (tbl) {
|
||||
std::vector<Thumbnail*> entries;
|
||||
entries.push_back (((FileBrowserEntry*)fd[fd.size()-1])->thumbnail);
|
||||
tbl->openRequested (entries);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int redrawtb (void* data) {
|
||||
|
||||
((FileBrowser*)data)->_thumbRearrangementNeeded ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileBrowser::_thumbRearrangementNeeded () {
|
||||
|
||||
refreshThumbImages ();
|
||||
}
|
||||
|
||||
void FileBrowser::thumbRearrangementNeeded () {
|
||||
|
||||
g_idle_add (redrawtb, this);
|
||||
}
|
||||
void FileBrowser::selectionChanged () {
|
||||
|
||||
notifySelectionListener ();
|
||||
}
|
||||
|
||||
void FileBrowser::notifySelectionListener () {
|
||||
|
||||
if (tbl) {
|
||||
std::vector<Thumbnail*> thm;
|
||||
for (int i=0; i<selected.size(); i++)
|
||||
thm.push_back (((FileBrowserEntry*)selected[i])->thumbnail);
|
||||
tbl->selectionChanged (thm);
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowser::redrawNeeded (ThumbBrowserEntryBase* entry) {
|
||||
|
||||
if (entry->insideWindow (0, 0, internal.get_width(), internal.get_height())) {
|
||||
if (!internal.isDirty ()) {
|
||||
internal.setDirty ();
|
||||
internal.queue_draw ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowser::redrawNeeded (LWButton* button) {
|
||||
|
||||
queue_draw ();
|
||||
}
|
||||
116
rtgui/filebrowser.h
Executable file
116
rtgui/filebrowser.h
Executable file
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _FILEBROWSER_
|
||||
#define _FILEBROWSER_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <thumbbrowserbase.h>
|
||||
#include <exiffiltersettings.h>
|
||||
#include <filebrowserentry.h>
|
||||
#include <browserfilter.h>
|
||||
#include <partialpastedlg.h>
|
||||
|
||||
class FileBrowser;
|
||||
class FileBrowserEntry;
|
||||
class FileBrowserListener {
|
||||
|
||||
public:
|
||||
virtual void openRequested (std::vector<Thumbnail*> tbe) {}
|
||||
virtual void developRequested (std::vector<FileBrowserEntry*> tbe) {}
|
||||
virtual void renameRequested (std::vector<FileBrowserEntry*> tbe) {}
|
||||
virtual void deleteRequested (std::vector<FileBrowserEntry*> tbe) {}
|
||||
virtual void selectionChanged (std::vector<Thumbnail*> tbe) {}
|
||||
};
|
||||
|
||||
struct FileBrowserIdleHelper {
|
||||
FileBrowser* fbrowser;
|
||||
bool destroyed;
|
||||
int pending;
|
||||
};
|
||||
|
||||
class FileBrowser : public ThumbBrowserBase, public LWButtonListener {
|
||||
|
||||
protected:
|
||||
|
||||
Gtk::MenuItem* rank[6];
|
||||
Gtk::MenuItem* trash;
|
||||
Gtk::MenuItem* untrash;
|
||||
Gtk::MenuItem* develop;
|
||||
Gtk::MenuItem* rename;
|
||||
Gtk::MenuItem* remove;
|
||||
Gtk::MenuItem* open;
|
||||
Gtk::MenuItem* selall;
|
||||
Gtk::MenuItem* copyprof;
|
||||
Gtk::MenuItem* pasteprof;
|
||||
Gtk::MenuItem* partpasteprof;
|
||||
Gtk::MenuItem* applyprof;
|
||||
Gtk::MenuItem* clearprof;
|
||||
Gtk::Menu* pmenu;
|
||||
Gtk::Menu* profmenu;
|
||||
Glib::RefPtr<Gtk::AccelGroup> pmaccelgroup;
|
||||
|
||||
FileBrowserListener* tbl;
|
||||
BrowserFilter filter;
|
||||
PartialPasteDlg partialPasteDlg;
|
||||
|
||||
FileBrowserIdleHelper* fbih;
|
||||
|
||||
void toTrashRequested (std::vector<FileBrowserEntry*> tbe);
|
||||
void fromTrashRequested (std::vector<FileBrowserEntry*> tbe);
|
||||
void rankingRequested (std::vector<FileBrowserEntry*> tbe, int rank);
|
||||
void notifySelectionListener ();
|
||||
|
||||
public:
|
||||
|
||||
FileBrowser ();
|
||||
|
||||
void addEntry (FileBrowserEntry* entry); // can be called from any thread
|
||||
void addEntry_ (FileBrowserEntry* entry); // this must be executed inside the gtk thread
|
||||
FileBrowserEntry* delEntry (const Glib::ustring& fname); // return the entry if found here return NULL otherwise
|
||||
FileBrowserEntry* findEntry (const Glib::ustring& fname); // return the entry if found here return NULL otherwise
|
||||
void close ();
|
||||
|
||||
void setFileBrowserListener (FileBrowserListener* l) { tbl = l; }
|
||||
|
||||
void menuItemActivated (Gtk::MenuItem* m);
|
||||
void applyMenuItemActivated (Glib::ustring ppname);
|
||||
|
||||
void applyFilter (const BrowserFilter& filter);
|
||||
|
||||
void buttonPressed (LWButton* button, int actionCode, void* actionData);
|
||||
void redrawNeeded (LWButton* button);
|
||||
bool checkFilter (ThumbBrowserEntryBase* entry);
|
||||
void rightClicked (ThumbBrowserEntryBase* entry);
|
||||
void doubleClicked (ThumbBrowserEntryBase* entry);
|
||||
bool keyPressed (GdkEventKey* event);
|
||||
|
||||
void openNextImage ();
|
||||
void openPrevImage ();
|
||||
void copyProfile ();
|
||||
void pasteProfile ();
|
||||
void partPasteProfile ();
|
||||
|
||||
void redrawNeeded (ThumbBrowserEntryBase* entry);
|
||||
void thumbRearrangementNeeded ();
|
||||
void _thumbRearrangementNeeded ();
|
||||
|
||||
void selectionChanged ();
|
||||
};
|
||||
|
||||
#endif
|
||||
558
rtgui/filebrowserentry.cc
Executable file
558
rtgui/filebrowserentry.cc
Executable file
@@ -0,0 +1,558 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <filebrowserentry.h>
|
||||
#include <thumbbrowserbase.h>
|
||||
#include <cursormanager.h>
|
||||
#include <iomanip>
|
||||
#include <guiutils.h>
|
||||
#include <safegtk.h>
|
||||
|
||||
#define CROPRESIZEBORDER 4
|
||||
|
||||
bool FileBrowserEntry::iconsLoaded = false;
|
||||
Glib::RefPtr<Gdk::Pixbuf> FileBrowserEntry::editedIcon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> FileBrowserEntry::recentlySavedIcon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> FileBrowserEntry::enqueuedIcon;
|
||||
|
||||
FileBrowserEntry::FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname)
|
||||
: ThumbBrowserEntryBase (fname), thumbnail(thm), iatlistener(NULL), state(SNormal), cropgl(NULL) {
|
||||
|
||||
feih = new FileBrowserEntryIdleHelper;
|
||||
feih->fbentry = this;
|
||||
feih->destroyed = false;
|
||||
feih->pending = 0;
|
||||
|
||||
italicstyle = thumbnail->getType() != FT_Raw;
|
||||
datetimeline = thumbnail->getDateTimeString ();
|
||||
exifline = thumbnail->getExifString ();
|
||||
|
||||
scale = 1;
|
||||
|
||||
if (!iconsLoaded) {
|
||||
editedIcon = safe_create_from_file (argv0+"/images/edited.png");
|
||||
recentlySavedIcon = safe_create_from_file (argv0+"/images/saved.png");
|
||||
enqueuedIcon = safe_create_from_file (argv0+"/images/processing.png");
|
||||
}
|
||||
|
||||
if (thm)
|
||||
thm->addThumbnailListener (this);
|
||||
}
|
||||
|
||||
FileBrowserEntry::~FileBrowserEntry () {
|
||||
|
||||
thumbImageUpdater.removeJobs (this);
|
||||
if (thumbnail)
|
||||
thumbnail->removeThumbnailListener (this);
|
||||
|
||||
if (feih->pending)
|
||||
feih->destroyed = true;
|
||||
else
|
||||
delete feih;
|
||||
}
|
||||
|
||||
void FileBrowserEntry::refreshThumbnailImage () {
|
||||
|
||||
if (!thumbnail)
|
||||
return;
|
||||
|
||||
thumbImageUpdater.add (thumbnail, thumbnail->getProcParams(), preh, &updatepriority, this);
|
||||
thumbImageUpdater.process ();
|
||||
}
|
||||
|
||||
void FileBrowserEntry::calcThumbnailSize () {
|
||||
|
||||
if (thumbnail)
|
||||
thumbnail->getThumbnailSize (prew, preh);
|
||||
}
|
||||
|
||||
std::vector<Glib::RefPtr<Gdk::Pixbuf> > FileBrowserEntry::getIconsOnImageArea () {
|
||||
|
||||
std::vector<Glib::RefPtr<Gdk::Pixbuf> > ret;
|
||||
|
||||
if (!thumbnail)
|
||||
return ret;
|
||||
|
||||
if (thumbnail->hasProcParams() && editedIcon)
|
||||
ret.push_back (editedIcon);
|
||||
if (thumbnail->isRecentlySaved() && recentlySavedIcon)
|
||||
ret.push_back (recentlySavedIcon);
|
||||
if (thumbnail->isEnqueued () && enqueuedIcon)
|
||||
ret.push_back (enqueuedIcon);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FileBrowserEntry::customBackBufferUpdate (Cairo::RefPtr<Cairo::Context> c) {
|
||||
|
||||
if (state==SCropSelecting || state==SResizeH1 || state==SResizeH2 || state==SResizeW1 || state==SResizeW2 || state==SCropMove)
|
||||
drawCrop (c, prex, prey, prew, preh, 0, 0, scale, cropParams);
|
||||
else {
|
||||
rtengine::procparams::CropParams cparams = thumbnail->getProcParams().crop;
|
||||
if (cparams.enabled)
|
||||
drawCrop (c, prex, prey, prew, preh, 0, 0, scale, cparams);
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowserEntry::getIconSize (int& w, int& h) {
|
||||
|
||||
w = editedIcon->get_width ();
|
||||
h = editedIcon->get_height ();
|
||||
}
|
||||
|
||||
FileThumbnailButtonSet* FileBrowserEntry::getThumbButtonSet () {
|
||||
|
||||
return (FileThumbnailButtonSet*)buttonSet;
|
||||
}
|
||||
|
||||
void FileBrowserEntry::procParamsChanged (Thumbnail* thm, int whoChangedIt) {
|
||||
|
||||
refreshThumbnailImage ();
|
||||
}
|
||||
|
||||
struct tiupdate {
|
||||
FileBrowserEntryIdleHelper* feih;
|
||||
rtengine::IImage8* img;
|
||||
double scale;
|
||||
rtengine::procparams::CropParams cropParams;
|
||||
};
|
||||
|
||||
int fbeupdate (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
tiupdate* params = (tiupdate*)data;
|
||||
FileBrowserEntryIdleHelper* feih = params->feih;
|
||||
|
||||
if (feih->destroyed) {
|
||||
if (feih->pending == 1)
|
||||
delete feih;
|
||||
else
|
||||
feih->pending--;
|
||||
params->img->free ();
|
||||
delete params;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
feih->fbentry->_updateImage (params->img, params->scale, params->cropParams);
|
||||
feih->pending--;
|
||||
|
||||
gdk_threads_leave ();
|
||||
delete params;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileBrowserEntry::updateImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cropParams) {
|
||||
|
||||
redrawRequests++;
|
||||
feih->pending++;
|
||||
tiupdate* param = new tiupdate ();
|
||||
param->feih = feih;
|
||||
param->img = img;
|
||||
param->scale = scale;
|
||||
param->cropParams = cropParams;
|
||||
g_idle_add (fbeupdate, param);
|
||||
}
|
||||
|
||||
void FileBrowserEntry::_updateImage (rtengine::IImage8* img, double s, rtengine::procparams::CropParams cropParams) {
|
||||
|
||||
redrawRequests--;
|
||||
scale = s;
|
||||
this->cropParams = cropParams;
|
||||
if (preh == img->getHeight ()) {
|
||||
prew = img->getWidth ();
|
||||
guint8* temp = preview;
|
||||
preview = NULL;
|
||||
delete [] temp;
|
||||
temp = new guint8 [prew*preh*3];
|
||||
memcpy (temp, img->getData(), prew*preh*3);
|
||||
preview = temp;
|
||||
updateBackBuffer ();
|
||||
}
|
||||
if (redrawRequests==0 && parent)
|
||||
parent->redrawNeeded (this);
|
||||
img->free ();
|
||||
}
|
||||
|
||||
bool FileBrowserEntry::motionNotify (int x, int y) {
|
||||
|
||||
bool b = ThumbBrowserEntryBase::motionNotify (x, y);
|
||||
|
||||
int ix = x - startx - ofsX;
|
||||
int iy = y - starty - ofsY;
|
||||
|
||||
if (inside (x,y))
|
||||
updateCursor (ix, iy);
|
||||
|
||||
if (state==SRotateSelecting) {
|
||||
action_x = x;
|
||||
action_y = y;
|
||||
parent->redrawNeeded (this);
|
||||
}
|
||||
else if (state==SResizeH1 && cropgl) {
|
||||
int oy = cropParams.y;
|
||||
cropParams.y = action_y + (y-press_y) / scale;
|
||||
cropParams.h += oy - cropParams.y;
|
||||
cropgl->cropHeight1Resized (cropParams.x, cropParams.y, cropParams.w, cropParams.h);
|
||||
updateBackBuffer ();
|
||||
parent->redrawNeeded (this);
|
||||
}
|
||||
else if (state==SResizeH2 && cropgl) {
|
||||
cropParams.h = action_y + (y-press_y) / scale;
|
||||
cropgl->cropHeight2Resized (cropParams.x, cropParams.y, cropParams.w, cropParams.h);
|
||||
updateBackBuffer ();
|
||||
parent->redrawNeeded (this);
|
||||
}
|
||||
else if (state==SResizeW1 && cropgl) {
|
||||
int ox = cropParams.x;
|
||||
cropParams.x = action_x + (x-press_x) / scale;
|
||||
cropParams.w += ox - cropParams.x;
|
||||
cropgl->cropWidth1Resized (cropParams.x, cropParams.y, cropParams.w, cropParams.h);
|
||||
updateBackBuffer ();
|
||||
parent->redrawNeeded (this);
|
||||
}
|
||||
else if (state==SResizeW2 && cropgl) {
|
||||
cropParams.w = action_x + (x-press_x) / scale;
|
||||
cropgl->cropWidth2Resized (cropParams.x, cropParams.y, cropParams.w, cropParams.h);
|
||||
updateBackBuffer ();
|
||||
parent->redrawNeeded (this);
|
||||
}
|
||||
else if (state==SCropMove && cropgl) {
|
||||
cropParams.x = action_x + (x-press_x) / scale;
|
||||
cropParams.y = action_y + (y-press_y) / scale;
|
||||
cropgl->cropMoved (cropParams.x, cropParams.y, cropParams.w, cropParams.h);
|
||||
updateBackBuffer ();
|
||||
parent->redrawNeeded (this);
|
||||
}
|
||||
else if (state==SCropSelecting && cropgl) {
|
||||
int cx1 = press_x, cy1 = press_y;
|
||||
int cx2 = (ix-prex) / scale, cy2 = (iy-prey) / scale;
|
||||
cropgl->cropResized (cx1, cy1, cx2, cy2);
|
||||
if (cx2 > cx1) {
|
||||
cropParams.x = cx1;
|
||||
cropParams.w = cx2 - cx1 + 1;
|
||||
}
|
||||
else {
|
||||
cropParams.x = cx2;
|
||||
cropParams.w = cx1 - cx2 + 1;
|
||||
}
|
||||
if (cy2 > cy1) {
|
||||
cropParams.y = cy1;
|
||||
cropParams.h = cy2 - cy1 + 1;
|
||||
}
|
||||
else {
|
||||
cropParams.y = cy2;
|
||||
cropParams.h = cy1 - cy2 + 1;
|
||||
}
|
||||
updateBackBuffer ();
|
||||
parent->redrawNeeded (this);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
bool FileBrowserEntry::pressNotify (int button, int type, int bstate, int x, int y) {
|
||||
|
||||
bool b = ThumbBrowserEntryBase::pressNotify (button, type, bstate, x, y);
|
||||
|
||||
ToolMode tm = iatlistener->getToolBar()->getTool ();
|
||||
int ix = x - startx - ofsX;
|
||||
int iy = y - starty - ofsY;
|
||||
if (!b && selected && inside (x,y)) {
|
||||
if (button==1 && type==GDK_BUTTON_PRESS && state==SNormal) {
|
||||
if (onArea (CropTop, ix, iy)) {
|
||||
state = SResizeH1;
|
||||
press_y = y;
|
||||
action_y = cropParams.y;
|
||||
cropgl = iatlistener->startCropEditing (thumbnail);
|
||||
b = true;
|
||||
}
|
||||
else if (onArea (CropBottom, ix, iy)) {
|
||||
state = SResizeH2;
|
||||
press_y = y;
|
||||
action_y = cropParams.h;
|
||||
cropgl = iatlistener->startCropEditing (thumbnail);
|
||||
b = true;
|
||||
}
|
||||
else if (onArea (CropLeft, ix, iy)) {
|
||||
state = SResizeW1;
|
||||
press_x = x;
|
||||
action_x = cropParams.x;
|
||||
cropgl = iatlistener->startCropEditing (thumbnail);
|
||||
b = true;
|
||||
}
|
||||
else if (onArea (CropRight, ix, iy)) {
|
||||
state = SResizeW2;
|
||||
press_x = x;
|
||||
action_x = cropParams.w;
|
||||
cropgl = iatlistener->startCropEditing (thumbnail);
|
||||
b = true;
|
||||
}
|
||||
else if ((bstate & GDK_SHIFT_MASK) && onArea (CropInside, ix, iy)) {
|
||||
state = SCropMove;
|
||||
press_x = x;
|
||||
press_y = y;
|
||||
action_x = cropParams.x;
|
||||
action_y = cropParams.y;
|
||||
cropgl = iatlistener->startCropEditing (thumbnail);
|
||||
b = true;
|
||||
}
|
||||
else if (onArea (CropImage, ix, iy)) {
|
||||
if (tm == TMStraighten) {
|
||||
state = SRotateSelecting;
|
||||
press_x = x;
|
||||
press_y = y;
|
||||
action_x = x;
|
||||
action_y = y;
|
||||
rot_deg = 0;
|
||||
b = true;
|
||||
}
|
||||
else if (tm == TMSpotWB) {
|
||||
iatlistener->spotWBselected ((ix-prex)/scale, (iy-prey)/scale, thumbnail);
|
||||
b = true;
|
||||
}
|
||||
else if (tm == TMCropSelect) {
|
||||
cropgl = iatlistener->startCropEditing (thumbnail);
|
||||
if (cropgl) {
|
||||
state = SCropSelecting;
|
||||
press_x = cropParams.x = (ix-prex) / scale;
|
||||
press_y = cropParams.y = (iy-prey) / scale;
|
||||
cropParams.w = cropParams.h = 1;
|
||||
cropgl->cropInit (cropParams.x, cropParams.y, cropParams.w, cropParams.h);
|
||||
b = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
updateCursor (ix, iy);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
bool FileBrowserEntry::releaseNotify (int button, int type, int bstate, int x, int y) {
|
||||
|
||||
bool b = ThumbBrowserEntryBase::releaseNotify (button, type, bstate, x, y);
|
||||
|
||||
int ix = x - startx - ofsX;
|
||||
int iy = y - starty - ofsY;
|
||||
if (!b) {
|
||||
if (state==SRotateSelecting) {
|
||||
iatlistener->rotateSelectionReady (rot_deg, thumbnail);
|
||||
iatlistener->getToolBar()->setTool (TMHand);
|
||||
}
|
||||
else if (cropgl && (state==SCropSelecting || state==SResizeH1 || state==SResizeH2 || state==SResizeW1 || state==SResizeW2 || state==SCropMove)) {
|
||||
cropgl->cropManipReady ();
|
||||
cropgl = NULL;
|
||||
iatlistener->cropSelectionReady ();
|
||||
iatlistener->getToolBar()->setTool (TMHand);
|
||||
}
|
||||
state = SNormal;
|
||||
if (parent)
|
||||
parent->redrawNeeded (this);
|
||||
updateCursor (ix, iy);
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
bool FileBrowserEntry::onArea (CursorArea a, int x, int y) {
|
||||
|
||||
if (!drawable || !preview)
|
||||
return false;
|
||||
|
||||
int x1 = (x-prex) / scale;
|
||||
int y1 = (y-prey) / scale;
|
||||
int cropResizeBorder = CROPRESIZEBORDER / scale;
|
||||
switch (a) {
|
||||
case CropImage:
|
||||
return x>=prex && x<prex+prew && y>=prey && y<prey+preh;
|
||||
case CropTop:
|
||||
return cropParams.enabled &&
|
||||
x1>cropParams.x+cropResizeBorder &&
|
||||
x1<cropParams.x+cropParams.w-1-cropResizeBorder &&
|
||||
y1>cropParams.y-cropResizeBorder &&
|
||||
y1<cropParams.y+cropResizeBorder;
|
||||
case CropBottom:
|
||||
return cropParams.enabled &&
|
||||
x1>cropParams.x+cropResizeBorder &&
|
||||
x1<cropParams.x+cropParams.w-1-cropResizeBorder &&
|
||||
y1>cropParams.y+cropParams.h-1-cropResizeBorder &&
|
||||
y1<cropParams.y+cropParams.h-1+cropResizeBorder;
|
||||
case CropLeft:
|
||||
return cropParams.enabled &&
|
||||
y1>cropParams.y+cropResizeBorder &&
|
||||
y1<cropParams.y+cropParams.h-1-cropResizeBorder &&
|
||||
x1>cropParams.x-cropResizeBorder &&
|
||||
x1<cropParams.x+cropResizeBorder;
|
||||
case CropRight:
|
||||
return cropParams.enabled &&
|
||||
y1>cropParams.y+cropResizeBorder &&
|
||||
y1<cropParams.y+cropParams.h-1-cropResizeBorder &&
|
||||
x1>cropParams.x+cropParams.w-1-cropResizeBorder &&
|
||||
x1<cropParams.x+cropParams.w-1+cropResizeBorder;
|
||||
case CropInside:
|
||||
return cropParams.enabled &&
|
||||
y1>cropParams.y &&
|
||||
y1<cropParams.y+cropParams.h-1 &&
|
||||
x1>cropParams.x &&
|
||||
x1<cropParams.x+cropParams.w-1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void FileBrowserEntry::updateCursor (int x, int y) {
|
||||
|
||||
if (!iatlistener)
|
||||
return;
|
||||
|
||||
ToolMode tm = iatlistener->getToolBar()->getTool ();
|
||||
Glib::RefPtr<Gdk::Window> w = parent->getDrawingArea ()->get_window();
|
||||
|
||||
if (!selected) {
|
||||
cursorManager.setCursor (w, CSArrow);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state==SNormal) {
|
||||
if (tm==TMHand && (onArea (CropTop, x, y) || onArea (CropBottom, x, y)))
|
||||
cursorManager.setCursor (w, CSResizeHeight);
|
||||
else if (tm==TMHand && (onArea (CropLeft, x, y) || onArea (CropRight, x, y)))
|
||||
cursorManager.setCursor (w, CSResizeWidth);
|
||||
else if (onArea (CropImage, x, y)) {
|
||||
if (tm==TMHand)
|
||||
cursorManager.setCursor (w, CSArrow);
|
||||
else if (tm==TMSpotWB)
|
||||
cursorManager.setCursor (w, CSSpotWB);
|
||||
else if (tm==TMCropSelect)
|
||||
cursorManager.setCursor (w, CSCropSelect);
|
||||
else if (tm==TMStraighten)
|
||||
cursorManager.setCursor (w, CSStraighten);
|
||||
}
|
||||
else
|
||||
cursorManager.setCursor (w, CSArrow);
|
||||
}
|
||||
else if (state==SCropSelecting)
|
||||
cursorManager.setCursor (w, CSCropSelect);
|
||||
else if (state==SRotateSelecting)
|
||||
cursorManager.setCursor (w, CSStraighten);
|
||||
else if (state==SCropMove)
|
||||
cursorManager.setCursor (w, CSMove);
|
||||
else if (state==SResizeW1 || state==SResizeW2)
|
||||
cursorManager.setCursor (w, CSResizeWidth);
|
||||
else if (state==SResizeH1 || state==SResizeH2)
|
||||
cursorManager.setCursor (w, CSResizeHeight);
|
||||
}
|
||||
|
||||
void FileBrowserEntry::draw () {
|
||||
|
||||
ThumbBrowserEntryBase::draw ();
|
||||
if (state==SRotateSelecting) {
|
||||
Cairo::RefPtr<Cairo::Context> cr = parent->getDrawingArea ()->get_window()->create_cairo_context();
|
||||
drawStraightenGuide (cr);
|
||||
}
|
||||
}
|
||||
|
||||
void FileBrowserEntry::drawStraightenGuide (Cairo::RefPtr<Cairo::Context> cr) {
|
||||
|
||||
if (action_x!=press_x || action_y!=press_y) {
|
||||
double arg = (press_x-action_x) / sqrt(double((press_x-action_x)*(press_x-action_x)+(press_y-action_y)*(press_y-action_y)));
|
||||
double sol1, sol2;
|
||||
double pi = M_PI;
|
||||
if (press_y>action_y) {
|
||||
sol1 = acos(arg)*180/pi;
|
||||
sol2 = -acos(-arg)*180/pi;
|
||||
}
|
||||
else {
|
||||
sol1 = acos(-arg)*180/pi;
|
||||
sol2 = -acos(arg)*180/pi;
|
||||
}
|
||||
if (fabs(sol1)<fabs(sol2))
|
||||
rot_deg = sol1;
|
||||
else
|
||||
rot_deg = sol2;
|
||||
|
||||
if (rot_deg<-45)
|
||||
rot_deg = 90.0 + rot_deg;
|
||||
else if (rot_deg>45)
|
||||
rot_deg = - 90.0 + rot_deg;
|
||||
}
|
||||
else
|
||||
rot_deg = 0;
|
||||
|
||||
Glib::RefPtr<Pango::Context> context = parent->getDrawingArea()->get_pango_context () ;
|
||||
Pango::FontDescription fontd = context->get_font_description ();
|
||||
fontd.set_weight (Pango::WEIGHT_BOLD);
|
||||
fontd.set_size (8*Pango::SCALE);
|
||||
context->set_font_description (fontd);
|
||||
Glib::RefPtr<Pango::Layout> deglayout = parent->getDrawingArea()->create_pango_layout(Glib::ustring::compose ("%1 deg", Glib::ustring::format(std::setprecision(2), rot_deg)));
|
||||
|
||||
int x1 = press_x;
|
||||
int y1 = press_y;
|
||||
int y2 = action_y;
|
||||
int x2 = action_x;
|
||||
|
||||
if (x2<prex+ofsX+startx) {
|
||||
y2 = y1 - (double)(y1-y2)*(x1 - (prex+ofsX+startx)) / (x1-x2);
|
||||
x2 = prex+ofsX+startx;
|
||||
}
|
||||
else if (x2>=prew+prex+ofsX+startx) {
|
||||
y2 = y1 - (double)(y1-y2)*(x1 - (prew+prex+ofsX+startx-1)) / (x1-x2);
|
||||
x2 = prew+prex+ofsX+startx-1;
|
||||
}
|
||||
if (y2<prey+ofsY+starty) {
|
||||
x2 = x1 - (double)(x1-x2)*(y1 - (prey+ofsY+starty)) / (y1-y2);
|
||||
y2 = prey+ofsY+starty;
|
||||
}
|
||||
else if (y2>=preh+prey+ofsY+starty) {
|
||||
x2 = x1 - (double)(x1-x2)*(y1 - (preh+prey+ofsY+starty-1)) / (y1-y2);
|
||||
y2 = preh+prey+ofsY+starty-1;
|
||||
}
|
||||
|
||||
cr->set_line_width (1.5);
|
||||
cr->set_source_rgb (1.0, 1.0, 1.0);
|
||||
cr->move_to (x1, y1);
|
||||
cr->line_to (x2, y2);
|
||||
cr->stroke ();
|
||||
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||
std::valarray<double> ds (1);
|
||||
ds[0] = 4;
|
||||
cr->set_dash (ds, 0);
|
||||
cr->move_to (x1, y1);
|
||||
cr->line_to (x2, y2);
|
||||
cr->stroke ();
|
||||
|
||||
if (press_x!=action_x && press_y!=action_y) {
|
||||
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||
cr->move_to ((x1+x2)/2+1, (y1+y2)/2+1);
|
||||
deglayout->add_to_cairo_context (cr);
|
||||
cr->move_to ((x1+x2)/2+1, (y1+y2)/2-1);
|
||||
deglayout->add_to_cairo_context (cr);
|
||||
cr->move_to ((x1+x2)/2-1, (y1+y2)/2+1);
|
||||
deglayout->add_to_cairo_context (cr);
|
||||
cr->move_to ((x1+x2)/2+1, (y1+y2)/2+1);
|
||||
deglayout->add_to_cairo_context (cr);
|
||||
cr->fill ();
|
||||
cr->set_source_rgb (1.0, 1.0, 1.0);
|
||||
cr->move_to ((x1+x2)/2, (y1+y2)/2);
|
||||
deglayout->add_to_cairo_context (cr);
|
||||
cr->fill ();
|
||||
}
|
||||
}
|
||||
|
||||
95
rtgui/filebrowserentry.h
Executable file
95
rtgui/filebrowserentry.h
Executable file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _FILEBROWSERENTRY_
|
||||
#define _FILEBROWSERENTRY_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <thumbbrowserentrybase.h>
|
||||
#include <thumbnail.h>
|
||||
#include <filethumbnailbuttonset.h>
|
||||
#include <thumbnaillistener.h>
|
||||
#include <thumbimageupdater.h>
|
||||
#include <imageareatoollistener.h>
|
||||
#include <editenums.h>
|
||||
#include <rtengine.h>
|
||||
#include <crophandler.h>
|
||||
|
||||
|
||||
class FileBrowserEntry;
|
||||
struct FileBrowserEntryIdleHelper {
|
||||
FileBrowserEntry* fbentry;
|
||||
bool destroyed;
|
||||
int pending;
|
||||
};
|
||||
|
||||
class FileThumbnailButtonSet;
|
||||
class FileBrowserEntry : public ThumbBrowserEntryBase,
|
||||
public ThumbnailListener,
|
||||
public ThumbImageUpdateListener {
|
||||
|
||||
double scale;
|
||||
static bool iconsLoaded;
|
||||
ImageAreaToolListener* iatlistener;
|
||||
int press_x, press_y, action_x, action_y;
|
||||
double rot_deg;
|
||||
rtengine::procparams::CropParams cropParams;
|
||||
CropGUIListener* cropgl;
|
||||
FileBrowserEntryIdleHelper* feih;
|
||||
|
||||
ImgEditState state;
|
||||
|
||||
bool onArea (CursorArea a, int x, int y);
|
||||
void updateCursor (int x, int y);
|
||||
void drawStraightenGuide (Cairo::RefPtr<Cairo::Context> c);
|
||||
void customBackBufferUpdate (Cairo::RefPtr<Cairo::Context> c);
|
||||
|
||||
public:
|
||||
|
||||
static Glib::RefPtr<Gdk::Pixbuf> editedIcon;
|
||||
static Glib::RefPtr<Gdk::Pixbuf> recentlySavedIcon;
|
||||
static Glib::RefPtr<Gdk::Pixbuf> enqueuedIcon;
|
||||
|
||||
Thumbnail* thumbnail;
|
||||
|
||||
FileBrowserEntry (Thumbnail* thm, const Glib::ustring& fname);
|
||||
~FileBrowserEntry ();
|
||||
void draw ();
|
||||
|
||||
void setImageAreaToolListener (ImageAreaToolListener* l) { iatlistener = l; }
|
||||
|
||||
FileThumbnailButtonSet* getThumbButtonSet ();
|
||||
|
||||
void refreshThumbnailImage ();
|
||||
void calcThumbnailSize ();
|
||||
|
||||
std::vector<Glib::RefPtr<Gdk::Pixbuf> > getIconsOnImageArea ();
|
||||
void getIconSize (int& w, int& h);
|
||||
|
||||
// thumbnaillistener interface
|
||||
void procParamsChanged (Thumbnail* thm, int whoChangedIt);
|
||||
// thumbimageupdatelistener interface
|
||||
void updateImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cropParams);
|
||||
void _updateImage (rtengine::IImage8* img, double scale, rtengine::procparams::CropParams cropParams); // inside gtk thread
|
||||
|
||||
bool motionNotify (int x, int y);
|
||||
bool pressNotify (int button, int type, int bstate, int x, int y);
|
||||
bool releaseNotify (int button, int type, int bstate, int x, int y);
|
||||
};
|
||||
|
||||
#endif
|
||||
797
rtgui/filecatalog.cc
Executable file
797
rtgui/filecatalog.cc
Executable file
@@ -0,0 +1,797 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <filecatalog.h>
|
||||
#include <options.h>
|
||||
#include <cachemanager.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <guiutils.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <iostream>
|
||||
#include <renamedlg.h>
|
||||
#include <thumbimageupdater.h>
|
||||
#include <safegtk.h>
|
||||
|
||||
#define CHECKTIME 2000
|
||||
|
||||
extern Glib::ustring argv0;
|
||||
|
||||
#ifdef _WIN32
|
||||
int _directoryUpdater (void* cat) {
|
||||
|
||||
((FileCatalog*)cat)->checkCounter++;
|
||||
if (((FileCatalog*)cat)->checkCounter==2) {
|
||||
gdk_threads_enter ();
|
||||
((FileCatalog*)cat)->reparseDirectory ();
|
||||
gdk_threads_leave ();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb) : listener(NULL), fslistener(NULL), hasValidCurrentEFS(false), coarsePanel(cp), filterPanel(NULL), toolBar(tb) {
|
||||
|
||||
previewLoader.setPreviewLoaderListener (this);
|
||||
|
||||
// construct and initialize thumbnail browsers
|
||||
fileBrowser = new FileBrowser();
|
||||
fileBrowser->setFileBrowserListener (this);
|
||||
fileBrowser->setArrangement (ThumbBrowserBase::TB_Vertical);
|
||||
fileBrowser->show ();
|
||||
|
||||
// construct trash panel with the extra "empty trash" button
|
||||
trashButtonBox = new Gtk::VBox;
|
||||
Gtk::Button* emptyT = new Gtk::Button (M("FILEBROWSER_EMPTYTRASH"));
|
||||
emptyT->set_tooltip_text (M("FILEBROWSER_EMPTYTRASHHINT"));
|
||||
emptyT->set_image (*(new Gtk::Image (Gtk::StockID("gtk-delete"), Gtk::ICON_SIZE_BUTTON)));
|
||||
emptyT->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::emptyTrash));
|
||||
trashButtonBox->pack_start (*emptyT, Gtk::PACK_SHRINK, 4);
|
||||
emptyT->show ();
|
||||
trashButtonBox->show ();
|
||||
|
||||
// setup button bar
|
||||
buttonBar = new Gtk::HBox ();
|
||||
pack_start (*buttonBar, Gtk::PACK_SHRINK);
|
||||
|
||||
buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK);
|
||||
bDir = new Gtk::ToggleButton ();
|
||||
bDir->set_active (true);
|
||||
bDir->set_image (*(new Gtk::Image (argv0+"/images/folder.png")));
|
||||
bDir->set_relief (Gtk::RELIEF_NONE);
|
||||
bDir->set_tooltip_text (M("FILEBROWSER_SHOWDIRHINT"));
|
||||
bCateg[0] = bDir->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bDir));
|
||||
buttonBar->pack_start (*bDir, Gtk::PACK_SHRINK);
|
||||
buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK);
|
||||
|
||||
bUnRanked = new Gtk::ToggleButton ();
|
||||
bUnRanked->set_active (false);
|
||||
bUnRanked->set_image (*(new Gtk::Image (argv0+"/images/unrated.png")));
|
||||
bUnRanked->set_relief (Gtk::RELIEF_NONE);
|
||||
bUnRanked->set_tooltip_text (M("FILEBROWSER_SHOWUNRANKHINT"));
|
||||
bCateg[1] = bUnRanked->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bUnRanked));
|
||||
buttonBar->pack_start (*bUnRanked, Gtk::PACK_SHRINK);
|
||||
buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK);
|
||||
|
||||
for (int i=0; i<5; i++) {
|
||||
iranked[i] = new Gtk::Image (argv0+"/images/rated.png");
|
||||
igranked[i] = new Gtk::Image (argv0+"/images/grayrated.png");
|
||||
iranked[i]->show ();
|
||||
igranked[i]->show ();
|
||||
bRank[i] = new Gtk::ToggleButton ();
|
||||
bRank[i]->set_image (*igranked[i]);
|
||||
bRank[i]->set_relief (Gtk::RELIEF_NONE);
|
||||
buttonBar->pack_start (*bRank[i], Gtk::PACK_SHRINK);
|
||||
bCateg[i+2] = bRank[i]->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bRank[i]));
|
||||
}
|
||||
bRank[0]->set_tooltip_text (M("FILEBROWSER_SHOWRANK1HINT"));
|
||||
bRank[1]->set_tooltip_text (M("FILEBROWSER_SHOWRANK2HINT"));
|
||||
bRank[2]->set_tooltip_text (M("FILEBROWSER_SHOWRANK3HINT"));
|
||||
bRank[3]->set_tooltip_text (M("FILEBROWSER_SHOWRANK4HINT"));
|
||||
bRank[4]->set_tooltip_text (M("FILEBROWSER_SHOWRANK5HINT"));
|
||||
buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK);
|
||||
|
||||
bTrash = new Gtk::ToggleButton ();
|
||||
bTrash->set_image (*(new Gtk::Image (Gtk::StockID("gtk-delete"), Gtk::ICON_SIZE_SMALL_TOOLBAR)));
|
||||
bTrash->set_relief (Gtk::RELIEF_NONE);
|
||||
bTrash->set_tooltip_text (M("FILEBROWSER_SHOWTRASHHINT"));
|
||||
bCateg[7] = bTrash->signal_toggled().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::categoryButtonToggled), bTrash));
|
||||
buttonBar->pack_start (*bTrash, Gtk::PACK_SHRINK);
|
||||
buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK);
|
||||
|
||||
categoryButtons[0] = bDir;
|
||||
categoryButtons[1] = bUnRanked;
|
||||
for (int i=0; i<5; i++)
|
||||
categoryButtons[i+2] = bRank[i];
|
||||
categoryButtons[7] = bTrash;
|
||||
|
||||
exifInfo = Gtk::manage(new Gtk::ToggleButton ());
|
||||
exifInfo->set_image (*(new Gtk::Image (argv0+"/images/info.png")));
|
||||
exifInfo->set_relief (Gtk::RELIEF_NONE);
|
||||
exifInfo->set_active( options.showFileNames );
|
||||
exifInfo->signal_toggled().connect(sigc::mem_fun(*this, &FileCatalog::exifInfoButtonToggled));
|
||||
buttonBar->pack_start (*exifInfo, Gtk::PACK_SHRINK);
|
||||
|
||||
// thumbnail zoom
|
||||
Gtk::HBox* zoomBox = new Gtk::HBox ();
|
||||
zoomInButton = new Gtk::Button ();
|
||||
zoomInButton->set_image (*(new Gtk::Image (Gtk::StockID("gtk-zoom-in"), Gtk::ICON_SIZE_SMALL_TOOLBAR)));
|
||||
zoomInButton->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::zoomIn));
|
||||
zoomInButton->set_relief (Gtk::RELIEF_NONE);
|
||||
zoomInButton->set_tooltip_text (M("FILEBROWSER_ZOOMINHINT"));
|
||||
zoomBox->pack_end (*zoomInButton, Gtk::PACK_SHRINK);
|
||||
zoomOutButton = new Gtk::Button ();
|
||||
zoomOutButton->set_image (*(new Gtk::Image (Gtk::StockID("gtk-zoom-out"), Gtk::ICON_SIZE_SMALL_TOOLBAR)));
|
||||
zoomOutButton->signal_pressed().connect (sigc::mem_fun(*this, &FileCatalog::zoomOut));
|
||||
zoomOutButton->set_relief (Gtk::RELIEF_NONE);
|
||||
zoomOutButton->set_tooltip_text (M("FILEBROWSER_ZOOMOUTHINT"));
|
||||
zoomBox->pack_end (*zoomOutButton, Gtk::PACK_SHRINK);
|
||||
|
||||
// add default panel
|
||||
hBox = new Gtk::HBox ();
|
||||
hBox->show ();
|
||||
hBox->pack_end (*fileBrowser);
|
||||
fileBrowser->applyFilter (getFilter());
|
||||
pack_start (*hBox);
|
||||
|
||||
buttonBar2 = new Gtk::HBox ();
|
||||
pack_end (*buttonBar2, Gtk::PACK_SHRINK);
|
||||
progressBar = new Gtk::ProgressBar ();
|
||||
buttonBar2->pack_start (*progressBar, Gtk::PACK_SHRINK, 4);
|
||||
progressBar->set_size_request (-1, 16);
|
||||
|
||||
buttonBar->pack_start (*zoomBox, Gtk::PACK_SHRINK);
|
||||
|
||||
buttonBar->pack_end (*coarsePanel, Gtk::PACK_SHRINK);
|
||||
buttonBar->pack_end (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK, 4);
|
||||
buttonBar->pack_end (*toolBar, Gtk::PACK_SHRINK);
|
||||
buttonBar->pack_end (*Gtk::manage(new Gtk::VSeparator), Gtk::PACK_SHRINK, 4);
|
||||
|
||||
enabled = true;
|
||||
|
||||
lastScrollPos = 0;
|
||||
for (int i=0; i<8; i++) {
|
||||
hScrollPos[i] = 0;
|
||||
vScrollPos[i] = 0;
|
||||
}
|
||||
|
||||
selectedDirectory = "";
|
||||
#ifdef _WIN32
|
||||
wdMonitor = NULL;
|
||||
checkCounter = 2;
|
||||
g_timeout_add (CHECKTIME, _directoryUpdater, this);
|
||||
#endif
|
||||
}
|
||||
|
||||
void FileCatalog::exifInfoButtonToggled()
|
||||
{
|
||||
options.showFileNames = exifInfo->get_active();
|
||||
fileBrowser->refreshThumbImages ();
|
||||
}
|
||||
|
||||
void FileCatalog::on_realize() {
|
||||
|
||||
Gtk::VBox::on_realize();
|
||||
Pango::FontDescription fontd = get_pango_context()->get_font_description ();
|
||||
fileBrowser->get_pango_context()->set_font_description (fontd);
|
||||
// batchQueue->get_pango_context()->set_font_description (fontd);
|
||||
}
|
||||
|
||||
void FileCatalog::closeDir () {
|
||||
|
||||
if (filterPanel)
|
||||
filterPanel->set_sensitive (false);
|
||||
|
||||
#ifndef _WIN32
|
||||
if (dirMonitor)
|
||||
dirMonitor->cancel ();
|
||||
#else
|
||||
if (wdMonitor) {
|
||||
delete wdMonitor;
|
||||
wdMonitor = NULL;
|
||||
}
|
||||
#endif
|
||||
// terminate thumbnail preview loading
|
||||
previewLoader.terminate ();
|
||||
|
||||
// terminate thumbnail updater
|
||||
thumbImageUpdater.terminate ();
|
||||
|
||||
// remove entries
|
||||
fileBrowser->close ();
|
||||
fileNameList.clear ();
|
||||
|
||||
dirEFS.clear ();
|
||||
hasValidCurrentEFS = false;
|
||||
selectedDirectory = "";
|
||||
redrawAll ();
|
||||
}
|
||||
|
||||
std::vector<Glib::ustring> FileCatalog::getFileList () {
|
||||
|
||||
std::vector<Glib::ustring> names;
|
||||
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (selectedDirectory);
|
||||
safe_build_file_list (dir, names, selectedDirectory);
|
||||
return names;
|
||||
}
|
||||
|
||||
void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile) {
|
||||
|
||||
try {
|
||||
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (dirname);
|
||||
|
||||
if (!dir)
|
||||
return;
|
||||
closeDir ();
|
||||
previewsToLoad = 0;
|
||||
previewsLoaded = 0;
|
||||
// if openfile exists, we have to open it first (it is a command line argument)
|
||||
if (openfile!="")
|
||||
addAndOpenFile (openfile);
|
||||
|
||||
selectedDirectory = dir->get_parse_name();
|
||||
fileNameList = getFileList ();
|
||||
|
||||
for (int i=0; i<fileNameList.size(); i++) {
|
||||
Glib::RefPtr<Gio::File> f = Gio::File::create_for_path(fileNameList[i]);
|
||||
if (f->get_parse_name() != openfile) // if we opened a file at the beginning dont add it again
|
||||
checkAndAddFile (f);
|
||||
}
|
||||
|
||||
_refreshProgressBar ();
|
||||
previewLoader.process ();
|
||||
|
||||
#ifdef _WIN32
|
||||
wdMonitor = new WinDirMonitor (selectedDirectory, this);
|
||||
#elif defined __APPLE__
|
||||
printf("TODO fix dir->monitor_directory () for OSX\n");
|
||||
#else
|
||||
dirMonitor = dir->monitor_directory ();
|
||||
dirMonitor->signal_changed().connect (sigc::bind(sigc::mem_fun(*this, &FileCatalog::on_dir_changed), false));
|
||||
#endif
|
||||
}
|
||||
catch (Glib::Exception& ex) {
|
||||
std::cout << ex.what();
|
||||
}
|
||||
}
|
||||
|
||||
void FileCatalog::_refreshProgressBar () {
|
||||
|
||||
// check if progress bar is visible
|
||||
/* Glib::ListHandle<Gtk::Widget*> list = buttonBar2->get_children ();
|
||||
Glib::ListHandle<Gtk::Widget*>::iterator i = list.begin ();
|
||||
for (; i!=list.end() && *i!=progressBar; i++);
|
||||
if (i==list.end()) {
|
||||
buttonBar2->pack_start (*progressBar, Gtk::PACK_SHRINK, 4);
|
||||
buttonBar2->reorder_child (*progressBar, 2);
|
||||
}
|
||||
*/
|
||||
progressBar->show ();
|
||||
if (previewsToLoad>0)
|
||||
progressBar->set_fraction ((double)previewsLoaded / previewsToLoad);
|
||||
else
|
||||
progressBar->set_fraction (1.0);
|
||||
}
|
||||
|
||||
int refreshpb (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
((FileCatalog*)data)->_refreshProgressBar ();
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileCatalog::previewReady (FileBrowserEntry* fdn) {
|
||||
|
||||
// put it into the "full directory" browser
|
||||
fdn->setImageAreaToolListener (iatlistener);
|
||||
fileBrowser->addEntry (fdn);
|
||||
|
||||
// update exif filter settings (minimal & maximal values of exif tags, cameras, lenses, etc...)
|
||||
const CacheImageData* cfs = fdn->thumbnail->getCacheImageData();
|
||||
if (cfs->exifValid) {
|
||||
if (cfs->fnumber < dirEFS.fnumberFrom)
|
||||
dirEFS.fnumberFrom = cfs->fnumber;
|
||||
if (cfs->fnumber > dirEFS.fnumberTo)
|
||||
dirEFS.fnumberTo = cfs->fnumber;
|
||||
if (cfs->shutter < dirEFS.shutterFrom)
|
||||
dirEFS.shutterFrom = cfs->shutter;
|
||||
if (cfs->shutter > dirEFS.shutterTo)
|
||||
dirEFS.shutterTo = cfs->shutter;
|
||||
if (cfs->iso>0 && cfs->iso < dirEFS.isoFrom)
|
||||
dirEFS.isoFrom = cfs->iso;
|
||||
if (cfs->iso>0 && cfs->iso > dirEFS.isoTo)
|
||||
dirEFS.isoTo = cfs->iso;
|
||||
if (cfs->focalLen < dirEFS.focalFrom)
|
||||
dirEFS.focalFrom = cfs->focalLen;
|
||||
if (cfs->focalLen > dirEFS.focalTo)
|
||||
dirEFS.focalTo = cfs->focalLen;
|
||||
}
|
||||
dirEFS.cameras.insert (cfs->camera);
|
||||
dirEFS.lenses.insert (cfs->lens);
|
||||
previewsLoaded++;
|
||||
g_idle_add (refreshpb, this);
|
||||
}
|
||||
|
||||
int prevfinished (void* data) {
|
||||
|
||||
gdk_threads_enter();
|
||||
((FileCatalog*)data)->_previewsFinished ();
|
||||
gdk_threads_leave();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileCatalog::_previewsFinished () {
|
||||
|
||||
redrawAll ();
|
||||
previewsToLoad = 0;
|
||||
previewsLoaded = 0;
|
||||
// removeIfThere (buttonBar2, progressBar);
|
||||
progressBar->hide ();
|
||||
if (filterPanel) {
|
||||
filterPanel->set_sensitive (true);
|
||||
if ( !hasValidCurrentEFS ){
|
||||
currentEFS = dirEFS;
|
||||
filterPanel->setFilter ( dirEFS,true );
|
||||
}else {
|
||||
filterPanel->setFilter ( currentEFS,false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileCatalog::previewsFinished () {
|
||||
|
||||
if (!hasValidCurrentEFS)
|
||||
currentEFS = dirEFS;
|
||||
g_idle_add (prevfinished, this);
|
||||
}
|
||||
|
||||
void PreviewLoader::remove (Glib::ustring fname) {
|
||||
std::list<DirEntry>::iterator i;
|
||||
for (i=jqueue.begin(); i!=jqueue.end(); i++)
|
||||
if (i->fullName==fname)
|
||||
break;
|
||||
if (i!=jqueue.end())
|
||||
jqueue.erase (i);
|
||||
}
|
||||
|
||||
void PreviewLoader::start () {
|
||||
|
||||
jqueue.sort ();
|
||||
}
|
||||
|
||||
void PreviewLoader::process (DirEntry& current) {
|
||||
|
||||
if (Glib::file_test (current.fullName, Glib::FILE_TEST_EXISTS)) {
|
||||
Thumbnail* tmb = cacheMgr.getEntry (current.fullName);
|
||||
if (tmb && pl)
|
||||
pl->previewReady (new FileBrowserEntry (tmb, current.fullName));
|
||||
}
|
||||
}
|
||||
|
||||
void PreviewLoader::end () {
|
||||
|
||||
if (pl)
|
||||
pl->previewsFinished ();
|
||||
}
|
||||
|
||||
void FileCatalog::setEnabled (bool e) {
|
||||
|
||||
enabled = e;
|
||||
}
|
||||
|
||||
void FileCatalog::redrawAll () {
|
||||
|
||||
fileBrowser->queue_draw ();
|
||||
}
|
||||
|
||||
void FileCatalog::refreshAll () {
|
||||
|
||||
fileBrowser->refreshThumbImages ();
|
||||
}
|
||||
|
||||
void FileCatalog::_openImage (std::vector<Thumbnail*> tmb) {
|
||||
|
||||
if (enabled && listener!=NULL) {
|
||||
previewLoader.stop ();
|
||||
thumbImageUpdater.stop ();
|
||||
for (int i=0; i<tmb.size(); i++) {
|
||||
if (editedFiles.find (tmb[i]->getFileName())==editedFiles.end())
|
||||
listener->fileSelected (tmb[i]);
|
||||
tmb[i]->decreaseRef ();
|
||||
}
|
||||
previewLoader.process ();
|
||||
thumbImageUpdater.process ();
|
||||
}
|
||||
}
|
||||
|
||||
struct FCOIParams {
|
||||
FileCatalog* catalog;
|
||||
std::vector<Thumbnail*> tmb;
|
||||
};
|
||||
|
||||
int fcopenimg (void* p) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
FCOIParams* params = (FCOIParams*)p;
|
||||
params->catalog->_openImage (params->tmb);
|
||||
delete params;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FileCatalog::openRequested (std::vector<Thumbnail*> tmb) {
|
||||
|
||||
FCOIParams* params = new FCOIParams;
|
||||
params->catalog = this;
|
||||
params->tmb = tmb;
|
||||
for (int i=0; i<tmb.size(); i++)
|
||||
tmb[i]->increaseRef ();
|
||||
g_idle_add (fcopenimg, params);
|
||||
}
|
||||
|
||||
void FileCatalog::deleteRequested (std::vector<FileBrowserEntry*> tbe) {
|
||||
|
||||
if (tbe.size()==0)
|
||||
return;
|
||||
|
||||
Gtk::MessageDialog msd (M("FILEBROWSER_DELETEDLGLABEL"), false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true);
|
||||
msd.set_secondary_text(Glib::ustring::compose (M("FILEBROWSER_DELETEDLGMSG"), tbe.size()));
|
||||
|
||||
if (msd.run()==Gtk::RESPONSE_YES) {
|
||||
for (int i=0; i<tbe.size(); i++) {
|
||||
Glib::ustring fname = tbe[i]->filename;
|
||||
// remove from browser
|
||||
FileBrowserEntry* t = fileBrowser->delEntry (fname);
|
||||
// t->thumbnail->decreaseRef ();
|
||||
delete t;
|
||||
// remove from cache
|
||||
cacheMgr.deleteEntry (fname);
|
||||
// delete from file system
|
||||
::g_remove (fname.c_str());
|
||||
// delete .pp2 if found
|
||||
::g_remove (Glib::ustring(fname+".pp2").c_str());
|
||||
::g_remove (Glib::ustring(removeExtension(fname)+".pp2").c_str());
|
||||
// delete .thm file
|
||||
::g_remove (Glib::ustring(removeExtension(fname)+".thm").c_str());
|
||||
::g_remove (Glib::ustring(removeExtension(fname)+".THM").c_str());
|
||||
}
|
||||
redrawAll ();
|
||||
}
|
||||
}
|
||||
|
||||
void FileCatalog::developRequested (std::vector<FileBrowserEntry*> tbe) {
|
||||
|
||||
if (listener) {
|
||||
thumbImageUpdater.stop ();
|
||||
for (int i=0; i<tbe.size(); i++) {
|
||||
rtengine::procparams::ProcParams params = tbe[i]->thumbnail->getProcParams();
|
||||
rtengine::ProcessingJob* pjob = rtengine::ProcessingJob::create (tbe[i]->filename, tbe[i]->thumbnail->getType()==FT_Raw, params);
|
||||
double tmpscale;
|
||||
rtengine::IImage8* img = tbe[i]->thumbnail->processThumbImage (params, options.maxThumbnailHeight, tmpscale);
|
||||
if (img) {
|
||||
int pw = img->getWidth ();
|
||||
int ph = img->getHeight ();
|
||||
guint8* prev = new guint8 [pw*ph*3];
|
||||
memcpy (prev, img->getData (), pw*ph*3);
|
||||
listener->addBatchQueueJob (new BatchQueueEntry (pjob, params, tbe[i]->filename, prev, pw, ph, tbe[i]->thumbnail));
|
||||
}
|
||||
else {
|
||||
int pw, ph;
|
||||
tbe[i]->thumbnail->getThumbnailSize (pw, ph);
|
||||
listener->addBatchQueueJob (new BatchQueueEntry (pjob, params, tbe[i]->filename, NULL, pw, ph, tbe[i]->thumbnail));
|
||||
}
|
||||
}
|
||||
thumbImageUpdater.process ();
|
||||
}
|
||||
}
|
||||
|
||||
void FileCatalog::renameRequested (std::vector<FileBrowserEntry*> tbe) {
|
||||
|
||||
RenameDialog* renameDlg = new RenameDialog ((Gtk::Window*)get_toplevel());
|
||||
|
||||
for (int i=0; i<tbe.size(); i++) {
|
||||
renameDlg->initName (Glib::path_get_basename (tbe[i]->filename), tbe[i]->thumbnail->getCacheImageData());
|
||||
|
||||
Glib::ustring ofname = tbe[i]->filename;
|
||||
Glib::ustring dirName = Glib::path_get_dirname (tbe[i]->filename);
|
||||
Glib::ustring baseName = Glib::path_get_basename (tbe[i]->filename);
|
||||
|
||||
if (renameDlg->run ()== Gtk::RESPONSE_OK) {
|
||||
Glib::ustring nBaseName = renameDlg->getNewName ();
|
||||
// if path has directory components, exit
|
||||
if (Glib::path_get_dirname (nBaseName) != ".")
|
||||
continue;
|
||||
// if no extension is given, concatenate the extension of the original file
|
||||
Glib::ustring ext = getExtension (nBaseName);
|
||||
if (ext=="")
|
||||
nBaseName += "." + getExtension (baseName);
|
||||
Glib::ustring nfname = Glib::build_filename (dirName, nBaseName);
|
||||
if (!::g_rename (ofname.c_str(), nfname.c_str())) {
|
||||
cacheMgr.renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname);
|
||||
reparseDirectory ();
|
||||
}
|
||||
renameDlg->hide ();
|
||||
}
|
||||
}
|
||||
delete renameDlg;
|
||||
/* // ask for new file name
|
||||
Gtk::Dialog dialog (M("FILEBROWSER_RENAMEDLGLABEL"), *((Gtk::Window*)get_toplevel()), true, true);
|
||||
|
||||
dialog.add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
|
||||
dialog.add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
|
||||
|
||||
Gtk::Label l;
|
||||
dialog.get_vbox()->pack_start (l, Gtk::PACK_SHRINK);
|
||||
|
||||
Gtk::Entry nfentry;
|
||||
|
||||
dialog.get_vbox()->pack_start (nfentry, Gtk::PACK_SHRINK);
|
||||
dialog.get_vbox()->show_all ();
|
||||
|
||||
nfentry.set_activates_default (true);
|
||||
dialog.set_default_response (Gtk::RESPONSE_OK);
|
||||
|
||||
for (int i=0; i<tbe.size(); i++) {
|
||||
|
||||
Glib::ustring ofname = tbe[i]->filename;
|
||||
Glib::ustring dirName = Glib::path_get_dirname (tbe[i]->filename);
|
||||
Glib::ustring baseName = Glib::path_get_basename (tbe[i]->filename);
|
||||
|
||||
l.set_markup (Glib::ustring("<big><b>") + Glib::ustring::compose (M("FILEBROWSER_RENAMEDLGMSG"), baseName) + Glib::ustring("</b></big>"));
|
||||
nfentry.set_text (baseName);
|
||||
nfentry.select_region (0, baseName.size());
|
||||
|
||||
if (dialog.run ()== Gtk::RESPONSE_OK) {
|
||||
Glib::ustring nBaseName = nfentry.get_text ();
|
||||
// if path has directory components, exit
|
||||
if (Glib::path_get_dirname (nBaseName) != ".")
|
||||
continue;
|
||||
// if no extension is given, concatenate the extension of the original file
|
||||
if (nBaseName.find ('.')==nBaseName.npos) {
|
||||
int lastdot = baseName.find_last_of ('.');
|
||||
nBaseName += "." + (lastdot!=Glib::ustring::npos ? baseName.substr (lastdot+1) : "");
|
||||
}
|
||||
Glib::ustring nfname = Glib::build_filename (dirName, nBaseName);
|
||||
if (!::g_rename (ofname.c_str(), nfname.c_str())) {
|
||||
cacheMgr.renameEntry (ofname, tbe[i]->thumbnail->getMD5(), nfname);
|
||||
// the remaining part (removing old and adding new entry) is done by the directory monitor
|
||||
reparseDirectory ();
|
||||
// on_dir_changed (Gio::File::create_for_path (nfname), Gio::File::create_for_path (nfname), Gio::FILE_MONITOR_EVENT_CHANGED, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void FileCatalog::categoryButtonToggled (Gtk::ToggleButton* b) {
|
||||
|
||||
for (int i=0; i<8; i++)
|
||||
bCateg[i].block (true);
|
||||
|
||||
fileBrowser->getScrollPosition (hScrollPos[lastScrollPos], vScrollPos[lastScrollPos]);
|
||||
|
||||
// seek the one pressed
|
||||
for (int i=0; i<8; i++) {
|
||||
categoryButtons[i]->set_active (categoryButtons[i]==b);
|
||||
if (categoryButtons[i]==b)
|
||||
lastScrollPos = i;
|
||||
}
|
||||
|
||||
// change the images of the buttons to reflect current ranking
|
||||
for (int i=0; i<5; i++)
|
||||
bRank[i]->set_image (*igranked[i]);
|
||||
for (int i=0; i<5; i++)
|
||||
if (b==bRank[i])
|
||||
for (int j=0; j<=i; j++)
|
||||
bRank[j]->set_image (*iranked[j]);
|
||||
|
||||
fileBrowser->applyFilter (getFilter ());
|
||||
|
||||
// rearrange panels according to the selected filter
|
||||
removeIfThere (hBox, trashButtonBox);
|
||||
if (bTrash->get_active ())
|
||||
hBox->pack_start (*trashButtonBox, Gtk::PACK_SHRINK, 4);
|
||||
hBox->queue_draw ();
|
||||
|
||||
fileBrowser->setScrollPosition (hScrollPos[lastScrollPos], vScrollPos[lastScrollPos]);
|
||||
|
||||
for (int i=0; i<8; i++)
|
||||
bCateg[i].block (false);
|
||||
}
|
||||
|
||||
BrowserFilter FileCatalog::getFilter () {
|
||||
|
||||
BrowserFilter filter;
|
||||
filter.showRanked[0] = bDir->get_active() || bUnRanked->get_active () || bTrash->get_active ();
|
||||
for (int i=1; i<=5; i++)
|
||||
filter.showRanked[i] = bDir->get_active() || bRank[i-1]->get_active () || bTrash->get_active ();
|
||||
filter.showTrash = bDir->get_active() || bTrash->get_active ();
|
||||
filter.showNotTrash = !bTrash->get_active ();
|
||||
if (!filterPanel)
|
||||
filter.exifFilterEnabled = false;
|
||||
else {
|
||||
if (!hasValidCurrentEFS)
|
||||
filter.exifFilter = dirEFS;
|
||||
else
|
||||
filter.exifFilter = currentEFS;
|
||||
filter.exifFilterEnabled = filterPanel->isEnabled ();
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
void FileCatalog::filterChanged () {
|
||||
|
||||
fileBrowser->applyFilter (getFilter());
|
||||
}
|
||||
|
||||
int FileCatalog::reparseDirectory () {
|
||||
|
||||
if (selectedDirectory=="")
|
||||
return 0;
|
||||
|
||||
if (!Glib::file_test (selectedDirectory, Glib::FILE_TEST_IS_DIR)) {
|
||||
closeDir ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<Glib::ustring> nfileNameList = getFileList ();
|
||||
|
||||
// check if a thumbnailed file has been deleted
|
||||
const std::vector<ThumbBrowserEntryBase*>& t = fileBrowser->getEntries ();
|
||||
std::vector<Glib::ustring> fileNamesToDel;
|
||||
for (int i=0; i<t.size(); i++)
|
||||
if (!Glib::file_test (t[i]->filename, Glib::FILE_TEST_EXISTS))
|
||||
fileNamesToDel.push_back (t[i]->filename);
|
||||
for (int i=0; i<fileNamesToDel.size(); i++) {
|
||||
delete fileBrowser->delEntry (fileNamesToDel[i]);
|
||||
cacheMgr.deleteEntry (fileNamesToDel[i]);
|
||||
}
|
||||
|
||||
// check if a new file has been added
|
||||
for (int i=0; i<nfileNameList.size(); i++) {
|
||||
bool found = false;
|
||||
for (int j=0; j<fileNameList.size(); j++)
|
||||
if (nfileNameList[i]==fileNameList[j]) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
previewLoader.stop ();
|
||||
checkAndAddFile (Gio::File::create_for_parse_name (nfileNameList[i]));
|
||||
_refreshProgressBar ();
|
||||
previewLoader.process ();
|
||||
}
|
||||
}
|
||||
|
||||
fileNameList = nfileNameList;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void FileCatalog::winDirChanged () {
|
||||
|
||||
checkCounter = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void FileCatalog::on_dir_changed (const Glib::RefPtr<Gio::File>& file, const Glib::RefPtr<Gio::File>& other_file, Gio::FileMonitorEvent event_type, bool internal) {
|
||||
|
||||
if (!internal)
|
||||
gdk_threads_enter();
|
||||
|
||||
if (event_type == Gio::FILE_MONITOR_EVENT_CREATED || event_type == Gio::FILE_MONITOR_EVENT_DELETED || event_type == Gio::FILE_MONITOR_EVENT_CHANGED)
|
||||
reparseDirectory ();
|
||||
|
||||
if (!internal)
|
||||
gdk_threads_leave();
|
||||
}
|
||||
|
||||
void FileCatalog::checkAndAddFile (Glib::RefPtr<Gio::File> file) {
|
||||
|
||||
if (!file)
|
||||
return;
|
||||
Glib::RefPtr<Gio::FileInfo> info = safe_query_file_info(file);
|
||||
if (info && info->get_file_type() != Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || !options.fbShowHidden)) {
|
||||
int lastdot = info->get_name().find_last_of ('.');
|
||||
if (options.is_extention_enabled(lastdot!=Glib::ustring::npos ? info->get_name().substr (lastdot+1) : "")){
|
||||
previewLoader.add (DirEntry (file->get_parse_name()));
|
||||
previewsToLoad++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileCatalog::addAndOpenFile (const Glib::ustring& fname) {
|
||||
|
||||
Glib::RefPtr<Gio::File> file = Gio::File::create_for_path (fname);
|
||||
if (!file)
|
||||
return;
|
||||
Glib::RefPtr<Gio::FileInfo> info = safe_query_file_info(file);
|
||||
int lastdot = info->get_name().find_last_of ('.');
|
||||
if (options.is_extention_enabled(lastdot!=Glib::ustring::npos ? info->get_name().substr (lastdot+1) : "")){
|
||||
// if supported, load thumbnail first
|
||||
Thumbnail* tmb = cacheMgr.getEntry (file->get_parse_name());
|
||||
if (tmb) {
|
||||
FileBrowserEntry* entry = new FileBrowserEntry (tmb, file->get_parse_name());
|
||||
previewReady (entry);
|
||||
// open the file
|
||||
FCOIParams* params = new FCOIParams;
|
||||
params->catalog = this;
|
||||
params->tmb.push_back (tmb);
|
||||
tmb->increaseRef ();
|
||||
g_idle_add (fcopenimg, params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FileCatalog::emptyTrash () {
|
||||
|
||||
const std::vector<ThumbBrowserEntryBase*> t = fileBrowser->getEntries ();
|
||||
std::vector<FileBrowserEntry*> toDel;
|
||||
for (int i=0; i<t.size(); i++)
|
||||
if (((FileBrowserEntry*)t[i])->thumbnail->getStage()==1)
|
||||
toDel.push_back (((FileBrowserEntry*)t[i]));
|
||||
deleteRequested (toDel);
|
||||
}
|
||||
|
||||
void FileCatalog::zoomIn () {
|
||||
|
||||
bool pLoad = previewLoader.runs();
|
||||
if (pLoad)
|
||||
previewLoader.stop ();
|
||||
|
||||
fileBrowser->zoomIn ();
|
||||
|
||||
if (pLoad)
|
||||
previewLoader.process ();
|
||||
}
|
||||
void FileCatalog::zoomOut () {
|
||||
|
||||
bool pLoad = previewLoader.runs();
|
||||
if (pLoad)
|
||||
previewLoader.stop ();
|
||||
|
||||
fileBrowser->zoomOut ();
|
||||
|
||||
if (pLoad)
|
||||
previewLoader.process ();
|
||||
}
|
||||
void FileCatalog::refreshEditedState (const std::set<Glib::ustring>& efiles) {
|
||||
|
||||
editedFiles = efiles;
|
||||
fileBrowser->refreshEditedState (efiles);
|
||||
}
|
||||
|
||||
void FileCatalog::selectionChanged (std::vector<Thumbnail*> tbe) {
|
||||
|
||||
if (fslistener)
|
||||
fslistener->selectionChanged (tbe);
|
||||
}
|
||||
|
||||
void FileCatalog::exifFilterChanged () {
|
||||
|
||||
currentEFS = filterPanel->getFilter ();
|
||||
hasValidCurrentEFS = true;
|
||||
fileBrowser->applyFilter (getFilter ());
|
||||
}
|
||||
|
||||
void FileCatalog::setFilterPanel (FilterPanel* fpanel) {
|
||||
|
||||
filterPanel = fpanel;
|
||||
filterPanel->set_sensitive (false);
|
||||
filterPanel->setFilterPanelListener (this);
|
||||
}
|
||||
192
rtgui/filecatalog.h
Executable file
192
rtgui/filecatalog.h
Executable file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _FILECATALOG_
|
||||
#define _FILECATALOG_
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windirmonitor.h>
|
||||
#endif
|
||||
#include <dirselectionlistener.h>
|
||||
#include <filebrowser.h>
|
||||
#include <procthread.h>
|
||||
#include <exiffiltersettings.h>
|
||||
#include <giomm.h>
|
||||
#include <fileselectionlistener.h>
|
||||
#include <set>
|
||||
#include <fileselectionchangelistener.h>
|
||||
#include <coarsepanel.h>
|
||||
#include <toolbar.h>
|
||||
#include <filterpanel.h>
|
||||
|
||||
class PreviewLoaderListener {
|
||||
public:
|
||||
virtual void previewReady (FileBrowserEntry* fd) {}
|
||||
virtual void previewsFinished () {}
|
||||
};
|
||||
|
||||
class DirEntry {
|
||||
|
||||
public:
|
||||
Glib::ustring fullName;
|
||||
|
||||
DirEntry (const Glib::ustring& n) : fullName (n) {}
|
||||
|
||||
bool operator< (DirEntry& other) {
|
||||
return fullName.casefold() < other.fullName.casefold();
|
||||
}
|
||||
};
|
||||
|
||||
class PreviewLoader : public ProcessingThread<DirEntry> {
|
||||
|
||||
protected:
|
||||
PreviewLoaderListener* pl;
|
||||
|
||||
public:
|
||||
PreviewLoader () : pl(NULL) { ProcessingThread<DirEntry>(); }
|
||||
void setPreviewLoaderListener (PreviewLoaderListener* p) { pl = p; }
|
||||
void start ();
|
||||
void process () { ProcessingThread<DirEntry>::process (); }
|
||||
void process (DirEntry& current);
|
||||
void remove (Glib::ustring fname);
|
||||
void end ();
|
||||
};
|
||||
|
||||
class FileCatalog : public Gtk::VBox,
|
||||
public DirSelectionListener,
|
||||
public PreviewLoaderListener,
|
||||
public FilterPanelListener,
|
||||
public FileBrowserListener
|
||||
#ifdef _WIN32
|
||||
, public WinDirChangeListener
|
||||
#endif
|
||||
{
|
||||
|
||||
// thumbnail browsers
|
||||
FileBrowser* fileBrowser;
|
||||
|
||||
Gtk::HBox* hBox;
|
||||
Glib::ustring selectedDirectory;
|
||||
bool enabled;
|
||||
|
||||
PreviewLoader previewLoader;
|
||||
FileSelectionListener* listener;
|
||||
FileSelectionChangeListener* fslistener;
|
||||
ImageAreaToolListener* iatlistener;
|
||||
|
||||
Gtk::HBox* buttonBar;
|
||||
Gtk::HBox* buttonBar2;
|
||||
Gtk::ToggleButton* bDir;
|
||||
Gtk::ToggleButton* bUnRanked;
|
||||
Gtk::ToggleButton* bRank[5];
|
||||
Gtk::ToggleButton* bTrash;
|
||||
Gtk::ToggleButton* categoryButtons[8];
|
||||
Gtk::ToggleButton* exifInfo;
|
||||
sigc::connection bCateg[8];
|
||||
Gtk::Image* iranked[5], *igranked[5];
|
||||
|
||||
double hScrollPos[8];
|
||||
double vScrollPos[8];
|
||||
int lastScrollPos;
|
||||
|
||||
Gtk::VBox* trashButtonBox;
|
||||
|
||||
Gtk::Button* zoomInButton;
|
||||
Gtk::Button* zoomOutButton;
|
||||
|
||||
ExifFilterSettings dirEFS;
|
||||
ExifFilterSettings currentEFS;
|
||||
bool hasValidCurrentEFS;
|
||||
|
||||
FilterPanel* filterPanel;
|
||||
|
||||
Glib::RefPtr<Gio::FileMonitor> dirMonitor;
|
||||
|
||||
Gtk::ProgressBar* progressBar;
|
||||
int previewsToLoad;
|
||||
int previewsLoaded;
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
WinDirMonitor* wdMonitor;
|
||||
public:
|
||||
int checkCounter;
|
||||
void winDirChanged ();
|
||||
private:
|
||||
#endif
|
||||
std::vector<Glib::ustring> fileNameList;
|
||||
std::set<Glib::ustring> editedFiles;
|
||||
|
||||
void addAndOpenFile (const Glib::ustring& fname);
|
||||
void checkAndAddFile (Glib::RefPtr<Gio::File> info);
|
||||
std::vector<Glib::ustring> getFileList ();
|
||||
BrowserFilter getFilter ();
|
||||
|
||||
public:
|
||||
CoarsePanel* coarsePanel;
|
||||
ToolBar* toolBar;
|
||||
|
||||
FileCatalog (CoarsePanel* cp, ToolBar* tb);
|
||||
void dirSelected (const Glib::ustring& dirname, const Glib::ustring& openfile="");
|
||||
void closeDir ();
|
||||
void refreshEditedState (const std::set<Glib::ustring>& efiles);
|
||||
|
||||
// previewloaderlistener interface
|
||||
void previewReady (FileBrowserEntry* fdn);
|
||||
void previewsFinished ();
|
||||
void _previewsFinished ();
|
||||
void _refreshProgressBar ();
|
||||
|
||||
// filterpanel interface
|
||||
void exifFilterChanged ();
|
||||
|
||||
Glib::ustring lastSelectedDir () { return selectedDirectory; }
|
||||
void setEnabled (bool e); // if not enabled, it does not open image
|
||||
|
||||
void redrawAll ();
|
||||
void refreshAll ();
|
||||
|
||||
void openRequested (std::vector<Thumbnail*> tbe);
|
||||
void deleteRequested (std::vector<FileBrowserEntry*> tbe);
|
||||
void developRequested (std::vector<FileBrowserEntry*> tbe);
|
||||
void renameRequested (std::vector<FileBrowserEntry*> tbe);
|
||||
void selectionChanged (std::vector<Thumbnail*> tbe);
|
||||
void emptyTrash ();
|
||||
|
||||
void setFileSelectionListener (FileSelectionListener* l) { listener = l; }
|
||||
void setFileSelectionChangeListener (FileSelectionChangeListener* l) { fslistener = l; }
|
||||
void setImageAreaToolListener (ImageAreaToolListener* l) { iatlistener = l; }
|
||||
void setFilterPanel (FilterPanel* fpanel);
|
||||
void exifInfoButtonToggled();
|
||||
void categoryButtonToggled (Gtk::ToggleButton* b);
|
||||
void filterChanged ();
|
||||
void runFilterDialog ();
|
||||
|
||||
void on_realize();
|
||||
void on_dir_changed (const Glib::RefPtr<Gio::File>& file, const Glib::RefPtr<Gio::File>& other_file, Gio::FileMonitorEvent event_type, bool internal);
|
||||
int reparseDirectory ();
|
||||
void _openImage (std::vector<Thumbnail*> tmb);
|
||||
|
||||
void zoomIn ();
|
||||
void zoomOut ();
|
||||
|
||||
void openNextImage () { fileBrowser->openNextImage(); }
|
||||
void openPrevImage () { fileBrowser->openPrevImage(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
187
rtgui/filepanel.cc
Executable file
187
rtgui/filepanel.cc
Executable file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <filepanel.h>
|
||||
#include <rtwindow.h>
|
||||
|
||||
int fbinit (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
((FilePanel*)data)->init ();
|
||||
gdk_threads_leave ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
FilePanel::FilePanel () : parent(NULL) {
|
||||
|
||||
dirpaned = new Gtk::HPaned ();
|
||||
dirpaned->set_position (options.dirBrowserWidth);
|
||||
|
||||
dirBrowser = new DirBrowser ();
|
||||
placesBrowser = new PlacesBrowser ();
|
||||
recentBrowser = new RecentBrowser ();
|
||||
|
||||
placespaned = new Gtk::VPaned ();
|
||||
placespaned->set_position (options.dirBrowserHeight);
|
||||
|
||||
Gtk::VBox* obox = Gtk::manage (new Gtk::VBox ());
|
||||
obox->pack_start (*recentBrowser, Gtk::PACK_SHRINK, 4);
|
||||
obox->pack_start (*dirBrowser);
|
||||
|
||||
placespaned->pack1 (*placesBrowser, false, true);
|
||||
placespaned->pack2 (*obox, true, true);
|
||||
|
||||
dirpaned->pack1 (*placespaned, Gtk::SHRINK);
|
||||
|
||||
tpc = new BatchToolPanelCoordinator (this);
|
||||
fileCatalog = new FileCatalog (tpc->coarse, tpc->getToolBar());
|
||||
dirpaned->pack2 (*fileCatalog, Gtk::EXPAND|Gtk::SHRINK);
|
||||
|
||||
placesBrowser->setDirBrowserRemoteInterface (dirBrowser);
|
||||
recentBrowser->setDirBrowserRemoteInterface (dirBrowser);
|
||||
dirBrowser->addDirSelectionListener (fileCatalog);
|
||||
dirBrowser->addDirSelectionListener (recentBrowser);
|
||||
dirBrowser->addDirSelectionListener (placesBrowser);
|
||||
fileCatalog->setFileSelectionListener (this);
|
||||
|
||||
rightBox = new Gtk::HBox ();
|
||||
rightNotebook = new Gtk::Notebook ();
|
||||
Gtk::VBox* taggingBox = new Gtk::VBox ();
|
||||
|
||||
history = new History (false);
|
||||
|
||||
tpc->addPParamsChangeListener (history);
|
||||
history->setProfileChangeListener (tpc);
|
||||
|
||||
Gtk::ScrolledWindow* sFilterPanel = new Gtk::ScrolledWindow();
|
||||
filterPanel = new FilterPanel ();
|
||||
sFilterPanel->add (*filterPanel);
|
||||
sFilterPanel->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||
|
||||
fileCatalog->setFilterPanel (filterPanel);
|
||||
fileCatalog->setImageAreaToolListener (tpc);
|
||||
|
||||
//------------------
|
||||
|
||||
rightNotebook->set_tab_pos (Gtk::POS_LEFT);
|
||||
|
||||
Gtk::Label* devLab = new Gtk::Label ("Develop");
|
||||
devLab->set_angle (90);
|
||||
Gtk::Label* filtLab = new Gtk::Label ("Filter");
|
||||
filtLab->set_angle (90);
|
||||
Gtk::Label* tagLab = new Gtk::Label ("Tagging");
|
||||
tagLab->set_angle (90);
|
||||
|
||||
Gtk::VPaned* tpcPaned = new Gtk::VPaned ();
|
||||
tpcPaned->pack1 (*tpc->toolPanelNotebook, true, true);
|
||||
tpcPaned->pack2 (*history, true, true);
|
||||
|
||||
rightNotebook->append_page (*tpcPaned, *devLab);
|
||||
rightNotebook->append_page (*sFilterPanel, *filtLab);
|
||||
rightNotebook->append_page (*taggingBox, *tagLab);
|
||||
|
||||
rightBox->pack_start (*rightNotebook);
|
||||
|
||||
pack1(*dirpaned, true, true);
|
||||
pack2(*rightBox, false, true);
|
||||
|
||||
fileCatalog->setFileSelectionChangeListener (tpc);
|
||||
|
||||
fileCatalog->setFileSelectionListener (this);
|
||||
g_idle_add (fbinit, this);
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
void FilePanel::on_realize () {
|
||||
|
||||
Gtk::HPaned::on_realize ();
|
||||
rightBox->set_size_request (options.browserToolPanelWidth, -1);
|
||||
}
|
||||
|
||||
void FilePanel::init () {
|
||||
|
||||
dirBrowser->fillDirTree ();
|
||||
placesBrowser->refreshPlacesList ();
|
||||
|
||||
if (argv1!="")
|
||||
dirBrowser->open (argv1);
|
||||
else {
|
||||
if (options.startupDir==STARTUPDIR_HOME)
|
||||
dirBrowser->open (Glib::get_home_dir());
|
||||
else if (options.startupDir==STARTUPDIR_CURRENT)
|
||||
dirBrowser->open (argv0);
|
||||
else if (options.startupDir==STARTUPDIR_CUSTOM || options.startupDir==STARTUPDIR_LAST)
|
||||
dirBrowser->open (options.startupPath);
|
||||
}
|
||||
}
|
||||
|
||||
bool FilePanel::fileSelected (Thumbnail* thm) {
|
||||
|
||||
if (!parent)
|
||||
return false;
|
||||
|
||||
// try to open the file
|
||||
bool succ = false;
|
||||
fileCatalog->setEnabled (false);
|
||||
rtengine::InitialImage* isrc = EditorPanel::loadImage (thm);
|
||||
if (isrc) {
|
||||
EditorPanel* epanel = Gtk::manage (new EditorPanel (thm, isrc));
|
||||
parent->addEditorPanel (epanel);
|
||||
succ = true;
|
||||
}
|
||||
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 ();
|
||||
}
|
||||
fileCatalog->setEnabled (true);
|
||||
return succ;
|
||||
}
|
||||
|
||||
void FilePanel::saveOptions () {
|
||||
|
||||
options.dirBrowserWidth = dirpaned->get_position ();
|
||||
options.dirBrowserHeight = placespaned->get_position ();
|
||||
options.browserToolPanelWidth = rightBox->get_width ();
|
||||
if (options.startupDir==STARTUPDIR_LAST && fileCatalog->lastSelectedDir ()!="")
|
||||
options.startupPath = fileCatalog->lastSelectedDir ();
|
||||
fileCatalog->closeDir ();
|
||||
}
|
||||
|
||||
void FilePanel::open (const Glib::ustring& d) {
|
||||
|
||||
if (Glib::file_test (d, Glib::FILE_TEST_IS_DIR))
|
||||
dirBrowser->open (d.c_str());
|
||||
else if (Glib::file_test (d, Glib::FILE_TEST_EXISTS))
|
||||
dirBrowser->open (Glib::path_get_dirname(d), Glib::path_get_basename(d));
|
||||
}
|
||||
|
||||
bool FilePanel::addBatchQueueJob (BatchQueueEntry* bqe) {
|
||||
|
||||
if (parent)
|
||||
parent->addBatchQueueJob (bqe);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FilePanel::optionsChanged () {
|
||||
|
||||
tpc->optionsChanged ();
|
||||
fileCatalog->refreshAll ();
|
||||
}
|
||||
74
rtgui/filepanel.h
Executable file
74
rtgui/filepanel.h
Executable file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _FILEPANEL_
|
||||
#define _FILEPANEL_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <batchtoolpanelcoord.h>
|
||||
#include <filecatalog.h>
|
||||
#include <dirbrowser.h>
|
||||
#include <fileselectionlistener.h>
|
||||
#include <placesbrowser.h>
|
||||
#include <recentbrowser.h>
|
||||
#include <pparamschangelistener.h>
|
||||
#include <history.h>
|
||||
#include <filterpanel.h>
|
||||
|
||||
class RTWindow;
|
||||
class FilePanel : public Gtk::HPaned,
|
||||
public FileSelectionListener,
|
||||
public PParamsChangeListener
|
||||
{
|
||||
|
||||
protected:
|
||||
Gtk::VPaned* placespaned;
|
||||
Gtk::HPaned* dirpaned;
|
||||
DirBrowser* dirBrowser;
|
||||
PlacesBrowser* placesBrowser;
|
||||
RecentBrowser* recentBrowser;
|
||||
FileCatalog* fileCatalog; // filecatalog is the file browser with the button bar above it
|
||||
Gtk::HBox* rightBox;
|
||||
BatchToolPanelCoordinator* tpc;
|
||||
History* history;
|
||||
FilterPanel* filterPanel;
|
||||
RTWindow* parent;
|
||||
Gtk::Notebook* rightNotebook;
|
||||
|
||||
public:
|
||||
FilePanel ();
|
||||
|
||||
void on_realize ();
|
||||
|
||||
void setParent (RTWindow* p) { parent = p; }
|
||||
void init (); // dont call it directly, the constructor calls it as idle source
|
||||
void open (const Glib::ustring& d); // open a file or a directory
|
||||
void refreshEditedState (const std::set<Glib::ustring>& efiles) { fileCatalog->refreshEditedState (efiles); }
|
||||
|
||||
// call this before closeing rt: it saves file browser relating things into options
|
||||
void saveOptions ();
|
||||
|
||||
// interface fileselectionlistener
|
||||
bool fileSelected (Thumbnail* thm);
|
||||
bool addBatchQueueJob (BatchQueueEntry* bqe);
|
||||
|
||||
void optionsChanged ();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
31
rtgui/fileselectionchangelistener.h
Executable file
31
rtgui/fileselectionchangelistener.h
Executable file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _FILESELECTIONCHANGELISTENER_
|
||||
#define _FILESELECTIONCHANGELISTENER_
|
||||
|
||||
#include <thumbnail.h>
|
||||
|
||||
class FileSelectionChangeListener {
|
||||
|
||||
public:
|
||||
virtual void selectionChanged (const std::vector<Thumbnail*>& selected) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
33
rtgui/fileselectionlistener.h
Executable file
33
rtgui/fileselectionlistener.h
Executable file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _FILESELECTIONLISTENER_
|
||||
#define _FILESELECTIONLISTENER_
|
||||
|
||||
#include <thumbnail.h>
|
||||
#include <batchqueueentry.h>
|
||||
|
||||
class FileSelectionListener {
|
||||
|
||||
public:
|
||||
virtual bool fileSelected (Thumbnail* thm) =0;
|
||||
virtual bool addBatchQueueJob (BatchQueueEntry* bqe) =0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
70
rtgui/filethumbnailbuttonset.cc
Executable file
70
rtgui/filethumbnailbuttonset.cc
Executable file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <filethumbnailbuttonset.h>
|
||||
#include <multilangmgr.h>
|
||||
|
||||
extern Glib::ustring argv0;
|
||||
|
||||
bool FileThumbnailButtonSet::iconsLoaded = false;
|
||||
|
||||
Cairo::RefPtr<Cairo::ImageSurface> FileThumbnailButtonSet::rankIcon;
|
||||
Cairo::RefPtr<Cairo::ImageSurface> FileThumbnailButtonSet::gRankIcon;
|
||||
Cairo::RefPtr<Cairo::ImageSurface> FileThumbnailButtonSet::unRankIcon;
|
||||
Cairo::RefPtr<Cairo::ImageSurface> FileThumbnailButtonSet::trashIcon;
|
||||
Cairo::RefPtr<Cairo::ImageSurface> FileThumbnailButtonSet::unTrashIcon;
|
||||
Cairo::RefPtr<Cairo::ImageSurface> FileThumbnailButtonSet::processIcon;
|
||||
|
||||
FileThumbnailButtonSet::FileThumbnailButtonSet (FileBrowserEntry* myEntry) {
|
||||
|
||||
if (!iconsLoaded) {
|
||||
try {
|
||||
unRankIcon = Cairo::ImageSurface::create_from_png (argv0+"/images/unrated.png");
|
||||
rankIcon = Cairo::ImageSurface::create_from_png (argv0+"/images/rated.png");
|
||||
gRankIcon = Cairo::ImageSurface::create_from_png (argv0+"/images/grayrated.png");
|
||||
trashIcon = Cairo::ImageSurface::create_from_png (argv0+"/images/trash.png");
|
||||
unTrashIcon = Cairo::ImageSurface::create_from_png (argv0+"/images/undelete.png");
|
||||
processIcon = Cairo::ImageSurface::create_from_png (argv0+"/images/processing.png");
|
||||
iconsLoaded = true;
|
||||
} catch (...) {}
|
||||
}
|
||||
|
||||
add (new LWButton (unRankIcon, 0, myEntry, LWButton::Left, LWButton::Center, M("FILEBROWSER_POPUPUNRANK")));
|
||||
for (int i=0; i<5; i++)
|
||||
add (new LWButton (rankIcon, i+1, myEntry, LWButton::Left));
|
||||
add (new LWButton (processIcon, 6, myEntry, LWButton::Right, LWButton::Center, M("FILEBROWSER_POPUPPROCESS")));
|
||||
add (new LWButton (trashIcon, 7, myEntry, LWButton::Right, LWButton::Center, M("FILEBROWSER_POPUPTRASH")));
|
||||
|
||||
buttons[1]->setToolTip (M("FILEBROWSER_POPUPRANK1"));
|
||||
buttons[2]->setToolTip (M("FILEBROWSER_POPUPRANK2"));
|
||||
buttons[3]->setToolTip (M("FILEBROWSER_POPUPRANK3"));
|
||||
buttons[4]->setToolTip (M("FILEBROWSER_POPUPRANK4"));
|
||||
buttons[5]->setToolTip (M("FILEBROWSER_POPUPRANK5"));
|
||||
}
|
||||
|
||||
void FileThumbnailButtonSet::setRank (int stars) {
|
||||
|
||||
for (int i=1; i<=5; i++)
|
||||
buttons[i]->setIcon (i<=stars ? rankIcon : gRankIcon);
|
||||
}
|
||||
|
||||
void FileThumbnailButtonSet::setInTrash (bool inTrash) {
|
||||
|
||||
buttons[7]->setIcon (inTrash ? unTrashIcon : trashIcon);
|
||||
buttons[7]->setToolTip (inTrash ? M("FILEBROWSER_POPUPUNTRASH") : M("FILEBROWSER_POPUPTRASH"));
|
||||
}
|
||||
45
rtgui/filethumbnailbuttonset.h
Executable file
45
rtgui/filethumbnailbuttonset.h
Executable file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _FILETHUMBNAILBUTTONSET_
|
||||
#define _FILETHUMBNAILBUTTONSET_
|
||||
|
||||
#include <lwbuttonset.h>
|
||||
#include <gtkmm.h>
|
||||
#include <filebrowserentry.h>
|
||||
|
||||
class FileBrowserEntry;
|
||||
class FileThumbnailButtonSet : public LWButtonSet {
|
||||
|
||||
static bool iconsLoaded;
|
||||
|
||||
public:
|
||||
static Cairo::RefPtr<Cairo::ImageSurface> rankIcon;
|
||||
static Cairo::RefPtr<Cairo::ImageSurface> gRankIcon;
|
||||
static Cairo::RefPtr<Cairo::ImageSurface> unRankIcon;
|
||||
static Cairo::RefPtr<Cairo::ImageSurface> trashIcon;
|
||||
static Cairo::RefPtr<Cairo::ImageSurface> unTrashIcon;
|
||||
static Cairo::RefPtr<Cairo::ImageSurface> processIcon;
|
||||
|
||||
FileThumbnailButtonSet (FileBrowserEntry* myEntry);
|
||||
void setRank (int stars);
|
||||
void setInTrash (bool inTrash);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
241
rtgui/filterpanel.cc
Executable file
241
rtgui/filterpanel.cc
Executable file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <filterpanel.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <rtengine.h>
|
||||
|
||||
using namespace rtengine;
|
||||
|
||||
FilterPanel::FilterPanel () : listener (NULL) {
|
||||
|
||||
set_border_width (4);
|
||||
|
||||
enabled = Gtk::manage (new Gtk::CheckButton ("Enable Metadata Filters"));
|
||||
pack_start (*enabled, Gtk::PACK_SHRINK, 2);
|
||||
pack_start (*Gtk::manage(new Gtk::HSeparator ()), Gtk::PACK_SHRINK, 2);
|
||||
|
||||
enaFNumber = Gtk::manage (new Gtk::CheckButton (M("EXIFFILTER_APERTURE")+":"));
|
||||
Gtk::VBox* fnvb = Gtk::manage(new Gtk::VBox ());
|
||||
Gtk::HBox* fnhb = Gtk::manage(new Gtk::HBox ());
|
||||
fnvb->pack_start (*enaFNumber, Gtk::PACK_SHRINK, 0);
|
||||
fnumberFrom = Gtk::manage(new Gtk::Entry ());
|
||||
fnumberTo = Gtk::manage(new Gtk::Entry ());
|
||||
fnhb->pack_start (*fnumberFrom, true, true, 2);
|
||||
fnhb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4);
|
||||
fnhb->pack_start (*fnumberTo, true, true, 2);
|
||||
fnvb->pack_start (*fnhb, Gtk::PACK_SHRINK, 0);
|
||||
pack_start (*fnvb, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
enaShutter = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_SHUTTER")+":"));
|
||||
Gtk::VBox* svb = Gtk::manage(new Gtk::VBox ());
|
||||
Gtk::HBox* shb = Gtk::manage(new Gtk::HBox ());
|
||||
svb->pack_start (*enaShutter, Gtk::PACK_SHRINK, 0);
|
||||
shutterFrom = Gtk::manage(new Gtk::Entry ());
|
||||
shutterTo = Gtk::manage(new Gtk::Entry ());
|
||||
shb->pack_start (*shutterFrom, true, true, 2);
|
||||
shb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4);
|
||||
shb->pack_start (*shutterTo, true, true, 2);
|
||||
svb->pack_start (*shb, Gtk::PACK_SHRINK, 0);
|
||||
pack_start (*svb, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
enaISO = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_ISO")+":"));
|
||||
Gtk::VBox* ivb = Gtk::manage(new Gtk::VBox ());
|
||||
Gtk::HBox* ihb = Gtk::manage(new Gtk::HBox ());
|
||||
ivb->pack_start (*enaISO, Gtk::PACK_SHRINK, 0);
|
||||
isoFrom = Gtk::manage(new Gtk::Entry ());
|
||||
isoTo = Gtk::manage(new Gtk::Entry ());
|
||||
ihb->pack_start (*isoFrom, true, true, 2);
|
||||
ihb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4);
|
||||
ihb->pack_start (*isoTo, true, true, 2);
|
||||
ivb->pack_start (*ihb, Gtk::PACK_SHRINK, 0);
|
||||
pack_start (*ivb, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
enaFocalLen = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_FOCALLEN")+":"));
|
||||
Gtk::VBox* fvb = Gtk::manage(new Gtk::VBox ());
|
||||
Gtk::HBox* fhb = Gtk::manage(new Gtk::HBox ());
|
||||
fvb->pack_start (*enaFocalLen, Gtk::PACK_SHRINK, 0);
|
||||
focalFrom = Gtk::manage(new Gtk::Entry ());
|
||||
focalTo = Gtk::manage(new Gtk::Entry ());
|
||||
fhb->pack_start (*focalFrom, true, true, 2);
|
||||
fhb->pack_start (*Gtk::manage(new Gtk::Label(" - ")), false, false, 4);
|
||||
fhb->pack_start (*focalTo, true, true, 2);
|
||||
fvb->pack_start (*fhb, Gtk::PACK_SHRINK, 0);
|
||||
pack_start (*fvb, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
enaCamera = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_CAMERA")+":"));
|
||||
Gtk::VBox* cvb = Gtk::manage(new Gtk::VBox ());
|
||||
cvb->pack_start (*enaCamera, Gtk::PACK_SHRINK, 0);
|
||||
camera = Gtk::manage(new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE));
|
||||
camera->set_headers_visible (false);
|
||||
Gtk::ScrolledWindow* scamera = Gtk::manage(new Gtk::ScrolledWindow());
|
||||
scamera->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
|
||||
scamera->add(*camera);
|
||||
cvb->pack_start (*scamera, Gtk::PACK_SHRINK, 0);
|
||||
pack_start (*cvb, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
enaLens = Gtk::manage(new Gtk::CheckButton(M("EXIFFILTER_LENS")+":"));
|
||||
Gtk::VBox* lvb = Gtk::manage(new Gtk::VBox ());
|
||||
lvb->pack_start (*enaLens, Gtk::PACK_SHRINK, 0);
|
||||
lens = Gtk::manage(new Gtk::ListViewText (1, false, Gtk::SELECTION_MULTIPLE));
|
||||
lens->set_headers_visible (false);
|
||||
Gtk::ScrolledWindow* slens = Gtk::manage(new Gtk::ScrolledWindow());
|
||||
slens->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS);
|
||||
slens->add(*lens);
|
||||
lvb->pack_start (*slens, Gtk::PACK_SHRINK, 0);
|
||||
pack_start (*lvb, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
conns = 0;
|
||||
sChange[conns++] = fnumberFrom->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged));
|
||||
sChange[conns++] = fnumberTo->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged));
|
||||
sChange[conns++] = shutterFrom->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged));
|
||||
sChange[conns++] = shutterTo->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged));
|
||||
sChange[conns++] = isoFrom->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged));
|
||||
sChange[conns++] = isoTo->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged));
|
||||
sChange[conns++] = focalFrom->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged));
|
||||
sChange[conns++] = focalTo->signal_changed().connect (sigc::mem_fun(*this, &FilterPanel::valueChanged));
|
||||
sChange[conns++] = camera->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &FilterPanel::valueChanged));
|
||||
sChange[conns++] = lens->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &FilterPanel::valueChanged));
|
||||
sChange[conns++] = enaFNumber->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) );
|
||||
sChange[conns++] = enaShutter->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) );
|
||||
sChange[conns++] = enaFocalLen->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) );
|
||||
sChange[conns++] = enaISO->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) );
|
||||
sChange[conns++] = enaCamera->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) );
|
||||
sChange[conns++] = enaLens->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) );
|
||||
sChange[conns++] = enabled->signal_toggled().connect( sigc::mem_fun(*this, &FilterPanel::valueChanged) );
|
||||
|
||||
set_size_request (0, -1);
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
void FilterPanel::setFilter (ExifFilterSettings& defefs, bool updateLists) {
|
||||
|
||||
|
||||
for (int i=0; i<conns; i++)
|
||||
sChange[i].block (true);
|
||||
|
||||
// enaFNumber->set_active (curefs.filterFNumber);
|
||||
fnumberFrom->set_text (ImageMetaData::apertureToString (defefs.fnumberFrom));
|
||||
curefs.fnumberFrom = defefs.fnumberFrom;
|
||||
fnumberTo->set_text (ImageMetaData::apertureToString (defefs.fnumberTo));
|
||||
curefs.fnumberTo = defefs.fnumberTo;
|
||||
|
||||
// enaShutter->set_active (curefs.filterShutter);
|
||||
shutterFrom->set_text (ImageMetaData::shutterToString (defefs.shutterFrom));
|
||||
curefs.shutterFrom = defefs.shutterFrom;
|
||||
shutterTo->set_text (ImageMetaData::shutterToString (defefs.shutterTo));
|
||||
curefs.shutterTo = defefs.shutterTo;
|
||||
|
||||
// enaISO->set_active (curefs.filterISO);
|
||||
isoFrom->set_text (Glib::ustring::format (defefs.isoFrom));
|
||||
curefs.isoFrom = defefs.isoFrom;
|
||||
isoTo->set_text (Glib::ustring::format (defefs.isoTo));
|
||||
curefs.isoTo = defefs.isoTo;
|
||||
|
||||
// enaFocalLen->set_active (curefs.filterFocalLen);
|
||||
focalFrom->set_text (Glib::ustring::format (defefs.focalFrom));
|
||||
curefs.focalFrom = defefs.focalFrom;
|
||||
focalTo->set_text (Glib::ustring::format (defefs.focalTo));
|
||||
curefs.focalTo = defefs.focalTo;
|
||||
|
||||
// enaCamera->set_active (curefs.filterCamera);
|
||||
Glib::RefPtr<Gtk::TreeSelection> cselection = camera->get_selection ();
|
||||
|
||||
// enaLens->set_active (curefs.filterLens);
|
||||
Glib::RefPtr<Gtk::TreeSelection> lselection = lens->get_selection ();
|
||||
if( updateLists ){
|
||||
lens->clear_items();
|
||||
curefs.lenses.clear();
|
||||
for (std::set<std::string>::iterator i = defefs.lenses.begin(); i!=defefs.lenses.end(); i++) {
|
||||
lens->append_text (*i);
|
||||
curefs.lenses.insert(*i);
|
||||
}
|
||||
lselection->select_all();
|
||||
|
||||
camera->clear_items();
|
||||
curefs.cameras.clear();
|
||||
for (std::set<std::string>::iterator i = defefs.cameras.begin(); i!=defefs.cameras.end(); i++) {
|
||||
camera->append_text(*i);
|
||||
curefs.cameras.insert(*i);
|
||||
}
|
||||
cselection->select_all();
|
||||
}else{
|
||||
for( Gtk::TreeModel::Children::iterator iter = lens->get_model()->children().begin(); iter != lens->get_model()->children().end();iter++){
|
||||
Glib::ustring v;
|
||||
iter->get_value(0,v);
|
||||
if( defefs.lenses.find( v ) != defefs.lenses.end() )
|
||||
lselection->select( iter );
|
||||
else
|
||||
lselection->unselect( iter );
|
||||
}
|
||||
for( Gtk::TreeModel::Children::iterator iter = camera->get_model()->children().begin(); iter != camera->get_model()->children().end();iter++){
|
||||
Glib::ustring v;
|
||||
iter->get_value(0,v);
|
||||
if( defefs.cameras.find( v ) != defefs.cameras.end() )
|
||||
cselection->select(iter);
|
||||
else
|
||||
cselection->unselect(iter);
|
||||
}
|
||||
}
|
||||
|
||||
curefs = defefs;
|
||||
|
||||
for (int i=0; i<conns; i++)
|
||||
sChange[i].block (false);
|
||||
}
|
||||
|
||||
bool FilterPanel::isEnabled () {
|
||||
|
||||
return enabled->get_active () && is_sensitive();
|
||||
}
|
||||
|
||||
ExifFilterSettings FilterPanel::getFilter () {
|
||||
|
||||
ExifFilterSettings efs;
|
||||
efs.fnumberFrom = atof (fnumberFrom->get_text().c_str());
|
||||
efs.fnumberTo = atof (fnumberTo->get_text().c_str());
|
||||
efs.focalFrom = atof (focalFrom->get_text().c_str());
|
||||
efs.focalTo = atof (focalTo->get_text().c_str());
|
||||
efs.isoFrom = atoi (isoFrom->get_text().c_str());
|
||||
efs.isoTo = atoi (isoTo->get_text().c_str());
|
||||
efs.shutterFrom = ImageMetaData::shutterFromString (shutterFrom->get_text());
|
||||
efs.shutterTo = ImageMetaData::shutterFromString (shutterTo->get_text());
|
||||
|
||||
efs.filterFNumber = enaFNumber->get_active ();
|
||||
efs.filterShutter = enaShutter->get_active ();
|
||||
efs.filterFocalLen = enaFocalLen->get_active ();
|
||||
efs.filterISO = enaISO->get_active ();
|
||||
efs.filterCamera = enaCamera->get_active ();
|
||||
efs.filterLens = enaLens->get_active ();
|
||||
|
||||
std::vector<int> sel = camera->get_selected ();
|
||||
for (int i=0; i<sel.size(); i++)
|
||||
efs.cameras.insert (camera->get_text (sel[i]));
|
||||
sel = lens->get_selected ();
|
||||
for (int i=0; i<sel.size(); i++)
|
||||
efs.lenses.insert (lens->get_text (sel[i]));
|
||||
|
||||
return efs;
|
||||
}
|
||||
|
||||
void FilterPanel::valueChanged () {
|
||||
|
||||
if (listener)
|
||||
listener->exifFilterChanged ();
|
||||
}
|
||||
71
rtgui/filterpanel.h
Executable file
71
rtgui/filterpanel.h
Executable file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _FILTERPANEL_
|
||||
#define _FILTERPANEL_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <exiffiltersettings.h>
|
||||
|
||||
class FilterPanelListener {
|
||||
|
||||
public:
|
||||
virtual void exifFilterChanged () {}
|
||||
};
|
||||
|
||||
class FilterPanel : public Gtk::VBox {
|
||||
|
||||
protected:
|
||||
Gtk::ListViewText* camera;
|
||||
Gtk::ListViewText* lens;
|
||||
Gtk::Entry* fnumberFrom;
|
||||
Gtk::Entry* fnumberTo;
|
||||
Gtk::Entry* shutterFrom;
|
||||
Gtk::Entry* shutterTo;
|
||||
Gtk::Entry* focalFrom;
|
||||
Gtk::Entry* focalTo;
|
||||
Gtk::Entry* isoFrom;
|
||||
Gtk::Entry* isoTo;
|
||||
Gtk::CheckButton* enabled;
|
||||
Gtk::CheckButton* enaFNumber;
|
||||
Gtk::CheckButton* enaShutter;
|
||||
Gtk::CheckButton* enaFocalLen;
|
||||
Gtk::CheckButton* enaISO;
|
||||
Gtk::CheckButton* enaCamera;
|
||||
Gtk::CheckButton* enaLens;
|
||||
|
||||
int conns;
|
||||
sigc::connection sChange[20];
|
||||
|
||||
ExifFilterSettings curefs;
|
||||
FilterPanelListener* listener;
|
||||
|
||||
public:
|
||||
FilterPanel ();
|
||||
|
||||
void setFilterPanelListener (FilterPanelListener* l) { listener = l; }
|
||||
|
||||
void setFilter (ExifFilterSettings& defefs, bool updateLists);
|
||||
ExifFilterSettings getFilter ();
|
||||
bool isEnabled ();
|
||||
|
||||
|
||||
void valueChanged ();
|
||||
};
|
||||
|
||||
#endif
|
||||
196
rtgui/guiutils.cc
Executable file
196
rtgui/guiutils.cc
Executable file
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <guiutils.h>
|
||||
#include <options.h>
|
||||
#include <utils.h>
|
||||
|
||||
bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference) {
|
||||
|
||||
Glib::ListHandle<Gtk::Widget*> list = cont->get_children ();
|
||||
Glib::ListHandle<Gtk::Widget*>::iterator i = list.begin ();
|
||||
for (; i!=list.end() && *i!=w; i++);
|
||||
if (i!=list.end()) {
|
||||
if (increference)
|
||||
w->reference ();
|
||||
cont->remove (*w);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void thumbInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh) {
|
||||
|
||||
if (options.thumbInterp==0)
|
||||
rtengine::nearestInterp (src, sw, sh, dst, dw, dh);
|
||||
else if (options.thumbInterp==1)
|
||||
rtengine::bilinearInterp (src, sw, sh, dst, dw, dh);
|
||||
}
|
||||
|
||||
Glib::ustring removeExtension (const Glib::ustring& filename) {
|
||||
|
||||
Glib::ustring bname = Glib::path_get_basename(filename);
|
||||
int lastdot = bname.find_last_of ('.');
|
||||
if (lastdot!=bname.npos)
|
||||
return filename.substr (0, filename.size()-(bname.size()-lastdot));
|
||||
else
|
||||
return filename;
|
||||
}
|
||||
|
||||
Glib::ustring getExtension (const Glib::ustring& filename) {
|
||||
|
||||
Glib::ustring bname = Glib::path_get_basename(filename);
|
||||
int lastdot = bname.find_last_of ('.');
|
||||
if (lastdot!=bname.npos)
|
||||
return filename.substr (filename.size()-(bname.size()-lastdot)+1, filename.npos);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
void drawCrop (Cairo::RefPtr<Cairo::Context> cr, int imx, int imy, int imw, int imh, int startx, int starty, double scale, const rtengine::procparams::CropParams& cparams) {
|
||||
|
||||
cr->set_line_width (1.0);
|
||||
cr->rectangle (imx+0.5, imy+0.5, imw, imh);
|
||||
cr->clip ();
|
||||
|
||||
double c1x = (cparams.x-startx)*scale;
|
||||
double c1y = (cparams.y-starty)*scale;
|
||||
double c2x = (cparams.x+cparams.w-1-startx)*scale;
|
||||
double c2y = (cparams.y+cparams.h-1-starty)*scale;
|
||||
|
||||
cr->set_source_rgba (0, 0, 0, 2.0/3.0);
|
||||
cr->rectangle (imx+0.5, imy+0.5, imw, c1y);
|
||||
cr->rectangle (imx+0.5, imy+0.5+c2y, imw, imh-c2y);
|
||||
cr->rectangle (imx+0.5, imy+0.5+c1y, c1x, c2y-c1y+1);
|
||||
cr->rectangle (imx+0.5+c2x, imy+0.5+c1y, imw-c2x, c2y-c1y+1);
|
||||
cr->fill ();
|
||||
|
||||
// rectangle around the cropped area and guides
|
||||
if (cparams.guide!="None") {
|
||||
double rectx1 = c1x + imx + 0.5;
|
||||
double recty1 = c1y + imy + 0.5;
|
||||
double rectx2 = c2x + imx + 0.5;
|
||||
double recty2 = c2y + imy + 0.5;
|
||||
cr->set_line_width (1.0);
|
||||
cr->set_source_rgb (1.0, 1.0, 1.0);
|
||||
cr->move_to (rectx1, recty1);
|
||||
cr->line_to (rectx2, recty1);
|
||||
cr->line_to (rectx2, recty2);
|
||||
cr->line_to (rectx1, recty2);
|
||||
cr->line_to (rectx1, recty1);
|
||||
cr->stroke ();
|
||||
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||
std::valarray<double> ds (1);
|
||||
ds[0] = 4;
|
||||
cr->set_dash (ds, 0);
|
||||
cr->move_to (rectx1, recty1);
|
||||
cr->line_to (rectx2, recty1);
|
||||
cr->line_to (rectx2, recty2);
|
||||
cr->line_to (rectx1, recty2);
|
||||
cr->line_to (rectx1, recty1);
|
||||
cr->stroke ();
|
||||
ds.resize (0);
|
||||
cr->set_dash (ds, 0);
|
||||
|
||||
if (cparams.guide!="Rule of diagonals") {
|
||||
// draw guide lines
|
||||
std::vector<double> horiz_ratios;
|
||||
std::vector<double> vert_ratios;
|
||||
|
||||
if (cparams.guide=="Rule of thirds") {
|
||||
horiz_ratios.push_back (1.0/3.0);
|
||||
horiz_ratios.push_back (2.0/3.0);
|
||||
vert_ratios.push_back (1.0/3.0);
|
||||
vert_ratios.push_back (2.0/3.0);
|
||||
}
|
||||
else if (cparams.guide=="Harmonic means 1") {
|
||||
horiz_ratios.push_back (1.0-0.618);
|
||||
vert_ratios.push_back (1.0-0.618);
|
||||
}
|
||||
else if (cparams.guide=="Harmonic means 2") {
|
||||
horiz_ratios.push_back (0.618);
|
||||
vert_ratios.push_back (1.0-0.618);
|
||||
}
|
||||
else if (cparams.guide=="Harmonic means 3") {
|
||||
horiz_ratios.push_back (1.0-0.618);
|
||||
vert_ratios.push_back (0.618);
|
||||
}
|
||||
else if (cparams.guide=="Harmonic means 4") {
|
||||
horiz_ratios.push_back (0.618);
|
||||
vert_ratios.push_back (0.618);
|
||||
}
|
||||
for (int i=0; i<vert_ratios.size(); i++) {
|
||||
cr->set_source_rgb (1.0, 1.0, 1.0);
|
||||
cr->move_to (rectx1 + (rectx2-rectx1) * vert_ratios[i], recty1);
|
||||
cr->line_to (rectx1 + (rectx2-rectx1) * vert_ratios[i], recty2);
|
||||
cr->move_to (rectx1, recty1 + (recty2-recty1) * horiz_ratios[i]);
|
||||
cr->line_to (rectx2, recty1 + (recty2-recty1) * horiz_ratios[i]);
|
||||
cr->stroke ();
|
||||
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||
std::valarray<double> ds (1);
|
||||
ds[0] = 4;
|
||||
cr->set_dash (ds, 0);
|
||||
cr->move_to (rectx1 + (rectx2-rectx1) * vert_ratios[i], recty1);
|
||||
cr->line_to (rectx1 + (rectx2-rectx1) * vert_ratios[i], recty2);
|
||||
cr->move_to (rectx1, recty1 + (recty2-recty1) * horiz_ratios[i]);
|
||||
cr->line_to (rectx2, recty1 + (recty2-recty1) * horiz_ratios[i]);
|
||||
cr->stroke ();
|
||||
ds.resize (0);
|
||||
cr->set_dash (ds, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int corners_from[4][2];
|
||||
int corners_to[4][2];
|
||||
int mindim = MIN (rectx2-rectx1+1, recty2-recty1+1);
|
||||
corners_from[0][0] = rectx1;
|
||||
corners_from[0][1] = recty1;
|
||||
corners_to[0][0] = rectx1 + mindim;
|
||||
corners_to[0][1] = recty1 + mindim;
|
||||
corners_from[1][0] = rectx1;
|
||||
corners_from[1][1] = recty2;
|
||||
corners_to[1][0] = rectx1 + mindim;
|
||||
corners_to[1][1] = recty2 - mindim;
|
||||
corners_from[2][0] = rectx2;
|
||||
corners_from[2][1] = recty1;
|
||||
corners_to[2][0] = rectx2 - mindim;
|
||||
corners_to[2][1] = recty1 + mindim;
|
||||
corners_from[3][0] = rectx2;
|
||||
corners_from[3][1] = recty2;
|
||||
corners_to[3][0] = rectx2 - mindim;
|
||||
corners_to[3][1] = recty2 - mindim;
|
||||
for (int i=0; i<4; i++) {
|
||||
cr->set_source_rgb (1.0, 1.0, 1.0);
|
||||
cr->move_to (corners_from[i][0], corners_from[i][1]);
|
||||
cr->line_to (corners_to[i][0], corners_to[i][1]);
|
||||
cr->stroke ();
|
||||
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||
std::valarray<double> ds (1);
|
||||
ds[0] = 4;
|
||||
cr->set_dash (ds, 0);
|
||||
cr->move_to (corners_from[i][0], corners_from[i][1]);
|
||||
cr->line_to (corners_to[i][0], corners_to[i][1]);
|
||||
cr->stroke ();
|
||||
ds.resize (0);
|
||||
cr->set_dash (ds, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
cr->reset_clip ();
|
||||
}
|
||||
31
rtgui/guiutils.h
Executable file
31
rtgui/guiutils.h
Executable file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 __UTILS_
|
||||
#define __UTILS_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <rtengine.h>
|
||||
|
||||
bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference=true);
|
||||
void thumbInterp (const unsigned char* src, int sw, int sh, unsigned char* dst, int dw, int dh);
|
||||
Glib::ustring removeExtension (const Glib::ustring& filename);
|
||||
Glib::ustring getExtension (const Glib::ustring& filename);
|
||||
void drawCrop (Cairo::RefPtr<Cairo::Context> cr, int imx, int imy, int imw, int imh, int startx, int starty, double scale, const rtengine::procparams::CropParams& cparams);
|
||||
|
||||
#endif
|
||||
466
rtgui/histogrampanel.cc
Executable file
466
rtgui/histogrampanel.cc
Executable file
@@ -0,0 +1,466 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <histogrampanel.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <string.h>
|
||||
|
||||
HistogramPanel::HistogramPanel () {
|
||||
|
||||
histogramArea = Gtk::manage (new HistogramArea ());
|
||||
showRed = Gtk::manage (new Gtk::ToggleButton ("R"));
|
||||
showGreen = Gtk::manage (new Gtk::ToggleButton ("G"));
|
||||
showBlue = Gtk::manage (new Gtk::ToggleButton ("B"));
|
||||
showValue = Gtk::manage (new Gtk::ToggleButton ("L"));
|
||||
Gtk::VBox* vbox = Gtk::manage (new Gtk::VBox (false, 0));
|
||||
|
||||
showRed->set_active (true);
|
||||
showGreen->set_active (true);
|
||||
showBlue->set_active (true);
|
||||
showValue->set_active (true);
|
||||
vbox->pack_start (*showRed, Gtk::PACK_SHRINK, 2);
|
||||
vbox->pack_start (*showGreen, Gtk::PACK_SHRINK, 2);
|
||||
vbox->pack_start (*showBlue, Gtk::PACK_SHRINK, 2);
|
||||
vbox->pack_start (*showValue, Gtk::PACK_SHRINK, 2);
|
||||
pack_start (*histogramArea);
|
||||
pack_end (*vbox, Gtk::PACK_SHRINK, 2);
|
||||
|
||||
showRed->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::rgbv_toggled) );
|
||||
showGreen->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::rgbv_toggled) );
|
||||
showBlue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::rgbv_toggled) );
|
||||
showValue->signal_toggled().connect( sigc::mem_fun(*this, &HistogramPanel::rgbv_toggled) );
|
||||
|
||||
show_all ();
|
||||
|
||||
showRed->set_tooltip_text (M("HISTOGRAM_TOOLTIP_R"));
|
||||
showGreen->set_tooltip_text (M("HISTOGRAM_TOOLTIP_G"));
|
||||
showBlue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_B"));
|
||||
showValue->set_tooltip_text (M("HISTOGRAM_TOOLTIP_L"));
|
||||
|
||||
rconn = signal_size_allocate().connect( sigc::mem_fun(*this, &HistogramPanel::resized) );
|
||||
}
|
||||
|
||||
void HistogramPanel::resized (Gtk::Allocation& req) {
|
||||
|
||||
rconn.block (true);
|
||||
|
||||
if (req.get_width()/2>150)
|
||||
set_size_request (req.get_width(), 150);
|
||||
else
|
||||
set_size_request (req.get_width(), req.get_width()/2);
|
||||
rconn.block (false);
|
||||
histogramArea->renderHistogram ();
|
||||
histogramArea->queue_draw ();
|
||||
}
|
||||
|
||||
void HistogramPanel::rgbv_toggled () {
|
||||
|
||||
histogramArea->updateOptions (showRed->get_active(), showGreen->get_active(), showBlue->get_active(), showValue->get_active());
|
||||
histogramArea->queue_draw ();
|
||||
}
|
||||
|
||||
HistogramArea::HistogramArea () :
|
||||
needVal(true), needRed(true), needGreen(true), needBlue(true), oldwidth(-1), valid(false), showFull(true) {
|
||||
|
||||
haih = new HistogramAreaIdleHelper;
|
||||
haih->harea = this;
|
||||
haih->destroyed = false;
|
||||
haih->pending = 0;
|
||||
|
||||
signal_style_changed().connect( sigc::mem_fun(*this, &HistogramArea::styleChanged) );
|
||||
}
|
||||
|
||||
HistogramArea::~HistogramArea () {
|
||||
|
||||
if (haih->pending)
|
||||
haih->destroyed = true;
|
||||
else
|
||||
delete haih;
|
||||
}
|
||||
|
||||
void HistogramArea::updateOptions (bool r, bool g, bool b, bool v) {
|
||||
|
||||
needRed = r;
|
||||
needGreen = g;
|
||||
needBlue = b;
|
||||
needVal = v;
|
||||
|
||||
renderHistogram ();
|
||||
}
|
||||
|
||||
int histupdate (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
|
||||
HistogramAreaIdleHelper* haih = (HistogramAreaIdleHelper*)data;
|
||||
|
||||
if (haih->destroyed) {
|
||||
if (haih->pending == 1)
|
||||
delete haih;
|
||||
else
|
||||
haih->pending--;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
haih->harea->renderHistogram ();
|
||||
haih->harea->queue_draw ();
|
||||
|
||||
haih->pending--;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void HistogramArea::update (unsigned int* rh, unsigned int* gh, unsigned int* bh, unsigned int* lh) {
|
||||
|
||||
if (rh!=NULL) {
|
||||
memcpy (lhist, lh, 256*sizeof(unsigned int));
|
||||
memcpy (rhist, rh, 256*sizeof(unsigned int));
|
||||
memcpy (ghist, gh, 256*sizeof(unsigned int));
|
||||
memcpy (bhist, bh, 256*sizeof(unsigned int));
|
||||
valid = true;
|
||||
}
|
||||
else
|
||||
valid = false;
|
||||
|
||||
haih->pending++;
|
||||
g_idle_add (histupdate, haih);
|
||||
}
|
||||
|
||||
void HistogramArea::renderHistogram () {
|
||||
|
||||
if (!is_realized ())
|
||||
return;
|
||||
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
int winx, winy, winw, winh, wind;
|
||||
window->get_geometry(winx, winy, winw, winh, wind);
|
||||
|
||||
backBuffer = Gdk::Pixmap::create (window, winw, winh, -1);
|
||||
|
||||
Glib::RefPtr<Gdk::GC> bgc = Gdk::GC::create(backBuffer);
|
||||
|
||||
bgc->set_foreground (white);
|
||||
backBuffer->draw_rectangle (bgc, true, 0, 0, winw, winh);
|
||||
|
||||
if (valid) {
|
||||
|
||||
// compute height of the full histogram (realheight) and
|
||||
|
||||
int fullhistheight = 0;
|
||||
for (int i=0; i<256; i++) {
|
||||
if (needVal && lhist[i]>fullhistheight)
|
||||
fullhistheight = lhist[i];
|
||||
if (needRed && rhist[i]>fullhistheight)
|
||||
fullhistheight = rhist[i];
|
||||
if (needGreen && ghist[i]>fullhistheight)
|
||||
fullhistheight = ghist[i];
|
||||
if (needBlue && bhist[i]>fullhistheight)
|
||||
fullhistheight = bhist[i];
|
||||
}
|
||||
|
||||
// compute two hights, one for the magnified view and one for the threshold
|
||||
int realhistheight = fullhistheight;
|
||||
|
||||
if (!showFull) {
|
||||
int area1thres = 0;
|
||||
int area2thres = 0;
|
||||
int area = 0;
|
||||
for (int i=0; i<fullhistheight; i++) {
|
||||
for (int j=0; j<256; j++)
|
||||
if ((needVal && lhist[j]>i) || (needRed && rhist[j]>i) || (needGreen && ghist[j]>i) || (needBlue && bhist[j]>i))
|
||||
area++;
|
||||
if (area1thres==0 && (double)area / (256*(i+1)) < 0.3)
|
||||
area1thres = i;
|
||||
if (area2thres==0 && (double)area / (256*(i+1)) < 0.3)
|
||||
area2thres = i;
|
||||
if (area1thres && area2thres)
|
||||
break;
|
||||
}
|
||||
if (area1thres>0 && area2thres>0 && area1thres<fullhistheight)
|
||||
realhistheight = area2thres;
|
||||
}
|
||||
|
||||
if (realhistheight<winh-2)
|
||||
realhistheight = winh-2;
|
||||
|
||||
Cairo::RefPtr<Cairo::Context> cr = backBuffer->create_cairo_context();
|
||||
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||
cr->set_line_width (1.0);
|
||||
double stepSize = (winw-1) / 256.0;
|
||||
if (needVal) {
|
||||
cr->move_to (0, winh-1);
|
||||
cr->set_source_rgb (0.75, 0.75, 0.75);
|
||||
for (int i=0; i<256; i++) {
|
||||
double val = lhist[i] * (double)(winh-2) / realhistheight;
|
||||
if (val>winh-1)
|
||||
val = winh-1;
|
||||
if (i>0)
|
||||
cr->line_to (i*stepSize, winh-1-val);
|
||||
}
|
||||
cr->save ();
|
||||
cr->line_to (winw-1, winh-1);
|
||||
cr->fill_preserve ();
|
||||
cr->restore ();
|
||||
cr->set_source_rgb (0.5, 0.5, 0.5);
|
||||
cr->stroke ();
|
||||
}
|
||||
if (needRed) {
|
||||
cr->move_to (0, winh-1);
|
||||
cr->set_source_rgb (1.0, 0.0, 0.0);
|
||||
for (int i=0; i<256; i++) {
|
||||
double val = rhist[i] * (double)(winh-2) / realhistheight;
|
||||
if (val>winh-1)
|
||||
val = winh-1;
|
||||
if (i>0)
|
||||
cr->line_to (i*stepSize, winh-1-val);
|
||||
}
|
||||
cr->stroke ();
|
||||
}
|
||||
if (needGreen) {
|
||||
cr->move_to (0, winh-1);
|
||||
cr->set_source_rgb (0.0, 1.0, 0.0);
|
||||
for (int i=0; i<256; i++) {
|
||||
double val = ghist[i] * (double)(winh-2) / realhistheight;
|
||||
if (val>winh-1)
|
||||
val = winh-1;
|
||||
if (i>0)
|
||||
cr->line_to (i*stepSize, winh-1-val);
|
||||
}
|
||||
cr->stroke ();
|
||||
}
|
||||
if (needBlue) {
|
||||
cr->move_to (0, winh-1);
|
||||
cr->set_source_rgb (0.0, 0.0, 1.0);
|
||||
for (int i=0; i<256; i++) {
|
||||
int val = bhist[i] * (double)(winh-2) / realhistheight;
|
||||
if (val>winh-1)
|
||||
val = winh-1;
|
||||
if (i>0)
|
||||
cr->line_to (i*stepSize, winh-1-val);
|
||||
}
|
||||
cr->stroke ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
// scale histogram to width winw-1
|
||||
|
||||
int* vval = new int[winw-1];
|
||||
int* vred = new int[winw-1];
|
||||
int* vgreen = new int[winw-1];
|
||||
int* vblue = new int[winw-1];
|
||||
|
||||
memset (vval, 0, sizeof(int)*(winw-1));
|
||||
memset (vred, 0, sizeof(int)*(winw-1));
|
||||
memset (vgreen, 0, sizeof(int)*(winw-1));
|
||||
memset (vblue, 0, sizeof(int)*(winw-1));
|
||||
|
||||
int index = 0;
|
||||
double scale = 256.0 / (winw-2);
|
||||
for (int i=0; i<=winw-2; i++) {
|
||||
int samples = 0;
|
||||
while (index < 256 && (int)(index/scale) == i) {
|
||||
vval[i] += lhist[index];
|
||||
vred[i] += rhist[index];
|
||||
vgreen[i] += ghist[index];
|
||||
vblue[i] += bhist[index];
|
||||
index++;
|
||||
samples++;
|
||||
}
|
||||
if (samples>0) {
|
||||
vval[i] /= samples;
|
||||
vred[i] /= samples;
|
||||
vgreen[i] /= samples;
|
||||
vblue[i] /= samples;
|
||||
}
|
||||
}
|
||||
|
||||
// compute height of the full histogram (realheight) and
|
||||
|
||||
int fullhistheight = 0;
|
||||
for (int i=0; i<=winw-2; i++) {
|
||||
if (needVal && vval[i]>fullhistheight)
|
||||
fullhistheight = vval[i];
|
||||
if (needRed && vred[i]>fullhistheight)
|
||||
fullhistheight = vred[i];
|
||||
if (needGreen && vgreen[i]>fullhistheight)
|
||||
fullhistheight = vgreen[i];
|
||||
if (needBlue && vblue[i]>fullhistheight)
|
||||
fullhistheight = vblue[i];
|
||||
}
|
||||
|
||||
// compute two hights, one for the magnified view and one for the threshold
|
||||
|
||||
int realhistheight = fullhistheight;
|
||||
|
||||
if (!showFull) {
|
||||
int area1thres = 0;
|
||||
int area2thres = 0;
|
||||
int area = 0;
|
||||
for (int i=0; i<fullhistheight; i++) {
|
||||
for (int j=0; j<winw-1; j++)
|
||||
if ((needVal && vval[j]>i) || (needRed && vred[j]>i) || (needGreen && vgreen[j]>i) || (needBlue && vblue[j]>i))
|
||||
area++;
|
||||
if (area1thres==0 && (double)area / ((winw-1)*(i+1)) < 0.3)
|
||||
area1thres = i;
|
||||
if (area2thres==0 && (double)area / ((winw-1)*(i+1)) < 0.3)
|
||||
area2thres = i;
|
||||
if (area1thres && area2thres)
|
||||
break;
|
||||
}
|
||||
if (area1thres>0 && area2thres>0 && area1thres<fullhistheight)
|
||||
realhistheight = area2thres;
|
||||
}
|
||||
|
||||
if (realhistheight<winh-2)
|
||||
realhistheight = winh-2;
|
||||
|
||||
Cairo::RefPtr<Cairo::Context> cr = backBuffer->create_cairo_context();
|
||||
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||
cr->set_line_width (1.0);
|
||||
if (needVal) {
|
||||
cr->move_to (0, winh-1);
|
||||
cr->set_source_rgb (0.75, 0.75, 0.75);
|
||||
for (int i=0; i<=winw-2; i++) {
|
||||
int val = (int)(vval[i] * (double)(winh-2) / realhistheight);
|
||||
if (val>winh-1)
|
||||
val = winh-1;
|
||||
if (i>0)
|
||||
cr->line_to (i+1, winh-1-val);
|
||||
}
|
||||
cr->fill_preserve ();
|
||||
cr->set_source_rgb (0.5, 0.5, 0.5);
|
||||
cr->stroke ();
|
||||
}
|
||||
if (needRed) {
|
||||
cr->move_to (0, winh-1);
|
||||
cr->set_source_rgb (1.0, 0.0, 0.0);
|
||||
for (int i=0; i<=winw-2; i++) {
|
||||
int val = (int)(vred[i] * (double)(winh-2) / realhistheight);
|
||||
if (val>winh-1)
|
||||
val = winh-1;
|
||||
if (i>0)
|
||||
cr->line_to (i+1, winh-1-val);
|
||||
}
|
||||
cr->stroke ();
|
||||
}
|
||||
if (needGreen) {
|
||||
cr->move_to (0, winh-1);
|
||||
cr->set_source_rgb (0.0, 1.0, 0.0);
|
||||
for (int i=0; i<=winw-2; i++) {
|
||||
int val = (int)(vgreen[i] * (double)(winh-2) / realhistheight);
|
||||
if (val>winh-1)
|
||||
val = winh-1;
|
||||
if (i>0)
|
||||
cr->line_to (i+1, winh-1-val);
|
||||
}
|
||||
cr->stroke ();
|
||||
}
|
||||
if (needBlue) {
|
||||
cr->move_to (0, winh-1);
|
||||
cr->set_source_rgb (0.0, 0.0, 1.0);
|
||||
for (int i=0; i<=winw-2; i++) {
|
||||
int val = (int)(vblue[i] * (double)(winh-2) / realhistheight);
|
||||
if (val>winh-1)
|
||||
val = winh-1;
|
||||
if (i>0)
|
||||
cr->line_to (i+1, winh-1-val);
|
||||
}
|
||||
cr->stroke ();
|
||||
}
|
||||
|
||||
delete [] vval;
|
||||
delete [] vred;
|
||||
delete [] vgreen;
|
||||
delete [] vblue;
|
||||
}
|
||||
*/
|
||||
bgc->set_foreground (mgray);
|
||||
backBuffer->draw_rectangle (bgc, false, 0, 0, winw-1, winh-1);
|
||||
|
||||
bgc->set_line_attributes (1, Gdk::LINE_ON_OFF_DASH, Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER);
|
||||
|
||||
backBuffer->draw_line (bgc, winw/3, 0, winw/3, winh-1);
|
||||
backBuffer->draw_line (bgc, 2*winw/3, 0, 2*winw/3, winh-1);
|
||||
backBuffer->draw_line (bgc, 0, winh/3, winw-1, winh/3);
|
||||
backBuffer->draw_line (bgc, 0, 2*winh/3, winw-1, 2*winh/3);
|
||||
|
||||
bgc->set_line_attributes (1, Gdk::LINE_SOLID, Gdk::CAP_NOT_LAST, Gdk::JOIN_MITER);
|
||||
|
||||
oldwidth = winw;
|
||||
oldheight = winh;
|
||||
}
|
||||
|
||||
void HistogramArea::on_realize () {
|
||||
|
||||
Gtk::DrawingArea::on_realize();
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
gc_ = Gdk::GC::create(window);
|
||||
add_events(Gdk::EXPOSURE_MASK | Gdk::BUTTON_PRESS_MASK);
|
||||
Glib::RefPtr<Gdk::Colormap> colormap = get_default_colormap();
|
||||
|
||||
black = Gdk::Color ("black");
|
||||
red = Gdk::Color ("red");
|
||||
green = Gdk::Color ("green");
|
||||
blue = Gdk::Color ("blue");
|
||||
lgray = Gdk::Color ("gray75");
|
||||
mgray = Gdk::Color ("gray50");
|
||||
dgray = Gdk::Color ("gray25");
|
||||
colormap->alloc_color(black);
|
||||
colormap->alloc_color(white);
|
||||
colormap->alloc_color(red);
|
||||
colormap->alloc_color(green);
|
||||
colormap->alloc_color(blue);
|
||||
colormap->alloc_color(lgray);
|
||||
colormap->alloc_color(mgray);
|
||||
colormap->alloc_color(dgray);
|
||||
|
||||
}
|
||||
|
||||
void HistogramArea::styleChanged (const Glib::RefPtr<Gtk::Style>& style) {
|
||||
|
||||
white = get_style()->get_base(Gtk::STATE_NORMAL);
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
bool HistogramArea::on_expose_event(GdkEventExpose* event) {
|
||||
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
|
||||
int winx, winy, winw, winh, wind;
|
||||
window->get_geometry(winx, winy, winw, winh, wind);
|
||||
|
||||
if (winw!=oldwidth && winh!=oldheight)
|
||||
renderHistogram ();
|
||||
window->draw_drawable (gc_, backBuffer, 0, 0, 0, 0, -1, -1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool HistogramArea::on_button_press_event (GdkEventButton* event) {
|
||||
|
||||
if (event->type==GDK_2BUTTON_PRESS && event->button==1) {
|
||||
showFull = !showFull;
|
||||
renderHistogram ();
|
||||
queue_draw ();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
97
rtgui/histogrampanel.h
Executable file
97
rtgui/histogrampanel.h
Executable file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _HISTOGRAMPANEL_
|
||||
#define _HISTOGRAMPANEL_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <glibmm.h>
|
||||
|
||||
class HistogramArea;
|
||||
struct HistogramAreaIdleHelper {
|
||||
HistogramArea* harea;
|
||||
bool destroyed;
|
||||
int pending;
|
||||
};
|
||||
|
||||
class HistogramArea : public Gtk::DrawingArea {
|
||||
|
||||
protected:
|
||||
|
||||
Glib::RefPtr<Gdk::GC> gc_;
|
||||
Glib::RefPtr<Gdk::Pixmap> backBuffer;
|
||||
|
||||
Gdk::Color black;
|
||||
Gdk::Color white;
|
||||
Gdk::Color red;
|
||||
Gdk::Color green;
|
||||
Gdk::Color blue;
|
||||
Gdk::Color lgray;
|
||||
Gdk::Color mgray;
|
||||
Gdk::Color dgray;
|
||||
unsigned int lhist[256];
|
||||
unsigned int rhist[256];
|
||||
unsigned int ghist[256];
|
||||
unsigned int bhist[256];
|
||||
bool valid;
|
||||
bool showFull;
|
||||
int oldwidth, oldheight;
|
||||
|
||||
bool needVal;
|
||||
bool needRed;
|
||||
bool needGreen;
|
||||
bool needBlue;
|
||||
|
||||
HistogramAreaIdleHelper* haih;
|
||||
|
||||
public:
|
||||
|
||||
HistogramArea();
|
||||
~HistogramArea();
|
||||
|
||||
void renderHistogram ();
|
||||
void update (unsigned int* rh, unsigned int* gh, unsigned int* bh, unsigned int* lh);
|
||||
void updateOptions (bool r, bool g, bool b, bool v);
|
||||
void on_realize();
|
||||
bool on_expose_event(GdkEventExpose* event);
|
||||
bool on_button_press_event (GdkEventButton* event);
|
||||
void styleChanged (const Glib::RefPtr<Gtk::Style>& style);
|
||||
};
|
||||
|
||||
class HistogramPanel : public Gtk::HBox {
|
||||
|
||||
protected:
|
||||
|
||||
HistogramArea* histogramArea;
|
||||
Gtk::ToggleButton* showRed;
|
||||
Gtk::ToggleButton* showGreen;
|
||||
Gtk::ToggleButton* showBlue;
|
||||
Gtk::ToggleButton* showValue;
|
||||
|
||||
sigc::connection rconn;
|
||||
|
||||
public:
|
||||
|
||||
HistogramPanel ();
|
||||
|
||||
void histogramChanged (unsigned int* rh, unsigned int* gh, unsigned int* bh, unsigned int* lh) { histogramArea->update (rh, gh, bh, lh); }
|
||||
void rgbv_toggled ();
|
||||
void resized (Gtk::Allocation& req);
|
||||
};
|
||||
|
||||
#endif
|
||||
326
rtgui/history.cc
Executable file
326
rtgui/history.cc
Executable file
@@ -0,0 +1,326 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <history.h>
|
||||
#include <multilangmgr.h>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
Glib::ustring eventDescrArray[NUMOFEVENTS];
|
||||
extern Glib::ustring argv0;
|
||||
|
||||
History::History (bool bookmarkSupport) : tpc (NULL), bmnum (1), blistener(NULL) {
|
||||
|
||||
// fill history event message array
|
||||
for (int i=0; i<NUMOFEVENTS; i++)
|
||||
eventDescrArray[i] = M(Glib::ustring::compose("HISTORY_MSG_%1", i+1));
|
||||
|
||||
// History List
|
||||
// ~~~~~~~~~~~~
|
||||
hscrollw = Gtk::manage (new Gtk::ScrolledWindow ());
|
||||
hscrollw->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||
|
||||
Gtk::Frame* histFrame = Gtk::manage (new Gtk::Frame (M("HISTORY_LABEL")));
|
||||
histFrame->add (*hscrollw);
|
||||
|
||||
pack_start (*histFrame);
|
||||
|
||||
hTreeView = Gtk::manage (new Gtk::TreeView ());
|
||||
hscrollw->add (*hTreeView);
|
||||
|
||||
historyModel = Gtk::ListStore::create (historyColumns);
|
||||
hTreeView->set_model (historyModel);
|
||||
// hTreeView->set_headers_visible (false);
|
||||
|
||||
Gtk::CellRendererText *changecrt = Gtk::manage (new Gtk::CellRendererText());
|
||||
Gtk::CellRendererText *valuecrt = Gtk::manage (new Gtk::CellRendererText());
|
||||
Gtk::TreeView::Column *hviewcol = Gtk::manage (new Gtk::TreeView::Column (""));
|
||||
hviewcol->pack_start (*changecrt, true);
|
||||
hviewcol->add_attribute (changecrt->property_markup (), historyColumns.text);
|
||||
hviewcol->set_resizable (true);
|
||||
|
||||
Gtk::TreeView::Column *hviewcol2 = Gtk::manage (new Gtk::TreeView::Column (""));
|
||||
hviewcol2->pack_start (*valuecrt, true);
|
||||
hviewcol2->add_attribute (valuecrt->property_markup (), historyColumns.value);
|
||||
valuecrt->set_property ("xalign", 1.0);
|
||||
|
||||
hTreeView->append_column (*hviewcol);
|
||||
hTreeView->append_column (*hviewcol2);
|
||||
|
||||
hviewcol2->set_sizing (Gtk::TREE_VIEW_COLUMN_FIXED);
|
||||
|
||||
selchangehist = hTreeView->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &History::historySelectionChanged));
|
||||
|
||||
// Bookmark List
|
||||
// ~~~~~~~~~~~~~
|
||||
|
||||
Gtk::HSeparator* hsepb = Gtk::manage (new Gtk::HSeparator ());
|
||||
pack_end (*hsepb, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
Gtk::HBox* ahbox = Gtk::manage (new Gtk::HBox ());
|
||||
addBookmark = Gtk::manage (new Gtk::Button (M("HISTORY_NEWSNAPSHOT")));
|
||||
Gtk::Image* addimg = Gtk::manage (new Gtk::Image (argv0+"/images/list-add.png"));
|
||||
addBookmark->set_image (*addimg);
|
||||
ahbox->pack_start (*addBookmark);
|
||||
|
||||
delBookmark = Gtk::manage (new Gtk::Button (M("HISTORY_DELSNAPSHOT")));
|
||||
Gtk::Image* delimg = Gtk::manage (new Gtk::Image (argv0+"/images/list-remove.png"));
|
||||
delBookmark->set_image (*delimg);
|
||||
ahbox->pack_start (*delBookmark);
|
||||
|
||||
bscrollw = Gtk::manage (new Gtk::ScrolledWindow ());
|
||||
// bscrollw->set_policy (Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
|
||||
bscrollw->set_policy (Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC);
|
||||
bscrollw->set_size_request (-1, 75);
|
||||
|
||||
Gtk::Frame* bmFrame = Gtk::manage (new Gtk::Frame (M("HISTORY_SNAPSHOTS")));
|
||||
Gtk::VBox* bmBox = Gtk::manage (new Gtk::VBox ());
|
||||
bmFrame->add (*bmBox);
|
||||
bmBox->pack_start (*bscrollw, Gtk::PACK_SHRINK, 4);
|
||||
bmBox->pack_end (*ahbox, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
if (bookmarkSupport)
|
||||
pack_end (*bmFrame, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
bTreeView = Gtk::manage (new Gtk::TreeView ());
|
||||
bscrollw->add (*bTreeView);
|
||||
|
||||
bookmarkModel = Gtk::ListStore::create (bookmarkColumns);
|
||||
bTreeView->set_model (bookmarkModel);
|
||||
bTreeView->set_headers_visible (false);
|
||||
bTreeView->append_column_editable (M("HISTORY_SNAPSHOTS"), bookmarkColumns.text);
|
||||
|
||||
selchangebm = bTreeView->get_selection()->signal_changed().connect(sigc::mem_fun(*this, &History::bookmarkSelectionChanged));
|
||||
|
||||
addBookmark->signal_clicked().connect( sigc::mem_fun(*this, &History::addBookmarkPressed) );
|
||||
delBookmark->signal_clicked().connect( sigc::mem_fun(*this, &History::delBookmarkPressed) );
|
||||
|
||||
// hTreeView->set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_HORIZONTAL);
|
||||
hTreeView->set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_BOTH);
|
||||
hTreeView->signal_size_allocate().connect( sigc::mem_fun(*this, &History::resized) );
|
||||
|
||||
hTreeView->set_enable_search(false);
|
||||
bTreeView->set_enable_search(false);
|
||||
|
||||
show_all_children ();
|
||||
}
|
||||
|
||||
void History::initHistory () {
|
||||
|
||||
historyModel->clear ();
|
||||
bookmarkModel->clear ();
|
||||
}
|
||||
|
||||
void History::clearParamChanges () {
|
||||
|
||||
initHistory ();
|
||||
}
|
||||
|
||||
void History::historySelectionChanged () {
|
||||
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = hTreeView->get_selection();
|
||||
Gtk::TreeModel::iterator iter = selection->get_selected();
|
||||
if (iter) {
|
||||
Gtk::TreeModel::Row row = *iter;
|
||||
if (row)
|
||||
bTreeView->get_selection()->unselect_all ();
|
||||
if (row && tpc) {
|
||||
ProcParams params = row[historyColumns.params];
|
||||
ParamsEdited paramsEdited = row[historyColumns.paramsEdited];
|
||||
tpc->profileChange (¶ms, EvHistoryBrowsed, row[historyColumns.text], ¶msEdited);
|
||||
}
|
||||
if (blistener) {
|
||||
Gtk::TreeModel::Path path = historyModel->get_path (iter);
|
||||
path.prev ();
|
||||
iter = historyModel->get_iter (path);
|
||||
if (blistener && iter)
|
||||
blistener->historyBeforeLineChanged (iter->get_value (historyColumns.params));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void History::bookmarkSelectionChanged () {
|
||||
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = bTreeView->get_selection();
|
||||
Gtk::TreeModel::iterator iter = selection->get_selected();
|
||||
if (iter) {
|
||||
Gtk::TreeModel::Row row = *iter;
|
||||
if (row)
|
||||
hTreeView->get_selection()->unselect_all ();
|
||||
if (row && tpc) {
|
||||
ProcParams params = row[bookmarkColumns.params];
|
||||
ParamsEdited paramsEdited = row[bookmarkColumns.paramsEdited];
|
||||
tpc->profileChange (¶ms, EvBookmarkSelected, row[bookmarkColumns.text], ¶msEdited);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void History::procParamsChanged (ProcParams* params, ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited) {
|
||||
|
||||
// to prevent recursion, we filter out the events triggered by the history
|
||||
if (ev==EvHistoryBrowsed)
|
||||
return;
|
||||
|
||||
selchangehist.block (true);
|
||||
|
||||
if (ev==EvPhotoLoaded)
|
||||
initHistory ();
|
||||
// construct formatted list content
|
||||
Glib::ustring text = Glib::ustring::compose ("<b>%1</b>", eventDescrArray[ev]);
|
||||
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = hTreeView->get_selection();
|
||||
Gtk::TreeModel::iterator iter = selection->get_selected();
|
||||
// remove all rows after the selection
|
||||
if (iter) {
|
||||
iter++;
|
||||
while (iter)
|
||||
iter = historyModel->erase (iter);
|
||||
}
|
||||
// lookup the last remaining item in the list
|
||||
int size = historyModel->children().size ();
|
||||
Gtk::TreeModel::Row row;
|
||||
if (size>0)
|
||||
row = historyModel->children()[size-1];
|
||||
// if there is no last item or its chev!=ev, create a new one
|
||||
if (size==0 || !row || row[historyColumns.chev]!=ev) {
|
||||
Gtk::TreeModel::Row newrow = *(historyModel->append());
|
||||
newrow[historyColumns.realText] = eventDescrArray[ev];
|
||||
newrow[historyColumns.text] = text;
|
||||
newrow[historyColumns.value] = descr;
|
||||
newrow[historyColumns.chev] = ev;
|
||||
newrow[historyColumns.params] = *params;
|
||||
newrow[historyColumns.paramsEdited] = paramsEdited ? *paramsEdited : defParamsEdited;
|
||||
if (ev!=EvBookmarkSelected)
|
||||
selection->select (newrow);
|
||||
if (blistener && row)
|
||||
blistener->historyBeforeLineChanged (row[historyColumns.params]);
|
||||
else if (blistener && size==0)
|
||||
blistener->historyBeforeLineChanged (newrow[historyColumns.params]);
|
||||
}
|
||||
// else just update it
|
||||
else {
|
||||
row[historyColumns.realText] = eventDescrArray[ev];
|
||||
row[historyColumns.text] = text;
|
||||
row[historyColumns.value] = descr;
|
||||
row[historyColumns.chev] = ev;
|
||||
row[historyColumns.params] = *params;
|
||||
row[historyColumns.paramsEdited] = paramsEdited ? *paramsEdited : defParamsEdited;
|
||||
if (ev!=EvBookmarkSelected)
|
||||
selection->select (row);
|
||||
}
|
||||
if (ev!=EvBookmarkSelected)
|
||||
bTreeView->get_selection()->unselect_all ();
|
||||
|
||||
|
||||
if (!selection->get_selected_rows().empty()) {
|
||||
Gtk::TreeView::Selection::ListHandle_Path selp = selection->get_selected_rows();
|
||||
hTreeView->scroll_to_row (*selp.begin());
|
||||
}
|
||||
selchangehist.block (false);
|
||||
}
|
||||
|
||||
void History::addBookmarkWithText (Glib::ustring text) {
|
||||
|
||||
// lookup the selected item in the history
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = hTreeView->get_selection();
|
||||
Gtk::TreeModel::iterator iter = selection->get_selected();
|
||||
Gtk::TreeModel::Row row = *iter;
|
||||
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
|
||||
// append new row to bookmarks
|
||||
Gtk::TreeModel::Row newrow = *(bookmarkModel->append());
|
||||
newrow[bookmarkColumns.text] = text;
|
||||
ProcParams params = row[historyColumns.params];
|
||||
newrow[bookmarkColumns.params] = params;
|
||||
ParamsEdited paramsEdited = row[historyColumns.paramsEdited];
|
||||
newrow[bookmarkColumns.paramsEdited] = paramsEdited;
|
||||
}
|
||||
|
||||
void History::addBookmarkPressed () {
|
||||
|
||||
if (hTreeView->get_selection()->get_selected())
|
||||
addBookmarkWithText (Glib::ustring::compose ("%1 %2", M("HISTORY_SNAPSHOT"), bmnum++));
|
||||
}
|
||||
|
||||
void History::delBookmarkPressed () {
|
||||
|
||||
// lookup the selected item in the bookmark
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = bTreeView->get_selection();
|
||||
Gtk::TreeModel::iterator iter = selection->get_selected();
|
||||
|
||||
if (!iter) {
|
||||
return;
|
||||
}
|
||||
// remove selected bookmark
|
||||
bookmarkModel->erase (iter);
|
||||
// select last item in history
|
||||
int size = historyModel->children().size ();
|
||||
Gtk::TreeModel::Row row = historyModel->children()[size-1];
|
||||
hTreeView->get_selection()->select (row);
|
||||
}
|
||||
|
||||
void History::undo () {
|
||||
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = hTreeView->get_selection();
|
||||
Gtk::TreeModel::iterator iter = selection->get_selected();
|
||||
|
||||
if (iter && iter!=historyModel->children().begin())
|
||||
selection->select (--iter);
|
||||
else if (!iter) {
|
||||
int size = historyModel->children().size ();
|
||||
if (size>1)
|
||||
selection->select (historyModel->children()[size-2]);
|
||||
}
|
||||
}
|
||||
|
||||
void History::redo () {
|
||||
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = hTreeView->get_selection();
|
||||
Gtk::TreeModel::iterator iter = selection->get_selected();
|
||||
|
||||
if (iter) {
|
||||
iter++;
|
||||
if (iter!=historyModel->children().end())
|
||||
selection->select (iter);
|
||||
}
|
||||
else {
|
||||
int size = historyModel->children().size ();
|
||||
if (size>1)
|
||||
selection->select (historyModel->children()[size-2]);
|
||||
}
|
||||
}
|
||||
|
||||
void History::resized (Gtk::Allocation& req) {
|
||||
}
|
||||
|
||||
bool History::getBeforeLineParams (rtengine::procparams::ProcParams& params) {
|
||||
|
||||
int size = historyModel->children().size ();
|
||||
if (size==0 || !blistener)
|
||||
return false;
|
||||
|
||||
Gtk::TreeModel::Row row;
|
||||
row = historyModel->children()[size==1 ? 0 : size-2];
|
||||
params = row[historyColumns.params];
|
||||
return true;
|
||||
}
|
||||
|
||||
105
rtgui/history.h
Executable file
105
rtgui/history.h
Executable file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _HISTORY_
|
||||
#define _HISTORY_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <rtengine.h>
|
||||
#include <pparamschangelistener.h>
|
||||
#include <profilechangelistener.h>
|
||||
#include <paramsedited.h>
|
||||
|
||||
class HistoryBeforeLineListener {
|
||||
|
||||
public:
|
||||
virtual void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) {}
|
||||
};
|
||||
|
||||
class History : public Gtk::VBox, public PParamsChangeListener {
|
||||
|
||||
public:
|
||||
|
||||
class HistoryColumns : public Gtk::TreeModel::ColumnRecord {
|
||||
public:
|
||||
Gtk::TreeModelColumn<Glib::ustring> realText;
|
||||
Gtk::TreeModelColumn<Glib::ustring> text;
|
||||
Gtk::TreeModelColumn<Glib::ustring> value;
|
||||
Gtk::TreeModelColumn<rtengine::procparams::ProcParams> params;
|
||||
Gtk::TreeModelColumn<rtengine::ProcEvent> chev;
|
||||
Gtk::TreeModelColumn<ParamsEdited> paramsEdited;
|
||||
HistoryColumns() { add(text); add(realText); add(value); add(chev); add(params); add(paramsEdited); }
|
||||
};
|
||||
HistoryColumns historyColumns;
|
||||
class BookmarkColumns : public Gtk::TreeModel::ColumnRecord {
|
||||
public:
|
||||
Gtk::TreeModelColumn<Glib::ustring> text;
|
||||
Gtk::TreeModelColumn<rtengine::procparams::ProcParams> params;
|
||||
Gtk::TreeModelColumn<ParamsEdited> paramsEdited;
|
||||
BookmarkColumns() { add(text); add(params); add(paramsEdited); }
|
||||
};
|
||||
BookmarkColumns bookmarkColumns;
|
||||
|
||||
protected:
|
||||
Gtk::ScrolledWindow* hscrollw;
|
||||
Gtk::TreeView* hTreeView;
|
||||
Glib::RefPtr<Gtk::ListStore> historyModel;
|
||||
|
||||
Gtk::ScrolledWindow* bscrollw;
|
||||
Gtk::TreeView* bTreeView;
|
||||
Glib::RefPtr<Gtk::ListStore> bookmarkModel;
|
||||
|
||||
Gtk::Button* addBookmark;
|
||||
Gtk::Button* delBookmark;
|
||||
|
||||
sigc::connection selchangehist;
|
||||
sigc::connection selchangebm;
|
||||
|
||||
HistoryBeforeLineListener * blistener;
|
||||
ProfileChangeListener* tpc;
|
||||
ParamsEdited defParamsEdited;
|
||||
int bmnum;
|
||||
|
||||
public:
|
||||
|
||||
History (bool bookmarkSupport = true);
|
||||
|
||||
void setProfileChangeListener (ProfileChangeListener* tpc_) { tpc = tpc_; }
|
||||
void setHistoryBeforeLineListener (HistoryBeforeLineListener* bll) { blistener = bll; }
|
||||
|
||||
// pparamschangelistener interface
|
||||
void procParamsChanged (rtengine::procparams::ProcParams* params, rtengine::ProcEvent ev, Glib::ustring descr, ParamsEdited* paramsEdited=NULL);
|
||||
void clearParamChanges ();
|
||||
|
||||
void historySelectionChanged ();
|
||||
void bookmarkSelectionChanged ();
|
||||
void initHistory ();
|
||||
|
||||
bool getBeforeLineParams (rtengine::procparams::ProcParams& params);
|
||||
|
||||
void addBookmarkWithText (Glib::ustring text);
|
||||
void addBookmarkPressed ();
|
||||
void delBookmarkPressed ();
|
||||
|
||||
void resized (Gtk::Allocation& req);
|
||||
|
||||
void undo ();
|
||||
void redo ();
|
||||
};
|
||||
|
||||
#endif
|
||||
131
rtgui/hlrec.cc
Executable file
131
rtgui/hlrec.cc
Executable file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <hlrec.h>
|
||||
#include <sstream>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
HLRecovery::HLRecovery () : ToolPanel() {
|
||||
|
||||
enabled = Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLE")));
|
||||
enabled->set_active (false);
|
||||
pack_start (*enabled);
|
||||
|
||||
method = Gtk::manage (new Gtk::ComboBoxText ());
|
||||
method->append_text (M("TP_HLREC_LUMINANCE"));
|
||||
method->append_text (M("TP_HLREC_CIELAB"));
|
||||
method->append_text (M("TP_HLREC_COLOR"));
|
||||
method->set_active (0);
|
||||
Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ());
|
||||
Gtk::Label* lab = Gtk::manage (new Gtk::Label (M("TP_HLREC_METHOD")));
|
||||
hb->pack_start (*lab, Gtk::PACK_SHRINK, 4);
|
||||
hb->pack_start (*method);
|
||||
pack_start (*hb);
|
||||
|
||||
enaconn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &HLRecovery::enabledChanged) );
|
||||
methconn = method->signal_changed().connect ( sigc::mem_fun(*this, &HLRecovery::methodChanged) );
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
void HLRecovery::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
|
||||
if (pedited)
|
||||
enabled->set_inconsistent (!pedited->hlrecovery.enabled);
|
||||
enaconn.block (true);
|
||||
enabled->set_active (pp->hlrecovery.enabled);
|
||||
enaconn.block (false);
|
||||
|
||||
if (pedited && !pedited->hlrecovery.method)
|
||||
method->set_active (3);
|
||||
else if (pp->hlrecovery.method=="Luminance")
|
||||
method->set_active (0);
|
||||
else if (pp->hlrecovery.method=="CIELab blending")
|
||||
method->set_active (1);
|
||||
else if (pp->hlrecovery.method=="Color")
|
||||
method->set_active (2);
|
||||
|
||||
lastEnabled = pp->hlrecovery.enabled;
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void HLRecovery::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
if (pedited) {
|
||||
pedited->hlrecovery.method = method->get_active_row_number()!=3;
|
||||
pedited->hlrecovery.enabled = !enabled->get_inconsistent();
|
||||
}
|
||||
|
||||
pp->hlrecovery.enabled = enabled->get_active();
|
||||
if (method->get_active_row_number()==0)
|
||||
pp->hlrecovery.method = "Luminance";
|
||||
else if (method->get_active_row_number()==1)
|
||||
pp->hlrecovery.method = "CIELab blending";
|
||||
else if (method->get_active_row_number()==2)
|
||||
pp->hlrecovery.method = "Color";
|
||||
}
|
||||
|
||||
void HLRecovery::enabledChanged () {
|
||||
|
||||
if (batchMode) {
|
||||
if (enabled->get_inconsistent()) {
|
||||
enabled->set_inconsistent (false);
|
||||
enaconn.block (true);
|
||||
enabled->set_active (false);
|
||||
enaconn.block (false);
|
||||
}
|
||||
else if (lastEnabled)
|
||||
enabled->set_inconsistent (true);
|
||||
|
||||
lastEnabled = enabled->get_active ();
|
||||
}
|
||||
|
||||
if (listener) {
|
||||
if (enabled->get_active ())
|
||||
listener->panelChanged (EvHREnabled, M("GENERAL_ENABLED"));
|
||||
else
|
||||
listener->panelChanged (EvHREnabled, M("GENERAL_DISABLED"));
|
||||
}
|
||||
}
|
||||
|
||||
void HLRecovery::methodChanged () {
|
||||
|
||||
if (listener) {
|
||||
if (enabled->get_active ())
|
||||
listener->panelChanged (EvHRMethod, method->get_active_text ());
|
||||
}
|
||||
}
|
||||
|
||||
void HLRecovery::setRaw (bool raw) {
|
||||
|
||||
disableListener ();
|
||||
set_sensitive (raw);
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void HLRecovery::setBatchMode (bool batchMode) {
|
||||
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
method->append_text ("(Unchanged)");
|
||||
}
|
||||
48
rtgui/hlrec.h
Executable file
48
rtgui/hlrec.h
Executable file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _HLREC_H_
|
||||
#define _HLREC_H_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <toolpanel.h>
|
||||
|
||||
class HLRecovery : public Gtk::VBox, public ToolPanel {
|
||||
|
||||
protected:
|
||||
Gtk::CheckButton* enabled;
|
||||
Gtk::ComboBoxText* method;
|
||||
sigc::connection methconn;
|
||||
sigc::connection enaconn;
|
||||
bool lastEnabled;
|
||||
|
||||
public:
|
||||
|
||||
HLRecovery ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setBatchMode (bool batchMode);
|
||||
|
||||
void setRaw (bool raw);
|
||||
|
||||
void enabledChanged ();
|
||||
void methodChanged ();
|
||||
};
|
||||
|
||||
#endif
|
||||
21
rtgui/iccfromwindows.txt
Executable file
21
rtgui/iccfromwindows.txt
Executable file
@@ -0,0 +1,21 @@
|
||||
+#elif defined G_OS_WIN32
|
||||
+ if (config->display_profile_from_gdk)
|
||||
+ {
|
||||
+ HDC hdc = GetDC (NULL);
|
||||
+
|
||||
+ if (hdc)
|
||||
+ {
|
||||
+ gchar *path;
|
||||
+ gint32 len = 0;
|
||||
+
|
||||
+ GetICMProfile (hdc, &len, NULL);
|
||||
+ path = g_new (gchar, len);
|
||||
+
|
||||
+ if (GetICMProfile (hdc, &len, path))
|
||||
+ profile = cmsOpenProfileFromFile (path, "r");
|
||||
+
|
||||
+ g_free (path);
|
||||
+ ReleaseDC (NULL, hdc);
|
||||
+ }
|
||||
+ }
|
||||
#endif
|
||||
290
rtgui/icmpanel.cc
Executable file
290
rtgui/icmpanel.cc
Executable file
@@ -0,0 +1,290 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <icmpanel.h>
|
||||
#include <options.h>
|
||||
#include <guiutils.h>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
extern Options options;
|
||||
|
||||
ICMPanel::ICMPanel () : ToolPanel(), icmplistener(NULL), iunchanged(NULL) {
|
||||
|
||||
// set_border_width (4);
|
||||
|
||||
ipDialog = Gtk::manage (new Gtk::FileChooserButton (M("TP_ICM_INPUTDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN));
|
||||
opDialog = Gtk::manage (new Gtk::FileChooserButton (M("TP_ICM_INPUTDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN));
|
||||
|
||||
Gtk::Label* ilab = Gtk::manage (new Gtk::Label ());
|
||||
ilab->set_alignment (0.0, 0.5);
|
||||
ilab->set_markup (Glib::ustring("<b>") + M("TP_ICM_INPUTPROFILE") + "</b>");
|
||||
pack_start (*ilab, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
iembedded = Gtk::manage (new Gtk::RadioButton (M("TP_ICM_INPUTEMBEDDED")));
|
||||
pack_start (*iembedded, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
icamera = Gtk::manage (new Gtk::RadioButton (M("TP_ICM_INPUTCAMERA")));
|
||||
pack_start (*icamera, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
ifromfile = Gtk::manage (new Gtk::RadioButton (M("TP_ICM_INPUTCUSTOM")+":"));
|
||||
Gtk::HBox* ffbox = Gtk::manage (new Gtk::HBox ());
|
||||
ffbox->pack_start (*ifromfile, Gtk::PACK_SHRINK);
|
||||
ffbox->pack_start (*ipDialog);
|
||||
|
||||
pack_start (*ffbox, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
opts = icamera->get_group();
|
||||
iembedded->set_group (opts);
|
||||
ifromfile->set_group (opts);
|
||||
|
||||
igamma = Gtk::manage (new Gtk::CheckButton (M("TP_ICM_GAMMABEFOREINPUT")));
|
||||
igamma->set_sensitive (false);
|
||||
pack_start (*igamma, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
saveRef = Gtk::manage (new Gtk::Button (M("TP_ICM_SAVEREFERENCE")));
|
||||
saveRef->set_image (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
|
||||
pack_start (*saveRef, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
|
||||
Gtk::HSeparator* hsep1 = Gtk::manage (new Gtk::HSeparator ());
|
||||
pack_start (*hsep1, Gtk::PACK_SHRINK, 2);
|
||||
|
||||
Gtk::Label* wlab = Gtk::manage (new Gtk::Label ());
|
||||
wlab->set_alignment (0.0, 0.5);
|
||||
wlab->set_markup (Glib::ustring("<b>") + M("TP_ICM_WORKINGPROFILE") + "</b>");
|
||||
|
||||
pack_start (*wlab, Gtk::PACK_SHRINK, 4);
|
||||
wnames = Gtk::manage (new Gtk::ComboBoxText ());
|
||||
pack_start (*wnames, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
Gtk::HSeparator* hsep2 = Gtk::manage (new Gtk::HSeparator ());
|
||||
pack_start (*hsep2, Gtk::PACK_SHRINK, 2);
|
||||
|
||||
Gtk::Label* olab = Gtk::manage (new Gtk::Label ());
|
||||
olab->set_alignment (0.0, 0.5);
|
||||
olab->set_markup (Glib::ustring("<b>") + M("TP_ICM_OUTPUTPROFILE") + "</b>");
|
||||
|
||||
pack_start (*olab, Gtk::PACK_SHRINK, 4);
|
||||
onames = Gtk::manage (new Gtk::ComboBoxText ());
|
||||
pack_start (*onames, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
std::vector<std::string> wpnames = rtengine::getWorkingProfiles ();
|
||||
for (int i=0; i<wpnames.size(); i++)
|
||||
wnames->append_text (wpnames[i]);
|
||||
|
||||
onames->append_text (M("TP_ICM_NOICM"));
|
||||
onames->set_active (0);
|
||||
|
||||
std::vector<std::string> opnames = rtengine::getOutputProfiles ();
|
||||
for (int i=0; i<opnames.size(); i++)
|
||||
onames->append_text (opnames[i]);
|
||||
|
||||
wnames->set_active (0);
|
||||
onames->set_active (0);
|
||||
|
||||
Gtk::FileFilter filter_icc;
|
||||
filter_icc.set_name(M("TP_ICM_FILEDLGFILTERICM"));
|
||||
filter_icc.add_pattern("*.icc");
|
||||
filter_icc.add_pattern("*.icm");
|
||||
filter_icc.add_pattern("*.ICC");
|
||||
filter_icc.add_pattern("*.ICM");
|
||||
Gtk::FileFilter filter_any;
|
||||
filter_any.set_name(M("TP_ICM_FILEDLGFILTERANY"));
|
||||
filter_any.add_pattern("*");
|
||||
|
||||
ipDialog->add_filter (filter_icc);
|
||||
ipDialog->add_filter (filter_any);
|
||||
opDialog->add_filter (filter_icc);
|
||||
opDialog->add_filter (filter_any);
|
||||
|
||||
if (Glib::file_test (options.rtSettings.iccDirectory, Glib::FILE_TEST_IS_DIR)) {
|
||||
ipDialog->set_current_folder (options.rtSettings.iccDirectory);
|
||||
opDialog->set_current_folder (options.rtSettings.iccDirectory);
|
||||
}
|
||||
|
||||
oldip = "";
|
||||
|
||||
wnames->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::wpChanged) );
|
||||
onames->signal_changed().connect( sigc::mem_fun(*this, &ICMPanel::opChanged) );
|
||||
icamera->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::ipChanged) );
|
||||
iembedded->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::ipChanged) );
|
||||
ifromfile->signal_toggled().connect( sigc::mem_fun(*this, &ICMPanel::ipChanged) );
|
||||
ipc = ipDialog->signal_selection_changed().connect( sigc::mem_fun(*this, &ICMPanel::ipSelectionChanged) );
|
||||
saveRef->signal_pressed().connect( sigc::mem_fun(*this, &ICMPanel::saveReferencePressed) );
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
void ICMPanel::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
ipc.block (true);
|
||||
if (pp->icm.input == "(embedded)" || ((pp->icm.input == "(camera)" || pp->icm.input=="") && icamera->get_state()==Gtk::STATE_INSENSITIVE)) {
|
||||
iembedded->set_active (true);
|
||||
igamma->set_sensitive (false);
|
||||
}
|
||||
else if ((pp->icm.input == "(camera)" || pp->icm.input=="") && icamera->get_state()!=Gtk::STATE_INSENSITIVE) {
|
||||
icamera->set_active (true);
|
||||
igamma->set_sensitive (false);
|
||||
}
|
||||
else {
|
||||
ifromfile->set_active (true);
|
||||
oldip = pp->icm.input.substr(5);
|
||||
ipDialog->set_filename (pp->icm.input.substr(5));
|
||||
igamma->set_sensitive (true);
|
||||
}
|
||||
|
||||
wnames->set_active_text (pp->icm.working);
|
||||
if (pp->icm.output=="No ICM: sRGB output")
|
||||
onames->set_active_text (M("TP_ICM_NOICM"));
|
||||
else
|
||||
onames->set_active_text (pp->icm.output);
|
||||
|
||||
if (onames->get_active_row_number()==-1)
|
||||
onames->set_active_text (M("TP_ICM_NOICM"));
|
||||
|
||||
igamma->set_active (pp->icm.gammaOnInput);
|
||||
|
||||
if (pedited) {
|
||||
iunchanged->set_active (!pedited->icm.input);
|
||||
igamma->set_sensitive (false);
|
||||
if (!pedited->icm.working)
|
||||
wnames->set_active_text("(Unchanged)");
|
||||
if (!pedited->icm.output)
|
||||
onames->set_active_text("(Unchanged)");
|
||||
}
|
||||
|
||||
ipc.block (false);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void ICMPanel::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
if (iembedded->get_active ())
|
||||
pp->icm.input = "(embedded)";
|
||||
else if (icamera->get_active ())
|
||||
pp->icm.input = "(camera)";
|
||||
else
|
||||
pp->icm.input = "file:"+ipDialog->get_filename ();
|
||||
|
||||
pp->icm.working = wnames->get_active_text ();
|
||||
|
||||
if (onames->get_active_text()==M("TP_ICM_NOICM"))
|
||||
pp->icm.output = "No ICM: sRGB output";
|
||||
else
|
||||
pp->icm.output = onames->get_active_text();
|
||||
pp->icm.gammaOnInput = igamma->get_active ();
|
||||
|
||||
if (pedited) {
|
||||
pedited->icm.input = !iunchanged->get_active ();
|
||||
pedited->icm.working = wnames->get_active_text()!="(Unchanged)";
|
||||
pedited->icm.output = onames->get_active_text()!="(Unchanged)";
|
||||
pedited->icm.gammaOnInput = !ifromfile->get_active ();
|
||||
}
|
||||
}
|
||||
|
||||
void ICMPanel::wpChanged () {
|
||||
|
||||
if (listener)
|
||||
listener->panelChanged (EvWProfile, wnames->get_active_text ());
|
||||
}
|
||||
|
||||
void ICMPanel::ipChanged () {
|
||||
|
||||
std::string profname;
|
||||
if (iembedded->get_active ()) {
|
||||
profname = "(embedded)";
|
||||
igamma->set_sensitive (false);
|
||||
}
|
||||
else if (icamera->get_active ()) {
|
||||
profname = "(camera)";
|
||||
igamma->set_sensitive (false);
|
||||
}
|
||||
else {
|
||||
profname = ipDialog->get_filename ();
|
||||
igamma->set_sensitive (true);
|
||||
}
|
||||
|
||||
if (listener && profname!=oldip)
|
||||
listener->panelChanged (EvIProfile, profname);
|
||||
|
||||
oldip = profname;
|
||||
}
|
||||
|
||||
void ICMPanel::opChanged () {
|
||||
|
||||
if (listener)
|
||||
listener->panelChanged (EvOProfile, onames->get_active_text());
|
||||
}
|
||||
|
||||
void ICMPanel::setRaw (bool raw) {
|
||||
|
||||
disableListener ();
|
||||
|
||||
icamera->set_active (raw);
|
||||
iembedded->set_active (!raw);
|
||||
icamera->set_sensitive (raw);
|
||||
iembedded->set_sensitive (!raw);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void ICMPanel::ipSelectionChanged () {
|
||||
|
||||
if (ipDialog->get_filename () == "")
|
||||
return;
|
||||
else
|
||||
ipChanged ();
|
||||
|
||||
}
|
||||
void ICMPanel::saveReferencePressed () {
|
||||
|
||||
if (!icmplistener)
|
||||
return;
|
||||
Gtk::FileChooserDialog dialog(M("TP_ICM_SAVEREFERENCEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE);
|
||||
|
||||
dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
|
||||
dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_OK);
|
||||
|
||||
Gtk::FileFilter filter_jpg;
|
||||
filter_jpg.set_name(M("SAVEDLG_JPGFILTER"));
|
||||
filter_jpg.add_pattern("*.jpg");
|
||||
dialog.add_filter(filter_jpg);
|
||||
|
||||
dialog.set_do_overwrite_confirmation (true);
|
||||
|
||||
if (dialog.run()==Gtk::RESPONSE_OK)
|
||||
icmplistener->saveInputICCReference (dialog.get_filename());
|
||||
|
||||
}
|
||||
void ICMPanel::setBatchMode (bool batchMode) {
|
||||
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
iunchanged = Gtk::manage (new Gtk::RadioButton ("(Unchanged)"));
|
||||
iunchanged->set_group (opts);
|
||||
pack_start (*iunchanged, Gtk::PACK_SHRINK, 4);
|
||||
reorder_child (*iunchanged, 5);
|
||||
removeIfThere (this, saveRef);
|
||||
onames->append_text ("(Unchanged)");
|
||||
wnames->append_text ("(Unchanged)");
|
||||
}
|
||||
|
||||
70
rtgui/icmpanel.h
Executable file
70
rtgui/icmpanel.h
Executable file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _ICMPANEL_
|
||||
#define _ICMPANEL_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <toolpanel.h>
|
||||
|
||||
class ICMPanelListener {
|
||||
|
||||
public:
|
||||
virtual void saveInputICCReference (Glib::ustring fname) {}
|
||||
};
|
||||
|
||||
class ICMPanel : public Gtk::VBox, public ToolPanel {
|
||||
|
||||
private:
|
||||
Gtk::RadioButton* iembedded;
|
||||
Gtk::RadioButton* icamera;
|
||||
Gtk::RadioButton* ifromfile;
|
||||
Gtk::CheckButton* igamma;
|
||||
Gtk::ComboBoxText* wnames;
|
||||
Gtk::ComboBoxText* onames;
|
||||
Gtk::RadioButton* ofromdir;
|
||||
Gtk::RadioButton* ofromfile;
|
||||
Gtk::RadioButton* iunchanged;
|
||||
Gtk::FileChooserButton* ipDialog;
|
||||
Gtk::FileChooserButton* opDialog;
|
||||
Gtk::RadioButton::Group opts;
|
||||
Gtk::Button* saveRef;
|
||||
sigc::connection ipc;
|
||||
Glib::ustring oldip;
|
||||
ICMPanelListener* icmplistener;
|
||||
|
||||
public:
|
||||
ICMPanel ();
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setBatchMode (bool batchMode);
|
||||
|
||||
void wpChanged ();
|
||||
void opChanged ();
|
||||
void ipChanged ();
|
||||
|
||||
void ipSelectionChanged ();
|
||||
|
||||
void setRaw (bool raw);
|
||||
void saveReferencePressed ();
|
||||
|
||||
void setICMPanelListener (ICMPanelListener* ipl) { icmplistener = ipl; }
|
||||
};
|
||||
|
||||
#endif
|
||||
63
rtgui/ilabel.cc
Executable file
63
rtgui/ilabel.cc
Executable file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <ilabel.h>
|
||||
|
||||
ILabel::ILabel (Glib::ustring lab) : label(lab) {}
|
||||
|
||||
void ILabel::on_realize() {
|
||||
|
||||
Gtk::DrawingArea::on_realize();
|
||||
add_events(Gdk::EXPOSURE_MASK);
|
||||
|
||||
Glib::RefPtr<Pango::Layout> fn = create_pango_layout(label);
|
||||
fn->set_markup (label);
|
||||
int labw, labh;
|
||||
fn->get_pixel_size (labw, labh);
|
||||
set_size_request (2+labw,2+labh);
|
||||
|
||||
signal_style_changed().connect( sigc::mem_fun(*this, &ILabel::styleChanged) );
|
||||
}
|
||||
|
||||
bool ILabel::on_expose_event (GdkEventExpose* event) {
|
||||
|
||||
Glib::RefPtr<Gtk::Style> style = get_style ();
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
Glib::RefPtr<Gdk::GC> gc_ = style->get_bg_gc(get_state());
|
||||
Cairo::RefPtr<Cairo::Context> cr = window->create_cairo_context();
|
||||
|
||||
Gdk::Color c = style->get_fg (get_state());
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
cr->rectangle (0, 0, get_width (), get_height());
|
||||
cr->fill ();
|
||||
|
||||
Glib::RefPtr<Pango::Layout> fn = create_pango_layout (label);
|
||||
fn->set_markup (label);
|
||||
window->draw_layout(gc_, 1, 1, fn);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ILabel::styleChanged (const Glib::RefPtr<Gtk::Style>& style) {
|
||||
|
||||
Glib::RefPtr<Pango::Layout> fn = create_pango_layout(label);
|
||||
fn->set_markup (label);
|
||||
int labw, labh;
|
||||
fn->get_pixel_size (labw, labh);
|
||||
set_size_request (2+labw,2+labh);
|
||||
}
|
||||
36
rtgui/ilabel.h
Executable file
36
rtgui/ilabel.h
Executable file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _ILABEL_
|
||||
#define _ILABEL_
|
||||
|
||||
#include <gtkmm.h>
|
||||
|
||||
class ILabel : public Gtk::DrawingArea {
|
||||
|
||||
Glib::ustring label;
|
||||
|
||||
public:
|
||||
ILabel (Glib::ustring lab);
|
||||
bool on_expose_event(GdkEventExpose* event);
|
||||
void on_realize();
|
||||
void styleChanged (const Glib::RefPtr<Gtk::Style>& style);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
418
rtgui/imagearea.cc
Executable file
418
rtgui/imagearea.cc
Executable file
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <imagearea.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <options.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <iomanip>
|
||||
#include <cropwindow.h>
|
||||
|
||||
ImageArea::ImageArea (ImageAreaPanel* p) : parent(p) {
|
||||
|
||||
showInfo = false;
|
||||
infotext = "";
|
||||
cropgl = NULL;
|
||||
pmlistener = NULL;
|
||||
focusGrabber = NULL;
|
||||
mainCropWindow = NULL;
|
||||
previewHandler = NULL;
|
||||
lastClosedX = -1;
|
||||
showClippedH = false;
|
||||
showClippedS = false;
|
||||
listener = NULL;
|
||||
|
||||
zoomPanel = Gtk::manage (new ZoomPanel (this));
|
||||
indClippedPanel = Gtk::manage (new IndicateClippedPanel (this));
|
||||
|
||||
signal_style_changed().connect( sigc::mem_fun(*this, &ImageArea::styleChanged) );
|
||||
signal_size_allocate().connect( sigc::mem_fun(*this, &ImageArea::on_resized) );
|
||||
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
void ImageArea::on_realize()
|
||||
{
|
||||
Gtk::DrawingArea::on_realize();
|
||||
|
||||
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::SCROLL_MASK);
|
||||
|
||||
Cairo::FontOptions cfo;
|
||||
cfo.set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||
get_pango_context ()->set_cairo_font_options (cfo);
|
||||
}
|
||||
|
||||
void ImageArea::on_resized (Gtk::Allocation& req) {
|
||||
|
||||
if (ipc && !mainCropWindow) {
|
||||
mainCropWindow = new CropWindow (this, ipc);
|
||||
mainCropWindow->setDecorated (false);
|
||||
mainCropWindow->setFitZoomEnabled (true);
|
||||
mainCropWindow->setPosition (0, 0);
|
||||
mainCropWindow->setSize (get_width(), get_height());
|
||||
mainCropWindow->addCropWindowListener (this);
|
||||
mainCropWindow->setCropGUIListener (cropgl);
|
||||
mainCropWindow->setPointerMotionListener (pmlistener);
|
||||
}
|
||||
else if (ipc) {
|
||||
mainCropWindow->setSize (get_width(), get_height());
|
||||
}
|
||||
}
|
||||
|
||||
void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) {
|
||||
|
||||
ipc = ipc_;
|
||||
}
|
||||
|
||||
void ImageArea::setPreviewHandler (PreviewHandler* ph) {
|
||||
|
||||
previewHandler = ph;
|
||||
}
|
||||
|
||||
|
||||
ImageArea::~ImageArea () {
|
||||
|
||||
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
|
||||
delete *i;
|
||||
cropWins.clear ();
|
||||
|
||||
if (mainCropWindow)
|
||||
delete mainCropWindow;
|
||||
}
|
||||
|
||||
void ImageArea::styleChanged (const Glib::RefPtr<Gtk::Style>& style) {
|
||||
|
||||
// TODO: notify all crop windows that the style has been changed
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
void ImageArea::setInfoText (Glib::ustring text) {
|
||||
|
||||
infotext = text;
|
||||
|
||||
Glib::RefPtr<Pango::Context> context = get_pango_context () ;
|
||||
Pango::FontDescription fontd = context->get_font_description ();
|
||||
fontd.set_weight (Pango::WEIGHT_BOLD);
|
||||
fontd.set_size (12*Pango::SCALE);
|
||||
context->set_font_description (fontd);
|
||||
ilayout = create_pango_layout(text);
|
||||
int iw, ih;
|
||||
ilayout->get_pixel_size (iw, ih);
|
||||
ipixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, true, 8, iw+8, ih+8);
|
||||
ipixbuf->fill (128);
|
||||
}
|
||||
|
||||
void ImageArea::infoEnabled (bool e) {
|
||||
|
||||
if (showInfo!=e) {
|
||||
showInfo = e;
|
||||
queue_draw ();
|
||||
}
|
||||
}
|
||||
|
||||
CropWindow* ImageArea::getCropWindow (int x, int y) {
|
||||
|
||||
CropWindow* cw = mainCropWindow;
|
||||
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
|
||||
if ((*i)->isInside (x, y))
|
||||
return *i;
|
||||
return cw;
|
||||
}
|
||||
|
||||
bool ImageArea::on_expose_event(GdkEventExpose* event) {
|
||||
dirty = false;
|
||||
|
||||
if (event->count)
|
||||
return true;
|
||||
|
||||
Glib::RefPtr<Gdk::Window> window = get_window();
|
||||
Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context();
|
||||
|
||||
if (mainCropWindow)
|
||||
mainCropWindow->expose (cr);
|
||||
|
||||
if (showInfo==true && infotext!="") {
|
||||
int fnw, fnh;
|
||||
ilayout->get_pixel_size (fnw, fnh);
|
||||
window->draw_pixbuf (get_style()->get_base_gc (Gtk::STATE_NORMAL), ipixbuf, 0, 0, 4, 4, fnw+8, fnh+8, Gdk::RGB_DITHER_NONE, 0, 0);
|
||||
cr->set_source_rgb (1.0, 1.0, 1.0);
|
||||
cr->move_to (8, 8);
|
||||
ilayout->add_to_cairo_context (cr);
|
||||
cr->fill ();
|
||||
}
|
||||
|
||||
for (std::list<CropWindow*>::reverse_iterator i=cropWins.rbegin(); i!=cropWins.rend(); i++)
|
||||
(*i)->expose (cr);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ImageArea::on_motion_notify_event (GdkEventMotion* event) {
|
||||
|
||||
if (focusGrabber)
|
||||
focusGrabber->pointerMoved (event->x, event->y);
|
||||
else {
|
||||
CropWindow* cw = getCropWindow (event->x, event->y);
|
||||
if (cw)
|
||||
cw->pointerMoved (event->x, event->y);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImageArea::on_button_press_event (GdkEventButton* event) {
|
||||
|
||||
if (focusGrabber)
|
||||
focusGrabber->buttonPress (event->button, event->type, event->state, event->x, event->y);
|
||||
else {
|
||||
CropWindow* cw = getCropWindow (event->x, event->y);
|
||||
if (cw)
|
||||
cw->buttonPress (event->button, event->type, event->state, event->x, event->y);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImageArea::on_scroll_event (GdkEventScroll* event) {
|
||||
|
||||
CropWindow* cw = getCropWindow (event->x, event->y);
|
||||
if (cw) {
|
||||
if (event->direction==GDK_SCROLL_UP)
|
||||
cw->zoomIn ();
|
||||
else
|
||||
cw->zoomOut ();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ImageArea::on_button_release_event (GdkEventButton* event) {
|
||||
|
||||
if (focusGrabber)
|
||||
focusGrabber->buttonRelease (event->button, event->type, event->state, event->x, event->y);
|
||||
else {
|
||||
CropWindow* cw = getCropWindow (event->x, event->y);
|
||||
if (cw) {
|
||||
cw->buttonRelease (event->button, event->type, event->state, event->x, event->y);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ImageArea::grabFocus (CropWindow* cw) {
|
||||
|
||||
focusGrabber = cw;
|
||||
if (cw && cw!=mainCropWindow)
|
||||
cropWindowSelected (cw);
|
||||
}
|
||||
|
||||
void ImageArea::unGrabFocus () {
|
||||
|
||||
focusGrabber = NULL;
|
||||
}
|
||||
|
||||
void ImageArea::addCropWindow () {
|
||||
|
||||
CropWindow* cw = new CropWindow (this, ipc);
|
||||
cw->setCropGUIListener (cropgl);
|
||||
cw->setPointerMotionListener (pmlistener);
|
||||
cropWins.push_front (cw);
|
||||
|
||||
if (lastClosedX<0) {
|
||||
int K = 2;
|
||||
int hBorder = get_width()/K/8;
|
||||
int vBorder = get_height()/K/8;
|
||||
int N = cropWins.size()-1;
|
||||
int layer = N/K/K;
|
||||
int row = K-1 - (N % (K*K)) / K;
|
||||
int col = K-1 - (N % (K*K)) % K;
|
||||
|
||||
cw->setSize (get_width()/K - hBorder, get_height()/K - vBorder);
|
||||
cw->setPosition (col*get_width()/K + hBorder/2 + layer*30, row*get_height()/K + vBorder/2 + layer*30);
|
||||
}
|
||||
else {
|
||||
cw->setSize (lastClosedX, lastClosedY);
|
||||
cw->setPosition (lastClosedW, lastClosedH);
|
||||
}
|
||||
|
||||
mainCropWindow->setObservedCropWin (cropWins.front());
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
|
||||
void ImageArea::cropWindowSelected (CropWindow* cw) {
|
||||
|
||||
std::list<CropWindow*>::iterator i = std::find (cropWins.begin(), cropWins.end(), cw);
|
||||
if (i!=cropWins.end())
|
||||
cropWins.erase (i);
|
||||
cropWins.push_front (cw);
|
||||
mainCropWindow->setObservedCropWin (cropWins.front());
|
||||
}
|
||||
|
||||
void ImageArea::cropWindowClosed (CropWindow* cw) {
|
||||
|
||||
focusGrabber = NULL;
|
||||
cw->getPosition (lastClosedX, lastClosedY);
|
||||
cw->getSize (lastClosedW, lastClosedH);
|
||||
std::list<CropWindow*>::iterator i = std::find (cropWins.begin(), cropWins.end(), cw);
|
||||
if (i!=cropWins.end())
|
||||
cropWins.erase (i);
|
||||
delete cw;
|
||||
if (!cropWins.empty())
|
||||
mainCropWindow->setObservedCropWin (cropWins.front());
|
||||
else
|
||||
mainCropWindow->setObservedCropWin (NULL);
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
void ImageArea::straightenReady (double rotDeg) {
|
||||
|
||||
if (listener)
|
||||
listener->rotateSelectionReady (rotDeg);
|
||||
}
|
||||
|
||||
void ImageArea::spotWBSelected (int x, int y) {
|
||||
|
||||
if (listener)
|
||||
listener->spotWBselected (x, y);
|
||||
}
|
||||
|
||||
void ImageArea::redraw () {
|
||||
|
||||
if (!dirty) {
|
||||
dirty = true;
|
||||
queue_draw ();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageArea::getScrollImageSize (int& w, int& h) {
|
||||
|
||||
if (mainCropWindow && ipc) {
|
||||
double z = mainCropWindow->getZoom ();
|
||||
w = ipc->getFullWidth() * z;
|
||||
h = ipc->getFullHeight() * z;
|
||||
}
|
||||
else
|
||||
w = h = 0;
|
||||
}
|
||||
|
||||
void ImageArea::getScrollPosition (int& x, int& y) {
|
||||
|
||||
if (mainCropWindow) {
|
||||
int cropX, cropY;
|
||||
mainCropWindow->getCropPosition (cropX, cropY);
|
||||
x = cropX*mainCropWindow->getZoom ();
|
||||
y = cropY*mainCropWindow->getZoom ();
|
||||
}
|
||||
else
|
||||
x = y = 0;
|
||||
}
|
||||
|
||||
void ImageArea::setScrollPosition (int x, int y) {
|
||||
|
||||
if (mainCropWindow) {
|
||||
mainCropWindow->delCropWindowListener (this);
|
||||
mainCropWindow->setCropPosition (x/mainCropWindow->getZoom (), y/mainCropWindow->getZoom ());
|
||||
mainCropWindow->addCropWindowListener (this);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageArea::cropPositionChanged (CropWindow* cw) {
|
||||
|
||||
updateScrollbars ();
|
||||
}
|
||||
|
||||
void ImageArea::cropWindowSizeChanged (CropWindow* cw) {
|
||||
|
||||
updateScrollbars ();
|
||||
}
|
||||
|
||||
void ImageArea::cropZoomChanged (CropWindow* cw) {
|
||||
|
||||
if (cw==mainCropWindow) {
|
||||
parent->zoomChanged ();
|
||||
updateScrollbars ();
|
||||
zoomPanel->refreshZoomLabel ();
|
||||
}
|
||||
}
|
||||
|
||||
double ImageArea::getZoom () {
|
||||
|
||||
if (mainCropWindow)
|
||||
return mainCropWindow->getZoom ();
|
||||
else
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
void ImageArea::setZoom (double zoom) {
|
||||
|
||||
if (mainCropWindow)
|
||||
mainCropWindow->setZoom (zoom);
|
||||
zoomPanel->refreshZoomLabel ();
|
||||
}
|
||||
|
||||
void ImageArea::initialImageArrived (CropWindow* cw) {
|
||||
|
||||
if (mainCropWindow)
|
||||
mainCropWindow->zoomFit ();
|
||||
}
|
||||
|
||||
void ImageArea::updateScrollbars () {
|
||||
parent->refreshScrollBars ();
|
||||
}
|
||||
|
||||
void ImageArea::setCropGUIListener (CropGUIListener* l) {
|
||||
|
||||
cropgl = l;
|
||||
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
|
||||
(*i)->setCropGUIListener (cropgl);
|
||||
if (mainCropWindow)
|
||||
mainCropWindow->setCropGUIListener (cropgl);
|
||||
}
|
||||
|
||||
void ImageArea::setPointerMotionListener (PointerMotionListener* pml) {
|
||||
|
||||
pmlistener = pml;
|
||||
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
|
||||
(*i)->setPointerMotionListener (pml);
|
||||
if (mainCropWindow)
|
||||
mainCropWindow->setPointerMotionListener (pml);
|
||||
}
|
||||
|
||||
ToolMode ImageArea::getToolMode () {
|
||||
|
||||
if (listener)
|
||||
return listener->getToolBar()->getTool ();
|
||||
else
|
||||
return TMHand;
|
||||
}
|
||||
|
||||
void ImageArea::setToolHand () {
|
||||
|
||||
if (listener)
|
||||
listener->getToolBar()->setTool (TMHand);
|
||||
}
|
||||
|
||||
int ImageArea::getSpotWBRectSize () {
|
||||
|
||||
if (listener)
|
||||
return listener->getSpotWBRectSize ();
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
125
rtgui/imagearea.h
Executable file
125
rtgui/imagearea.h
Executable file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 __IMAGEAREA_H__
|
||||
#define __IMAGEAREA_H__
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <cropguilistener.h>
|
||||
#include <imageareapanel.h>
|
||||
#include <editenums.h>
|
||||
#include <toolbar.h>
|
||||
#include <previewhandler.h>
|
||||
#include <imageareatoollistener.h>
|
||||
#include <cropwindow.h>
|
||||
#include <zoompanel.h>
|
||||
#include <indclippedpanel.h>
|
||||
|
||||
class ImageAreaPanel;
|
||||
class ImageArea : public Gtk::DrawingArea, public CropWindowListener {
|
||||
|
||||
friend class ZoomPanel;
|
||||
|
||||
protected:
|
||||
|
||||
bool showInfo;
|
||||
Glib::ustring infotext;
|
||||
Glib::RefPtr<Pango::Layout> ilayout;
|
||||
Glib::RefPtr<Pango::Layout> deglayout;
|
||||
Glib::RefPtr<Gdk::Pixbuf> ipixbuf;
|
||||
bool showClippedH, showClippedS;
|
||||
|
||||
ImageAreaPanel* parent;
|
||||
CropWindow* mainCropWindow;
|
||||
std::list<CropWindow*> cropWins;
|
||||
PreviewHandler* previewHandler;
|
||||
rtengine::StagedImageProcessor* ipc;
|
||||
|
||||
int lastClosedX, lastClosedY, lastClosedW, lastClosedH;
|
||||
|
||||
bool dirty;
|
||||
CropWindow* focusGrabber;
|
||||
CropGUIListener* cropgl;
|
||||
PointerMotionListener* pmlistener;
|
||||
ImageAreaToolListener* listener;
|
||||
|
||||
CropWindow* getCropWindow (int x, int y);
|
||||
|
||||
public:
|
||||
|
||||
ZoomPanel* zoomPanel;
|
||||
IndicateClippedPanel* indClippedPanel;
|
||||
|
||||
ImageArea (ImageAreaPanel* p);
|
||||
~ImageArea ();
|
||||
|
||||
void setImProcCoordinator (rtengine::StagedImageProcessor* ipc_);
|
||||
|
||||
void getScrollImageSize (int& w, int& h);
|
||||
void getScrollPosition (int& x, int& y);
|
||||
void setScrollPosition (int x, int y); // called by the imageareapanel when the scrollbars have been changed
|
||||
|
||||
// enabling and setting text of info area
|
||||
void setInfoText (Glib::ustring text);
|
||||
void infoEnabled (bool e);
|
||||
|
||||
// widget base events
|
||||
void on_realize ();
|
||||
bool on_expose_event (GdkEventExpose* event);
|
||||
bool on_motion_notify_event (GdkEventMotion* event);
|
||||
bool on_button_press_event (GdkEventButton* event);
|
||||
bool on_button_release_event (GdkEventButton* event);
|
||||
bool on_scroll_event (GdkEventScroll* event);
|
||||
void on_resized (Gtk::Allocation& req);
|
||||
void styleChanged (const Glib::RefPtr<Gtk::Style>& style);
|
||||
void updateScrollbars ();
|
||||
|
||||
void setCropGUIListener (CropGUIListener* l);
|
||||
void setPointerMotionListener (PointerMotionListener* pml);
|
||||
void setImageAreaToolListener (ImageAreaToolListener* l) { listener = l; }
|
||||
void setPreviewHandler (PreviewHandler* ph);
|
||||
PreviewHandler* getPreviewHandler () { return previewHandler; }
|
||||
|
||||
void grabFocus (CropWindow* cw);
|
||||
void unGrabFocus ();
|
||||
void addCropWindow ();
|
||||
void cropWindowSelected (CropWindow* cw);
|
||||
void cropWindowClosed (CropWindow* cw);
|
||||
ToolMode getToolMode ();
|
||||
void setToolHand ();
|
||||
void straightenReady (double rotDeg);
|
||||
void spotWBSelected (int x, int y);
|
||||
int getSpotWBRectSize ();
|
||||
void redraw ();
|
||||
|
||||
void zoomFit ();
|
||||
double getZoom ();
|
||||
void setZoom (double zoom);
|
||||
|
||||
// cropwindowlistener interface
|
||||
void cropPositionChanged (CropWindow* cw);
|
||||
void cropWindowSizeChanged (CropWindow* cw);
|
||||
void cropZoomChanged (CropWindow* cw);
|
||||
void initialImageArrived (CropWindow* cw) ;
|
||||
|
||||
CropWindow* getMainCropWindow () { return mainCropWindow; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
173
rtgui/imageareapanel.cc
Executable file
173
rtgui/imageareapanel.cc
Executable file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <imageareapanel.h>
|
||||
|
||||
ImageAreaPanel::ImageAreaPanel () : before(NULL), after(NULL) {
|
||||
|
||||
set_border_width (2);
|
||||
|
||||
Gtk::HBox* hb1 = Gtk::manage (new Gtk::HBox ());
|
||||
Gtk::HBox* hb2 = Gtk::manage (new Gtk::HBox ());
|
||||
hscroll = Gtk::manage (new Gtk::HScrollbar ());
|
||||
vscroll = Gtk::manage (new Gtk::VScrollbar ());
|
||||
imageArea = new ImageArea (this);
|
||||
Gtk::Frame* frame = Gtk::manage (new Gtk::Frame ());
|
||||
frame->add (*imageArea);
|
||||
frame->set_shadow_type (Gtk::SHADOW_IN );
|
||||
hb1->pack_start (*frame);
|
||||
hb1->pack_end (*vscroll, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
pack_start (*hb1);
|
||||
vscroll->show ();
|
||||
frame->show ();
|
||||
imageArea->show ();
|
||||
hb1->show ();
|
||||
|
||||
Gtk::HBox* tmp = Gtk::manage (new Gtk::HBox ());
|
||||
hb2->pack_start (*hscroll);
|
||||
Gtk::Requisition vcr = vscroll->size_request ();
|
||||
tmp->set_size_request (vcr.width, vcr.width);
|
||||
hb2->pack_end (*tmp, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
pack_start (*hb2,Gtk::PACK_SHRINK, 0);
|
||||
hscroll->show ();
|
||||
tmp->show ();
|
||||
hb2->show ();
|
||||
|
||||
hscroll->set_update_policy (Gtk::UPDATE_CONTINUOUS);
|
||||
vscroll->set_update_policy (Gtk::UPDATE_CONTINUOUS);
|
||||
|
||||
vscrollconn = vscroll->signal_value_changed().connect( sigc::mem_fun(*this, &ImageAreaPanel::scrollChanged) );
|
||||
hscrollconn = hscroll->signal_value_changed().connect( sigc::mem_fun(*this, &ImageAreaPanel::scrollChanged) );
|
||||
|
||||
imageArea->signal_size_allocate().connect( sigc::mem_fun(*this, &ImageAreaPanel::imageAreaResized) );
|
||||
}
|
||||
|
||||
ImageAreaPanel::~ImageAreaPanel () {
|
||||
|
||||
delete imageArea;
|
||||
}
|
||||
|
||||
void ImageAreaPanel::configScrollBars () {
|
||||
|
||||
int imgw, imgh;
|
||||
imageArea->getScrollImageSize (imgw, imgh);
|
||||
|
||||
if (imgw>0 && imgh>0) {
|
||||
|
||||
int iw = imageArea->get_width ();
|
||||
int ih = imageArea->get_height ();
|
||||
|
||||
hscrollconn.block (true);
|
||||
vscrollconn.block (true);
|
||||
|
||||
hscroll->get_adjustment()->set_upper (imgw);
|
||||
vscroll->get_adjustment()->set_upper (imgh);
|
||||
hscroll->get_adjustment()->set_lower (0);
|
||||
vscroll->get_adjustment()->set_lower (0);
|
||||
hscroll->get_adjustment()->set_step_increment (imgw/100);
|
||||
vscroll->get_adjustment()->set_step_increment (imgh/100);
|
||||
hscroll->get_adjustment()->set_page_increment (imgw/5);
|
||||
vscroll->get_adjustment()->set_page_increment (imgh/5);
|
||||
hscroll->get_adjustment()->set_page_size (iw);
|
||||
vscroll->get_adjustment()->set_page_size (ih);
|
||||
|
||||
int x, y;
|
||||
imageArea->getScrollPosition (x, y);
|
||||
hscroll->set_value (x);
|
||||
vscroll->set_value (y);
|
||||
|
||||
if (before && this==after)
|
||||
before->synchronize ();
|
||||
else if (after && this==before)
|
||||
after->synchronize ();
|
||||
|
||||
hscrollconn.block (false);
|
||||
vscrollconn.block (false);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageAreaPanel::refreshScrollBars () {
|
||||
|
||||
configScrollBars ();
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
void ImageAreaPanel::imageAreaResized (Gtk::Allocation& req) {
|
||||
|
||||
configScrollBars ();
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
void ImageAreaPanel::scrollChanged () {
|
||||
|
||||
imageArea->setScrollPosition ((int)(hscroll->get_value()), (int)(vscroll->get_value()));
|
||||
imageArea->queue_draw ();
|
||||
#ifdef _WIN32
|
||||
gdk_window_process_updates (get_window()->gobj(), true);
|
||||
#endif
|
||||
if (before && this==after)
|
||||
before->synchronize ();
|
||||
else if (after && this==before)
|
||||
after->synchronize ();
|
||||
}
|
||||
|
||||
void ImageAreaPanel::setBeforeAfterViews (ImageAreaPanel* bef, ImageAreaPanel* aft) {
|
||||
|
||||
before = bef;
|
||||
after = aft;
|
||||
configScrollBars ();
|
||||
}
|
||||
|
||||
void ImageAreaPanel::zoomChanged () {
|
||||
|
||||
if (after && this==before)
|
||||
after->imageArea->setZoom (imageArea->getZoom ());
|
||||
else if (before && this==after)
|
||||
before->imageArea->setZoom (imageArea->getZoom ());
|
||||
}
|
||||
|
||||
void ImageAreaPanel::synchronize () {
|
||||
|
||||
hscrollconn.block (true);
|
||||
vscrollconn.block (true);
|
||||
|
||||
if (after && this==before) {
|
||||
int imgw, imgh, x, y;
|
||||
after->imageArea->getScrollImageSize (imgw, imgh);
|
||||
after->imageArea->getScrollPosition (x, y);
|
||||
int bimgw, bimgh;
|
||||
imageArea->getScrollImageSize (bimgw, bimgh);
|
||||
imageArea->setScrollPosition (x*bimgw/imgw, y*bimgh/imgh);
|
||||
imageArea->queue_draw ();
|
||||
}
|
||||
else if (before && this==after) {
|
||||
int imgw, imgh, x, y;
|
||||
before->imageArea->getScrollImageSize (imgw, imgh);
|
||||
before->imageArea->getScrollPosition (x, y);
|
||||
int bimgw, bimgh;
|
||||
imageArea->getScrollImageSize (bimgw, bimgh);
|
||||
imageArea->setScrollPosition (x*bimgw/imgw, y*bimgh/imgh);
|
||||
imageArea->queue_draw ();
|
||||
}
|
||||
|
||||
hscrollconn.block (false);
|
||||
vscrollconn.block (false);
|
||||
}
|
||||
|
||||
53
rtgui/imageareapanel.h
Executable file
53
rtgui/imageareapanel.h
Executable file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _IMAGEAREAPANEL_
|
||||
#define _IMAGEAREAPANEL_
|
||||
|
||||
#include <imagearea.h>
|
||||
|
||||
class ImageArea;
|
||||
class ImageAreaPanel : public Gtk::VBox {
|
||||
|
||||
protected:
|
||||
Gtk::HScrollbar* hscroll;
|
||||
Gtk::VScrollbar* vscroll;
|
||||
sigc::connection hscrollconn;
|
||||
sigc::connection vscrollconn;
|
||||
|
||||
void synchronize ();
|
||||
void configScrollBars ();
|
||||
|
||||
ImageAreaPanel *before, *after;
|
||||
|
||||
public:
|
||||
ImageArea* imageArea;
|
||||
|
||||
ImageAreaPanel ();
|
||||
~ImageAreaPanel ();
|
||||
|
||||
void scrollChanged ();
|
||||
void imageAreaResized (Gtk::Allocation& req);
|
||||
|
||||
void refreshScrollBars ();
|
||||
void zoomChanged ();
|
||||
|
||||
void setBeforeAfterViews (ImageAreaPanel* bef, ImageAreaPanel* aft);
|
||||
};
|
||||
|
||||
#endif
|
||||
38
rtgui/imageareatoollistener.h
Executable file
38
rtgui/imageareatoollistener.h
Executable file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 _IMAGEAREATOOLLISTENER_
|
||||
#define _IMAGEAREATOOLLISTENER_
|
||||
|
||||
#include <toolbar.h>
|
||||
#include <thumbnail.h>
|
||||
#include <cropguilistener.h>
|
||||
|
||||
class ImageAreaToolListener {
|
||||
|
||||
public:
|
||||
virtual void spotWBselected (int x, int y, Thumbnail* thm=NULL) {}
|
||||
virtual int getSpotWBRectSize () { return 8; }
|
||||
virtual void cropSelectionReady () {}
|
||||
virtual void rotateSelectionReady (double rotate_deg, Thumbnail* thm=NULL) {}
|
||||
virtual ToolBar* getToolBar () { return NULL; }
|
||||
virtual CropGUIListener* startCropEditing (Thumbnail* thm=NULL) { return NULL; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
51
rtgui/indclippedpanel.cc
Executable file
51
rtgui/indclippedpanel.cc
Executable file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* 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 <indclippedpanel.h>
|
||||
#include <options.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <imagearea.h>
|
||||
|
||||
IndicateClippedPanel::IndicateClippedPanel (ImageArea* ia) : imageArea(ia) {
|
||||
|
||||
indclippedh = Gtk::manage (new Gtk::ToggleButton ());
|
||||
indclippedh->set_relief(Gtk::RELIEF_NONE);
|
||||
indclippedh->add (*Gtk::manage (new Gtk::Image (argv0+"/images/warnhl.png")));
|
||||
indclippedh->set_tooltip_text (M("MAIN_TOOLTIP_INDCLIPPEDH"));
|
||||
|
||||
indclippeds = Gtk::manage (new Gtk::ToggleButton ());
|
||||
indclippeds->set_relief(Gtk::RELIEF_NONE);
|
||||
indclippeds->add (*Gtk::manage (new Gtk::Image (argv0+"/images/warnsh.png")));
|
||||
indclippeds->set_tooltip_text (M("MAIN_TOOLTIP_INDCLIPPEDS"));
|
||||
|
||||
indclippedh->set_active (options.showClippedHighlights);
|
||||
indclippeds->set_active (options.showClippedShadows);
|
||||
|
||||
pack_start (*indclippedh, Gtk::PACK_SHRINK, 0);
|
||||
pack_start (*indclippeds, Gtk::PACK_SHRINK, 0);
|
||||
|
||||
indclippedh->signal_toggled().connect( sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled) );
|
||||
indclippeds->signal_toggled().connect( sigc::mem_fun(*this, &IndicateClippedPanel::buttonToggled) );
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
||||
void IndicateClippedPanel::buttonToggled () {
|
||||
|
||||
imageArea->queue_draw ();
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user