diff --git a/rtdata/images/Dark/actions/nav-next.png b/rtdata/images/Dark/actions/nav-next.png new file mode 100644 index 000000000..a3e8ed0b0 Binary files /dev/null and b/rtdata/images/Dark/actions/nav-next.png differ diff --git a/rtdata/images/Dark/actions/nav-prev.png b/rtdata/images/Dark/actions/nav-prev.png new file mode 100644 index 000000000..cd621d372 Binary files /dev/null and b/rtdata/images/Dark/actions/nav-prev.png differ diff --git a/rtdata/images/Dark/actions/nav-sync.png b/rtdata/images/Dark/actions/nav-sync.png new file mode 100644 index 000000000..cbad9711e Binary files /dev/null and b/rtdata/images/Dark/actions/nav-sync.png differ diff --git a/rtdata/images/Light/actions/nav-next.png b/rtdata/images/Light/actions/nav-next.png new file mode 100644 index 000000000..d68e1df60 Binary files /dev/null and b/rtdata/images/Light/actions/nav-next.png differ diff --git a/rtdata/images/Light/actions/nav-prev.png b/rtdata/images/Light/actions/nav-prev.png new file mode 100644 index 000000000..ad37367ba Binary files /dev/null and b/rtdata/images/Light/actions/nav-prev.png differ diff --git a/rtdata/images/Light/actions/nav-sync.png b/rtdata/images/Light/actions/nav-sync.png new file mode 100644 index 000000000..eb8445a40 Binary files /dev/null and b/rtdata/images/Light/actions/nav-sync.png differ diff --git a/rtdata/languages/default b/rtdata/languages/default index 97b50d105..17f531128 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -88,7 +88,7 @@ FILEBROWSER_ARRANGEMENTHINT;Change between vertical/horizontal alignment of thum FILEBROWSER_AUTODARKFRAME;Auto Dark Frame FILEBROWSER_AUTOFLATFIELD;Auto Flat Field FILEBROWSER_BROWSEPATHBUTTONHINT;Click to browse to the chosen path -FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\nCtrl-O to focus the path text box.\nEnter / Ctrl-Enter (in the File Browser) to browse there;\n\nPath shortcuts:\n ~ - user's home directory\n ! - user's pictures directory +FILEBROWSER_BROWSEPATHHINT;Type a path to navigate to.\nCtrl-O to focus to the path text box.\nEnter / Ctrl-Enter to browse there;\nEsc to clear changes.\nShift-Esc to remove focus.\n\n\nPath shortcuts:\n ~ - user's home directory\n ! - user's pictures directory FILEBROWSER_CACHECLEARFROMFULL;Clear from cache - full FILEBROWSER_CACHECLEARFROMPARTIAL;Clear from cache - partial FILEBROWSER_CACHE;Cache @@ -149,7 +149,7 @@ FILEBROWSER_POPUPUNTRASH;Remove from trash FILEBROWSER_PROCESSINGSETTINGSHINT;Set the file format and output directory FILEBROWSER_PROCESSINGSETTINGS;Settings FILEBROWSER_QUERYBUTTONHINT;Clear the Find query -FILEBROWSER_QUERYHINT;Type a partial filename to search for or a comma-separated list.\nE.g. 1001,1004,1199 \n\nCtrl-F to focus to the Find text box (in the File Browser).\nEnter to commence search.\nEscape to clear. +FILEBROWSER_QUERYHINT;Type a partial filename to search for or a comma-separated list.\nE.g. 1001,1004,1199 \n\nCtrl-F to focus to the Find text box.\nEnter to commence search.\nEsc to clear.\nShift-Esc to remove focus. FILEBROWSER_QUERYLABEL; Find: FILEBROWSER_RENAMEDLGLABEL;Rename file FILEBROWSER_RENAMEDLGMSG;Rename file "%1" to: @@ -163,7 +163,7 @@ FILEBROWSER_SHOWCOLORLABEL5HINT;Show images labeled Purple.\nShortcut: Alt-5< FILEBROWSER_SHOWDIRHINT;Clear all filters.\nShortcut: D FILEBROWSER_SHOWEDITEDHINT;Show edited images.\nShortcut: 7 FILEBROWSER_SHOWEDITEDNOTHINT;Show not edited images.\nShortcut: 6 -FILEBROWSER_SHOWEXIFINFO;Show Exif info.\nShortcut: i +FILEBROWSER_SHOWEXIFINFO;Show Exif info.\nShortcut: i\n\nShortcut in Single Editor Tab: Alt-i FILEBROWSER_SHOWQUEUEHINT;Show content of the processing queue FILEBROWSER_SHOWRANK1HINT;Show images ranked as 1 star.\nShortcut: 1 FILEBROWSER_SHOWRANK2HINT;Show images ranked as 2 star.\nShortcut: 2 @@ -182,8 +182,8 @@ FILEBROWSER_STOPPROCESSING;Stop Processing FILEBROWSER_THUMBSIZE;Thumbnail size FILEBROWSER_TOOLTIP_STOPPROCESSING;Start processing automatically when a new job arrives FILEBROWSER_USETEMPLATE;Use template: -FILEBROWSER_ZOOMINHINT;Increase thumbnail size.\nShortcut: + -FILEBROWSER_ZOOMOUTHINT;Decrease thumbnail size.\nShortcut: - +FILEBROWSER_ZOOMINHINT;Increase thumbnail size.\nShortcut: +\n\nShortcut in Single Editor Tab: Alt + +FILEBROWSER_ZOOMOUTHINT;Decrease thumbnail size.\nShortcut: -\n\nShortcut in Single Editor Tab: Alt - GENERAL_ABOUT;About GENERAL_AFTER;After GENERAL_AUTO;Automatic @@ -497,6 +497,9 @@ IPTCPANEL_TRANSREFERENCEHINT;A code representing the location of the original tr IPTCPANEL_TRANSREFERENCE;Trans. reference MAIN_BUTTON_EXIT;Exit MAIN_BUTTON_FULLSCREEN;Fullscreen +MAIN_BUTTON_NAVNEXT_TOOLTIP;Navigate to the Next image relative to image open in Editor\nShortcut: Shift-F4\n\nTo navigate to the Next image relative to thumbnail selected in File Browser\nShortcut: F4 +MAIN_BUTTON_NAVPREV_TOOLTIP;Navigate to the Previous image relative to image open in Editor\nShortcut: Shift-F3 \n\nTo navigate to the Previous image relative to thumbnail selected in File Browser\nShortcut: F3 +MAIN_BUTTON_NAVSYNC_TOOLTIP;Synchronize the File Browser with the Editor to reveal the thumbnail of the currently open image, and clear filters in File Browser \nShortcut: x\n\nAs above, but without clearing filters in File Browser\nShortcut: y\n(Note that thumbnail of the open file will not be shown if filtered out). MAIN_BUTTON_PREFERENCES;Preferences MAIN_BUTTON_PUTTOQUEUE_TOOLTIP;Put current image to processing queue.\nShortcut: Ctrl+Q MAIN_BUTTON_QUEUE;Put to Queue @@ -909,8 +912,8 @@ TP_CHMIXER_LABEL;Channel Mixer TP_CHMIXER_RED;Red Channel TP_CHROMATABERR_LABEL;Chromatic Aberration TP_COARSETRAF_TOOLTIP_HFLIP;Flip horizontally -TP_COARSETRAF_TOOLTIP_ROTLEFT;Rotate left.\nShortcut: [ -TP_COARSETRAF_TOOLTIP_ROTRIGHT;Rotate right.\nShortcut: ] +TP_COARSETRAF_TOOLTIP_ROTLEFT;Rotate left.\nShortcut: [\n\nShortcut in Single Editor Tab: Alt-[ +TP_COARSETRAF_TOOLTIP_ROTRIGHT;Rotate right.\nShortcut: ]\n\nShortcut in Single Editor Tab: Alt-] TP_COARSETRAF_TOOLTIP_VFLIP;Flip vertically TP_COLORAPP_ADAPTSCENE;Adaptation scene luminosity (cd/m²) TP_COLORAPP_ADAPTSCENE_TOOLTIP;Absolute luminance of the scene environnement\n(usually 2000cd/m²) @@ -1324,7 +1327,7 @@ ZOOMBAR_SCALE;Scale ZOOMBAR_SMALL;Small ZOOMPANEL_100;(100%) ZOOMPANEL_NEWCROPWINDOW;Open (new) detail window -ZOOMPANEL_ZOOM100;Zoom to 100%\nShortcut: 1 +ZOOMPANEL_ZOOM100;Zoom to 100%\nShortcut: z ZOOMPANEL_ZOOMFITSCREEN;Fit to screen\nShortcut: f ZOOMPANEL_ZOOMIN;Zoom In\nShortcut: + ZOOMPANEL_ZOOMOUT;Zoom Out\nShortcut: - diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index e544e2e38..614b38ce7 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -223,6 +223,35 @@ EditorPanel::EditorPanel (FilePanel* filePanel) iops->pack_end (*iareapanel->imageArea->zoomPanel, Gtk::PACK_SHRINK, 1); iops->pack_end (*vsepz3, Gtk::PACK_SHRINK, 2); + // Navigation buttons + Gtk::Image *navPrevImage = Gtk::manage (new RTImage ("nav-prev.png")); + navPrevImage->set_padding(0,0); + navPrev = Gtk::manage (new Gtk::Button ()); + navPrev->add(*navPrevImage); + navPrev->set_relief(Gtk::RELIEF_NONE); + navPrev->set_tooltip_markup(M("MAIN_BUTTON_NAVPREV_TOOLTIP")); + + Gtk::Image *navNextImage = Gtk::manage (new RTImage ("nav-next.png")); + navNextImage->set_padding(0,0); + navNext = Gtk::manage (new Gtk::Button ()); + navNext->add(*navNextImage); + navNext->set_relief(Gtk::RELIEF_NONE); + navNext->set_tooltip_markup(M("MAIN_BUTTON_NAVNEXT_TOOLTIP")); + + Gtk::Image *navSyncImage = Gtk::manage (new RTImage ("nav-sync.png")); + navSyncImage->set_padding(0,0); + navSync = Gtk::manage (new Gtk::Button ()); + navSync->add(*navSyncImage); + navSync->set_relief(Gtk::RELIEF_NONE); + navSync->set_tooltip_markup(M("MAIN_BUTTON_NAVSYNC_TOOLTIP")); + + if (!simpleEditor && !options.tabbedUI){ + iops->pack_end (*Gtk::manage(new Gtk::VSeparator()), Gtk::PACK_SHRINK, 0); + iops->pack_end (*navNext, Gtk::PACK_SHRINK, 0); + iops->pack_end (*navSync, Gtk::PACK_SHRINK, 0); + iops->pack_end (*navPrev, Gtk::PACK_SHRINK, 0); + } + editbox->pack_start (*Gtk::manage(new Gtk::HSeparator()), Gtk::PACK_SHRINK, 0); editbox->pack_start (*iops, Gtk::PACK_SHRINK, 0); editbox->show_all (); @@ -295,6 +324,10 @@ EditorPanel::EditorPanel (FilePanel* filePanel) 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) ); + navPrev->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::openPreviousEditorImage) ); + navNext->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::openNextEditorImage) ); + navSync->signal_pressed().connect( sigc::mem_fun(*this, &EditorPanel::syncFileBrowser) ); + ShowHideSidePanelsconn = tbShowHideSidePanels->signal_toggled().connect ( sigc::mem_fun(*this, &EditorPanel::toggleSidePanels), true); if (tbTopPanel_1) tbTopPanel_1->signal_toggled().connect( sigc::mem_fun(*this, &EditorPanel::tbTopPanel_1_toggled) ); @@ -866,7 +899,7 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) { case GDK_underscore: iareapanel->imageArea->zoomPanel->zoomOutClicked(); return true; - case GDK_1: + case GDK_z://GDK_1 iareapanel->imageArea->zoomPanel->zoom11Clicked(); return true; @@ -909,6 +942,18 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) { case GDK_F5: openThm->openDefaultViewer(event->state & GDK_SHIFT_MASK ? 2 : 1); return true; + case GDK_y: // synchronize filebrowser with image in Editor + if (!simpleEditor && fPanel && fname!=""){ + fPanel->fileCatalog->selectImage(fname, false); + return true; + } + break; // to avoid gcc complain + case GDK_x: // clear filters and synchronize filebrowser with image in Editor + if (!simpleEditor && fPanel && fname!=""){ + fPanel->fileCatalog->selectImage(fname, true); + return true; + } + break; // to avoid gcc complain } } else { @@ -949,12 +994,34 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event) { return true; } } + + if (shift){ + switch (event->keyval) { + case GDK_F3: // open Previous image from Editor's perspective + if (!simpleEditor && fPanel && fname!=""){ + EditorPanel::openPreviousEditorImage(); + return true; + } + break; // to avoid gcc complain + case GDK_F4: // open next image from Editor's perspective + if (!simpleEditor && fPanel && fname!=""){ + EditorPanel::openNextEditorImage(); + return true; + } + break; // to avoid gcc complain + } + } - if(tpc->getToolBar()->handleShortcutKey(event)) + if(tpc->getToolBar() && tpc->getToolBar()->handleShortcutKey(event)) return true; if(tpc->handleShortcutKey(event)) return true; + if (!simpleEditor && fPanel){ + if (fPanel->handleShortcutKey(event)) + return true; + } + return false; } @@ -1163,6 +1230,22 @@ void EditorPanel::sendToGimpPressed () { sendtogimp->set_sensitive(false); } + +void EditorPanel::openPreviousEditorImage() { + if (!simpleEditor && fPanel && fname!="") + fPanel->fileCatalog->openNextPreviousEditorImage(fname, true, NAV_PREVIOUS); +} + +void EditorPanel::openNextEditorImage() { + if (!simpleEditor && fPanel && fname!="") + fPanel->fileCatalog->openNextPreviousEditorImage(fname, true, NAV_NEXT); +} + +void EditorPanel::syncFileBrowser() { // synchronize filebrowser with image in Editor + if (!simpleEditor && fPanel && fname!="") + fPanel->fileCatalog->selectImage(fname, true); +} + bool EditorPanel::idle_sendToGimp( ProgressConnector *pc){ rtengine::IImage16* img = pc->returnValue(); diff --git a/rtgui/editorpanel.h b/rtgui/editorpanel.h index 2a56cbaf1..bd47e87d4 100644 --- a/rtgui/editorpanel.h +++ b/rtgui/editorpanel.h @@ -78,6 +78,9 @@ class EditorPanel : public Gtk::VBox, Gtk::Button* queueimg; Gtk::Button* saveimgas; Gtk::Button* sendtogimp; + Gtk::Button* navSync; + Gtk::Button* navNext; + Gtk::Button* navPrev; ImageAreaPanel* iareapanel; PreviewHandler* previewHandler; @@ -105,7 +108,7 @@ class EditorPanel : public Gtk::VBox, bool firstProcessingDone; Thumbnail* openThm; // may get invalid on external delete event - Glib::ustring fname; // must be safed seperately + Glib::ustring fname; // must be saved separately rtengine::InitialImage* isrc; rtengine::StagedImageProcessor* ipc; @@ -174,6 +177,9 @@ class EditorPanel : public Gtk::VBox, void saveAsPressed (); void queueImgPressed (); void sendToGimpPressed (); + void openNextEditorImage (); + void openPreviousEditorImage (); + void syncFileBrowser (); void tbTopPanel_1_visible (bool visible); bool CheckSidePanelsVisibility(); diff --git a/rtgui/filebrowser.cc b/rtgui/filebrowser.cc index f975c74bd..997c694af 100644 --- a/rtgui/filebrowser.cc +++ b/rtgui/filebrowser.cc @@ -808,38 +808,51 @@ void FileBrowser::openDefaultViewer (int destination) { bool FileBrowser::keyPressed (GdkEventKey* event) { - if ((event->keyval==GDK_C || event->keyval==GDK_c) && event->state & GDK_CONTROL_MASK) { + bool ctrl = event->state & GDK_CONTROL_MASK; + bool shift = event->state & GDK_SHIFT_MASK; + bool alt = event->state & GDK_MOD1_MASK; + + if ((event->keyval==GDK_C || event->keyval==GDK_c) && ctrl) { copyProfile (); return true; } - else if ((event->keyval==GDK_V || event->keyval==GDK_v) && event->state & GDK_CONTROL_MASK && !(event->state & GDK_SHIFT_MASK)) { + else if ((event->keyval==GDK_V || event->keyval==GDK_v) && ctrl && !shift) { pasteProfile (); return true; } - else if ((event->keyval==GDK_V || event->keyval==GDK_v) && event->state & GDK_CONTROL_MASK && event->state & GDK_SHIFT_MASK) { + else if ((event->keyval==GDK_V || event->keyval==GDK_v) && ctrl && shift) { partPasteProfile (); return true; } - else if (event->keyval==GDK_Delete && !(event->state & GDK_SHIFT_MASK)) { + else if (event->keyval==GDK_Delete && !shift) { menuItemActivated (trash); return true; } - else if (event->keyval==GDK_Delete && event->state & GDK_SHIFT_MASK) { + else if (event->keyval==GDK_Delete && shift) { menuItemActivated (untrash); return true; } - else if ((event->keyval==GDK_Q || event->keyval==GDK_q) && event->state & GDK_CONTROL_MASK) { + else if ((event->keyval==GDK_Q || event->keyval==GDK_q) && ctrl) { menuItemActivated (develop); return true; } - else if ((event->keyval==GDK_A || event->keyval==GDK_a) && event->state & GDK_CONTROL_MASK) { + else if ((event->keyval==GDK_A || event->keyval==GDK_a) && ctrl) { menuItemActivated (selall); return true; } - else if (event->keyval==GDK_F2 && !(event->state & GDK_CONTROL_MASK)) { + else if (event->keyval==GDK_F2 && !ctrl) { menuItemActivated (rename); return true; } + else if (event->keyval==GDK_F3 && !(ctrl || shift || alt)) { // open Previous image from FileBrowser perspective + FileBrowser::openPrevImage (); + return true; + } + else if (event->keyval==GDK_F4 && !(ctrl || shift || alt)) { // open Next image from FileBrowser perspective + FileBrowser::openNextImage (); + return true; + } + else if (event->keyval==GDK_F5) { int dest = 1; if (event->state & GDK_SHIFT_MASK) @@ -1103,51 +1116,151 @@ void FileBrowser::buttonPressed (LWButton* button, int actionCode, void* actionD } void FileBrowser::openNextImage () { - // TODO: Check for Linux - #ifdef WIN32 - Glib::RWLock::ReaderLock l(entryRW); - #endif + // TODO: Check for Linux + #ifdef WIN32 + Glib::RWLock::ReaderLock l(entryRW); + #endif - if (!fd.empty()) { - for (size_t i=fd.size()-1; i>0; i--) - if (editedFiles.find (fd[i]->filename)!=editedFiles.end()) - if (i entries; - entries.push_back ((static_cast(fd[i+1]))->thumbnail); - tbl->openRequested (entries); - return; + if (!fd.empty() && selected.size()>0 && !options.tabbedUI) { + + for (size_t i=0; ithumbnail->getFileName()==fd[i]->filename) {// located 1-st image in current selection + if (ifiltered/*checkFilter (fd[k])*/){ + // clear current selection + for (size_t j=0; jselected = false; + selected.clear (); + + // set new selection + fd[k]->selected = true; + selected.push_back (fd[k]); + //queue_draw (); + notifySelectionListener (); + + // scroll to the selected position + double h1, v1; + getScrollPosition(h1,v1); + + double h2=selected[0]->getStartX(); + double v2=selected[0]->getStartY(); + + // scroll only when selected[0] is outside of the displayed bounds + if (h2+fd[k]->getMinimalWidth()-h1 > get_width()) + setScrollPosition(h2-(get_width()-fd[k]->getMinimalWidth()),v2); + if (h1>h2) + setScrollPosition(h2,v2); + + // open the selected image + std::vector entries; + entries.push_back ((static_cast(fd[k]))->thumbnail); + tbl->openRequested (entries); + return; + } + } } - if (tbl) { - std::vector entries; - entries.push_back ((static_cast(fd[0]))->thumbnail); - tbl->openRequested (entries); + } } } } void FileBrowser::openPrevImage () { - // TODO: Check for Linux - #ifdef WIN32 - Glib::RWLock::ReaderLock l(entryRW); - #endif + // TODO: Check for Linux + #ifdef WIN32 + Glib::RWLock::ReaderLock l(entryRW); + #endif - if (!fd.empty()) { - for (size_t i=0; ifilename)!=editedFiles.end()) + if (!fd.empty() && selected.size()>0 && !options.tabbedUI) { + + for (size_t i=1; ithumbnail->getFileName()==fd[i]->filename) {// located 1-st image in current selection if (i>0 && tbl) { - std::vector entries; - entries.push_back ((static_cast(fd[i-1]))->thumbnail); - tbl->openRequested (entries); - return; + // find the first not-filtered-out (previous) image + for (size_t k=i-1; k>=0; k--){ + if (!fd[k]->filtered/*checkFilter (fd[k])*/){ + // clear current selection + for (size_t j=0; jselected = false; + selected.clear (); + + // set new selection + fd[k]->selected = true; + selected.push_back (fd[k]); + //queue_draw (); + notifySelectionListener (); + + // scroll to the selected position + double h1, v1; + getScrollPosition(h1,v1); + + double h2=selected[0]->getStartX(); + double v2=selected[0]->getStartY(); + + // scroll only when selected[0] is outside of the displayed bounds + if (h2+fd[k]->getMinimalWidth()-h1 > get_width()) + setScrollPosition(h2-(get_width()-fd[k]->getMinimalWidth()),v2); + if (h1>h2) + setScrollPosition(h2,v2); + + // open the selected image + std::vector entries; + entries.push_back ((static_cast(fd[k]))->thumbnail); + tbl->openRequested (entries); + return; + } + } } - if (tbl) { - std::vector entries; - entries.push_back ((static_cast(fd[fd.size()-1]))->thumbnail); - tbl->openRequested (entries); + } } } } + +void FileBrowser::selectImage (Glib::ustring fname) { + + // need to clear the filter in filecatalog + + if (!fd.empty() && !options.tabbedUI) { + for (size_t i=0; ifilename && !fd[i]->filtered) { + // matching file found for sync + + // clear current selection + for (size_t j=0; jselected = false; + selected.clear (); + + // set new selection + fd[i]->selected = true; + selected.push_back (fd[i]); + queue_draw (); + notifySelectionListener (); + + // scroll to the selected position + double h=selected[0]->getStartX(); + double v=selected[0]->getStartY(); + setScrollPosition(h,v); + + return; + } + } + } +} + +void FileBrowser::openNextPreviousEditorImage (Glib::ustring fname, eRTNav nextPrevious) { + + // let FileBrowser acquire Editor's perspective + selectImage (fname); + + // now switch to the requested image + if (nextPrevious==NAV_NEXT) + openNextImage(); + else if (nextPrevious==NAV_PREVIOUS) + openPrevImage(); +} + int refreshThumbImagesUI (void* data) { (static_cast(data))->_thumbRearrangementNeeded (); return 0; diff --git a/rtgui/filebrowser.h b/rtgui/filebrowser.h index 529b1f4a6..5188f19f9 100644 --- a/rtgui/filebrowser.h +++ b/rtgui/filebrowser.h @@ -154,6 +154,8 @@ class FileBrowser : public ThumbBrowserBase, void copyProfile (); void pasteProfile (); void partPasteProfile (); + void selectImage (Glib::ustring fname); + void openNextPreviousEditorImage (Glib::ustring fname, eRTNav eNextPrevious); void openDefaultViewer (int destination); diff --git a/rtgui/filecatalog.cc b/rtgui/filecatalog.cc index 65a2ae45e..3b5734e9f 100644 --- a/rtgui/filecatalog.cc +++ b/rtgui/filecatalog.cc @@ -94,6 +94,7 @@ FileCatalog::FileCatalog (CoarsePanel* cp, ToolBar* tb, FilePanel* filepanel) : hbToolBar1->pack_start (*hbBrowsePath, Gtk::PACK_EXPAND_WIDGET,0); BrowsePath->signal_activate().connect (sigc::mem_fun(*this, &FileCatalog::buttonBrowsePathPressed)); //respond to the Enter key + BrowsePath->signal_key_press_event().connect(sigc::mem_fun(*this, &FileCatalog::BrowsePath_key_pressed)); //setup Query iQueryClear = new RTImage("gtk-close-small.png"); @@ -487,7 +488,7 @@ void FileCatalog::dirSelected (const Glib::ustring& dirname, const Glib::ustring previewsToLoad = 0; previewsLoaded = 0; // if openfile exists, we have to open it first (it is a command line argument) - if (openfile!="") + if (!openfile.empty()) addAndOpenFile (openfile); selectedDirectory = dir->get_parse_name(); @@ -643,6 +644,17 @@ void FileCatalog::previewsFinishedUI () { fileBrowser->applyFilter (getFilter()); // refresh total image count _refreshProgressBar(); filepanel->loadingThumbs(M("PROGRESSBAR_READY"),0); + + if (!imageToSelect_fname.empty()){ + fileBrowser->selectImage(imageToSelect_fname); + imageToSelect_fname = ""; + } + + if (!refImageForOpen_fname.empty() && actionNextPrevious!=NAV_NONE){ + fileBrowser->openNextPreviousEditorImage(refImageForOpen_fname,actionNextPrevious); + refImageForOpen_fname = ""; + actionNextPrevious = NAV_NONE; + } } void FileCatalog::previewsFinished (int dir_id) { @@ -968,7 +980,7 @@ void FileCatalog::renameRequested (std::vector tbe) { continue; // if no extension is given, concatenate the extension of the original file Glib::ustring ext = getExtension (nBaseName); - if (ext=="") + if (ext.empty()) nBaseName += "." + getExtension (baseName); Glib::ustring nfname = Glib::build_filename (dirName, nBaseName); @@ -1061,6 +1073,9 @@ void FileCatalog::categoryButtonToggled (Gtk::ToggleButton* b, bool isMouseClick //was shift key pressed bool shift_down = modifierKey & GDK_SHIFT_MASK; + // The event is process here, we can clear modifierKey now, it'll be set again on the next even + modifierKey = 0; + for (int i=0; i<18; i++) bCateg[i].block (true); @@ -1337,7 +1352,7 @@ void FileCatalog::filterChanged () { void FileCatalog::reparseDirectory () { - if (selectedDirectory=="") + if (selectedDirectory.empty()) return; if (!safe_file_test (selectedDirectory, Glib::FILE_TEST_IS_DIR)) { @@ -1528,14 +1543,19 @@ void FileCatalog::executeQuery(){ } bool FileCatalog::Query_key_pressed (GdkEventKey *event){ - switch (event->keyval) - { - case GDK_Escape: - // Clear Query if the Escape character is pressed within it - FileCatalog::buttonQueryClearPressed (); - return true; - default: return false; - } + + bool shift = event->state & GDK_SHIFT_MASK; + + switch (event->keyval) { + case GDK_Escape: + // Clear Query if the Escape character is pressed within it + if (!shift){ + FileCatalog::buttonQueryClearPressed (); + return true; + } + default: + return false; + } } void FileCatalog::updateFBQueryTB (bool singleRow) { @@ -1573,7 +1593,7 @@ void FileCatalog::buttonBrowsePathPressed () { DecodedPathPrefix = safe_get_user_picture_dir(); } - if (DecodedPathPrefix!=""){ + if (!DecodedPathPrefix.empty()){ BrowsePathValue = Glib::ustring::compose ("%1%2",DecodedPathPrefix,BrowsePathValue.substr (1,BrowsePath->get_text_length()-1)); BrowsePath->set_text(BrowsePathValue); } @@ -1588,6 +1608,24 @@ void FileCatalog::buttonBrowsePathPressed () { buttonBrowsePath->set_image (*iRefreshRed); } +bool FileCatalog::BrowsePath_key_pressed (GdkEventKey *event){ + + bool shift = event->state & GDK_SHIFT_MASK; + + switch (event->keyval) { + case GDK_Escape: + // On Escape character Reset BrowsePath to selectedDirectory + if (!shift){ + BrowsePath->set_text(selectedDirectory); + // place cursor at the end + BrowsePath->select_region(BrowsePath->get_text_length(), BrowsePath->get_text_length()); + return true; + } + default: + return false; + } +} + void FileCatalog::tbLeftPanel_1_visible (bool visible){ if (visible) tbLeftPanel_1->show(); @@ -1638,6 +1676,65 @@ void FileCatalog::toggleSidePanels(){ tbRightPanel_1->set_active (!bAllSidePanelsVisible); } +void FileCatalog::selectImage (Glib::ustring fname, bool clearFilters) { + + Glib::ustring dirname = Glib::path_get_dirname(fname); + if (!dirname.empty()){ + BrowsePath->set_text(dirname); + + + if (clearFilters){ // clear all filters + Query->set_text(""); + categoryButtonToggled(bFilterClear,false); + // disable exif filters + if (filterPanel->isEnabled()) filterPanel->setEnabled (false); + } + + if (BrowsePath->get_text()!=selectedDirectory){ + // reload or refresh thumbs and select image + buttonBrowsePathPressed (); + // the actual selection of image will be handled asynchronously at the end of FileCatalog::previewsFinishedUI + imageToSelect_fname = fname; + } + else{ + // FileCatalog::filterChanged ();//this will be replaced by queue_draw() in fileBrowser->selectImage + fileBrowser->selectImage(fname); + imageToSelect_fname = ""; + } + } +} + + +void FileCatalog::openNextPreviousEditorImage (Glib::ustring fname, bool clearFilters, eRTNav nextPrevious) { + + Glib::ustring dirname = Glib::path_get_dirname(fname); + if (!dirname.empty()){ + BrowsePath->set_text(dirname); + + + if (clearFilters){ // clear all filters + Query->set_text(""); + categoryButtonToggled(bFilterClear,false); + // disable exif filters + if (filterPanel->isEnabled()) filterPanel->setEnabled (false); + } + + if (BrowsePath->get_text()!=selectedDirectory){ + // reload or refresh thumbs and select image + buttonBrowsePathPressed (); + // the actual selection of image will be handled asynchronously at the end of FileCatalog::previewsFinishedUI + refImageForOpen_fname = fname; + actionNextPrevious = nextPrevious; + } + else{ + // FileCatalog::filterChanged ();//this was replace by queue_draw() in fileBrowser->selectImage + fileBrowser->openNextPreviousEditorImage(fname,nextPrevious); + refImageForOpen_fname = ""; + actionNextPrevious = NAV_NONE; + } + } +} + bool FileCatalog::handleShortcutKey (GdkEventKey* event) { bool ctrl = event->state & GDK_CONTROL_MASK; @@ -1661,6 +1758,17 @@ bool FileCatalog::handleShortcutKey (GdkEventKey* event) { return true; } + if (shift){ + switch(event->keyval) { + case GDK_Escape: + BrowsePath->set_text(selectedDirectory); + // set focus on something neutral, this is useful to remove focus from BrowsePath and Query + // when need to execute a shortcut, which otherwise will be typed into those fields + filepanel->grab_focus(); + return true; + } + } + if (!alt) { switch(event->keyval) { case GDK_grave: @@ -1690,8 +1798,10 @@ bool FileCatalog::handleShortcutKey (GdkEventKey* event) { case GDK_Return: case GDK_KP_Enter: - FileCatalog::buttonBrowsePathPressed (); - return true; + if (BrowsePath->is_focus()){ + FileCatalog::buttonBrowsePathPressed (); + return true; + } } } @@ -1737,7 +1847,7 @@ bool FileCatalog::handleShortcutKey (GdkEventKey* event) { } } - if (!ctrl) { + if (!ctrl || (alt && !options.tabbedUI)) { switch(event->keyval) { case GDK_bracketright: @@ -1761,22 +1871,21 @@ bool FileCatalog::handleShortcutKey (GdkEventKey* event) { return true; } } - else { // with Ctrl + if (ctrl && !alt) { switch (event->keyval) { - case GDK_o: - if (!alt){ - BrowsePath->select_region(0, BrowsePath->get_text_length()); - BrowsePath->grab_focus(); - return true; - } - case GDK_f: - if (!alt){ - Query->select_region(0, Query->get_text_length()); - Query->grab_focus(); - return true; - } + case GDK_o: + BrowsePath->select_region(0, BrowsePath->get_text_length()); + BrowsePath->grab_focus(); + return true; + case GDK_f: + Query->select_region(0, Query->get_text_length()); + Query->grab_focus(); + return true; } } + if (fileBrowser->keyPressed(event)) + return true; + return false; } diff --git a/rtgui/filecatalog.h b/rtgui/filecatalog.h index b53fb4324..83a5e2381 100644 --- a/rtgui/filecatalog.h +++ b/rtgui/filecatalog.h @@ -74,6 +74,9 @@ class FileCatalog : public Gtk::VBox, int selectedDirectoryId; bool enabled; bool inTabMode; // Tab mode has e.g. different progress bar handling + Glib::ustring imageToSelect_fname; + Glib::ustring refImageForOpen_fname; // Next/previous for Editor's perspective + eRTNav actionNextPrevious; FileSelectionListener* listener; FileSelectionChangeListener* fslistener; @@ -223,6 +226,7 @@ class FileCatalog : public Gtk::VBox, void zoomOut (); void buttonBrowsePathPressed (); + bool BrowsePath_key_pressed (GdkEventKey *event); void buttonQueryClearPressed (); void executeQuery (); bool Query_key_pressed(GdkEventKey *event); @@ -234,7 +238,9 @@ class FileCatalog : public Gtk::VBox, void tbRightPanel_1_visible (bool visible); void openNextImage () { fileBrowser->openNextImage(); } - void openPrevImage () { fileBrowser->openPrevImage(); } + void openPrevImage () { fileBrowser->openPrevImage(); } + void selectImage (Glib::ustring fname, bool clearFilters); + void openNextPreviousEditorImage (Glib::ustring fname, bool clearFilters, eRTNav nextPrevious); bool handleShortcutKey (GdkEventKey* event); diff --git a/rtgui/filterpanel.h b/rtgui/filterpanel.h index 4f3c86a78..3d2303b0c 100644 --- a/rtgui/filterpanel.h +++ b/rtgui/filterpanel.h @@ -24,8 +24,8 @@ class FilterPanelListener { - public: - virtual void exifFilterChanged () {} + public: + virtual void exifFilterChanged () {} }; class FilterPanel : public Gtk::VBox { @@ -43,33 +43,33 @@ class FilterPanel : public Gtk::VBox { 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* enaExpComp; - Gtk::CheckButton* enaCamera; - Gtk::CheckButton* enaLens; - Gtk::CheckButton* enaFiletype; + Gtk::CheckButton* enabled; + Gtk::CheckButton* enaFNumber; + Gtk::CheckButton* enaShutter; + Gtk::CheckButton* enaFocalLen; + Gtk::CheckButton* enaISO; + Gtk::CheckButton* enaExpComp; + Gtk::CheckButton* enaCamera; + Gtk::CheckButton* enaLens; + Gtk::CheckButton* enaFiletype; - int conns; - sigc::connection sChange[22]; - - ExifFilterSettings curefs; - FilterPanelListener* listener; - - public: - FilterPanel (); - - void setFilterPanelListener (FilterPanelListener* l) { listener = l; } - - void setFilter (ExifFilterSettings& defefs, bool updateLists); + int conns; + sigc::connection sChange[22]; + + ExifFilterSettings curefs; + FilterPanelListener* listener; + + public: + FilterPanel (); + + void setFilterPanelListener (FilterPanelListener* l) { listener = l; } + + void setFilter (ExifFilterSettings& defefs, bool updateLists); ExifFilterSettings getFilter (); - bool isEnabled (); - - - void valueChanged (); + bool isEnabled (); + + void valueChanged (); + void setEnabled(bool enabledState){enabled->set_active(enabledState);} }; #endif diff --git a/rtgui/guiutils.h b/rtgui/guiutils.h index c2f400419..45eaf99ef 100644 --- a/rtgui/guiutils.h +++ b/rtgui/guiutils.h @@ -187,6 +187,12 @@ enum TOITypes { TOI_ICON }; +typedef enum RTNav { + NAV_NONE, + NAV_NEXT, + NAV_PREVIOUS +} eRTNav; + /** * @brief Handle the switch between text and image to be displayed in the HBox (to be used in a button/toolpanel) */ diff --git a/rtgui/toolbar.cc b/rtgui/toolbar.cc index de852e63d..c90677dcd 100644 --- a/rtgui/toolbar.cc +++ b/rtgui/toolbar.cc @@ -93,8 +93,9 @@ void ToolBar::setTool (ToolMode tool) { handTool->set_active (true); handTool->grab_focus();; // switch focus to the handTool button } - else if (tool==TMSpotWB) + else if (tool==TMSpotWB) { if (wbTool) wbTool->set_active (true); + } else if (tool==TMCropSelect) cropTool->set_active (true); else if (tool==TMStraighten) @@ -199,7 +200,7 @@ void ToolBar::stra_pressed () { bool ToolBar::handleShortcutKey (GdkEventKey* event) { bool ctrl = event->state & GDK_CONTROL_MASK; - bool shift = event->state & GDK_SHIFT_MASK; + //bool shift = event->state & GDK_SHIFT_MASK; bool alt = event->state & GDK_MOD1_MASK; if (!ctrl && !alt) { diff --git a/tools/source_icons/scalable/nav-next.file b/tools/source_icons/scalable/nav-next.file new file mode 100644 index 000000000..cf444112a --- /dev/null +++ b/tools/source_icons/scalable/nav-next.file @@ -0,0 +1 @@ +nav-next.png,w19,actions \ No newline at end of file diff --git a/tools/source_icons/scalable/nav-next.svg b/tools/source_icons/scalable/nav-next.svg new file mode 100644 index 000000000..123f334d9 --- /dev/null +++ b/tools/source_icons/scalable/nav-next.svg @@ -0,0 +1,649 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/tools/source_icons/scalable/nav-prev.file b/tools/source_icons/scalable/nav-prev.file new file mode 100644 index 000000000..0c9254b3c --- /dev/null +++ b/tools/source_icons/scalable/nav-prev.file @@ -0,0 +1 @@ +nav-prev.png,w19,actions \ No newline at end of file diff --git a/tools/source_icons/scalable/nav-prev.svg b/tools/source_icons/scalable/nav-prev.svg new file mode 100644 index 000000000..4112c31fb --- /dev/null +++ b/tools/source_icons/scalable/nav-prev.svg @@ -0,0 +1,649 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + diff --git a/tools/source_icons/scalable/nav-sync.file b/tools/source_icons/scalable/nav-sync.file new file mode 100644 index 000000000..7a0e01b10 --- /dev/null +++ b/tools/source_icons/scalable/nav-sync.file @@ -0,0 +1 @@ +nav-sync.png,w14,actions \ No newline at end of file diff --git a/tools/source_icons/scalable/nav-sync.svg b/tools/source_icons/scalable/nav-sync.svg new file mode 100644 index 000000000..420e2c335 --- /dev/null +++ b/tools/source_icons/scalable/nav-sync.svg @@ -0,0 +1,833 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + +