From 510d7da958153afd3749906e2dd816bc9c41efc6 Mon Sep 17 00:00:00 2001
From: "jsc@umbraculum.org" <jsc@umbraculum.org>
Date: Fri, 26 Apr 2013 09:30:45 +0200
Subject: Re-factored and -written. Does not change working directory. Showing
 drives on windows when in root is a missing feature (will be fixed later).

---
 plugingui/Makefile.am    |   4 +-
 plugingui/directory.cc   | 167 +++++++++++++++++++++++++++++++++++++++++++++++
 plugingui/directory.h    |  80 +++++++++++++++++++++++
 plugingui/filebrowser.cc |  76 +++++++++++++++++----
 plugingui/filebrowser.h  |   1 +
 5 files changed, 316 insertions(+), 12 deletions(-)
 create mode 100644 plugingui/directory.cc
 create mode 100644 plugingui/directory.h

diff --git a/plugingui/Makefile.am b/plugingui/Makefile.am
index 53c44e6..3219987 100644
--- a/plugingui/Makefile.am
+++ b/plugingui/Makefile.am
@@ -14,6 +14,7 @@ plugingui_CFLAGS = $(plugingui_CXXFLAGS)
 
 plugingui_SOURCES = \
 	$(PLUGIN_GUI_SOURCES) \
+  directory.cc \
 	$(top_srcdir)/src/thread.cc \
 	$(top_srcdir)/src/semaphore.cc
 
@@ -23,7 +24,8 @@ EXTRA_DIST = \
 	button.h \
 	checkbox.h \
 	colour.h \
-	eventhandler.h \
+	directory.h \
+  eventhandler.h \
 	font.h \
 	globalcontext.h \
 	guievent.h \
diff --git a/plugingui/directory.cc b/plugingui/directory.cc
new file mode 100644
index 0000000..f38d444
--- /dev/null
+++ b/plugingui/directory.cc
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ *            directory.cc
+ *
+ *  Tue Apr 23 22:01:07 CEST 2013
+ *  Copyright 2013 Jonas Suhr Christensen
+ *  jsc@umbraculum.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 "directory.h"
+
+#include <dirent.h>
+
+#include <hugin.hpp>
+
+Directory::Directory(std::string path) {
+  setPath(path);
+}
+
+Directory::~Directory() {
+}
+
+void Directory::setPath(std::string path) {
+  DEBUG(directory, "Setting path to '%s'\n", path.c_str());
+  this->_path = path;
+  refresh();
+}
+
+size_t Directory::count() {
+  return _files.size();
+}
+
+void Directory::refresh() {
+  _files = listFiles(this->_path);
+}
+
+bool Directory::cd(std::string dir) {
+  DEBUG(directory, "Changing to '%s'\n", dir.c_str());
+  int r = chdir(dir.c_str());
+  refresh();
+  if(!r) return true;
+  else return false;
+}
+
+bool Directory::cdUp() {
+  this->cd("..");
+}
+
+std::string Directory::path() {
+  return _path;
+}
+
+Directory::EntryList Directory::entryList() {
+  return _files;
+}
+
+#define MAX_FILE_LENGTH 1024
+std::string Directory::cwd() {
+  char path[MAX_FILE_LENGTH];
+  char* c = getcwd(path, MAX_FILE_LENGTH);
+
+  if(c) return c;
+  else return "";
+}
+
+std::string Directory::cleanPath(std::string path) {
+  // TODO!
+  return path;
+}
+
+Directory::EntryList Directory::listFiles(std::string path) {
+  Directory::EntryList entries;
+  DIR *dir = opendir(".");
+  if(!dir) {
+    return entries;
+  }
+
+  struct dirent *entry;
+  while((entry = readdir(dir)) != NULL) {
+    entries.push_back(entry->d_name);
+  }
+
+  return entries;
+}
+
+bool Directory::isRoot(std::string path) {
+  if(path == "/") return true;
+  else return false;
+}
+
+Directory::DriveList Directory::drives() {
+  Directory::DriveList drives;
+#ifdef WIN32
+  unsigned int d = GetLogicalDrives();
+  for(int i = 0; i < 32; i++) {
+    if(d & (1 << i)) {
+      drive_t drive;
+      char name[] = "X:";
+      name[0] = i + 'A';
+
+      char num[32];
+      sprintf(num, "%d", i);
+
+      drive.name = name;
+      drive.number = num;
+      drives.push_back(drive);
+    }
+  }
+#endif
+  return drives;
+}
+
+bool Directory::isDir()
+{
+  return isDir(path());
+}
+
+bool Directory::exists(std::string filename) {
+  return !isDir(path() + "/" + filename);
+}
+
+bool Directory::isDir(std::string path) {
+  DEBUG(directory, "Is '%s' dir?\n", path.c_str());
+  struct stat st;
+  if(stat(path.c_str(), &st) == 0) {
+    if((st.st_mode & S_IFDIR) != 0) {
+      DEBUG(directory, "Yes\n");
+      return true;
+    }
+  }
+  DEBUG(directory, "No\n");
+  return false;
+}
+
+#ifdef TEST_DIRECTORY
+//Additional dependency files
+//deps:
+//Required cflags (autoconf vars may be used)
+//cflags:
+//Required link options (autoconf vars may be used)
+//libs:
+#include "test.h"
+
+TEST_BEGIN;
+
+// TODO: Put some testcode here (see test.h for usable macros).
+
+TEST_END;
+
+#endif/*TEST_DIRECTORY*/
diff --git a/plugingui/directory.h b/plugingui/directory.h
new file mode 100644
index 0000000..53213ee
--- /dev/null
+++ b/plugingui/directory.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/***************************************************************************
+ *            directory.h
+ *
+ *  Tue Apr 23 22:01:07 CEST 2013
+ *  Copyright 2013 Jonas Suhr Christensen
+ *  jsc@umbraculum.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.
+ */
+#ifndef __DRUMGIZMO_DIRECTORY_H__
+#define __DRUMGIZMO_DIRECTORY_H__
+
+#include <string>
+#include <list>
+
+#include <libgen.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+class Directory {
+
+  public:
+    typedef struct drive {
+      int number;
+      std::string name;
+    } drive_t;
+
+    typedef std::list<std::string> EntryList;
+    typedef std::list<drive> DriveList;
+    
+    Directory(std::string path);
+    ~Directory();
+
+    size_t count();
+    void refresh();
+    std::string path();
+    bool cdUp();
+    bool cd(std::string dir);
+    bool isDir();
+    void setPath(std::string path);
+    bool exists(std::string file);
+
+    // Add filter, ie. directories or files only
+    EntryList entryList();
+
+    //void setSorting();
+
+    static std::string cwd();
+    static std::string cleanPath(std::string path);
+    static Directory::EntryList listFiles(std::string path);
+    static bool isRoot(std::string path);
+    static Directory::DriveList drives();
+    static bool isDir(std::string path);
+     
+  private:
+    std::string _path;
+    EntryList _files;
+    DriveList _drives;
+};
+
+#endif/*__DRUMGIZMO_DIRECTORY_H__*/
diff --git a/plugingui/filebrowser.cc b/plugingui/filebrowser.cc
index 2bd1a10..be909dd 100644
--- a/plugingui/filebrowser.cc
+++ b/plugingui/filebrowser.cc
@@ -27,9 +27,10 @@
 #include "filebrowser.h"
 
 #include "painter.h"
-
 #include "button.h"
 
+#include "directory.h"
+
 #include <sys/types.h>
 #include <dirent.h>
 #include <stdio.h>
@@ -50,9 +51,10 @@ struct GUI::FileBrowser::private_data {
   GUI::ComboBox *drives;
   void (*filesel_handler)(void *, std::string);
   void *ptr;
-#ifdef WIN32
-  int drvidx;
-#endif
+  Directory *dir;
+//#ifdef WIN32
+//  int drvidx;
+//#endif
 };
 
 static void cancel(void *ptr)
@@ -61,6 +63,48 @@ static void cancel(void *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;
+  
+  INFO(filebrowser, "Changing dir to '%s'\n", (dir->path() + "/" + value).c_str());
+  
+  if(!value.empty() && dir->exists(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;
+  }
+
+  //TODO: If root and windows show drives instead of files
+
+  lb->clear();
+  std::vector<GUI::ListBoxBasic::Item> items;
+  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);
+  }
+  lb->addItems(items);
+}
+
+#if 0
 static void changeDir(void *ptr)
 {
   struct GUI::FileBrowser::private_data *prv =
@@ -139,6 +183,7 @@ static void changeDir(void *ptr)
 
   closedir(dir);
 }
+#endif/*0*/
 
 GUI::FileBrowser::FileBrowser(GUI::Widget *parent)
   : GUI::Widget(parent),
@@ -151,6 +196,8 @@ GUI::FileBrowser::FileBrowser(GUI::Widget *parent)
   prv = new struct GUI::FileBrowser::private_data();
   prv->filesel_handler = NULL;
 
+  prv->dir = new Directory(Directory::cwd());
+
   lbl_path.setText("Path:");
 
   lineedit.setReadOnly(true);
@@ -165,6 +212,8 @@ GUI::FileBrowser::FileBrowser(GUI::Widget *parent)
   btn_esc.setText("Cancel");
   btn_esc.registerClickHandler(cancel, this);
 
+  changeDir(prv);
+/*
 #ifdef WIN32
   lbl_drive.setText("Drive:");
 
@@ -185,8 +234,9 @@ GUI::FileBrowser::FileBrowser(GUI::Widget *parent)
   }
   prv->drives = &drv;
 #endif
+*/
 
-  changeDir(prv);
+//  changeDir(prv);
 
   resize(200, 190);
 }
@@ -197,6 +247,7 @@ GUI::FileBrowser::~FileBrowser()
   delete prv;
 }
 
+#if 0
 #include <libgen.h>
 
 static bool isDir(std::string d)
@@ -213,23 +264,26 @@ static bool isDir(std::string d)
   DEBUG(dir, "No\n");
   return false;
 }
+#endif
 
 void GUI::FileBrowser::setPath(std::string path)
 {
+//  prv->dir->setPath(path);
+/*
   std::string dir;
-  if(isDir(path)) {
+  if(prv->dir->isDir()) {
     dir = path;
   } else {
     char *d = strdup(path.c_str());
     std::string _dirname = dirname(d);
     free(d);
-    if(isDir(_dirname)) dir = _dirname;
+    if(prv->dir->isDir(_dirname)) dir = _dirname;
     else return;
   }
-
-  if(chdir(dir.c_str()) == -1) return;
-  prv->listbox->clear();
-  changeDir(prv);
+*/
+//  if(chdir(dir.c_str()) == -1) return;
+//  prv->listbox->clear();
+//  changeDir(prv);
 
   /*
   std::string dirname = path;
diff --git a/plugingui/filebrowser.h b/plugingui/filebrowser.h
index 6953dad..cd389be 100644
--- a/plugingui/filebrowser.h
+++ b/plugingui/filebrowser.h
@@ -35,6 +35,7 @@
 #include "lineedit.h"
 #include "label.h"
 #include "image.h"
+#include "directory.h"
 
 namespace GUI {
 
-- 
cgit v1.2.3