This is what it looks like simplifed and rewritten to use
boost.filesystem.
I have not changed the visual apparence of the dialog, so there are
one widget too many on it currently (unused).
Please comment.
Index: FormFiledialog.C
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/xforms/FormFiledialog.C,v
retrieving revision 1.65
diff -u -p -B -b -w -r1.65 FormFiledialog.C
--- FormFiledialog.C 10 Jan 2005 19:17:41 -0000 1.65
+++ FormFiledialog.C 29 Jan 2005 14:18:32 -0000
@@ -19,8 +19,6 @@
#include "frontends/Dialogs.h"
-#include "support/convert.h"
-#include "support/FileInfo.h"
#include "support/filefilterlist.h"
#include "support/filetools.h"
#include "support/globbing.h"
@@ -31,47 +29,21 @@
#include "lyx_forms.h"
#include <boost/bind.hpp>
-#include <boost/regex.hpp>
+#include <boost/filesystem/operations.hpp>
#include <boost/tokenizer.hpp>
#include <algorithm>
-#include <map>
#include <sstream>
-#include <grp.h>
-#include <pwd.h>
-
-//#ifdef HAVE_ERRNO_H
-//#include <cerrno>
-//#endif
-
-#if HAVE_DIRENT_H
-# include <dirent.h>
-#else
-# define dirent direct
-# if HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# if HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# if HAVE_NDIR_H
-# include <ndir.h>
-# endif
-#endif
-
using lyx::support::AbsolutePath;
using lyx::support::AddName;
using lyx::support::ExpandPath;
using lyx::support::FileFilterList;
-using lyx::support::FileInfo;
using lyx::support::getcwd;
-using lyx::support::LyXReadLink;
using lyx::support::MakeAbsPath;
using lyx::support::OnlyFilename;
using lyx::support::package;
using lyx::support::split;
-using lyx::support::subst;
using lyx::support::suffixIs;
using lyx::support::trim;
@@ -79,11 +51,10 @@ using std::max;
using std::sort;
using std::ostringstream;
using std::string;
-using std::map;
using std::vector;
using namespace lyx::frontend;
-
+namespace fs = boost::filesystem;
namespace {
@@ -114,11 +85,6 @@ vector<string> const expand_globs(string
}
-// six months, in seconds
-long const SIX_MONTH_SEC = 6L * 30L * 24L * 60L * 60L;
-//static
-long const ONE_HOUR_SEC = 60L * 60L;
-
extern "C" {
static
@@ -141,72 +107,6 @@ extern "C" {
}
-// *** User cache class implementation
-/// User cache class definition
-class UserCache {
-public:
- /// seeks user name from group ID
- string const & find(uid_t ID) const {
- Users::const_iterator cit = users.find(ID);
- if (cit == users.end()) {
- add(ID);
- return users[ID];
- }
- return cit->second;
- }
-private:
- ///
- void add(uid_t ID) const;
- ///
- typedef map<uid_t, string> Users;
- ///
- mutable Users users;
-};
-
-
-void UserCache::add(uid_t ID) const
-{
- struct passwd const * entry = getpwuid(ID);
- users[ID] = entry ? entry->pw_name : convert<string>(int(ID));
-}
-
-
-/// Group cache class definition
-class GroupCache {
-public:
- /// seeks group name from group ID
- string const & find(gid_t ID) const ;
-private:
- ///
- void add(gid_t ID) const;
- ///
- typedef map<gid_t, string> Groups;
- ///
- mutable Groups groups;
-};
-
-
-string const & GroupCache::find(gid_t ID) const
-{
- Groups::const_iterator cit = groups.find(ID);
- if (cit == groups.end()) {
- add(ID);
- return groups[ID];
- }
- return cit->second;
-}
-
-
-void GroupCache::add(gid_t ID) const
-{
- struct group const * entry = getgrgid(ID);
- groups[ID] = entry ? entry->gr_name : convert<string>(int(ID));
-}
-
-
-// local instances
-UserCache lyxUserCache;
-GroupCache lyxGroupCache;
// compares two LyXDirEntry objects content (used for sort)
class comp_direntry : public std::binary_function<DirEntry, DirEntry, bool> {
@@ -240,15 +140,13 @@ int FileDialog::Private::minh_ = 0;
void FileDialog::Private::Reread()
{
// Opens directory
- DIR * dir = ::opendir(directory_.c_str());
- if (!dir) {
+ if (!fs::exists(directory_) || !fs::is_directory(directory_)) {
// FIXME: re-add ...
#if 0
Alert::err_alert(_("Warning! Couldn't open directory."),
directory_);
#endif
directory_ = getcwd();
- dir = ::opendir(directory_.c_str());
}
// Clear the present namelist
@@ -261,14 +159,14 @@ void FileDialog::Private::Reread()
// Splits complete directory name into directories and compute depth
depth_ = 0;
- string line, Temp;
- string mode;
+ string line;
+ string Temp;
string File = directory_;
if (File != "/")
File = split(File, Temp, '/');
while (!File.empty() || !Temp.empty()) {
- string dline = "@b" + line + Temp + '/';
+ string const dline = "@b" + line + Temp + '/';
fl_add_browser_line(file_dlg_form_->List, dline.c_str());
File = split(File, Temp, '/');
line += ' ';
@@ -277,118 +175,37 @@ void FileDialog::Private::Reread()
vector<string> const glob_matches = expand_globs(mask_, directory_);
- time_t curTime = time(0);
- rewinddir(dir);
- while (dirent * entry = readdir(dir)) {
- bool isLink = false, isDir = false;
+ fs::directory_iterator beg(directory_);
+ fs::directory_iterator end;
+ for (; beg != end; ++beg) {
+ string const fname = beg->leaf();
// If the pattern doesn't start with a dot, skip hidden files
- if (!mask_.empty() && mask_[0] != '.' &&
- entry->d_name[0] == '.')
- continue;
-
- // Gets filename
- string fname = entry->d_name;
-
- // Under all circumstances, "." and ".." are not wanted
- if (fname == "." || fname == "..")
- continue;
-
- // gets file status
- File = AddName(directory_, fname);
-
- FileInfo fileInfo(File, true);
-
- // can this really happen?
- if (!fileInfo.isOK())
+ if (!mask_.empty() && mask_[0] != '.' && fname[0] == '.')
continue;
- mode = fileInfo.modeString();
- string const user = lyxUserCache.find(fileInfo.getUid());
- string const group = lyxGroupCache.find(fileInfo.getGid());
-
- time_t modtime = fileInfo.getModificationTime();
- string Time = ctime(&modtime);
-
- if (curTime > modtime + SIX_MONTH_SEC
- || curTime < modtime + ONE_HOUR_SEC) {
- // The file is fairly old or in the future. POSIX says
- // the cutoff is 6 months old. Allow a 1 hour slop
- // factor for what is considered "the future", to
- // allow for NFS server/client clock disagreement.
- // Show the year instead of the time of day.
- Time.erase(10, 9);
- Time.erase(15, string::npos);
- } else {
- Time.erase(16, string::npos);
- }
-
- string buffer = mode + ' ' +
- user + ' ' +
- group + ' ' +
- Time.substr(4, string::npos) + ' ';
-
- buffer += entry->d_name;
- buffer += fileInfo.typeIndicator();
-
- isLink = fileInfo.isLink();
- if (isLink) {
- string Link;
-
- if (LyXReadLink(File, Link)) {
- buffer += " -> ";
- buffer += Link;
-
- // This gives the FileType of the file that
- // is really pointed to after resolving all
- // symlinks. This is not necessarily the same
- // as the type of Link (which could again be a
- // link). Is that intended?
- // JV 199902
- fileInfo.newFile(File);
- if (fileInfo.isOK())
- buffer += fileInfo.typeIndicator();
- else
- continue;
- }
- }
+ bool const isDir = fs::is_directory(*beg);
// filters files according to pattern and type
- if (fileInfo.isRegular()
- || fileInfo.isChar()
- || fileInfo.isBlock()
- || fileInfo.isFifo()) {
typedef vector<string>::const_iterator viterator;
viterator gbegin = glob_matches.begin();
viterator const gend = glob_matches.end();
- if (std::find(gbegin, gend, fname) == gend)
- continue;
- } else if (!(isDir = fileInfo.isDir()))
+
+ if (!isDir && std::find(gbegin, gend, fname) == gend)
continue;
DirEntry tmp;
-
- // Note ls_entry_ is an string!
- tmp.ls_entry_ = buffer;
// creates used name
- string temp = fname;
+ tmp.name_ = fname;
+
if (isDir)
- temp += '/';
+ tmp.name_ += '/';
- tmp.name_ = temp;
// creates displayed name
- temp = entry->d_name;
- if (isLink)
- temp += '@';
- else
- temp += fileInfo.typeIndicator();
- tmp.displayed_ = temp;
-
+ tmp.displayed_ = fname;
dir_entries_.push_back(tmp);
}
- closedir(dir);
-
// Sort the names
sort(dir_entries_.begin(), dir_entries_.end(), comp_direntry());
@@ -414,14 +231,12 @@ void FileDialog::Private::SetDirectory(s
tmp = MakeAbsPath(ExpandPath(path), directory_);
// must check the directory exists
- DIR * dir = ::opendir(tmp.c_str());
- if (!dir) {
+ if (!fs::exists(tmp) || !fs::is_directory(tmp)) {
// FIXME: re-add ...
#if 0
Alert::err_alert(_("Warning! Couldn't open directory."), tmp);
#endif
} else {
- ::closedir(dir);
directory_ = tmp;
}
}
@@ -457,14 +272,6 @@ void FileDialog::Private::SetFilters(Fil
}
-// SetInfoLine: sets dialog information line
-void FileDialog::Private::SetInfoLine(string const & line)
-{
- info_line_ = line;
- fl_set_object_label(file_dlg_form_->FileInfo, info_line_.c_str());
-}
-
-
FileDialog::Private::Private()
{
directory_ = MakeAbsPath(string("."));
@@ -644,10 +451,12 @@ void FileDialog::Private::HandleListHit(
{
// set info line
int const select_ = fl_get_browser(file_dlg_form_->List);
- if (select_ > depth_)
- SetInfoLine(dir_entries_[select_ - depth_ - 1].ls_entry_);
- else
- SetInfoLine(string());
+ string line = (select_ > depth_ ?
+ dir_entries_[select_ - depth_ - 1].name_ :
+ string());
+ if (suffixIs(line, '/'))
+ line.clear();
+ fl_set_input(file_dlg_form_->Filename, line.c_str());
}
@@ -670,14 +479,11 @@ bool FileDialog::Private::HandleDoubleCl
int const select_ = fl_get_browser(file_dlg_form_->List);
if (select_ > depth_) {
tmp = dir_entries_[select_ - depth_ - 1].name_;
- SetInfoLine(dir_entries_[select_ - depth_ - 1].ls_entry_);
if (!suffixIs(tmp, '/')) {
isDir = false;
fl_set_input(file_dlg_form_->Filename, tmp.c_str());
}
- } else if (select_ != 0) {
- SetInfoLine(string());
- } else
+ } else if (select_ == 0)
return true;
// executes action
@@ -696,7 +502,7 @@ bool FileDialog::Private::HandleDoubleCl
// Directory higher up
Temp.erase();
for (int i = 0; i < select_; ++i) {
- string piece = fl_get_browser_line(file_dlg_form_->List, i+1);
+ string const piece = fl_get_browser_line(file_dlg_form_->List, i + 1);
// The '+2' is here to count the '@b' (JMarc)
Temp += piece.substr(i + 2);
}
@@ -808,7 +614,6 @@ string const FileDialog::Private::Select
current_dlg_ = this;
// runs dialog
- SetInfoLine(string());
setEnabled(file_dlg_form_->Filename, true);
fl_set_input(file_dlg_form_->Filename, suggested.c_str());
fl_set_button(file_dlg_form_->Cancel, 0);
@@ -858,11 +663,10 @@ string const FileDialog::Private::Select
string tmp = suggested;
if (!suffixIs(tmp, '/'))
tmp += '/';
- string full_path = path;
- full_path += tmp;
+ string const full_path = path + tmp;
// check if this is really a directory
- DIR * dir = ::opendir(full_path.c_str());
- if (dir)
+ if (fs::exists(full_path)
+ && fs::is_directory(full_path))
SetDirectory(full_path);
else
SetDirectory(path);
@@ -879,7 +683,6 @@ string const FileDialog::Private::Select
current_dlg_ = this;
// runs dialog
- SetInfoLine(string());
fl_set_input(file_dlg_form_->Filename, "");
setEnabled(file_dlg_form_->Filename, false);
fl_set_button(file_dlg_form_->Cancel, 0);
Index: FormFiledialog.h
===================================================================
RCS file: /usr/local/lyx/cvsroot/lyx-devel/src/frontends/xforms/FormFiledialog.h,v
retrieving revision 1.21
diff -u -p -B -b -w -r1.21 FormFiledialog.h
--- FormFiledialog.h 19 May 2004 15:11:35 -0000 1.21
+++ FormFiledialog.h 29 Jan 2005 14:18:32 -0000
@@ -43,8 +43,6 @@ public:
std::string name_;
///
std::string displayed_;
- ///
- std::string ls_entry_;
};
@@ -115,8 +113,6 @@ private:
///
long last_time_;
///
- std::string info_line_;
- ///
typedef std::vector<lyx::frontend::DirEntry> DirEntries;
///
DirEntries dir_entries_;
@@ -136,8 +132,6 @@ private:
/// sets dialog file mask
void SetFilters(std::string const & filters);
void SetFilters(lyx::support::FileFilterList const & filters);
- /// sets dialog information line
- void SetInfoLine(std::string const & pszLine);
/// handle dialog during file selection
bool RunDialog();
/// Handle callback from list
--
Lgb