/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * filebrowser.cc * * Mon Feb 25 21:09:44 CET 2013 * Copyright 2013 Bent Bisballe Nyeng * deva@aasimon.org ****************************************************************************/ /* * This file is part of DrumGizmo. * * DrumGizmo is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * DrumGizmo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with DrumGizmo; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include "filebrowser.h" #include "painter.h" #include "button.h" #include "directory.h" #include #include #include #include #include #include #include #ifdef WIN32 #include #endif struct GUI::FileBrowser::private_data { GUI::LineEdit *lineedit; GUI::ListBox *listbox; GUI::ComboBox *drives; void (*filesel_handler)(void *, std::string); void *ptr; Directory *dir; //#ifdef WIN32 // int drvidx; //#endif }; static void cancel(void *ptr) { GUI::FileBrowser *fp = (GUI::FileBrowser *)ptr; fp->hide(); } static void changeDir(void *ptr) { struct GUI::FileBrowser::private_data *prv = (struct GUI::FileBrowser::private_data *) ptr; GUI::ListBox *lb = prv->listbox; GUI::LineEdit *le = prv->lineedit; std::string value = lb->selectedValue(); Directory* dir = prv->dir; lb->clear(); INFO(filebrowser, "Changing path to '%s'\n", (dir->path() + "/" + value).c_str()); #ifdef WIN32 if(!value.empty() && dir->isRoot()) { dir->setPath(value); return; } #endif if(!value.empty() && dir->fileExists(value)) { std::string file = dir->path() + "/" + value; DEBUG(filebrowser, "Selecting file '%s'\n", file.c_str()); if(prv->filesel_handler) prv->filesel_handler(prv->ptr, file); return; } if(!value.empty() && !dir->cd(value)) { DEBUG(filebrowser, "Error changing to '%s'\n", (dir->path() + "/" + value).c_str()); return; } DEBUG(filebrowser, "Setting path of lineedit to %s\n", dir->path().c_str()); le->setText(dir->path()); lb->clear(); std::vector items; #ifdef WIN32 if(Directory::isRoot(dir->path()) && value == "..") { DEBUG(filebrowser, "Showing partitions...\n"); Directory::DriveList entries = dir->drives(); for(Directory::DriveList::iterator it = entries.begin(); it != entries.end(); it++) { GUI::ListBoxBasic::Item item; std::string name = (*it).name; item.name = name; item.value = name; items.push_back(item); } } else { #endif Directory::EntryList entries = dir->entryList(); for(Directory::EntryList::iterator it = entries.begin(); it != entries.end(); it++) { GUI::ListBoxBasic::Item item; std::string name = *it; item.name = name; item.value = name; items.push_back(item); } #ifdef WIN32 } #endif lb->addItems(items); } #if 0 static void changeDir(void *ptr) { struct GUI::FileBrowser::private_data *prv = (struct GUI::FileBrowser::private_data *)ptr; GUI::ListBox *lb = prv->listbox; GUI::LineEdit *le = prv->lineedit; std::string value = lb->selectedValue(); #ifdef WIN32 std::string drive = prv->drives->selectedValue(); int drvidx = atoi(drive.c_str()); /*if(prv->drvidx != drvidx)*/ _chdrive(drvidx + 1); // one based... sigh //printf("DRV: [%d %s]\n", drvidx, drive.c_str()); #endif char filename[1024]; char *c = getcwd(filename, sizeof(filename)); (void)c; DEBUG(cwd, "CWD1: [%s]\n", filename); if(value != "") { #ifdef WIN32 if(prv->drvidx == drvidx) { strcat(filename, "\\"); strcat(filename, value.c_str()); } prv->drvidx = drvidx; #else strcat(filename, "/"); strcat(filename, value.c_str()); #endif } struct stat st; if(stat(filename, &st) == 0) { if((st.st_mode & S_IFDIR) != 0) { DEBUG(cwd, "'%s' is present and is a directory\n", filename); } if((st.st_mode & S_IFREG) != 0) { DEBUG(cwd, "'%s' is present and is a file\n", filename); if(prv->filesel_handler) prv->filesel_handler(prv->ptr, filename); return; } } else { DEBUG(cwd, "'%s' is not present or unreadable\n", filename); //perror("!"); return; } lb->clear(); int i = chdir(value.c_str()); (void)i; c = getcwd(filename, sizeof(filename)); le->setText(filename); DEBUG(cwd, "CWD2: [%s]\n", filename); DIR *dir = opendir("."); if(!dir) { lb->addItem("[ Could not open dir ]", ""); return; } std::vector items; struct dirent *entry; while((entry = readdir(dir)) != NULL) { GUI::ListBoxBasic::Item item; item.name = entry->d_name; item.value = entry->d_name; items.push_back(item); } lb->addItems(items); closedir(dir); } #endif/*0*/ GUI::FileBrowser::FileBrowser(GUI::Widget *parent) : GUI::Widget(parent), lbl_path(this), lineedit(this), listbox(this), btn_sel(this), btn_esc(this), back(":bg.png") #ifdef WIN32 , drv(this), lbl_drive(this) #endif { prv = new struct GUI::FileBrowser::private_data(); prv->filesel_handler = NULL; prv->dir = new Directory(Directory::cwd()); lbl_path.setText("Path:"); lineedit.setReadOnly(true); prv->lineedit = &lineedit; prv->listbox = &listbox; listbox.registerSelectHandler(changeDir, prv); btn_sel.setText("Select"); btn_sel.registerClickHandler(changeDir, prv); btn_esc.setText("Cancel"); btn_esc.registerClickHandler(cancel, this); changeDir(prv); /* #ifdef WIN32 lbl_drive.setText("Drive:"); drv.registerValueChangedHandler(changeDir, prv); unsigned int d = GetLogicalDrives(); for(int i = 0; i < 32; i++) { if(d & (1 << i)) { char name[] = "X:"; name[0] = i + 'A'; char num[32]; sprintf(num, "%d", i); drv.addItem(name, num); } } prv->drives = &drv; #endif */ // changeDir(prv); resize(200, 190); } GUI::FileBrowser::~FileBrowser() { // delete prv->listbox; delete prv; } #if 0 #include static bool isDir(std::string d) { DEBUG(dir, "Is '%s' a dir?\n", d.c_str()); struct stat st; if(stat(d.c_str(), &st) == 0) { if((st.st_mode & S_IFDIR) != 0) { DEBUG(dir, "Yes\n"); return true; } } DEBUG(dir, "No\n"); return false; } #endif void GUI::FileBrowser::setPath(std::string path) { // WARN(filebrowser, "Not implemented yet!"); // TODO: Remove this check to directoy.cc INFO(filebrowser, "Setting path to '%s'\n", path.c_str()); if(path.empty()) path = Directory::cwd(); // TODO: Strip path to set path to a directory prv->dir->setPath(Directory::pathDirectory(path)); prv->listbox->clear(); changeDir(prv); /* std::string dir; if(prv->dir->isDir()) { dir = path; } else { char *d = strdup(path.c_str()); std::string _dirname = dirname(d); free(d); if(prv->dir->isDir(_dirname)) dir = _dirname; else return; } */ // if(chdir(dir.c_str()) == -1) return; // prv->listbox->clear(); // changeDir(prv); /* std::string dirname = path; while(dirname != "") { DEBUG(filebrowser, "dirname: %s\n", dirname.c_str()); struct stat st; if(stat(dirname.c_str(), &st) == 0) { if((st.st_mode & S_IFDIR) != 0) { dirname += "/."; int i = chdir(dirname.c_str()); (void)i; changeDir(prv); DEBUG(filebrowser, "chdir to: %s\n", dirname.c_str()); return; } } dirname = dirname.substr(0, dirname.length() - 1); while(dirname[dirname.length() - 1] != '/' && dirname[dirname.length() - 1] != '\\' && dirname != "") { dirname = dirname.substr(0, dirname.length() - 1); } } */ } void GUI::FileBrowser::resize(int w, int h) { GUI::Widget::resize(w,h); int offset = 0; int brd = 5; // border int btn_h = 30; #ifdef WIN32 offset += brd; lbl_drive.move(0, offset); drv.move(60, offset); offset += btn_h; lbl_drive.resize(60, btn_h); drv.resize(w - 60 - brd, btn_h); #endif offset += brd; lbl_path.move(0, offset); lineedit.move(60, offset); offset += btn_h; lbl_path.resize(60, btn_h); lineedit.resize(w - 60 - brd, btn_h); offset += brd; listbox.move(brd, offset); listbox.resize(w - 1 - 2*brd, h - btn_h - 2*brd - offset); btn_esc.move(brd, h - btn_h - brd); btn_esc.resize((w - 1 - 2*brd) / 2 - brd / 2, btn_h); btn_sel.move(brd + w / 2 - brd / 2, h - btn_h - brd); btn_sel.resize((w - 1 - 2*brd) / 2, btn_h); } void GUI::FileBrowser::registerFileSelectHandler(void (*handler)(void *, std::string), void *ptr) { prv->filesel_handler = handler; prv->ptr = ptr; } void GUI::FileBrowser::repaintEvent(GUI::RepaintEvent *e) { Painter p(this); p.drawImageStretched(0,0, &back, width(), height()); }