Initial system location finder (unix only)

This commit is contained in:
Jack Andersen 2016-01-01 16:27:17 -10:00
parent 4ca3cb8081
commit 29fd504475
3 changed files with 213 additions and 5 deletions

2
hecl/extern/libBoo vendored

@ -1 +1 @@
Subproject commit 9c173505248875ee9bf7e943030a134401da6e05
Subproject commit 4d7e9656f1b3ac11ab0609b4e6a68c9612418e79

View File

@ -91,6 +91,7 @@ public:
: m_utf8(WideToUTF8(str)) {}
operator const std::string&() const {return m_utf8;}
const std::string& str() const {return m_utf8;}
const char* c_str() const {return m_utf8.c_str();}
std::string operator+(const std::string& other) const {return m_utf8 + other;}
std::string operator+(const char* other) const {return m_utf8 + other;}
};
@ -104,6 +105,7 @@ public:
: m_sys(UTF8ToWide(str)) {}
operator const std::wstring&() const {return m_sys;}
const std::wstring& sys_str() const {return m_sys;}
const SystemChar* c_str() const {return m_sys.c_str();}
std::wstring operator+(const std::wstring& other) const {return m_sys + other;}
std::wstring operator+(const wchar_t* other) const {return m_sys + other;}
};
@ -129,6 +131,7 @@ public:
: m_utf8(str) {}
operator const std::string&() const {return m_utf8;}
const std::string& str() const {return m_utf8;}
const char* c_str() const {return m_utf8.c_str();}
std::string operator+(const std::string& other) const {return std::string(m_utf8) + other;}
std::string operator+(const char* other) const {return std::string(m_utf8) + other;}
};
@ -142,6 +145,7 @@ public:
: m_sys(str) {}
operator const std::string&() const {return m_sys;}
const std::string& sys_str() const {return m_sys;}
const SystemChar* c_str() const {return m_sys.c_str();}
std::string operator+(const std::string& other) const {return m_sys + other;}
std::string operator+(const char* other) const {return m_sys + other;}
};
@ -561,10 +565,10 @@ private:
public:
DirectoryEnumerator(const HECL::SystemString& path, Mode mode=Mode::DirsThenFilesSorted,
bool sizeSort=false, bool reverse=false)
: DirectoryEnumerator(path.c_str(), mode, sizeSort, reverse) {}
bool sizeSort=false, bool reverse=false, bool noHidden=false)
: DirectoryEnumerator(path.c_str(), mode, sizeSort, reverse, noHidden) {}
DirectoryEnumerator(const HECL::SystemChar* path, Mode mode=Mode::DirsThenFilesSorted,
bool sizeSort=false, bool reverse=false);
bool sizeSort=false, bool reverse=false, bool noHidden=false);
operator bool() const {return m_entries.size() != 0;}
size_t size() const {return m_entries.size();}
@ -572,6 +576,11 @@ public:
std::vector<Entry>::const_iterator end() const {return m_entries.cend();}
};
/**
* @brief Build list of common OS-specific directories
*/
std::vector<HECL::SystemString> GetSystemLocations();
/**
* @brief Special ProjectRootPath class for opening HECLDatabase::IProject instances
*

View File

@ -1,5 +1,21 @@
#include "HECL/HECL.hpp"
#ifdef WIN32
#include <windows.h>
#ifndef _WIN32_IE
#define _WIN32_IE 0x0400
#endif
#include <shlobj.h>
#endif
#ifdef __APPLE__
#include <Carbon/Carbon.h>
#endif
#ifdef __linux__
#include <mntent.h>
#endif
namespace HECL
{
unsigned VerbosityLevel = 0;
@ -118,7 +134,7 @@ bool IsPathYAML(const HECL::ProjectPath& path)
}
HECL::DirectoryEnumerator::DirectoryEnumerator(const HECL::SystemChar* path, Mode mode,
bool sizeSort, bool reverse)
bool sizeSort, bool reverse, bool noHidden)
{
HECL::Sstat theStat;
if (HECL::Stat(path, &theStat) || !S_ISDIR(theStat.st_mode))
@ -138,6 +154,8 @@ HECL::DirectoryEnumerator::DirectoryEnumerator(const HECL::SystemChar* path, Mod
{
if (!wcscmp(d.cFileName, _S(".")) || !wcscmp(d.cFileName, _S("..")))
continue;
if (noHidden && (d.cFileName == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
continue;
HECL::SystemString fp(path);
fp += _S('/');
fp += d.cFileName;
@ -165,6 +183,8 @@ HECL::DirectoryEnumerator::DirectoryEnumerator(const HECL::SystemChar* path, Mod
{
if (!wcscmp(d.cFileName, _S(".")) || !wcscmp(d.cFileName, _S("..")))
continue;
if (noHidden && (d.cFileName == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
continue;
HECL::SystemString fp(path);
fp +=_S('/');
fp += d.cFileName;
@ -198,6 +218,8 @@ HECL::DirectoryEnumerator::DirectoryEnumerator(const HECL::SystemChar* path, Mod
{
if (!wcscmp(d.cFileName, _S(".")) || !wcscmp(d.cFileName, _S("..")))
continue;
if (noHidden && (d.cFileName == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
continue;
HECL::SystemString fp(path);
fp += _S('/');
fp += d.cFileName;
@ -221,6 +243,8 @@ HECL::DirectoryEnumerator::DirectoryEnumerator(const HECL::SystemChar* path, Mod
{
if (!wcscmp(d.cFileName, _S(".")) || !wcscmp(d.cFileName, _S("..")))
continue;
if (noHidden && (d.cFileName == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
continue;
HECL::SystemString fp(path);
fp += _S('/');
fp += d.cFileName;
@ -256,6 +280,8 @@ HECL::DirectoryEnumerator::DirectoryEnumerator(const HECL::SystemChar* path, Mod
{
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
continue;
HECL::SystemString fp(path);
fp += '/';
fp += d->d_name;
@ -283,6 +309,8 @@ HECL::DirectoryEnumerator::DirectoryEnumerator(const HECL::SystemChar* path, Mod
{
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
continue;
HECL::SystemString fp(path);
fp += '/';
fp += d->d_name;
@ -315,6 +343,8 @@ HECL::DirectoryEnumerator::DirectoryEnumerator(const HECL::SystemChar* path, Mod
{
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
continue;
HECL::SystemString fp(path);
fp += '/';
fp += d->d_name;
@ -338,6 +368,8 @@ HECL::DirectoryEnumerator::DirectoryEnumerator(const HECL::SystemChar* path, Mod
{
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
continue;
HECL::SystemString fp(path);
fp += '/';
fp += d->d_name;
@ -363,4 +395,171 @@ HECL::DirectoryEnumerator::DirectoryEnumerator(const HECL::SystemChar* path, Mod
#endif
}
std::vector<HECL::SystemString> GetSystemLocations()
{
HECL::Sstat theStat;
std::vector<HECL::SystemString> ret;
#ifdef WIN32
/* Add the drive names to the listing */
{
wchar_t wline[FILE_MAXDIR];
__int64 tmp;
char tmps[4], *name;
int i;
tmp = GetLogicalDrives();
for (i = 0; i < 26; i++) {
if ((tmp >> i) & 1) {
tmps[0] = 'A' + i;
tmps[1] = ':';
tmps[2] = '\\';
tmps[3] = '\0';
name = NULL;
/* Flee from horrible win querying hover floppy drives! */
if (i > 1) {
/* Try to get volume label as well... */
BLI_strncpy_wchar_from_utf8(wline, tmps, 4);
if (GetVolumeInformationW(wline, wline + 4, FILE_MAXDIR - 4, NULL, NULL, NULL, NULL, 0)) {
size_t label_len;
BLI_strncpy_wchar_as_utf8(line, wline + 4, FILE_MAXDIR - 4);
label_len = MIN2(strlen(line), FILE_MAXDIR - 6);
BLI_snprintf(line + label_len, 6, " (%.2s)", tmps);
name = line;
}
}
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, tmps, name, FS_INSERT_SORTED);
}
}
/* Adding Desktop and My Documents */
if (read_bookmarks) {
SHGetSpecialFolderPathW(0, wline, CSIDL_PERSONAL, 0);
BLI_strncpy_wchar_as_utf8(line, wline, FILE_MAXDIR);
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
SHGetSpecialFolderPathW(0, wline, CSIDL_DESKTOPDIRECTORY, 0);
BLI_strncpy_wchar_as_utf8(line, wline, FILE_MAXDIR);
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_SORTED);
}
}
#else
#ifdef __APPLE__
{
/* Get mounted volumes better method OSX 10.6 and higher, see: */
/*https://developer.apple.com/library/mac/#documentation/CoreFOundation/Reference/CFURLRef/Reference/reference.html*/
/* we get all volumes sorted including network and do not relay on user-defined finder visibility, less confusing */
CFURLRef cfURL = NULL;
CFURLEnumeratorResult result = kCFURLEnumeratorSuccess;
CFURLEnumeratorRef volEnum = CFURLEnumeratorCreateForMountedVolumes(NULL, kCFURLEnumeratorSkipInvisibles, NULL);
while (result != kCFURLEnumeratorEnd) {
unsigned char defPath[FILE_MAX];
result = CFURLEnumeratorGetNextURL(volEnum, &cfURL, NULL);
if (result != kCFURLEnumeratorSuccess)
continue;
CFURLGetFileSystemRepresentation(cfURL, false, (UInt8 *)defPath, FILE_MAX);
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM, (char *)defPath, NULL, FS_INSERT_SORTED);
}
CFRelease(volEnum);
/* Finally get user favorite places */
if (read_bookmarks) {
UInt32 seed;
OSErr err = noErr;
CFArrayRef pathesArray;
LSSharedFileListRef list;
LSSharedFileListItemRef itemRef;
CFIndex i, pathesCount;
CFURLRef cfURL = NULL;
CFStringRef pathString = NULL;
list = LSSharedFileListCreate(NULL, kLSSharedFileListFavoriteItems, NULL);
pathesArray = LSSharedFileListCopySnapshot(list, &seed);
pathesCount = CFArrayGetCount(pathesArray);
for (i = 0; i < pathesCount; i++) {
itemRef = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(pathesArray, i);
err = LSSharedFileListItemResolve(itemRef,
kLSSharedFileListNoUserInteraction |
kLSSharedFileListDoNotMountVolumes,
&cfURL, NULL);
if (err != noErr)
continue;
pathString = CFURLCopyFileSystemPath(cfURL, kCFURLPOSIXPathStyle);
if (pathString == NULL || !CFStringGetCString(pathString, line, sizeof(line), kCFStringEncodingUTF8))
continue;
/* Exclude "all my files" as it makes no sense in blender fileselector */
/* Exclude "airdrop" if wlan not active as it would show "" ) */
if (!strstr(line, "myDocuments.cannedSearch") && (*line != '\0')) {
fsmenu_insert_entry(fsmenu, FS_CATEGORY_SYSTEM_BOOKMARKS, line, NULL, FS_INSERT_LAST);
}
CFRelease(pathString);
CFRelease(cfURL);
}
CFRelease(pathesArray);
CFRelease(list);
}
}
#else
/* unix */
{
const char* home = getenv("HOME");
if (home)
{
ret.push_back(home);
std::string desktop(home);
desktop += "/Desktop";
if (!HECL::Stat(desktop.c_str(), &theStat))
ret.push_back(std::move(desktop));
}
{
bool found = false;
#ifdef __linux__
/* Loop over mount points */
struct mntent *mnt;
FILE* fp = setmntent(MOUNTED, "r");
if (fp)
{
while ((mnt = getmntent(fp)))
{
if (strlen(mnt->mnt_fsname) < 4 || strncmp(mnt->mnt_fsname, "/dev", 4))
continue;
std::string mntStr(mnt->mnt_dir);
if (mntStr.size() > 1 && mntStr.back() == '/')
mntStr.pop_back();
ret.push_back(std::move(mntStr));
found = true;
}
endmntent(fp);
}
#endif
/* Fallback */
if (!found)
ret.push_back("/");
}
}
#endif
#endif
return ret;
}
}