/* * This file is part of RawTherapee. * * Copyright (c) 2004-2010 Gabor Horvath * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RawTherapee is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ #include #include #include #include #include #include #include #include #include #include #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_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")); 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 FileCatalog::getFileList () { std::vector names; Glib::RefPtr 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 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 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 list = buttonBar2->get_children (); Glib::ListHandle::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::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 tmb) { if (enabled && listener!=NULL) { previewLoader.stop (); thumbImageUpdater.stop (); for (unsigned int i=0; igetFileName())==editedFiles.end()) listener->fileSelected (tmb[i]); tmb[i]->decreaseRef (); } previewLoader.process (); thumbImageUpdater.process (); } } struct FCOIParams { FileCatalog* catalog; std::vector 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 tmb) { FCOIParams* params = new FCOIParams; params->catalog = this; params->tmb = tmb; for (unsigned int i=0; iincreaseRef (); g_idle_add (fcopenimg, params); } void FileCatalog::deleteRequested (std::vector 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; ifilename; // 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 tbe) { if (listener) { thumbImageUpdater.stop (); for (unsigned int i=0; ithumbnail->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 tbe) { RenameDialog* renameDlg = new RenameDialog ((Gtk::Window*)get_toplevel()); for (unsigned int i=0; iinitName (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; ifilename; 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("") + Glib::ustring::compose (M("FILEBROWSER_RENAMEDLGMSG"), baseName) + Glib::ustring("")); 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 nfileNameList = getFileList (); // check if a thumbnailed file has been deleted const std::vector& t = fileBrowser->getEntries (); std::vector fileNamesToDel; for (unsigned int i=0; ifilename, Glib::FILE_TEST_EXISTS)) fileNamesToDel.push_back (t[i]->filename); for (unsigned int i=0; idelEntry (fileNamesToDel[i]); cacheMgr.deleteEntry (fileNamesToDel[i]); } // check if a new file has been added for (unsigned int i=0; i& file, const Glib::RefPtr& 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 file) { if (!file ) return; if( !file->query_exists()) return; Glib::RefPtr 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 file = Gio::File::create_for_path (fname); if (!file ) return; if( !file->query_exists()) return; Glib::RefPtr 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 t = fileBrowser->getEntries (); std::vector toDel; for (unsigned int i=0; ithumbnail->getStage()==1) toDel.push_back (((FileBrowserEntry*)t[i])); deleteRequested (toDel); trashChanged(); } bool FileCatalog::trashIsEmpty () { const std::vector t = fileBrowser->getEntries (); for (unsigned int i=0; ithumbnail->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& efiles) { editedFiles = efiles; fileBrowser->refreshEditedState (efiles); } void FileCatalog::selectionChanged (std::vector 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); } }