FileBrowserControl.cc
Go to the documentation of this file.00001 #include "FileBrowserControl.h"
00002 #include "NullControl.h"
00003 #include "Shared/Config.h"
00004 #include <sys/types.h>
00005 #include <sys/stat.h>
00006 #include <unistd.h>
00007 #include <dirent.h>
00008
00009 using namespace std;
00010
00011 ControlBase * FileBrowserControl::activate(MC_ID display, Socket * gui) {
00012 rebuildmenu();
00013 return ControlBase::activate(display,gui);
00014 }
00015
00016 ControlBase* FileBrowserControl::doSelect() {
00017 for(unsigned int i=0; i<hilights.size(); i++) {
00018 unsigned int cur=hilights[i];
00019 if(cur>=options.size() || options[cur]==NULL)
00020 continue;
00021 ControlBase::doSelect();
00022 std::string nm(options[cur]->getName());
00023 if(nm[nm.size()-1]=='/' || nm=="..") {
00024 if(hilights.size()>1)
00025 continue;
00026 if(nm=="..")
00027 paths.pop_back();
00028 else
00029 paths.push_back(nm.substr(0,nm.size()-1));
00030 rebuildmenu();
00031 refresh();
00032 return this;
00033 } else {
00034 ControlBase * ret=selectedFile(makePath(nm));
00035 if(ret!=this)
00036 return ret;
00037 }
00038 }
00039 refresh();
00040 return this;
00041 }
00042
00043 ControlBase * FileBrowserControl::takeInput(const std::string& msg) {
00044 if(msg.size()==0)
00045 return this;
00046 if(msg.find('/')==string::npos) {
00047 if(options.size()==1 && options.front()==NULL)
00048 rebuildmenu();
00049 return ControlBase::takeInput(msg);
00050 } else {
00051 string::size_type pos=msg.rfind('/');
00052 if(msg[0]=='/') {
00053 if(msg.substr(0,root.size())!=root)
00054 return this;
00055 if(msg.size()>root.size() && msg[root.size()]!='/')
00056 return this;
00057 paths.clear();
00058 if(pos<=root.size())
00059 return this;
00060 appendPath(msg.substr(root.size(),pos-root.size()));
00061 } else {
00062 appendPath(msg.substr(0,pos));
00063 }
00064 rebuildmenu();
00065 if(msg.size()>pos+1)
00066 return ControlBase::takeInput(msg.substr(pos+1));
00067 return this;
00068 }
00069 }
00070
00071 void FileBrowserControl::setRoot(const std::string& path) {
00072 root=config->portPath(path);
00073 if(root[root.size()-1]=='/')
00074 root.erase(root.size()-1);
00075 paths.clear();
00076 }
00077
00078
00079 void FileBrowserControl::appendPath(const std::string& path) {
00080 paths.push_back(std::string());
00081 for(unsigned int i=0; i<path.size(); i++) {
00082 if(path[i]!='/')
00083 paths.back().append(1,path[i]);
00084 else if(paths.back().size()!=0)
00085 paths.push_back(std::string());
00086 }
00087 }
00088
00089
00090 std::string FileBrowserControl::makePath() {
00091 std::string path=root;
00092 for(unsigned int i=0; i<paths.size(); i++) {
00093 path+="/";
00094 path+=paths[i];
00095 }
00096 return path;
00097 }
00098
00099
00100 std::string FileBrowserControl::makePath(const std::string& filename) {
00101 std::string path=makePath();
00102 path.append("/");
00103 path.append(filename);
00104 return path;
00105 }
00106
00107 bool FileBrowserControl::match(const std::string& file, const std::string& filt) {
00108 unsigned int i=0;
00109 if(i==filt.size() && i==file.size())
00110 return true;
00111 if(i==filt.size() || i==file.size())
00112 return false;
00113 while(filt[i]!='*') {
00114 if(toupper(filt[i])!=toupper(file[i]))
00115 return false;
00116 i++;
00117 if(i==filt.size() && i==file.size())
00118 return true;
00119 if(i==filt.size() || i==file.size())
00120 return false;
00121 }
00122 i=filt.size()-1;
00123 unsigned int j=file.size()-1;
00124 while(filt[i]!='*') {
00125 if(toupper(filt[i])!=toupper(file[j]))
00126 return false;
00127 i--; j--;
00128 }
00129 return true;
00130 }
00131
00132 void FileBrowserControl::rebuildmenu() {
00133 clearSlots();
00134 DIR* dir=opendir(makePath().c_str());
00135 if(dir==NULL) {
00136 pushSlot(new NullControl("Bad Path: "+makePath(),makePath(),this));
00137 return;
00138 }
00139 if(paths.size()!=0 && recurse) {
00140 struct stat s;
00141 std::string path=makePath("..");
00142 int err=stat(path.c_str(),&s);
00143 if(err==0 && s.st_mode&S_IFDIR)
00144 pushSlot(new NullControl("..","go up a directory level",this));
00145 }
00146 std::map<std::string,std::string> files;
00147 struct dirent * ent=readdir(dir);
00148 while(ent!=NULL) {
00149 if(strcmp(ent->d_name,".")!=0 && strcmp(ent->d_name,"..")!=0) {
00150 struct stat s;
00151 std::string path=(makePath(ent->d_name));
00152 int err=stat(path.c_str(),&s);
00153 if(err!=0) {
00154 cout << "File disappeared: " << path << endl;
00155 return;
00156 }
00157 if(s.st_mode&S_IFDIR) {
00158 if(recurse)
00159 files[std::string(ent->d_name).append(1,'/')] = makePath(ent->d_name);
00160 } else {
00161 std::string nm=(makePath(ent->d_name));
00162 if(match(nm,filter))
00163 files[ent->d_name] = makePath(ent->d_name);
00164 }
00165 }
00166 ent=readdir(dir);
00167 }
00168 closedir(dir);
00169 for(std::map<std::string,std::string>::const_iterator fit=files.begin(); fit!=files.end(); ++fit)
00170 pushSlot(new NullControl(fit->first,fit->second,this));
00171 if(options.size()==0)
00172 pushSlot(new NullControl("[empty directory]",makePath(),this));
00173 else {
00174 hilights.push_back(0);
00175
00176
00177
00178
00179
00180
00181
00182 }
00183 }
00184
00185
00186
00187
00188
00189
00190