if no b/a area enabled some speed up when opening images
This commit is contained in:
911
rtgui/filecatalog.cc
Normal file
911
rtgui/filecatalog.cc
Normal file
@@ -0,0 +1,911 @@
|
||||
/*
|
||||
* 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), filterPanel(NULL), coarsePanel(cp), toolBar(tb) {
|
||||
|
||||
previewLoader.setPreviewLoaderListener (this);
|
||||
|
||||
// construct and initialize thumbnail browsers
|
||||
fileBrowser = new FileBrowser();
|
||||
fileBrowser->setFileBrowserListener (this);
|
||||
fileBrowser->setArrangement (ThumbBrowserBase::TB_Horizontal);
|
||||
fileBrowser->show ();
|
||||
|
||||
set_size_request(0,250);
|
||||
// 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"));
|
||||
bDir->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false);
|
||||
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);
|
||||
bUnRanked->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false);
|
||||
|
||||
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[i]->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false);
|
||||
}
|
||||
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);
|
||||
|
||||
iTrashEmpty = new Gtk::Image(argv0+"/images/trash-show-empty.png");
|
||||
iTrashFull = new Gtk::Image(argv0+"/images/trash-show-full.png");
|
||||
|
||||
bTrash = new Gtk::ToggleButton ();
|
||||
bTrash->set_image (*iTrashEmpty);
|
||||
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));
|
||||
bTrash->signal_button_press_event().connect (sigc::mem_fun(*this, &FileCatalog::capture_event),false);
|
||||
buttonBar->pack_start (*bTrash, Gtk::PACK_SHRINK);
|
||||
buttonBar->pack_start (*(new Gtk::VSeparator), Gtk::PACK_SHRINK);
|
||||
fileBrowser->trash_changed().connect( sigc::mem_fun(*this, &FileCatalog::trashChanged) );
|
||||
|
||||
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_tooltip_text (M("FILEBROWSER_SHOWEXIFINFO"));
|
||||
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
|
||||
}
|
||||
|
||||
bool FileCatalog::capture_event(GdkEventButton* event){
|
||||
// need to record modifiers on the button press, because signal_toggled does not pass the event.
|
||||
modifierKey = event->state;
|
||||
return false;
|
||||
}
|
||||
|
||||
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 (unsigned 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 don't 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 && (int)cfs->iso < dirEFS.isoFrom)
|
||||
dirEFS.isoFrom = (int)cfs->iso;
|
||||
if (cfs->iso>0 && (int)cfs->iso > dirEFS.isoTo)
|
||||
dirEFS.isoTo = (int)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 (unsigned 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 (unsigned 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 (unsigned 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 paramfile if found
|
||||
::g_remove (Glib::ustring(fname+paramFileExtension).c_str());
|
||||
::g_remove (Glib::ustring(removeExtension(fname)+paramFileExtension).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 (unsigned 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);
|
||||
img->free();
|
||||
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 (unsigned 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) {
|
||||
|
||||
//was control key pressed
|
||||
bool control_down = modifierKey & GDK_CONTROL_MASK;
|
||||
|
||||
//was shift key pressed
|
||||
bool shift_down = modifierKey & GDK_SHIFT_MASK;
|
||||
|
||||
for (int i=0; i<8; i++)
|
||||
bCateg[i].block (true);
|
||||
|
||||
//button is already toggled when entering this function, so we switch it back to its initial state
|
||||
b->set_active(!b->get_active());
|
||||
|
||||
//if both control and shift keys were pressed, do nothing
|
||||
if (!(control_down && shift_down)) {
|
||||
|
||||
fileBrowser->getScrollPosition (hScrollPos[lastScrollPos], vScrollPos[lastScrollPos]);
|
||||
|
||||
//we look how many stars are already toggled on, if any
|
||||
int toggled_stars_count=0, buttons=0, start_star=0, toggled_button=0;
|
||||
|
||||
for (int i=0; i<8; i++) {
|
||||
if (categoryButtons[i]->get_active()) {
|
||||
if (i>0 && i<7) {
|
||||
toggled_stars_count ++;
|
||||
start_star = i;
|
||||
}
|
||||
buttons |= (1 << i);
|
||||
}
|
||||
if (categoryButtons[i] == b) toggled_button = i;
|
||||
}
|
||||
|
||||
//if no modifier key were pressed, we can switch-on the button, and clear all others
|
||||
if (!(control_down || shift_down)) {
|
||||
for (int i=0; i<8; i++) {
|
||||
categoryButtons[i]->set_active (i==toggled_button);
|
||||
}
|
||||
}
|
||||
//modifier key allowed only for stars
|
||||
else if (toggled_button>0 && toggled_button<7) {
|
||||
if (control_down) {
|
||||
//control is pressed
|
||||
if (toggled_stars_count == 1 && (buttons & (1 << toggled_button))) {
|
||||
//we're deselecting the only star still active, so we activate the folder filter
|
||||
categoryButtons[0]->set_active(true);
|
||||
//and we deselect the toggled star
|
||||
categoryButtons[toggled_button]->set_active (false);
|
||||
}
|
||||
else if (toggled_stars_count >= 1) {
|
||||
//we toggle the state of a star (eventually another one than the only one selected)
|
||||
categoryButtons[toggled_button]->set_active(!categoryButtons[toggled_button]->get_active());
|
||||
}
|
||||
else {
|
||||
//no star selected
|
||||
//we deselect the 2 non star filters
|
||||
if (buttons & 1 ) categoryButtons[0]->set_active(false);
|
||||
if (buttons & (1 << 7)) categoryButtons[7]->set_active(false);
|
||||
//and we toggle on the star
|
||||
categoryButtons[toggled_button]->set_active (true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//shift is pressed, only allowed if 0 or 1 star is selected
|
||||
if (!toggled_stars_count) {
|
||||
//we deselect the 2 non star filters
|
||||
if (buttons & 1 ) categoryButtons[0]->set_active(false);
|
||||
if (buttons & (1 << 7)) categoryButtons[7]->set_active(false);
|
||||
//and we set the start star to 1 (unrated images)
|
||||
start_star = 1;
|
||||
//we act as if one star were selected
|
||||
toggled_stars_count = 1;
|
||||
}
|
||||
if (toggled_stars_count == 1) {
|
||||
int current_star=MIN(start_star,toggled_button);
|
||||
int last_star =MAX(start_star,toggled_button);
|
||||
//we permute the start and the end star for the next loop
|
||||
for (; current_star <= last_star; current_star++) {
|
||||
//we toggle on all the star in the range
|
||||
if (!(buttons & (1 << current_star))) categoryButtons[current_star]->set_active(true);
|
||||
}
|
||||
}
|
||||
//if more than one star selected, do nothing
|
||||
}
|
||||
}
|
||||
|
||||
//so set the right images
|
||||
for (int i=0; i<5; i++) {
|
||||
bool active_now, active_before;
|
||||
active_now = bRank[i]->get_active();
|
||||
active_before = buttons & (1 << (i+2));
|
||||
if ( active_now && !active_before) bRank[i]->set_image (*iranked[i]);
|
||||
else if (!active_now && active_before) bRank[i]->set_image (*igranked[i]);
|
||||
}
|
||||
|
||||
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 (unsigned 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 (unsigned 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 (unsigned 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;
|
||||
if( !file->query_exists())
|
||||
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!=(int)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;
|
||||
if( !file->query_exists())
|
||||
return;
|
||||
Glib::RefPtr<Gio::FileInfo> info = safe_query_file_info(file);
|
||||
if( !info )
|
||||
return;
|
||||
int lastdot = info->get_name().find_last_of ('.');
|
||||
if (options.is_extention_enabled(lastdot!=(int)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 (unsigned int i=0; i<t.size(); i++)
|
||||
if (((FileBrowserEntry*)t[i])->thumbnail->getStage()==1)
|
||||
toDel.push_back (((FileBrowserEntry*)t[i]));
|
||||
deleteRequested (toDel);
|
||||
trashChanged();
|
||||
}
|
||||
|
||||
bool FileCatalog::trashIsEmpty () {
|
||||
const std::vector<ThumbBrowserEntryBase*> t = fileBrowser->getEntries ();
|
||||
for (unsigned int i=0; i<t.size(); i++)
|
||||
if (((FileBrowserEntry*)t[i])->thumbnail->getStage()==1)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
void FileCatalog::trashChanged () {
|
||||
if (trashIsEmpty()) {
|
||||
bTrash->set_image(*iTrashEmpty);
|
||||
}
|
||||
else {
|
||||
bTrash->set_image(*iTrashFull);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user