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