2 * This file is part of RawTherapee.
4 * Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
6 * RawTherapee is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * RawTherapee is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
19 #include <filebrowser.h>
22 #include <multilangmgr.h>
23 #include <clipboard.h>
24 #include <profilestore.h>
25 #include <procparamchangers.h>
27 FileBrowser::FileBrowser ()
30 fbih
= new FileBrowserIdleHelper
;
31 fbih
->fbrowser
= this;
32 fbih
->destroyed
= false;
35 profileStore
.parseProfiles ();
37 signal_style_changed().connect( sigc::mem_fun(*this, &FileBrowser::styleChanged
) );
40 pmenu
= new Gtk::Menu ();
41 pmenu
->attach (*(open
= new Gtk::MenuItem (M("FILEBROWSER_POPUPOPEN"))), 0, 1, p
, p
+1); p
++;
42 pmenu
->attach (*(develop
= new Gtk::MenuItem (M("FILEBROWSER_POPUPPROCESS"))), 0, 1, p
, p
+1); p
++;
43 pmenu
->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p
, p
+1); p
++;
44 pmenu
->attach (*(rank
[0] = new Gtk::MenuItem (M("FILEBROWSER_POPUPUNRANK"))), 0, 1, p
, p
+1); p
++;
45 pmenu
->attach (*(rank
[1] = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK1"))), 0, 1, p
, p
+1); p
++;
46 pmenu
->attach (*(rank
[2] = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK2"))), 0, 1, p
, p
+1); p
++;
47 pmenu
->attach (*(rank
[3] = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK3"))), 0, 1, p
, p
+1); p
++;
48 pmenu
->attach (*(rank
[4] = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK4"))), 0, 1, p
, p
+1); p
++;
49 pmenu
->attach (*(rank
[5] = new Gtk::MenuItem (M("FILEBROWSER_POPUPRANK5"))), 0, 1, p
, p
+1); p
++;
50 pmenu
->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p
, p
+1); p
++;
51 pmenu
->attach (*(trash
= new Gtk::MenuItem (M("FILEBROWSER_POPUPTRASH"))), 0, 1, p
, p
+1); p
++;
52 pmenu
->attach (*(untrash
= new Gtk::MenuItem (M("FILEBROWSER_POPUPUNTRASH"))), 0, 1, p
, p
+1); p
++;
53 pmenu
->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p
, p
+1); p
++;
54 pmenu
->attach (*(rename
= new Gtk::MenuItem (M("FILEBROWSER_POPUPRENAME"))), 0, 1, p
, p
+1); p
++;
55 pmenu
->attach (*(remove
= new Gtk::MenuItem (M("FILEBROWSER_POPUPREMOVE"))), 0, 1, p
, p
+1); p
++;
56 pmenu
->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p
, p
+1); p
++;
57 pmenu
->attach (*(selall
= new Gtk::MenuItem (M("FILEBROWSER_POPUPSELECTALL"))), 0, 1, p
, p
+1); p
++;
58 pmenu
->attach (*(new Gtk::SeparatorMenuItem ()), 0, 1, p
, p
+1); p
++;
59 pmenu
->attach (*(copyprof
= new Gtk::MenuItem (M("FILEBROWSER_COPYPROFILE"))), 0, 1, p
, p
+1); p
++;
60 pmenu
->attach (*(pasteprof
= new Gtk::MenuItem (M("FILEBROWSER_PASTEPROFILE"))), 0, 1, p
, p
+1); p
++;
61 pmenu
->attach (*(partpasteprof
= new Gtk::MenuItem (M("FILEBROWSER_PARTIALPASTEPROFILE"))), 0, 1, p
, p
+1); p
++;
62 pmenu
->attach (*(applyprof
= new Gtk::MenuItem (M("FILEBROWSER_APPLYPROFILE"))), 0, 1, p
, p
+1); p
++;
63 pmenu
->attach (*(clearprof
= new Gtk::MenuItem (M("FILEBROWSER_CLEARPROFILE"))), 0, 1, p
, p
+1); p
++;
66 pmaccelgroup
= Gtk::AccelGroup::create ();
67 pmenu
->set_accel_group (pmaccelgroup
);
68 selall
->add_accelerator ("activate", pmenu
->get_accel_group(), GDK_a
, Gdk::CONTROL_MASK
, Gtk::ACCEL_VISIBLE
);
69 trash
->add_accelerator ("activate", pmenu
->get_accel_group(), GDK_Delete
, (Gdk::ModifierType
)0, Gtk::ACCEL_VISIBLE
);
70 untrash
->add_accelerator ("activate", pmenu
->get_accel_group(), GDK_Delete
, Gdk::SHIFT_MASK
, Gtk::ACCEL_VISIBLE
);
71 develop
->add_accelerator ("activate", pmenu
->get_accel_group(), GDK_Q
, Gdk::CONTROL_MASK
, Gtk::ACCEL_VISIBLE
);
72 copyprof
->add_accelerator ("activate", pmenu
->get_accel_group(), GDK_C
, Gdk::CONTROL_MASK
, Gtk::ACCEL_VISIBLE
);
73 pasteprof
->add_accelerator ("activate", pmenu
->get_accel_group(), GDK_V
, Gdk::CONTROL_MASK
, Gtk::ACCEL_VISIBLE
);
74 partpasteprof
->add_accelerator ("activate", pmenu
->get_accel_group(), GDK_V
, Gdk::CONTROL_MASK
| Gdk::SHIFT_MASK
, Gtk::ACCEL_VISIBLE
);
76 profmenu
= new Gtk::Menu ();
78 open
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), open
));
79 for (int i
=0; i
<6; i
++)
80 rank
[i
]->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), rank
[i
]));
81 trash
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), trash
));
82 untrash
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), untrash
));
83 develop
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), develop
));
84 rename
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), rename
));
85 remove
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), remove
));
86 selall
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), selall
));
87 copyprof
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), copyprof
));
88 pasteprof
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), pasteprof
));
89 partpasteprof
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), partpasteprof
));
90 applyprof
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), applyprof
));
91 clearprof
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::menuItemActivated
), clearprof
));
94 void FileBrowser::rightClicked (ThumbBrowserEntryBase
* entry
) {
96 trash
->set_sensitive (false);
97 untrash
->set_sensitive (false);
98 for (int i
=0; i
<selected
.size(); i
++)
99 if (((FileBrowserEntry
*)selected
[i
])->thumbnail
->getStage()==1) {
100 untrash
->set_sensitive (true);
103 for (int i
=0; i
<selected
.size(); i
++)
104 if (((FileBrowserEntry
*)selected
[i
])->thumbnail
->getStage()==0) {
105 trash
->set_sensitive (true);
109 pasteprof
->set_sensitive (clipboard
.hasProcParams());
110 partpasteprof
->set_sensitive (clipboard
.hasProcParams());
111 copyprof
->set_sensitive (selected
.size()==1);
112 clearprof
->set_sensitive (selected
.size()>0);
115 Gtk::Menu
* applmenu
= Gtk::manage (new Gtk::Menu ());
116 std::vector
<Glib::ustring
> profnames
= profileStore
.getProfileNames ();
117 for (int i
=0; i
<profnames
.size(); i
++) {
118 Gtk::MenuItem
* mi
= Gtk::manage (new Gtk::MenuItem (profnames
[i
]));
119 applmenu
->attach (*mi
, 0, 1, p
, p
+1); p
++;
120 mi
->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &FileBrowser::applyMenuItemActivated
), profnames
[i
]));
123 applyprof
->set_submenu (*applmenu
);
125 pmenu
->popup (3, this->eventTime
);
128 void FileBrowser::doubleClicked (ThumbBrowserEntryBase
* entry
) {
131 std::vector
<Thumbnail
*> entries
;
132 entries
.push_back (((FileBrowserEntry
*)entry
)->thumbnail
);
133 tbl
->openRequested (entries
);
138 FileBrowserIdleHelper
* fbih
;
139 FileBrowserEntry
* entry
;
142 int addfl (void* data
) {
144 addparams
* ap
= (addparams
*) data
;
145 FileBrowserIdleHelper
* fbih
= ap
->fbih
;
149 if (fbih
->destroyed
) {
150 if (fbih
->pending
== 1)
156 gdk_threads_leave ();
160 ap
->fbih
->fbrowser
->addEntry_ (ap
->entry
);
167 void FileBrowser::addEntry (FileBrowserEntry
* entry
) {
170 entry
->setParent (this);
171 addparams
* ap
= new addparams
;
174 g_idle_add (addfl
, ap
);
177 void FileBrowser::addEntry_ (FileBrowserEntry
* entry
) {
179 entry
->selected
= false;
180 entry
->drawable
= false;
181 entry
->framed
= editedFiles
.find (entry
->filename
)!=editedFiles
.end();
183 // add button set to the thumbbrowserentry
184 entry
->addButtonSet (new FileThumbnailButtonSet (entry
));
185 entry
->getThumbButtonSet()->setRank (entry
->thumbnail
->getRank());
186 entry
->getThumbButtonSet()->setInTrash (entry
->thumbnail
->getStage()==1);
187 entry
->getThumbButtonSet()->setButtonListener (this);
188 entry
->resize (options
.thumbSize
);
190 // find place in abc order
191 std::vector
<ThumbBrowserEntryBase
*>::iterator i
= fd
.begin();
192 while (i
!=fd
.end() && *entry
< *((FileBrowserEntry
*)*i
))
195 fd
.insert (i
, entry
);
201 FileBrowserEntry
* FileBrowser::delEntry (const Glib::ustring
& fname
) {
203 for (std::vector
<ThumbBrowserEntryBase
*>::iterator i
=fd
.begin(); i
!=fd
.end(); i
++)
204 if ((*i
)->filename
==fname
) {
205 ThumbBrowserEntryBase
* entry
= *i
;
206 entry
->selected
= false;
208 std::vector
<ThumbBrowserEntryBase
*>::iterator j
= std::find (selected
.begin(), selected
.end(), entry
);
209 if (j
!=selected
.end()) {
211 notifySelectionListener ();
213 if (lastClicked
==entry
)
216 return (FileBrowserEntry
*)entry
;
221 FileBrowserEntry
* FileBrowser::findEntry (const Glib::ustring
& fname
) {
223 for (std::vector
<ThumbBrowserEntryBase
*>::iterator i
=fd
.begin(); i
!=fd
.end(); i
++)
224 if ((*i
)->filename
==fname
)
225 return (FileBrowserEntry
*)*i
;
229 void FileBrowser::close () {
231 fbih
->destroyed
= true;
235 fbih
= new FileBrowserIdleHelper
;
236 fbih
->fbrowser
= this;
237 fbih
->destroyed
= false;
240 for (int i
=0; i
<fd
.size(); i
++)
244 notifySelectionListener ();
246 for (int i
=0; i
<fd
.size(); i
++)
247 ((FileBrowserEntry
*)fd
[i
])->thumbnail
->decreaseRef ();
250 void FileBrowser::menuItemActivated (Gtk::MenuItem
* m
) {
252 std::vector
<FileBrowserEntry
*> mselected
;
253 for (int i
=0; i
<selected
.size(); i
++)
254 mselected
.push_back ((FileBrowserEntry
*)selected
[i
]);
256 if (!tbl
|| (m
!=selall
&& mselected
.size()==0) )
259 for (int i
=0; i
<6; i
++)
261 rankingRequested (mselected
, i
);
265 std::vector
<Thumbnail
*> entries
;
266 for (int i
=0; i
<mselected
.size(); i
++)
267 entries
.push_back (mselected
[i
]->thumbnail
);
268 tbl
->openRequested (entries
);
271 tbl
->deleteRequested (mselected
);
273 toTrashRequested (mselected
);
275 fromTrashRequested (mselected
);
277 tbl
->developRequested (mselected
);
279 tbl
->renameRequested (mselected
);
280 else if (m
==selall
) {
283 for (int i
=0; i
<fd
.size(); i
++)
284 if (checkFilter (fd
[i
])) {
285 fd
[i
]->selected
= true;
286 selected
.push_back (fd
[i
]);
289 notifySelectionListener ();
291 else if (m
==copyprof
)
293 else if (m
==pasteprof
)
295 else if (m
==partpasteprof
)
297 else if (m
==clearprof
) {
298 for (int i
=0; i
<mselected
.size(); i
++)
299 mselected
[i
]->thumbnail
->clearProcParams (FILEBROWSER
);
304 void FileBrowser::copyProfile () {
306 if (selected
.size()==1)
307 clipboard
.setProcParams (((FileBrowserEntry
*)selected
[0])->thumbnail
->getProcParams());
310 void FileBrowser::pasteProfile () {
312 std::vector
<FileBrowserEntry
*> mselected
;
313 for (int i
=0; i
<selected
.size(); i
++)
314 mselected
.push_back ((FileBrowserEntry
*)selected
[i
]);
316 if (!tbl
|| mselected
.size()==0)
319 for (int i
=0; i
<mselected
.size(); i
++)
320 mselected
[i
]->thumbnail
->setProcParams (clipboard
.getProcParams(), FILEBROWSER
);
325 void FileBrowser::partPasteProfile () {
327 std::vector
<FileBrowserEntry
*> mselected
;
328 for (int i
=0; i
<selected
.size(); i
++)
329 mselected
.push_back ((FileBrowserEntry
*)selected
[i
]);
331 if (!tbl
|| mselected
.size()==0)
334 if (partialPasteDlg
.run ()) {
336 for (int i
=0; i
<mselected
.size(); i
++) {
337 rtengine::procparams::ProcParams params
= mselected
[i
]->thumbnail
->getProcParams ();
338 partialPasteDlg
.applyPaste (¶ms
, &clipboard
.getProcParams());
339 mselected
[i
]->thumbnail
->setProcParams (params
, FILEBROWSER
);
344 partialPasteDlg
.hide ();
347 bool FileBrowser::keyPressed (GdkEventKey
* event
) {
349 if ((event
->keyval
==GDK_C
|| event
->keyval
==GDK_c
) && event
->state
& GDK_CONTROL_MASK
) {
353 else if ((event
->keyval
==GDK_V
|| event
->keyval
==GDK_v
) && event
->state
& GDK_CONTROL_MASK
&& !(event
->state
& GDK_SHIFT_MASK
)) {
357 else if ((event
->keyval
==GDK_V
|| event
->keyval
==GDK_v
) && event
->state
& GDK_CONTROL_MASK
&& event
->state
& GDK_SHIFT_MASK
) {
361 else if (event
->keyval
==GDK_Delete
&& !(event
->state
& GDK_SHIFT_MASK
)) {
362 menuItemActivated (trash
);
365 else if (event
->keyval
==GDK_Delete
&& event
->state
& GDK_SHIFT_MASK
) {
366 menuItemActivated (untrash
);
369 else if ((event
->keyval
==GDK_Q
|| event
->keyval
==GDK_q
) && event
->state
& GDK_CONTROL_MASK
) {
370 menuItemActivated (develop
);
373 else if ((event
->keyval
==GDK_A
|| event
->keyval
==GDK_a
) && event
->state
& GDK_CONTROL_MASK
) {
374 menuItemActivated (selall
);
381 void FileBrowser::applyMenuItemActivated (Glib::ustring ppname
) {
383 rtengine::procparams::ProcParams
* pparams
= profileStore
.getProfile (ppname
);
384 if (pparams
&& selected
.size()>0) {
385 for (int i
=0; i
<selected
.size(); i
++)
386 ((FileBrowserEntry
*)selected
[i
])->thumbnail
->setProcParams (*pparams
, FILEBROWSER
);
391 void FileBrowser::applyFilter (const BrowserFilter
& filter
) {
393 this->filter
= filter
;
395 // remove items not complying the filter from the selection
396 bool selchanged
= false;
397 for (int i
=0; i
<fd
.size(); i
++)
398 if (fd
[i
]->selected
&& !checkFilter (fd
[i
])) {
399 fd
[i
]->selected
= false;
400 std::vector
<ThumbBrowserEntryBase
*>::iterator j
= std::find (selected
.begin(), selected
.end(), fd
[i
]);
402 if (lastClicked
==fd
[i
])
407 notifySelectionListener ();
411 bool FileBrowser::checkFilter (ThumbBrowserEntryBase
* entryb
) { // true -> entry complies filter
413 FileBrowserEntry
* entry
= (FileBrowserEntry
*)entryb
;
414 // return false if basic filter settings are not satisfied
415 if (filter
.showRanked
[entry
->thumbnail
->getRank()]==false || (entry
->thumbnail
->getStage()==1 && !filter
.showTrash
) || (entry
->thumbnail
->getStage()==0 && !filter
.showNotTrash
))
419 const CacheImageData
* cfs
= entry
->thumbnail
->getCacheImageData();
423 if (!filter
.exifFilterEnabled
)
427 return (!filter
.exifFilter
.filterCamera
|| filter
.exifFilter
.cameras
.count(cfs
->camera
)>0)
428 && (!filter
.exifFilter
.filterLens
|| filter
.exifFilter
.lenses
.count(cfs
->lens
)>0);
431 (!filter
.exifFilter
.filterShutter
|| (rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs
->shutter
)) >= filter
.exifFilter
.shutterFrom
-tol2
&& rtengine::ImageMetaData::shutterFromString(rtengine::ImageMetaData::shutterToString(cfs
->shutter
)) <= filter
.exifFilter
.shutterTo
+tol2
))
432 && (!filter
.exifFilter
.filterFNumber
|| (rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs
->fnumber
)) >= filter
.exifFilter
.fnumberFrom
-tol2
&& rtengine::ImageMetaData::apertureFromString(rtengine::ImageMetaData::apertureToString(cfs
->fnumber
)) <= filter
.exifFilter
.fnumberTo
+tol2
))
433 && (!filter
.exifFilter
.filterFocalLen
|| (cfs
->focalLen
>= filter
.exifFilter
.focalFrom
-tol
&& cfs
->focalLen
<= filter
.exifFilter
.focalTo
+tol
))
434 && (!filter
.exifFilter
.filterISO
|| (cfs
->iso
>= filter
.exifFilter
.isoFrom
&& cfs
->iso
<= filter
.exifFilter
.isoTo
))
435 && (!filter
.exifFilter
.filterCamera
|| filter
.exifFilter
.cameras
.count(cfs
->camera
)>0)
436 && (!filter
.exifFilter
.filterLens
|| filter
.exifFilter
.lenses
.count(cfs
->lens
)>0);
439 void FileBrowser::toTrashRequested (std::vector
<FileBrowserEntry
*> tbe
) {
441 for (int i
=0; i
<tbe
.size(); i
++) {
442 if (tbe
[i
]->thumbnail
->getStage()==1)
444 tbe
[i
]->thumbnail
->setStage (1);
445 if (tbe
[i
]->getThumbButtonSet()) {
446 tbe
[i
]->getThumbButtonSet()->setRank (tbe
[i
]->thumbnail
->getRank());
447 tbe
[i
]->getThumbButtonSet()->setInTrash (true);
450 applyFilter (filter
);
453 void FileBrowser::fromTrashRequested (std::vector
<FileBrowserEntry
*> tbe
) {
455 for (int i
=0; i
<tbe
.size(); i
++) {
456 if (tbe
[i
]->thumbnail
->getStage()==0)
458 tbe
[i
]->thumbnail
->setStage (0);
459 if (tbe
[i
]->getThumbButtonSet()) {
460 tbe
[i
]->getThumbButtonSet()->setRank (tbe
[i
]->thumbnail
->getRank());
461 tbe
[i
]->getThumbButtonSet()->setInTrash (false);
464 applyFilter (filter
);
467 void FileBrowser::rankingRequested (std::vector
<FileBrowserEntry
*> tbe
, int rank
) {
469 for (int i
=0; i
<tbe
.size(); i
++) {
470 tbe
[i
]->thumbnail
->setRank (rank
);
471 if (tbe
[i
]->getThumbButtonSet())
472 tbe
[i
]->getThumbButtonSet()->setRank (tbe
[i
]->thumbnail
->getRank());
474 applyFilter (filter
);
477 void FileBrowser::buttonPressed (LWButton
* button
, int actionCode
, void* actionData
) {
479 if (actionCode
>=0 && actionCode
<=5) { // rank
480 std::vector
<FileBrowserEntry
*> tbe
;
481 tbe
.push_back ((FileBrowserEntry
*)actionData
);
482 rankingRequested (tbe
, actionCode
);
484 else if (actionCode
==6 && tbl
) { // to processin queue
485 std::vector
<FileBrowserEntry
*> tbe
;
486 tbe
.push_back ((FileBrowserEntry
*)actionData
);
487 tbl
->developRequested (tbe
);
489 else if (actionCode
==7) { // to trash / undelete
490 std::vector
<FileBrowserEntry
*> tbe
;
491 FileBrowserEntry
* entry
= (FileBrowserEntry
*)actionData
;
492 tbe
.push_back (entry
);
493 if (entry
->thumbnail
->getStage()==0)
494 toTrashRequested (tbe
);
496 fromTrashRequested (tbe
);
500 void FileBrowser::openNextImage () {
503 for (int i
=fd
.size()-1; i
>=0; i
--)
504 if (editedFiles
.find (fd
[i
]->filename
)!=editedFiles
.end())
505 if (i
<fd
.size()-1 && tbl
) {
506 std::vector
<Thumbnail
*> entries
;
507 entries
.push_back (((FileBrowserEntry
*)fd
[i
+1])->thumbnail
);
508 tbl
->openRequested (entries
);
512 std::vector
<Thumbnail
*> entries
;
513 entries
.push_back (((FileBrowserEntry
*)fd
[0])->thumbnail
);
514 tbl
->openRequested (entries
);
519 void FileBrowser::openPrevImage () {
522 for (int i
=0; i
<fd
.size(); i
++)
523 if (editedFiles
.find (fd
[i
]->filename
)!=editedFiles
.end())
525 std::vector
<Thumbnail
*> entries
;
526 entries
.push_back (((FileBrowserEntry
*)fd
[i
-1])->thumbnail
);
527 tbl
->openRequested (entries
);
531 std::vector
<Thumbnail
*> entries
;
532 entries
.push_back (((FileBrowserEntry
*)fd
[fd
.size()-1])->thumbnail
);
533 tbl
->openRequested (entries
);
538 int redrawtb (void* data
) {
540 ((FileBrowser
*)data
)->_thumbRearrangementNeeded ();
544 void FileBrowser::_thumbRearrangementNeeded () {
546 refreshThumbImages ();
549 void FileBrowser::thumbRearrangementNeeded () {
551 g_idle_add (redrawtb
, this);
553 void FileBrowser::selectionChanged () {
555 notifySelectionListener ();
558 void FileBrowser::notifySelectionListener () {
561 std::vector
<Thumbnail
*> thm
;
562 for (int i
=0; i
<selected
.size(); i
++)
563 thm
.push_back (((FileBrowserEntry
*)selected
[i
])->thumbnail
);
564 tbl
->selectionChanged (thm
);
568 void FileBrowser::redrawNeeded (ThumbBrowserEntryBase
* entry
) {
570 if (entry
->insideWindow (0, 0, internal
.get_width(), internal
.get_height())) {
571 if (!internal
.isDirty ()) {
572 internal
.setDirty ();
573 internal
.queue_draw ();
578 void FileBrowser::redrawNeeded (LWButton
* button
) {