Proper check for rawzor libraries.
[rawtherapee-fixes.git] / rtgui / dirbrowser.cc
blobcbe0cc03533c9f1bd1d6d8a4efa657969e715dd2
1 /*
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 <dirbrowser.h>
20 #ifdef WIN32
21 #define _WIN32_WINNT 0x0600
22 #include <windows.h>
23 #endif
24 #include <options.h>
25 #include "config.h"
27 #define CHECKTIME 5000
28 extern Glib::ustring argv0;
30 DirBrowser::DirBrowser () {
32 dirtree = new Gtk::TreeView();
33 scrolledwindow4 = new Gtk::ScrolledWindow();
35 // dirtree->set_flags(Gtk::CAN_FOCUS);
36 dirtree->set_headers_visible(false);
37 dirtree->set_rules_hint(false);
38 dirtree->set_reorderable(false);
39 dirtree->set_enable_search(false);
40 scrolledwindow4->set_flags(Gtk::CAN_FOCUS);
41 scrolledwindow4->set_border_width(2);
42 scrolledwindow4->set_shadow_type(Gtk::SHADOW_NONE);
43 scrolledwindow4->set_policy(Gtk::POLICY_ALWAYS, Gtk::POLICY_ALWAYS);
44 scrolledwindow4->property_window_placement().set_value(Gtk::CORNER_TOP_LEFT);
45 scrolledwindow4->add(*dirtree);
47 pack_start (*scrolledwindow4);
48 dirtree->show ();
49 scrolledwindow4->show ();
52 void DirBrowser::fillDirTree () {
54 openfolder = Gdk::Pixbuf::create_from_file (GET_DATA_PATH(argv0)+"/images/folder_open.png");
55 closedfolder = Gdk::Pixbuf::create_from_file (GET_DATA_PATH(argv0)+"/images/folder.png");
56 icdrom = Gdk::Pixbuf::create_from_file (GET_DATA_PATH(argv0)+"/images/cdrom.png");
57 ifloppy = Gdk::Pixbuf::create_from_file (GET_DATA_PATH(argv0)+"/images/floppy.png");
58 ihdd = Gdk::Pixbuf::create_from_file (GET_DATA_PATH(argv0)+"/images/hdd.png");
59 iremovable = Gdk::Pixbuf::create_from_file (GET_DATA_PATH(argv0)+"/images/usbpendrive.png");
60 inetwork = Gdk::Pixbuf::create_from_file (GET_DATA_PATH(argv0)+"/images/network.png");
62 //Create the Tree model:
63 dirTreeModel = Gtk::TreeStore::create(dtColumns);
64 dirtree->set_model (dirTreeModel);
66 fillRoot ();
68 Gtk::CellRendererPixbuf* render_pb = new Gtk::CellRendererPixbuf ();
69 tvc.pack_start (*render_pb, false);
70 tvc.add_attribute(*render_pb, "pixbuf-expander-closed", 1);
71 tvc.add_attribute(*render_pb, "pixbuf", 1);
72 tvc.add_attribute(*render_pb, "pixbuf-expander-open", 0);
73 tvc.pack_start (crt);
74 tvc.add_attribute(crt, "text", 2);
76 crt.property_ypad() = 0;
77 render_pb->property_ypad() = 0;
79 dirtree->append_column(tvc);
81 dirtree->signal_row_expanded().connect(sigc::mem_fun(*this, &DirBrowser::row_expanded));
82 dirtree->signal_row_activated().connect(sigc::mem_fun(*this, &DirBrowser::row_activated));
85 #ifdef WIN32
86 void DirBrowser::addRoot (char letter) {
88 char volume[4];
89 volume[0] = letter;
90 strcpy (volume+1, ":\\");
92 Gtk::TreeModel::iterator root = dirTreeModel->append();
93 root->set_value (dtColumns.filename, Glib::ustring(volume));
94 root->set_value (dtColumns.dirname, Glib::ustring(volume));
96 int type = GetDriveType (volume);
97 if (type==DRIVE_CDROM) {
98 root->set_value (0, icdrom);
99 root->set_value (1, icdrom);
101 else if (type==DRIVE_REMOVABLE) {
102 if (letter-'A'<2) {
103 root->set_value (0, ifloppy);
104 root->set_value (1, ifloppy);
106 else {
107 root->set_value (0, iremovable);
108 root->set_value (1, iremovable);
111 else if (type==DRIVE_REMOTE) {
112 root->set_value (0, inetwork);
113 root->set_value (1, inetwork);
115 else if (type==DRIVE_FIXED) {
116 root->set_value (0, ihdd);
117 root->set_value (1, ihdd);
120 Gtk::TreeModel::iterator child = dirTreeModel->append (root->children());
121 child->set_value (dtColumns.filename, Glib::ustring("foo"));
124 void DirBrowser::updateDirTreeRoot () {
126 for (Gtk::TreeModel::iterator i=dirTreeModel->children().begin(); i!=dirTreeModel->children().end(); i++)
127 updateDirTree (i);
130 void DirBrowser::updateDirTree (const Gtk::TreeModel::iterator& iter) {
132 if (dirtree->row_expanded (dirTreeModel->get_path (iter))) {
133 updateDir (iter);
134 for (Gtk::TreeModel::iterator i=iter->children().begin(); i!=iter->children().end(); i++)
135 updateDirTree (i);
139 void DirBrowser::updateVolumes () {
141 int nvolumes = GetLogicalDrives ();
142 if (nvolumes!=volumes) {
143 for (int i=0; i<32; i++)
144 if (((volumes >> i) & 1) && !((nvolumes >> i) & 1)) { // volume i has been deleted
145 for (Gtk::TreeModel::iterator iter = dirTreeModel->children().begin(); iter!=dirTreeModel->children().end(); iter++)
146 if (iter->get_value (dtColumns.filename).c_str()[0]-'A' == i) {
147 dirTreeModel->erase (iter);
148 break;
151 else if (!((volumes >> i) & 1) && ((nvolumes >> i) & 1))
152 addRoot ('A'+i); // volume i has been added
153 volumes = nvolumes;
157 int _updateVolumes (void* br) {
159 gdk_threads_enter ();
160 ((DirBrowser*)br)->updateVolumes ();
161 gdk_threads_leave ();
162 return 1;
164 int _updateDirTree (void* br) {
166 gdk_threads_enter ();
167 ((DirBrowser*)br)->updateDirTreeRoot ();
168 gdk_threads_leave ();
169 return 0;
172 void DirBrowser::winDirChanged () {
174 g_idle_add (_updateDirTree, this);
176 #endif
178 void DirBrowser::fillRoot () {
180 #ifdef WIN32
181 volumes = GetLogicalDrives ();
182 for (int i=0; i<32; i++)
183 if ((volumes >> i) & 1)
184 addRoot ('A'+i);
185 // since sigc++ is not thread safe, we have to use the glib function
186 g_timeout_add (CHECKTIME, _updateVolumes, this);
187 #else
188 Gtk::TreeModel::Row rootRow = *(dirTreeModel->append());
189 rootRow[dtColumns.filename] = "/";
190 rootRow[dtColumns.dirname] = "/";
191 Gtk::TreeModel::Row childRow = *(dirTreeModel->append(rootRow.children()));
192 childRow[dtColumns.filename] = "foo";
193 #endif
196 void DirBrowser::row_expanded (const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path) {
198 expandSuccess = false;
200 int todel = iter->children().size();
202 try {
203 std::vector<Glib::ustring> subDirs;
204 Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname));
205 if (!dir)
206 return;
207 Glib::RefPtr<Gio::FileEnumerator> dirList = dir->enumerate_children ();
208 try {
209 for (Glib::RefPtr<Gio::FileInfo> info = dirList->next_file(); info; info = dirList->next_file())
210 if (info->get_file_type() == Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || options.fbShowHidden))
211 subDirs.push_back (info->get_name());
213 catch (...) {}
214 std::sort (subDirs.begin(), subDirs.end());
215 for (int i=0; i<subDirs.size(); i++)
216 addDir (iter, subDirs[i]);
218 for (int i=0; i<todel; i++)
219 dirTreeModel->erase (iter->children().begin());
220 expandSuccess = true;
221 #ifdef _WIN32
222 Glib::RefPtr<WinDirMonitor> monitor = Glib::RefPtr<WinDirMonitor>(new WinDirMonitor (iter->get_value (dtColumns.dirname), this));
223 iter->set_value (dtColumns.monitor, monitor);
224 #else
225 Glib::RefPtr<Gio::FileMonitor> monitor = dir->monitor_directory ();
226 iter->set_value (dtColumns.monitor, monitor);
227 monitor->signal_changed().connect (sigc::bind(sigc::mem_fun(*this, &DirBrowser::file_changed), iter, dir->get_parse_name()));
228 #endif
230 catch (Glib::Exception &ex) {
231 printf ("HEJJ!\n");
232 dirtree->collapse_row (path);
236 void DirBrowser::updateDir (const Gtk::TreeModel::iterator& iter) {
238 // first test if some files are deleted
239 bool change = true;
240 while (change) {
241 change = false;
242 for (Gtk::TreeModel::iterator it=iter->children().begin(); it!=iter->children().end(); it++)
243 if (!Glib::file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_EXISTS)
244 || !Glib::file_test (it->get_value (dtColumns.dirname), Glib::FILE_TEST_IS_DIR)) {
245 dirTreeModel->erase (it);
246 change = true;
247 break;
250 // test if new files are created
251 try {
252 std::vector<Glib::ustring> subDirs;
253 Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path (iter->get_value (dtColumns.dirname));
254 if (!dir)
255 return;
256 Glib::RefPtr<Gio::FileEnumerator> dirList = dir->enumerate_children ();
257 for (Glib::RefPtr<Gio::FileInfo> info = dirList->next_file(); info; info = dirList->next_file())
258 if (info->get_file_type() == Gio::FILE_TYPE_DIRECTORY && (!info->is_hidden() || options.fbShowHidden))
259 subDirs.push_back (info->get_name());
261 for (int i=0; i<subDirs.size(); i++) {
262 bool found = false;
263 for (Gtk::TreeModel::iterator it=iter->children().begin(); it!=iter->children().end(); it++)
264 if (it->get_value (dtColumns.filename)==subDirs[i]) {
265 found = true;
266 break;
268 if (!found)
269 addDir (iter, subDirs[i]);
272 catch (Glib::Exception &ex) {
273 printf ("HEJJ!\n");
277 void DirBrowser::addDir (const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirname) {
279 Gtk::TreeModel::iterator child = dirTreeModel->append(iter->children());
280 child->set_value (dtColumns.filename, dirname);
281 child->set_value (0, openfolder);
282 child->set_value (1, closedfolder);
283 Glib::ustring fullname = Glib::build_filename (iter->get_value (dtColumns.dirname), dirname);
284 child->set_value (dtColumns.dirname, fullname);
285 Glib::RefPtr<Gio::File> f = Gio::File::create_for_path (fullname);
286 Gtk::TreeModel::iterator fooRow = dirTreeModel->append(child->children());
287 fooRow->set_value (dtColumns.filename, Glib::ustring("foo"));
290 void DirBrowser::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column) {
292 Glib::ustring dname = dirTreeModel->get_iter (path)->get_value (dtColumns.dirname);
293 if (Glib::file_test (dname, Glib::FILE_TEST_IS_DIR))
294 for (int i=0; i<dllisteners.size(); i++)
295 dllisteners[i]->dirSelected (dname);
298 Gtk::TreePath DirBrowser::expandToDir (const Glib::ustring& absDirPath) {
300 Gtk::TreeModel::Path path;
301 path.append_index(0);
303 int end = 0;
304 int beg = 0;
305 char* dir = new char [1024];
306 char* dcpy = strdup (absDirPath.c_str());
307 dir = strtok (dcpy, "/\\");
308 int count = 0;
309 expandSuccess = true;
311 #ifndef _WIN32
312 Gtk::TreeModel::iterator j = dirTreeModel->get_iter (path);
313 path.up ();
314 path.append_index (0);
315 row_expanded(j, path);
316 path.append_index (0);
317 #endif
319 while (dir) {
320 Glib::ustring dirstr = dir;
321 #ifdef _WIN32
322 if (count==0)
323 dirstr = dirstr + "\\";
324 #endif
325 Gtk::TreeModel::iterator i = dirTreeModel->get_iter (path);
326 int ix = 0;
327 while (i && expandSuccess) {
328 Gtk::TreeModel::Row crow = *i;
329 Glib::ustring str =crow[dtColumns.filename];
330 #ifdef _WIN32
331 if (str.casefold()==dirstr.casefold()) {
332 #else
333 if (str==dirstr) {
334 #endif
335 path.up ();
336 path.append_index (ix);
337 row_expanded(i, path);
338 path.append_index (0);
339 break;
341 ix++;
342 i++;
344 count++;
345 dir = strtok(NULL, "/\\");
348 delete dir;
349 delete dcpy;
351 path.up ();
352 dirtree->expand_to_path (path);
354 return path;
357 void DirBrowser::open (const Glib::ustring& dirname, const Glib::ustring& fileName) {
359 dirtree->collapse_all ();
361 Glib::ustring absDirPath = Gio::File::create_for_path(dirname)->get_parse_name ();
362 Gtk::TreePath path = expandToDir (absDirPath);
364 if (expandSuccess) {
365 dirtree->scroll_to_row (path);
366 dirtree->get_selection()->select (path);
367 for (int i=0; i<dllisteners.size(); i++)
368 dllisteners[i]->dirSelected (absDirPath, Glib::build_filename (absDirPath, fileName));
372 void DirBrowser::file_changed (const Glib::RefPtr<Gio::File>& file, const Glib::RefPtr<Gio::File>& other_file, Gio::FileMonitorEvent event_type, const Gtk::TreeModel::iterator& iter, const Glib::ustring& dirName) {
374 if (!file || !Glib::file_test (dirName, Glib::FILE_TEST_IS_DIR) || event_type==Gio::FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED)
375 return;
377 gdk_threads_enter();
378 updateDir (iter);
379 gdk_threads_leave();
381 void DirBrowser::selectDir (Glib::ustring dir) {
383 open (dir, "");