mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-11 17:17:42 +03:00
Methods UIWidget::setLayoutSizePolicy, UIWidget::setLayoutWidthPolicy, UIWidget::setLayoutHeightPolicy now trigger auto resize when changing its size policy to SizePolicy::WrapContent.
Added Sys::getLogicalDrives, implemented for Windows and Linux. UIFileDialog now shows the local drives when no more parent folders are present (when you can't go "up" anymore). Added DiskDrivesModel. Replaced all strcmp with strncmp. FileSystem::mkDir now supports recursive mkdir. Improvements and fixes in UIAbstractTableView, UITableView and UITreeView. Silenced use-after-free warning in the Memory Manager. Allow use premake option "--with-debug-symbols" for Windows builds. Closes SpartanJ/ecode#8.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace EE {
|
||||
|
||||
class EE_API AllocatedPointer {
|
||||
@@ -25,6 +26,8 @@ class EE_API AllocatedPointer {
|
||||
typedef std::map<void*, AllocatedPointer> AllocatedPointerMap;
|
||||
typedef AllocatedPointerMap::iterator AllocatedPointerMapIt;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuse-after-free"
|
||||
class EE_API MemoryManager {
|
||||
public:
|
||||
static void* addPointer( const AllocatedPointer& aAllocatedPointer );
|
||||
@@ -39,52 +42,22 @@ class EE_API MemoryManager {
|
||||
|
||||
template <class T> static T* deletePtr( T* data ) {
|
||||
delete data;
|
||||
#if defined( __GNUC__ ) && __GNUC__ >= 12
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuse-after-free"
|
||||
return data;
|
||||
#pragma GCC diagnostic pop
|
||||
#else
|
||||
return data;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T> static T* deleteArrayPtr( T* data ) {
|
||||
delete[] data;
|
||||
#if defined( __GNUC__ ) && __GNUC__ >= 12
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuse-after-free"
|
||||
return data;
|
||||
#pragma GCC diagnostic pop
|
||||
#else
|
||||
return data;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T> static T* free( T* data ) {
|
||||
::free( data );
|
||||
#if defined( __GNUC__ ) && __GNUC__ >= 12
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuse-after-free"
|
||||
return data;
|
||||
#pragma GCC diagnostic pop
|
||||
#else
|
||||
return data;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline static void* allocate( size_t size ) { return malloc( size ); }
|
||||
|
||||
inline static void* reallocate( void* ptr, size_t size ) {
|
||||
#if defined( __GNUC__ ) && __GNUC__ >= 12
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuse-after-free"
|
||||
return realloc( ptr, size );
|
||||
#pragma GCC diagnostic pop
|
||||
#else
|
||||
return realloc( ptr, size );
|
||||
#endif
|
||||
}
|
||||
inline static void* reallocate( void* ptr, size_t size ) { return realloc( ptr, size ); }
|
||||
|
||||
static size_t getPeakMemoryUsage();
|
||||
|
||||
@@ -92,6 +65,7 @@ class EE_API MemoryManager {
|
||||
|
||||
static const AllocatedPointer& getBiggestAllocation();
|
||||
};
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#ifdef EE_MEMORY_MANAGER
|
||||
#define eeNewTracked( classType, constructor ) \
|
||||
@@ -114,32 +88,42 @@ class EE_API MemoryManager {
|
||||
#define eeMalloc( amount ) \
|
||||
EE::MemoryManager::addPointer( EE::AllocatedPointer( EE::MemoryManager::allocate( amount ), \
|
||||
__FILE__, __LINE__, amount ) )
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuse-after-free"
|
||||
#define eeRealloc( ptr, amount ) \
|
||||
EE::MemoryManager::reallocPointer( \
|
||||
ptr, EE::AllocatedPointer( EE::MemoryManager::reallocate( ptr, amount ), __FILE__, \
|
||||
__LINE__, amount ) )
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuse-after-free"
|
||||
#define eeDelete( data ) \
|
||||
{ \
|
||||
if ( EE::MemoryManager::removePointer( EE::MemoryManager::deletePtr( data ), __FILE__, \
|
||||
__LINE__ ) == false ) \
|
||||
printf( "Deleting at '%s' %d\n", __FILE__, __LINE__ ); \
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuse-after-free"
|
||||
#define eeDeleteArray( data ) \
|
||||
{ \
|
||||
if ( EE::MemoryManager::removePointer( EE::MemoryManager::deleteArrayPtr( data ), \
|
||||
__FILE__, __LINE__ ) == false ) \
|
||||
printf( "Deleting at '%s' %d\n", __FILE__, __LINE__ ); \
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wuse-after-free"
|
||||
#define eeFree( data ) \
|
||||
{ \
|
||||
if ( EE::MemoryManager::removePointer( EE::MemoryManager::free( data ), __FILE__, \
|
||||
__LINE__ ) == false ) \
|
||||
printf( "Deleting at '%s' %d\n", __FILE__, __LINE__ ); \
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#else
|
||||
|
||||
#define eeNewTracked( classType, constructor ) new classType constructor
|
||||
@@ -162,6 +146,7 @@ class EE_API MemoryManager {
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
} // namespace EE
|
||||
|
||||
#endif
|
||||
|
||||
@@ -122,7 +122,8 @@ class EE_API FileSystem {
|
||||
static bool isDirectory( const String& path );
|
||||
|
||||
/** Creates a new directory */
|
||||
static bool makeDir( const std::string& path, const Uint16& mode = 0770 );
|
||||
static bool makeDir( const std::string& path, bool recursive = false,
|
||||
const Uint16& mode = 0770 );
|
||||
|
||||
/** @return The absolute path of a relative path */
|
||||
static std::string getRealPath( const std::string& path );
|
||||
|
||||
@@ -75,6 +75,9 @@ class EE_API Sys {
|
||||
/** @return the argument list in a vector of std::strings in UTF-8, ignoring the first argument
|
||||
* (the binary name) */
|
||||
static std::vector<std::string> parseArguments( int argc, char* argv[] );
|
||||
|
||||
/** @return The OS logical drives */
|
||||
static std::vector<std::string> getLogicalDrives();
|
||||
};
|
||||
|
||||
}} // namespace EE::System
|
||||
|
||||
@@ -37,7 +37,7 @@ class EE_API UIAbstractTableView : public UIAbstractView {
|
||||
|
||||
void setColumnHidden( const size_t& column, bool hidden );
|
||||
|
||||
void setColumnsHidden( const std::vector<size_t> columns, bool hidden );
|
||||
void setColumnsHidden( const std::vector<size_t>& columns, bool hidden );
|
||||
|
||||
virtual void selectAll();
|
||||
|
||||
@@ -152,7 +152,7 @@ class EE_API UIAbstractTableView : public UIAbstractView {
|
||||
|
||||
virtual void onModelUpdate( unsigned flags );
|
||||
|
||||
virtual void createOrUpdateColumns();
|
||||
virtual void createOrUpdateColumns( bool resetColumnData = false );
|
||||
|
||||
virtual void onSizeChange();
|
||||
|
||||
@@ -191,6 +191,10 @@ class EE_API UIAbstractTableView : public UIAbstractView {
|
||||
void updateHeaderSize();
|
||||
|
||||
int visibleColumn();
|
||||
|
||||
void updateCellsVisibility();
|
||||
|
||||
void resetColumnData();
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Abstract
|
||||
|
||||
@@ -45,7 +45,7 @@ class EE_API UIAbstractView : public UIScrollableWidget {
|
||||
|
||||
bool isType( const Uint32& type ) const;
|
||||
|
||||
void setModel( std::shared_ptr<Model> );
|
||||
void setModel( const std::shared_ptr<Model>& );
|
||||
|
||||
Model* getModel() { return mModel.get(); }
|
||||
|
||||
|
||||
@@ -197,9 +197,41 @@ class EE_API FileSystemModel : public Model {
|
||||
|
||||
size_t getFileIndex( Node* parent, const FileInfo& file );
|
||||
|
||||
|
||||
bool handleFileEventLocked( const FileEvent& event );
|
||||
};
|
||||
|
||||
class EE_API DiskDrivesModel : public Model {
|
||||
public:
|
||||
enum Column {
|
||||
Icon = 0,
|
||||
Name,
|
||||
Count,
|
||||
};
|
||||
|
||||
static std::shared_ptr<DiskDrivesModel> create( const std::vector<std::string>& data );
|
||||
|
||||
static std::shared_ptr<DiskDrivesModel> create();
|
||||
|
||||
virtual ~DiskDrivesModel() {}
|
||||
|
||||
virtual size_t rowCount( const ModelIndex& ) const { return mData.size(); }
|
||||
|
||||
virtual size_t columnCount( const ModelIndex& ) const { return 2; }
|
||||
|
||||
virtual std::string columnName( const size_t& index ) const {
|
||||
return index == 0 ? "Icon" : "Name";
|
||||
}
|
||||
|
||||
UIIcon* diskIcon() const;
|
||||
|
||||
virtual Variant data( const ModelIndex& index, ModelRole role = ModelRole::Display ) const;
|
||||
|
||||
virtual void update() { onModelUpdate(); }
|
||||
|
||||
private:
|
||||
explicit DiskDrivesModel( const std::vector<std::string>& data ) : mData( data ) {}
|
||||
|
||||
std::vector<std::string> mData;
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Models
|
||||
|
||||
@@ -138,9 +138,9 @@ class EE_API Model {
|
||||
|
||||
Mutex& resourceMutex();
|
||||
|
||||
void acquireResourceMutex() { mResourceLock.lock(); }
|
||||
void acquireResourceMutex();
|
||||
|
||||
void releaseResourceMutex() { mResourceLock.unlock(); }
|
||||
void releaseResourceMutex();
|
||||
|
||||
protected:
|
||||
Model(){};
|
||||
|
||||
@@ -136,6 +136,8 @@ class EE_API UIFileDialog : public UIWindow {
|
||||
KeyBindings::Shortcut mCloseShortcut;
|
||||
KeyBindings::Shortcut mOpenShortut{ KEY_RETURN, KeyMod::getDefaultModifier() };
|
||||
std::shared_ptr<FileSystemModel> mModel;
|
||||
std::shared_ptr<DiskDrivesModel> mDiskDrivesModel;
|
||||
bool mDisplayingDrives{ false };
|
||||
|
||||
UIFileDialog( Uint32 dialogFlags = UIFileDialog::DefaultFlags,
|
||||
const std::string& defaultFilePattern = "*",
|
||||
@@ -164,6 +166,10 @@ class EE_API UIFileDialog : public UIWindow {
|
||||
void setCurPath( const std::string& path );
|
||||
|
||||
const FileSystemModel::Node* getSelectionNode() const;
|
||||
|
||||
ModelIndex getSelectionModelIndex() const;
|
||||
|
||||
std::string getSelectedDrive() const;
|
||||
};
|
||||
|
||||
}} // namespace EE::UI
|
||||
|
||||
@@ -31,7 +31,7 @@ class EE_API UITableView : public UIAbstractTableView {
|
||||
|
||||
UITableView( const std::string& tag );
|
||||
|
||||
virtual void createOrUpdateColumns();
|
||||
virtual void createOrUpdateColumns( bool resetColumnData );
|
||||
|
||||
void updateContentSize();
|
||||
|
||||
|
||||
@@ -160,7 +160,7 @@ class EE_API UITreeView : public UIAbstractTableView {
|
||||
|
||||
UITreeView();
|
||||
|
||||
virtual void createOrUpdateColumns();
|
||||
virtual void createOrUpdateColumns( bool resetColumnData );
|
||||
|
||||
struct MetadataForIndex {
|
||||
bool open{ false };
|
||||
|
||||
10
premake4.lua
10
premake4.lua
@@ -1272,14 +1272,22 @@ solution "eepp"
|
||||
links { "CoreFoundation.framework", "CoreServices.framework", "Cocoa.framework" }
|
||||
links { "ecode-macos-helper-static" }
|
||||
end
|
||||
if _OPTIONS["with-debug-symbols"] then
|
||||
defines { "ECODE_USE_BACKWARD" }
|
||||
end
|
||||
if os.is_real("linux") then
|
||||
if _OPTIONS["with-debug-symbols"] then
|
||||
defines { "ECODE_USE_BACKWARD" }
|
||||
links { "util", "bfd", "dw", "dl" }
|
||||
else
|
||||
links { "util" }
|
||||
end
|
||||
end
|
||||
if (os.is_real("windows") or os.is_real("mingw32") or os.is_real("mingw64")) and _OPTIONS["with-debug-symbols"] then
|
||||
links { "dbghelp", "psapi" }
|
||||
if os.is_real("mingw32") or os.is_real("mingw64") then
|
||||
links { "msvcr90" }
|
||||
end
|
||||
end
|
||||
if os.is("haiku") then
|
||||
links { "bsd" }
|
||||
end
|
||||
|
||||
33
premake5.lua
33
premake5.lua
@@ -204,11 +204,11 @@ function build_base_cpp_configuration( package_name )
|
||||
filter "configurations:release*"
|
||||
defines { "NDEBUG" }
|
||||
optimize "Speed"
|
||||
if _OPTIONS["with-debug-symbols"] then
|
||||
symbols "On"
|
||||
end
|
||||
targetname ( package_name )
|
||||
|
||||
filter { "configurations:release*", "options:with-debug-symbols" }
|
||||
symbols "On"
|
||||
|
||||
filter "system:emscripten"
|
||||
buildoptions { "-O3 -s USE_SDL=2 -s PRECISE_F32=1 -s ENVIRONMENT=worker,web" }
|
||||
if _OPTIONS["with-emscripten-pthreads"] then
|
||||
@@ -668,11 +668,12 @@ workspace "eepp"
|
||||
filter "configurations:debug*"
|
||||
defines { "DEBUG" }
|
||||
symbols "On"
|
||||
|
||||
filter "configurations:release*"
|
||||
optimize "Speed"
|
||||
if _OPTIONS["with-debug-symbols"] then
|
||||
symbols "On"
|
||||
end
|
||||
|
||||
filter { "configurations:release*", "options:with-debug-symbols" }
|
||||
symbols "On"
|
||||
|
||||
filter { "system:windows", "action:vs*" }
|
||||
flags { "MultiProcessorCompile" }
|
||||
@@ -983,10 +984,9 @@ workspace "eepp"
|
||||
filter { "configurations:release*", "action:not vs*" }
|
||||
defines { "NDEBUG" }
|
||||
optimize "Speed"
|
||||
if _OPTIONS["with-debug-symbols"] then
|
||||
symbols "On"
|
||||
end
|
||||
targetname ( "ecode-macos-helper-static" )
|
||||
filter { "configurations:release*", "action:not vs*", "options:with-debug-symbols" }
|
||||
symbols "On"
|
||||
|
||||
project "ecode"
|
||||
set_kind()
|
||||
@@ -995,18 +995,21 @@ workspace "eepp"
|
||||
incdirs { "src/thirdparty/efsw/include", "src/thirdparty", "src/modules/eterm/include/" }
|
||||
links { "efsw-static", "eterm-static" }
|
||||
build_link_configuration( "ecode", true )
|
||||
filter "options:with-debug-symbols"
|
||||
defines { "ECODE_USE_BACKWARD" }
|
||||
filter "system:macosx"
|
||||
links { "CoreFoundation.framework", "CoreServices.framework", "Cocoa.framework" }
|
||||
links { "ecode-macos-helper-static" }
|
||||
filter { "system:not windows", "system:not haiku" }
|
||||
links { "pthread" }
|
||||
filter "system:linux"
|
||||
if _OPTIONS["with-debug-symbols"] then
|
||||
defines { "ECODE_USE_BACKWARD" }
|
||||
links { "util", "bfd", "dw", "dl" }
|
||||
else
|
||||
links { "util" }
|
||||
end
|
||||
links { "util" }
|
||||
filter { "system:windows", "options:with-debug-symbols" }
|
||||
links { "dbghelp", "psapi" }
|
||||
filter { "system:windows", "options:with-debug-symbols", "options:cc=mingw" }
|
||||
links { "msvcr90" }
|
||||
filter { "system:linux", "options:with-debug-symbols" }
|
||||
links { "bfd", "dw", "dl" }
|
||||
filter "system:haiku"
|
||||
links { "bsd" }
|
||||
|
||||
|
||||
@@ -296,8 +296,8 @@ bool FileSystem::isDirectory( const std::string& path ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
bool FileSystem::makeDir( const std::string& path, const Uint16& mode ) {
|
||||
Int16 v;
|
||||
static inline bool eepp_mkdir( const std::string& path, const Uint16& mode ) {
|
||||
int v;
|
||||
#if EE_PLATFORM == EE_PLATFORM_WIN
|
||||
#ifdef EE_COMPILER_MSVC
|
||||
v = _mkdir( path.c_str() );
|
||||
@@ -310,6 +310,35 @@ bool FileSystem::makeDir( const std::string& path, const Uint16& mode ) {
|
||||
return v == 0;
|
||||
}
|
||||
|
||||
bool FileSystem::makeDir( const std::string& path, bool recursive, const Uint16& mode ) {
|
||||
if ( recursive && path.size() > 1 ) {
|
||||
size_t i = path.size() - 1;
|
||||
for ( ; i >= 0; --i ) {
|
||||
if ( path[i] == '/' || path[i] == '\\' ) {
|
||||
if ( FileSystem::isDirectory( path.substr( 0, i ) ) ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( i == 0 )
|
||||
return false;
|
||||
|
||||
i++;
|
||||
for ( ; i < path.size(); ++i ) {
|
||||
if ( path[i] == '/' || path[i] == '\\' ) {
|
||||
if ( !eepp_mkdir( path.substr( 0, i ), mode ) )
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( path[path.size() - 1] == '/' || path[path.size() - 1] == '\\' )
|
||||
return true;
|
||||
}
|
||||
|
||||
return eepp_mkdir( path, mode );
|
||||
}
|
||||
|
||||
std::string FileSystem::getRealPath( const std::string& path ) {
|
||||
std::string realPath;
|
||||
#ifdef EE_PLATFORM_POSIX
|
||||
@@ -367,7 +396,8 @@ std::vector<String> FileSystem::filesGetInPath( const String& path, const bool&
|
||||
return files;
|
||||
|
||||
while ( ( dirp = readdir( dp ) ) != NULL ) {
|
||||
if ( strcmp( dirp->d_name, ".." ) != 0 && strcmp( dirp->d_name, "." ) != 0 ) {
|
||||
if ( strncmp( dirp->d_name, "..", sizeof( dirp->d_name ) ) != 0 &&
|
||||
strncmp( dirp->d_name, ".", sizeof( dirp->d_name ) ) != 0 ) {
|
||||
|
||||
char* p = &dirp->d_name[0];
|
||||
String tmp;
|
||||
@@ -476,7 +506,8 @@ std::vector<std::string> FileSystem::filesGetInPath( const std::string& path,
|
||||
return files;
|
||||
|
||||
while ( ( dirp = readdir( dp ) ) != NULL ) {
|
||||
if ( strcmp( dirp->d_name, ".." ) != 0 && strcmp( dirp->d_name, "." ) != 0 )
|
||||
if ( strncmp( dirp->d_name, "..", sizeof( dirp->d_name ) ) != 0 &&
|
||||
strncmp( dirp->d_name, ".", sizeof( dirp->d_name ) ) != 0 )
|
||||
files.push_back( std::string( dirp->d_name ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +115,7 @@ Int8 Pak::checkPack() {
|
||||
Int32 Pak::exists( const std::string& path ) {
|
||||
if ( isOpen() ) {
|
||||
for ( Uint32 i = 0; i < mPakFiles.size(); i++ )
|
||||
if ( strcmp( path.c_str(), mPakFiles[i].filename ) == 0 )
|
||||
if ( std::strncmp( path.c_str(), mPakFiles[i].filename, path.size() ) == 0 )
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#undef GetTempPath
|
||||
#elif EE_PLATFORM == EE_PLATFORM_LINUX || EE_PLATFORM == EE_PLATFORM_ANDROID
|
||||
#include <libgen.h>
|
||||
#include <mntent.h>
|
||||
#include <unistd.h>
|
||||
#elif EE_PLATFORM == EE_PLATFORM_HAIKU
|
||||
#include <kernel/OS.h>
|
||||
@@ -899,4 +900,60 @@ std::vector<std::string> Sys::parseArguments( int argc, char* argv[] ) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if EE_PLATFORM == EE_PLATFORM_WIN
|
||||
static inline bool isDriveReady( const wchar_t* path ) {
|
||||
DWORD fileSystemFlags;
|
||||
const UINT driveType = GetDriveTypeW( path );
|
||||
return ( driveType != DRIVE_REMOVABLE && driveType != DRIVE_CDROM ) ||
|
||||
GetVolumeInformationW( path, nullptr, 0, nullptr, nullptr, &fileSystemFlags, nullptr,
|
||||
0 ) == TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::vector<std::string> Sys::getLogicalDrives() {
|
||||
#if EE_PLATFORM == EE_PLATFORM_WIN
|
||||
std::vector<std::string> ret;
|
||||
const UINT oldErrorMode = ::SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX );
|
||||
Uint32 driveBits = (Uint32)GetLogicalDrives() & 0x3ffffff;
|
||||
wchar_t driveName[] = L"A:\\";
|
||||
|
||||
while ( driveBits ) {
|
||||
if ( ( driveBits & 1 ) && isDriveReady( driveName ) )
|
||||
ret.emplace_back( String::fromWide( driveName ).toUtf8() );
|
||||
driveName[0]++;
|
||||
driveBits = driveBits >> 1;
|
||||
}
|
||||
::SetErrorMode( oldErrorMode );
|
||||
return ret;
|
||||
#elif EE_PLATFORM == EE_PLATFORM_LINUX
|
||||
std::vector<std::string> ret;
|
||||
struct mntent* ent;
|
||||
FILE* file = setmntent( "/etc/mtab", "r" );
|
||||
if ( file == NULL ) {
|
||||
file = setmntent( "/proc/mounts", "r" );
|
||||
if ( file == NULL )
|
||||
return ret;
|
||||
}
|
||||
while ( NULL != ( ent = getmntent( file ) ) ) {
|
||||
std::string mntType( ent->mnt_type );
|
||||
if ( mntType == "rootfs" || mntType == "devtmpfs" || mntType == "tmpfs" ||
|
||||
mntType == "devpts" || mntType == "hugetlbfs" || mntType == "mqueue" ||
|
||||
mntType == "ramfs" || mntType == "rpc_pipefs" || mntType == "fuse.gvfsd-fuse" ||
|
||||
mntType == "fuse.portal" || mntType == "overlay" || mntType == "nsfs" )
|
||||
continue;
|
||||
|
||||
std::string mntDir( ent->mnt_dir );
|
||||
if ( String::startsWith( mntDir, "/proc" ) || String::startsWith( mntDir, "/var/run" ) ||
|
||||
String::startsWith( mntDir, "/sys" ) || String::startsWith( mntDir, "/var/lock" ) )
|
||||
continue;
|
||||
|
||||
ret.emplace_back( std::move( mntDir ) );
|
||||
}
|
||||
endmntent( file );
|
||||
return ret;
|
||||
#else
|
||||
return {};
|
||||
#endif
|
||||
}
|
||||
|
||||
}} // namespace EE::System
|
||||
|
||||
@@ -42,7 +42,7 @@ Float UIAbstractTableView::getRowHeight() const {
|
||||
void UIAbstractTableView::setRowHeight( const Float& rowHeight ) {
|
||||
if ( mRowHeight != rowHeight ) {
|
||||
mRowHeight = rowHeight;
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ void UIAbstractTableView::setColumnWidth( const size_t& colIndex, const Float& w
|
||||
columnData( colIndex ).width = width;
|
||||
updateHeaderSize();
|
||||
onColumnSizeChange( colIndex );
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,24 +77,37 @@ void UIAbstractTableView::onModelUpdate( unsigned flags ) {
|
||||
if ( !Engine::instance()->isMainThread() ) {
|
||||
runOnMainThread( [&, flags] {
|
||||
modelUpdate( flags );
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( true );
|
||||
} );
|
||||
} else {
|
||||
UIAbstractView::onModelUpdate( flags );
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( true );
|
||||
}
|
||||
}
|
||||
|
||||
void UIAbstractTableView::createOrUpdateColumns() {
|
||||
void UIAbstractTableView::resetColumnData() {
|
||||
Model* model = getModel();
|
||||
if ( !model )
|
||||
return;
|
||||
size_t count = model->columnCount();
|
||||
for ( size_t i = 0; i < count; i++ ) {
|
||||
ColumnData& col = columnData( i );
|
||||
col.minWidth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void UIAbstractTableView::createOrUpdateColumns( bool resetColumnData ) {
|
||||
Model* model = getModel();
|
||||
if ( !model )
|
||||
return;
|
||||
|
||||
size_t count = model->columnCount();
|
||||
Float totalWidth = 0;
|
||||
|
||||
auto visibleColCount = visibleColumnCount();
|
||||
|
||||
if ( resetColumnData )
|
||||
this->resetColumnData();
|
||||
|
||||
for ( size_t i = 0; i < count; i++ ) {
|
||||
ColumnData& col = columnData( i );
|
||||
if ( !col.widget ) {
|
||||
@@ -223,7 +236,7 @@ void UIAbstractTableView::setHeadersVisible( bool visible ) {
|
||||
|
||||
void UIAbstractTableView::onSizeChange() {
|
||||
UIAbstractView::onSizeChange();
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
|
||||
void UIAbstractTableView::onColumnSizeChange( const size_t&, bool fromUserInteraction ) {
|
||||
@@ -237,7 +250,7 @@ Float UIAbstractTableView::getMaxColumnContentWidth( const size_t&, bool ) {
|
||||
|
||||
void UIAbstractTableView::onColumnResizeToContent( const size_t& colIndex ) {
|
||||
columnData( colIndex ).width = getMaxColumnContentWidth( colIndex, true );
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
|
||||
void UIAbstractTableView::updateHeaderSize() {
|
||||
@@ -260,6 +273,17 @@ int UIAbstractTableView::visibleColumn() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void UIAbstractTableView::updateCellsVisibility() {
|
||||
auto colCount = mColumn.size();
|
||||
for ( size_t colIdx = 0; colIdx < colCount; ++colIdx ) {
|
||||
for ( auto row : mWidgets ) {
|
||||
auto rowCol = row.find( colIdx );
|
||||
if ( rowCol != row.end() )
|
||||
rowCol->second->setVisible( mColumn[colIdx].visible );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UIAbstractTableView::getAutoExpandOnSingleColumn() const {
|
||||
return mAutoExpandOnSingleColumn;
|
||||
}
|
||||
@@ -334,19 +358,38 @@ bool UIAbstractTableView::isColumnHidden( const size_t& column ) const {
|
||||
void UIAbstractTableView::setColumnHidden( const size_t& column, bool hidden ) {
|
||||
if ( columnData( column ).visible != !hidden ) {
|
||||
columnData( column ).visible = !hidden;
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
}
|
||||
|
||||
void UIAbstractTableView::setColumnsHidden( const std::vector<size_t> columns, bool hidden ) {
|
||||
void UIAbstractTableView::setColumnsHidden( const std::vector<size_t>& columns, bool hidden ) {
|
||||
for ( auto col : columns )
|
||||
columnData( col ).visible = !hidden;
|
||||
createOrUpdateColumns();
|
||||
updateCellsVisibility();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
|
||||
void UIAbstractTableView::setColumnsVisible( const std::vector<size_t> columns ) {
|
||||
if ( !getModel() )
|
||||
return;
|
||||
|
||||
// Check if the columns visible are the same
|
||||
if ( !mColumn.empty() && !columns.empty() ) {
|
||||
// TODO: Do not limit the column count to 64
|
||||
Uint64 colFlags = 0;
|
||||
Uint64 newColFlags = 0;
|
||||
for ( size_t i = 0; i < mColumn.size(); ++i ) {
|
||||
if ( mColumn[i].visible )
|
||||
colFlags |= 1 << i;
|
||||
}
|
||||
|
||||
for ( auto col : columns )
|
||||
newColFlags |= 1 << col;
|
||||
|
||||
if ( colFlags == newColFlags )
|
||||
return;
|
||||
}
|
||||
|
||||
for ( size_t i = 0; i < getModel()->columnCount(); i++ )
|
||||
columnData( i ).visible = false;
|
||||
|
||||
@@ -360,7 +403,9 @@ void UIAbstractTableView::setColumnsVisible( const std::vector<size_t> columns )
|
||||
if ( !foundMainColumn && !columns.empty() )
|
||||
mMainColumn = columns[0];
|
||||
|
||||
createOrUpdateColumns();
|
||||
updateCellsVisibility();
|
||||
|
||||
createOrUpdateColumns( true );
|
||||
}
|
||||
|
||||
UITableRow* UIAbstractTableView::createRow() {
|
||||
@@ -452,7 +497,12 @@ UIWidget* UIAbstractTableView::updateCell( const int& rowIndex, const ModelIndex
|
||||
mWidgets[rowIndex][index.column()] = widget;
|
||||
widget->reloadStyle( true, true, true );
|
||||
}
|
||||
widget->setPixelsSize( columnData( index.column() ).width, getRowHeight() );
|
||||
const auto& colData = columnData( index.column() );
|
||||
if ( !colData.visible ) {
|
||||
widget->setVisible( false );
|
||||
return widget;
|
||||
}
|
||||
widget->setPixelsSize( colData.width, getRowHeight() );
|
||||
widget->setPixelsPosition( { getColumnPosition( index.column() ).x, 0 } );
|
||||
if ( widget->isType( UI_TYPE_TABLECELL ) ) {
|
||||
UITableCell* cell = widget->asType<UITableCell>();
|
||||
|
||||
@@ -33,7 +33,7 @@ bool UIAbstractView::isType( const Uint32& type ) const {
|
||||
return UIAbstractView::getType() == type ? true : UIScrollableWidget::isType( type );
|
||||
}
|
||||
|
||||
void UIAbstractView::setModel( std::shared_ptr<Model> model ) {
|
||||
void UIAbstractView::setModel( const std::shared_ptr<Model>& model ) {
|
||||
if ( model.get() == mModel.get() )
|
||||
return;
|
||||
if ( mModel )
|
||||
|
||||
@@ -461,7 +461,8 @@ size_t FileSystemModel::getFileIndex( Node* parent, const FileInfo& file ) {
|
||||
files.emplace_back( file );
|
||||
|
||||
std::sort( files.begin(), files.end(), []( FileInfo a, FileInfo b ) {
|
||||
return std::strcmp( a.getFileName().c_str(), b.getFileName().c_str() ) < 0;
|
||||
return std::strncmp( a.getFileName().c_str(), b.getFileName().c_str(),
|
||||
a.getFileName().size() ) < 0;
|
||||
} );
|
||||
|
||||
if ( getDisplayConfig().foldersFirst ) {
|
||||
@@ -723,4 +724,40 @@ bool FileSystemModel::handleFileEvent( const FileEvent& event ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::shared_ptr<DiskDrivesModel> DiskDrivesModel::create( const std::vector<std::string>& data ) {
|
||||
return std::shared_ptr<DiskDrivesModel>( new DiskDrivesModel( data ) );
|
||||
}
|
||||
|
||||
std::shared_ptr<DiskDrivesModel> DiskDrivesModel::create() {
|
||||
return create( Sys::getLogicalDrives() );
|
||||
}
|
||||
|
||||
UIIcon* DiskDrivesModel::diskIcon() const {
|
||||
auto* scene = SceneManager::instance()->getUISceneNode();
|
||||
auto* d = scene->findIcon( "drive" );
|
||||
if ( !d )
|
||||
d = scene->findIcon( "folder" );
|
||||
return d;
|
||||
}
|
||||
|
||||
Variant DiskDrivesModel::data( const ModelIndex& index, ModelRole role ) const {
|
||||
eeASSERT( index.row() >= 0 && index.row() < (Int64)mData.size() );
|
||||
if ( role == ModelRole::Display ) {
|
||||
switch ( index.column() ) {
|
||||
case Column::Icon:
|
||||
return diskIcon();
|
||||
case Column::Name:
|
||||
return Variant( mData[index.row()].c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
if ( role == ModelRole::Icon )
|
||||
return diskIcon();
|
||||
|
||||
if ( role == ModelRole::Custom )
|
||||
return Variant( mData[index.row()].c_str() );
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}}} // namespace EE::UI::Models
|
||||
|
||||
@@ -307,6 +307,14 @@ Mutex& Model::resourceMutex() {
|
||||
return mResourceLock;
|
||||
}
|
||||
|
||||
void Model::acquireResourceMutex() {
|
||||
mResourceLock.lock();
|
||||
}
|
||||
|
||||
void Model::releaseResourceMutex() {
|
||||
mResourceLock.unlock();
|
||||
}
|
||||
|
||||
void Model::handleMove( Operation const& operation ) {
|
||||
bool isRow = operation.direction == Direction::Row;
|
||||
bool moveWithin = operation.sourceParent == operation.targetParent;
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace EE { namespace UI {
|
||||
|
||||
#define FDLG_MIN_WIDTH 640
|
||||
#define FDLG_MIN_HEIGHT 400
|
||||
#define FDLG_DRIVE_PATH "drives://"
|
||||
|
||||
UIFileDialog* UIFileDialog::New( Uint32 dialogFlags, const std::string& defaultFilePattern,
|
||||
const std::string& defaultDirectory ) {
|
||||
@@ -82,7 +83,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa
|
||||
mPath->addEventListener( Event::OnPressEnter, cb::Make1( this, &UIFileDialog::onPressEnter ) );
|
||||
|
||||
mButtonUp = UIPushButton::New();
|
||||
mButtonUp->setText( "Up" )
|
||||
mButtonUp->setText( getTranslatorString( "@string/uifiledialog_go_up", "Up" ) )
|
||||
->setLayoutMarginLeft( 4 )
|
||||
->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::MatchParent )
|
||||
->setParent( hLayout );
|
||||
@@ -116,7 +117,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa
|
||||
} );
|
||||
|
||||
mButtonListView = UISelectButton::New();
|
||||
mButtonListView->setText( "List" )
|
||||
mButtonListView->setText( getTranslatorString( "@string/uifiledialog_list", "List" ) )
|
||||
->setLayoutMarginLeft( 4 )
|
||||
->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::MatchParent )
|
||||
->setParent( hLayout );
|
||||
@@ -127,7 +128,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa
|
||||
} );
|
||||
|
||||
mButtonTableView = UISelectButton::New();
|
||||
mButtonTableView->setText( "Table" )
|
||||
mButtonTableView->setText( getTranslatorString( "@string/uifiledialog_table", "Table" ) )
|
||||
->setLayoutMarginLeft( 4 )
|
||||
->setLayoutSizePolicy( SizePolicy::WrapContent, SizePolicy::MatchParent )
|
||||
->setParent( hLayout );
|
||||
@@ -167,7 +168,7 @@ UIFileDialog::UIFileDialog( Uint32 dialogFlags, const std::string& defaultFilePa
|
||||
}
|
||||
} );
|
||||
mMultiView->setOnSelectionChange( [&] {
|
||||
if ( mMultiView->getSelection().isEmpty() )
|
||||
if ( mMultiView->getSelection().isEmpty() || mDisplayingDrives )
|
||||
return;
|
||||
const FileSystemModel::Node* node = getSelectionNode();
|
||||
if ( !node ) {
|
||||
@@ -306,29 +307,44 @@ void UIFileDialog::setTheme( UITheme* Theme ) {
|
||||
|
||||
void UIFileDialog::refreshFolder( bool resetScroll ) {
|
||||
FileSystem::dirAddSlashAtEnd( mCurPath );
|
||||
std::vector<String> flist = FileSystem::filesGetInPath(
|
||||
String( mCurPath ), getSortAlphabetically(), getFoldersFirst(), !getShowHidden() );
|
||||
std::vector<String> files;
|
||||
std::vector<std::string> patterns;
|
||||
|
||||
if ( "*" != mFiletype->getText() ) {
|
||||
patterns = String::split( mFiletype->getText().toUtf8(), ';' );
|
||||
if ( mCurPath == FDLG_DRIVE_PATH ) {
|
||||
if ( !mDiskDrivesModel )
|
||||
mDiskDrivesModel = DiskDrivesModel::create();
|
||||
|
||||
for ( size_t i = 0; i < patterns.size(); i++ )
|
||||
patterns[i] = FileSystem::fileExtension( String::trim( patterns[i] ) );
|
||||
}
|
||||
mDisplayingDrives = true;
|
||||
mMultiView->getTableView()->setColumnsVisible( { FileSystemModel::Name } );
|
||||
mMultiView->setModel( SortingProxyModel::New( mDiskDrivesModel ) );
|
||||
} else {
|
||||
std::vector<String> flist = FileSystem::filesGetInPath(
|
||||
String( mCurPath ), getSortAlphabetically(), getFoldersFirst(), !getShowHidden() );
|
||||
std::vector<String> files;
|
||||
std::vector<std::string> patterns;
|
||||
|
||||
if ( !mModel ) {
|
||||
mModel = FileSystemModel::New(
|
||||
mCurPath,
|
||||
getShowOnlyFolders() ? FileSystemModel::Mode::DirectoriesOnly
|
||||
: FileSystemModel::Mode::FilesAndDirectories,
|
||||
FileSystemModel::DisplayConfig( getSortAlphabetically(), getFoldersFirst(),
|
||||
!getShowHidden(), patterns ) );
|
||||
if ( "*" != mFiletype->getText() ) {
|
||||
patterns = String::split( mFiletype->getText().toUtf8(), ';' );
|
||||
|
||||
for ( size_t i = 0; i < patterns.size(); i++ )
|
||||
patterns[i] = FileSystem::fileExtension( String::trim( patterns[i] ) );
|
||||
}
|
||||
|
||||
if ( !mModel ) {
|
||||
mModel = FileSystemModel::New(
|
||||
mCurPath,
|
||||
getShowOnlyFolders() ? FileSystemModel::Mode::DirectoriesOnly
|
||||
: FileSystemModel::Mode::FilesAndDirectories,
|
||||
FileSystemModel::DisplayConfig( getSortAlphabetically(), getFoldersFirst(),
|
||||
!getShowHidden(), patterns ) );
|
||||
} else {
|
||||
mModel->setRootPath( mCurPath );
|
||||
}
|
||||
|
||||
mMultiView->setModel( SortingProxyModel::New( mModel ) );
|
||||
} else {
|
||||
mModel->setRootPath( mCurPath );
|
||||
|
||||
mMultiView->getTableView()->setColumnsVisible(
|
||||
{ FileSystemModel::Name, FileSystemModel::Size, FileSystemModel::ModificationTime } );
|
||||
|
||||
mDisplayingDrives = false;
|
||||
}
|
||||
|
||||
updateClickStep();
|
||||
@@ -365,13 +381,20 @@ void UIFileDialog::setCurPath( const std::string& path ) {
|
||||
refreshFolder( true );
|
||||
}
|
||||
|
||||
const FileSystemModel::Node* UIFileDialog::getSelectionNode() const {
|
||||
ModelIndex UIFileDialog::getSelectionModelIndex() const {
|
||||
if ( mMultiView->getSelection().isEmpty() )
|
||||
return nullptr;
|
||||
return {};
|
||||
auto index = mMultiView->getSelection().first();
|
||||
auto* filterModel = (SortingProxyModel*)mMultiView->getModel().get();
|
||||
auto localIndex = filterModel->mapToSource( index );
|
||||
const FileSystemModel::Node& node = mModel.get()->node( localIndex );
|
||||
return localIndex;
|
||||
}
|
||||
|
||||
const FileSystemModel::Node* UIFileDialog::getSelectionNode() const {
|
||||
if ( mMultiView->getSelection().isEmpty() || mDisplayingDrives )
|
||||
return nullptr;
|
||||
auto localIndex = getSelectionModelIndex();
|
||||
const FileSystemModel::Node& node = mModel->node( localIndex );
|
||||
return &node;
|
||||
}
|
||||
|
||||
@@ -405,9 +428,25 @@ void UIFileDialog::disableButtons() {
|
||||
mCloseShortcut = {};
|
||||
}
|
||||
|
||||
std::string UIFileDialog::getSelectedDrive() const {
|
||||
if ( !mDisplayingDrives )
|
||||
return "";
|
||||
ModelIndex index = getSelectionModelIndex();
|
||||
ModelIndex modelIndex( mDiskDrivesModel->index( index.row(), DiskDrivesModel::Name ) );
|
||||
Variant var( mDiskDrivesModel->data( modelIndex ) );
|
||||
std::string drive( var.asCStr() );
|
||||
return drive;
|
||||
}
|
||||
|
||||
void UIFileDialog::openFileOrFolder( bool shouldOpenFolder = false ) {
|
||||
if ( mMultiView->getSelection().isEmpty() )
|
||||
return;
|
||||
|
||||
if ( mDisplayingDrives ) {
|
||||
setCurPath( getSelectedDrive() );
|
||||
return;
|
||||
}
|
||||
|
||||
auto* node = getSelectionNode();
|
||||
if ( !node ) {
|
||||
Log::error( "UIFileDialog::getSelectionNode() was empty, shouldn't be empty" );
|
||||
@@ -427,8 +466,20 @@ void UIFileDialog::openFileOrFolder( bool shouldOpenFolder = false ) {
|
||||
}
|
||||
|
||||
void UIFileDialog::goFolderUp() {
|
||||
if ( mCurPath == FDLG_DRIVE_PATH )
|
||||
return;
|
||||
std::string prevFolderName( FileSystem::fileNameFromPath( mCurPath ) );
|
||||
setCurPath( FileSystem::removeLastFolderFromPath( mCurPath ) );
|
||||
std::string newPath( FileSystem::removeLastFolderFromPath( mCurPath ) );
|
||||
if ( newPath == mCurPath ) {
|
||||
auto drives = Sys::getLogicalDrives();
|
||||
if ( !drives.empty() ) {
|
||||
setCurPath( newPath != mCurPath ? newPath : FDLG_DRIVE_PATH );
|
||||
} else {
|
||||
setCurPath( newPath );
|
||||
}
|
||||
} else {
|
||||
setCurPath( newPath );
|
||||
}
|
||||
ModelIndex index = mMultiView->getCurrentView()->findRowWithText( prevFolderName, true, true );
|
||||
if ( index.isValid() )
|
||||
mMultiView->setSelection( index );
|
||||
@@ -486,6 +537,13 @@ void UIFileDialog::open() {
|
||||
!FileSystem::fileExists( getFullPath() ) )
|
||||
return;
|
||||
|
||||
if ( mDisplayingDrives ) {
|
||||
if ( !allowFolderSelect() )
|
||||
return;
|
||||
if ( FileSystem::isDirectory( getFullPath() ) )
|
||||
return;
|
||||
}
|
||||
|
||||
auto* node = !mMultiView->getSelection().isEmpty() ? getSelectionNode() : nullptr;
|
||||
if ( !node ) {
|
||||
node = mModel->getNodeFromPath( getFullPath() );
|
||||
@@ -515,7 +573,8 @@ void UIFileDialog::open() {
|
||||
}
|
||||
|
||||
void UIFileDialog::onPressEnter( const Event* ) {
|
||||
if ( FileSystem::isDirectory( mPath->getText() ) ) {
|
||||
if ( FileSystem::isDirectory( mPath->getText() ) ||
|
||||
( FDLG_DRIVE_PATH == mPath->getText().toUtf8() && !Sys::getLogicalDrives().empty() ) ) {
|
||||
setCurPath( mPath->getText() );
|
||||
} else if ( !allowFolderSelect() && FileSystem::fileExists( mPath->getText() ) ) {
|
||||
String folderPath( FileSystem::fileRemoveFileName( mPath->getText() ) );
|
||||
@@ -589,6 +648,9 @@ void UIFileDialog::setShowHidden( const bool& showHidden ) {
|
||||
}
|
||||
|
||||
std::string UIFileDialog::getFullPath() {
|
||||
if ( mDisplayingDrives )
|
||||
return getCurFile();
|
||||
|
||||
std::string tPath = mCurPath;
|
||||
|
||||
FileSystem::dirAddSlashAtEnd( tPath );
|
||||
@@ -607,14 +669,18 @@ std::string UIFileDialog::getCurFile() const {
|
||||
return mFile->getText();
|
||||
if ( mMultiView->getSelection().isEmpty() )
|
||||
return "";
|
||||
auto* node = getSelectionNode();
|
||||
if ( mDisplayingDrives ) {
|
||||
return getSelectedDrive();
|
||||
} else {
|
||||
auto* node = getSelectionNode();
|
||||
|
||||
if ( !node ) {
|
||||
Log::error( "UIFileDialog::getCurFile() - UIFileDialog::getSelectionNode() was empty, "
|
||||
"shouldn't be empty" );
|
||||
return "";
|
||||
if ( !node ) {
|
||||
Log::error( "UIFileDialog::getCurFile() - UIFileDialog::getSelectionNode() was empty, "
|
||||
"shouldn't be empty" );
|
||||
return "";
|
||||
}
|
||||
return node->getName();
|
||||
}
|
||||
return node->getName();
|
||||
}
|
||||
|
||||
UIPushButton* UIFileDialog::getButtonOpen() const {
|
||||
|
||||
@@ -40,10 +40,8 @@ void UITableView::drawChilds() {
|
||||
if ( yOffset - mScrollOffset.y + getRowHeight() < 0 )
|
||||
continue;
|
||||
for ( size_t colIndex = 0; colIndex < getModel()->columnCount(); colIndex++ ) {
|
||||
if ( columnData( colIndex ).visible ) {
|
||||
updateCell( realIndex, getModel()->index( index.row(), colIndex, index.parent() ),
|
||||
0, yOffset );
|
||||
}
|
||||
updateCell( realIndex, getModel()->index( index.row(), colIndex, index.parent() ), 0,
|
||||
yOffset );
|
||||
}
|
||||
updateRow( realIndex, index, yOffset )->nodeDraw();
|
||||
realIndex++;
|
||||
@@ -155,12 +153,12 @@ Float UITableView::getMaxColumnContentWidth( const size_t& colIndex, bool bestGu
|
||||
return lWidth;
|
||||
}
|
||||
|
||||
void UITableView::createOrUpdateColumns() {
|
||||
void UITableView::createOrUpdateColumns( bool resetColumnData ) {
|
||||
if ( !getModel() ) {
|
||||
updateContentSize();
|
||||
return;
|
||||
}
|
||||
UIAbstractTableView::createOrUpdateColumns();
|
||||
UIAbstractTableView::createOrUpdateColumns( resetColumnData );
|
||||
updateContentSize();
|
||||
}
|
||||
|
||||
@@ -181,7 +179,7 @@ Uint32 UITableView::onKeyDown( const KeyEvent& event ) {
|
||||
return UIAbstractTableView::onKeyDown( event );
|
||||
auto curIndex = getSelection().first();
|
||||
int pageSize = eefloor( getVisibleArea().getHeight() / getRowHeight() ) - 1;
|
||||
ConditionalLock l( getModel() != nullptr, getModel() ? &getModel()->resourceMutex() : nullptr );
|
||||
|
||||
switch ( event.getKeyCode() ) {
|
||||
case KEY_PAGEUP: {
|
||||
if ( curIndex.row() - pageSize < 0 ) {
|
||||
|
||||
@@ -84,11 +84,11 @@ void UITreeView::traverseTree( TreeViewCallback callback ) const {
|
||||
}
|
||||
}
|
||||
|
||||
void UITreeView::createOrUpdateColumns() {
|
||||
void UITreeView::createOrUpdateColumns( bool resetColumnData ) {
|
||||
updateContentSize();
|
||||
if ( !getModel() )
|
||||
return;
|
||||
UIAbstractTableView::createOrUpdateColumns();
|
||||
UIAbstractTableView::createOrUpdateColumns( resetColumnData );
|
||||
}
|
||||
|
||||
size_t UITreeView::getItemCount() const {
|
||||
@@ -124,7 +124,7 @@ void UITreeView::bindNavigationClick( UIWidget* widget ) {
|
||||
if ( getModel()->rowCount( idx ) ) {
|
||||
auto& data = getIndexMetadata( idx );
|
||||
data.open = !data.open;
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
onOpenTreeModelIndex( idx, data.open );
|
||||
} else {
|
||||
onOpenModelIndex( idx, event );
|
||||
@@ -153,7 +153,7 @@ bool UITreeView::tryOpenModelIndex( const ModelIndex& index, bool forceUpdate )
|
||||
if ( !data.open ) {
|
||||
data.open = true;
|
||||
if ( forceUpdate )
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
onOpenTreeModelIndex( index, data.open );
|
||||
}
|
||||
return true;
|
||||
@@ -186,7 +186,7 @@ UIWidget* UITreeView::setupCell( UITableCell* widget, UIWidget* rowWidget,
|
||||
if ( getModel()->rowCount( idx ) ) {
|
||||
auto& data = getIndexMetadata( idx );
|
||||
data.open = !data.open;
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
onOpenTreeModelIndex( idx, data.open );
|
||||
}
|
||||
}
|
||||
@@ -300,7 +300,7 @@ const Float& UITreeView::getIndentWidth() const {
|
||||
void UITreeView::setIndentWidth( const Float& indentWidth ) {
|
||||
if ( mIndentWidth != indentWidth ) {
|
||||
mIndentWidth = indentWidth;
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -403,14 +403,14 @@ void UITreeView::expandAll( const ModelIndex& index ) {
|
||||
if ( !getModel() )
|
||||
return;
|
||||
setAllExpanded( index, true );
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
|
||||
void UITreeView::collapseAll( const ModelIndex& index ) {
|
||||
if ( !getModel() )
|
||||
return;
|
||||
setAllExpanded( index, false );
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
|
||||
UIIcon* UITreeView::getExpandIcon() const {
|
||||
@@ -420,7 +420,7 @@ UIIcon* UITreeView::getExpandIcon() const {
|
||||
void UITreeView::setExpandedIcon( UIIcon* expandIcon ) {
|
||||
if ( mExpandIcon != expandIcon ) {
|
||||
mExpandIcon = expandIcon;
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -435,7 +435,7 @@ UIIcon* UITreeView::getContractIcon() const {
|
||||
void UITreeView::setContractedIcon( UIIcon* contractIcon ) {
|
||||
if ( mContractIcon != contractIcon ) {
|
||||
mContractIcon = contractIcon;
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -613,7 +613,7 @@ Uint32 UITreeView::onKeyDown( const KeyEvent& event ) {
|
||||
auto& metadata = getIndexMetadata( curIndex );
|
||||
if ( !metadata.open ) {
|
||||
metadata.open = true;
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
return 0;
|
||||
}
|
||||
getSelection().set( getModel()->index( 0, getModel()->treeColumn(), curIndex ) );
|
||||
@@ -625,7 +625,7 @@ Uint32 UITreeView::onKeyDown( const KeyEvent& event ) {
|
||||
auto& metadata = getIndexMetadata( curIndex );
|
||||
if ( metadata.open ) {
|
||||
metadata.open = false;
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -641,7 +641,7 @@ Uint32 UITreeView::onKeyDown( const KeyEvent& event ) {
|
||||
if ( getModel()->rowCount( curIndex ) ) {
|
||||
auto& metadata = getIndexMetadata( curIndex );
|
||||
metadata.open = !metadata.open;
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
} else {
|
||||
onOpenModelIndex( curIndex, &event );
|
||||
}
|
||||
@@ -791,7 +791,7 @@ void UITreeView::openModelIndexParentTree( const ModelIndex& index ) {
|
||||
indexes.pop();
|
||||
}
|
||||
|
||||
createOrUpdateColumns();
|
||||
createOrUpdateColumns( false );
|
||||
}
|
||||
|
||||
bool UITreeView::getFocusOnSelection() const {
|
||||
|
||||
@@ -181,6 +181,8 @@ const SizePolicy& UIWidget::getLayoutWidthPolicy() const {
|
||||
UIWidget* UIWidget::setLayoutWidthPolicy( const SizePolicy& widthPolicy ) {
|
||||
if ( mWidthPolicy != widthPolicy ) {
|
||||
mWidthPolicy = widthPolicy;
|
||||
if ( mWidthPolicy == SizePolicy::WrapContent )
|
||||
onAutoSize();
|
||||
notifyLayoutAttrChange();
|
||||
}
|
||||
|
||||
@@ -194,6 +196,8 @@ const SizePolicy& UIWidget::getLayoutHeightPolicy() const {
|
||||
UIWidget* UIWidget::setLayoutHeightPolicy( const SizePolicy& heightPolicy ) {
|
||||
if ( mHeightPolicy != heightPolicy ) {
|
||||
mHeightPolicy = heightPolicy;
|
||||
if ( mHeightPolicy == SizePolicy::WrapContent )
|
||||
onAutoSize();
|
||||
notifyLayoutAttrChange();
|
||||
}
|
||||
|
||||
@@ -205,6 +209,9 @@ UIWidget* UIWidget::setLayoutSizePolicy( const SizePolicy& widthPolicy,
|
||||
if ( mWidthPolicy != widthPolicy || mHeightPolicy != heightPolicy ) {
|
||||
mWidthPolicy = widthPolicy;
|
||||
mHeightPolicy = heightPolicy;
|
||||
if ( mWidthPolicy == SizePolicy::WrapContent || mHeightPolicy == SizePolicy::WrapContent ) {
|
||||
onAutoSize();
|
||||
}
|
||||
notifyLayoutAttrChange();
|
||||
}
|
||||
|
||||
|
||||
@@ -439,7 +439,7 @@ void AppConfig::loadProject( std::string projectFolder, UICodeEditorSplitter* ed
|
||||
size_t i = 0;
|
||||
std::vector<ProjectPath> paths;
|
||||
do {
|
||||
std::string val( ini.getValue( "files", String::format( "file_name_%lu", i ) ) );
|
||||
std::string val( ini.getValue( "files", String::format( "file_name_%zu", i ) ) );
|
||||
found = !val.empty();
|
||||
if ( found ) {
|
||||
auto pp = ProjectPath::fromString( val );
|
||||
|
||||
@@ -378,10 +378,12 @@ void App::loadConfig( const LogLevel& logLevel ) {
|
||||
FileSystem::makeDir( mConfigPath );
|
||||
FileSystem::dirAddSlashAtEnd( mConfigPath );
|
||||
mPluginsPath = mConfigPath + "plugins";
|
||||
mColorSchemesPath = mConfigPath + "editor" + FileSystem::getOSSlash() + "colorschemes";
|
||||
mColorSchemesPath = mConfigPath + "editor" + FileSystem::getOSSlash() + "colorschemes" +
|
||||
FileSystem::getOSSlash();
|
||||
mTerminalManager = std::make_unique<TerminalManager>( this );
|
||||
mTerminalManager->setTerminalColorSchemesPath( mConfigPath + "terminal" +
|
||||
FileSystem::getOSSlash() + "colorschemes" );
|
||||
FileSystem::getOSSlash() + "colorschemes" +
|
||||
FileSystem::getOSSlash() );
|
||||
mTerminalManager->setUseFrameBuffer( mUseFrameBuffer );
|
||||
|
||||
if ( !FileSystem::fileExists( mPluginsPath ) )
|
||||
@@ -3872,6 +3874,7 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe
|
||||
{ "palette", 0xefc5 },
|
||||
{ "file-code", 0xecd1 },
|
||||
{ "cursor-pointer", 0xec09 },
|
||||
{ "drive", 0xedf8 },
|
||||
};
|
||||
for ( const auto& icon : icons )
|
||||
iconTheme->add( UIGlyphIcon::New( icon.first, iconFont, icon.second ) );
|
||||
@@ -4007,10 +4010,13 @@ void App::init( const LogLevel& logLevel, std::string file, const Float& pidelDe
|
||||
if ( FileSystem::isDirectory( mColorSchemesPath ) ) {
|
||||
auto colorSchemesFiles = FileSystem::filesGetInPath( mColorSchemesPath );
|
||||
for ( auto& file : colorSchemesFiles ) {
|
||||
auto colorSchemesInFile = SyntaxColorScheme::loadFromFile( file );
|
||||
auto colorSchemesInFile =
|
||||
SyntaxColorScheme::loadFromFile( mColorSchemesPath + file );
|
||||
for ( auto& coloScheme : colorSchemesInFile )
|
||||
colorSchemes.emplace_back( coloScheme );
|
||||
}
|
||||
} else {
|
||||
FileSystem::makeDir( mColorSchemesPath, true );
|
||||
}
|
||||
|
||||
mTerminalManager->loadTerminalColorSchemes();
|
||||
|
||||
@@ -37,10 +37,13 @@ void TerminalManager::loadTerminalColorSchemes() {
|
||||
if ( FileSystem::isDirectory( mTerminalColorSchemesPath ) ) {
|
||||
auto colorSchemesFiles = FileSystem::filesGetInPath( mTerminalColorSchemesPath );
|
||||
for ( auto& file : colorSchemesFiles ) {
|
||||
auto colorSchemesInFile = TerminalColorScheme::loadFromFile( file );
|
||||
auto colorSchemesInFile =
|
||||
TerminalColorScheme::loadFromFile( mTerminalColorSchemesPath + file );
|
||||
for ( auto& coloScheme : colorSchemesInFile )
|
||||
colorSchemes.emplace_back( coloScheme );
|
||||
}
|
||||
} else {
|
||||
FileSystem::makeDir( mTerminalColorSchemesPath, true );
|
||||
}
|
||||
for ( const auto& colorScheme : colorSchemes )
|
||||
mTerminalColorSchemes.insert( { colorScheme.getName(), colorScheme } );
|
||||
|
||||
Reference in New Issue
Block a user