1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /***************************************************************************
3 * filebrowser.cc
4 *
5 * Mon Feb 25 21:09:44 CET 2013
6 * Copyright 2013 Bent Bisballe Nyeng
7 * deva@aasimon.org
8 ****************************************************************************/
9
10 /*
11 * This file is part of DrumGizmo.
12 *
13 * DrumGizmo is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
17 *
18 * DrumGizmo is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public License
24 * along with DrumGizmo; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 */
27 #include "filebrowser.h"
28
29 #include "painter.h"
30 #include "button.h"
31
32 #include <sys/types.h>
33 #include <dirent.h>
34 #include <stdio.h>
35
36 #include <sys/types.h>
37 #include <sys/stat.h>
38
39 #include <platform.h>
40 #include <hugin.hpp>
41
42 #ifdef __MINGW32__
43 #include <direct.h>
44 #endif
45
46 #include <translation.h>
47
48 namespace GUI
49 {
50
FileBrowser(Widget * parent)51 FileBrowser::FileBrowser(Widget* parent)
52 : Dialog(parent, true)
53 , dir(Directory::cwd())
54 , lbl_path(this)
55 , lineedit(this)
56 , listbox(this)
57 , btn_sel(this)
58 , btn_def(this)
59 , btn_esc(this)
60 , back(":resources/bg.png")
61 {
62 #if DG_PLATFORM == DG_PLATFORM_WINDOWS
63 above_root = false;
64 #endif
65
66 setCaption(_("Open file..."));
67
68 lbl_path.setText(_("Path:"));
69
70 //lineedit.setReadOnly(true);
71 CONNECT(&lineedit, enterPressedNotifier, this, &FileBrowser::handleKeyEvent);
72 CONNECT(&listbox, selectionNotifier,
73 this, &FileBrowser::listSelectionChanged);
74 CONNECT(this, fileSelectNotifier, this, &FileBrowser::select);
75 CONNECT(eventHandler(), closeNotifier, this, &FileBrowser::cancel);
76
77 btn_sel.setText(_("Select"));
78 CONNECT(&btn_sel, clickNotifier, this, &FileBrowser::selectButtonClicked);
79
80 btn_def.setText(_("Set default path"));
81 CONNECT(&btn_def, clickNotifier, this, &FileBrowser::setDefaultPath);
82
83 btn_esc.setText(_("Cancel"));
84 CONNECT(&btn_esc, clickNotifier, this, &FileBrowser::cancelButtonClicked);
85
86 changeDir();
87 }
88
setPath(const std::string & path)89 void FileBrowser::setPath(const std::string& path)
90 {
91 INFO(filebrowser, _("Setting path to '%s'\n"), path.c_str());
92
93 if(!path.empty() && Directory::exists(path))
94 {
95 dir.setPath(Directory::pathDirectory(path));
96 }
97 else
98 {
99 dir.setPath(Directory::pathDirectory(Directory::cwd()));
100 }
101
102 listbox.clear();
103
104 changeDir();
105 }
106
resize(std::size_t width,std::size_t height)107 void FileBrowser::resize(std::size_t width, std::size_t height)
108 {
109 Dialog::resize(width, height);
110
111 int offset = 0;
112 int brd = 5; // border
113 int btn_h = 30;
114 int btn_w = std::max(width * 2 / 7, std::size_t(0));
115
116 offset += brd;
117
118 lbl_path.move(brd, offset);
119 lineedit.move(60, offset);
120
121 offset += btn_h;
122
123 lbl_path.resize(60, btn_h);
124 lineedit.resize(std::max((int)width - 60 - brd, 0), btn_h);
125
126 offset += brd;
127
128 listbox.move(brd, offset);
129 listbox.resize(std::max((int)width - 1 - 2*brd, 0),
130 std::max((int)height - btn_h - 2*brd - offset, 0));
131
132 btn_def.move(brd, height - btn_h - brd);
133 btn_def.resize(btn_w, btn_h);
134
135 btn_esc.move(width - (brd + btn_w + brd + btn_w), height - btn_h - brd);
136 btn_esc.resize(btn_w, btn_h);
137
138 btn_sel.move(width - (brd + btn_w), height - btn_h - brd);
139 btn_sel.resize(btn_w, btn_h);
140 }
141
repaintEvent(RepaintEvent * repaintEvent)142 void FileBrowser::repaintEvent(RepaintEvent* repaintEvent)
143 {
144 Painter p(*this);
145 p.drawImageStretched(0,0, back, width(), height());
146 }
147
listSelectionChanged()148 void FileBrowser::listSelectionChanged()
149 {
150 changeDir();
151 }
152
selectButtonClicked()153 void FileBrowser::selectButtonClicked()
154 {
155 changeDir();
156 }
157
setDefaultPath()158 void FileBrowser::setDefaultPath()
159 {
160 defaultPathChangedNotifier(dir.path());
161 }
162
cancelButtonClicked()163 void FileBrowser::cancelButtonClicked()
164 {
165 cancel();
166 }
167
handleKeyEvent()168 void FileBrowser::handleKeyEvent()
169 {
170 listbox.clearSelectedValue();
171
172 std::string value = lineedit.getText();
173 if((value.size() > 1) && (value[0] == '@'))
174 {
175 DEBUG(filebrowser, _("Selecting ref-file '%s'\n"), value.c_str());
176 fileSelectNotifier(value);
177 return;
178 }
179
180 dir.setPath(lineedit.getText());
181 changeDir();
182 }
183
cancel()184 void FileBrowser::cancel()
185 {
186 has_filename = false;
187 hide();
188 fileSelectCancelNotifier();
189 }
190
select(const std::string & file)191 void FileBrowser::select(const std::string& file)
192 {
193 has_filename = true;
194 filename = file;
195 hide();
196 }
197
changeDir()198 void FileBrowser::changeDir()
199 {
200 std::string value = listbox.selectedValue();
201
202 // if(!Directory::isDir(dir->path() + dir->seperator()))
203 // {
204 // return;
205 // }
206
207 listbox.clear();
208
209 INFO(filebrowser, _("Changing path to '%s'\n"),
210 (dir.path() + dir.seperator() + value).c_str());
211
212 #if DG_PLATFORM == DG_PLATFORM_WINDOWS
213 if(above_root && !value.empty())
214 {
215 dir.setPath(value + dir.seperator());
216 value.clear();
217 above_root = false;
218 }
219 #endif
220
221 if(value.empty() && !dir.isDir() && Directory::exists(dir.path()))
222 {
223 DEBUG(filebrowser, _("Selecting file '%s'\n"), dir.path().c_str());
224 fileSelectNotifier(dir.path());
225 return;
226 }
227
228 if(!value.empty() && dir.fileExists(value))
229 {
230 std::string file = dir.path() + dir.seperator() + value;
231 DEBUG(filebrowser, _("Selecting file '%s'\n"), file.c_str());
232 fileSelectNotifier(file);
233 return;
234 }
235
236 std::vector<ListBoxBasic::Item> items;
237
238 #if DG_PLATFORM == DG_PLATFORM_WINDOWS
239 if(Directory::isRoot(dir.path()) && (value == ".."))
240 {
241 DEBUG(filebrowser, _("Showing partitions...\n"));
242 for(auto drive : dir.drives())
243 {
244 ListBoxBasic::Item item;
245 item.name = drive.name;
246 item.value = drive.name;
247 items.push_back(item);
248 }
249 above_root = true;
250 }
251 else
252 #endif
253 {
254 if(!value.empty() && !dir.cd(value))
255 {
256 DEBUG(filebrowser, _("Error changing to '%s'\n"),
257 (dir.path() + dir.seperator() + value).c_str());
258 return;
259 }
260
261 Directory::EntryList entries = dir.entryList();
262
263 if(entries.empty())
264 {
265 dir.cdUp();
266 entries = dir.entryList();
267 }
268
269 DEBUG(filebrowser, _("Setting path of lineedit to %s\n"), dir.path().c_str());
270 lineedit.setText(dir.path());
271
272 for(auto entry : entries)
273 {
274 ListBoxBasic::Item item;
275 item.name = entry;
276 item.value = entry;
277 items.push_back(item);
278 }
279 }
280
281 listbox.addItems(items);
282 }
283
getFilename() const284 std::string FileBrowser::getFilename() const
285 {
286 return filename;
287 }
288
hasFilename() const289 bool FileBrowser::hasFilename() const
290 {
291 return has_filename;
292 }
293
294 } // GUI::
295