From b896b3d07f7cc158c038797793bf83bb245dee39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sat, 14 Jan 2023 02:53:36 -0300 Subject: [PATCH] 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. --- include/eepp/core/memorymanager.hpp | 51 +++---- include/eepp/system/filesystem.hpp | 3 +- include/eepp/system/sys.hpp | 3 + .../eepp/ui/abstract/uiabstracttableview.hpp | 8 +- include/eepp/ui/abstract/uiabstractview.hpp | 2 +- include/eepp/ui/models/filesystemmodel.hpp | 34 ++++- include/eepp/ui/models/model.hpp | 4 +- include/eepp/ui/uifiledialog.hpp | 6 + include/eepp/ui/uitableview.hpp | 2 +- include/eepp/ui/uitreeview.hpp | 2 +- premake4.lua | 10 +- premake5.lua | 33 +++-- src/eepp/system/filesystem.cpp | 39 +++++- src/eepp/system/pak.cpp | 2 +- src/eepp/system/sys.cpp | 57 ++++++++ src/eepp/ui/abstract/uiabstracttableview.cpp | 76 ++++++++-- src/eepp/ui/abstract/uiabstractview.cpp | 2 +- src/eepp/ui/models/filesystemmodel.cpp | 39 +++++- src/eepp/ui/models/model.cpp | 8 ++ src/eepp/ui/uifiledialog.cpp | 132 +++++++++++++----- src/eepp/ui/uitableview.cpp | 12 +- src/eepp/ui/uitreeview.cpp | 28 ++-- src/eepp/ui/uiwidget.cpp | 7 + src/tools/ecode/appconfig.cpp | 2 +- src/tools/ecode/ecode.cpp | 12 +- src/tools/ecode/terminalmanager.cpp | 5 +- 26 files changed, 442 insertions(+), 137 deletions(-) diff --git a/include/eepp/core/memorymanager.hpp b/include/eepp/core/memorymanager.hpp index 443381f23..a977e60a1 100644 --- a/include/eepp/core/memorymanager.hpp +++ b/include/eepp/core/memorymanager.hpp @@ -8,6 +8,7 @@ #include #include + namespace EE { class EE_API AllocatedPointer { @@ -25,6 +26,8 @@ class EE_API AllocatedPointer { typedef std::map 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 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 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 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 diff --git a/include/eepp/system/filesystem.hpp b/include/eepp/system/filesystem.hpp index 9835b381e..9f72e998f 100644 --- a/include/eepp/system/filesystem.hpp +++ b/include/eepp/system/filesystem.hpp @@ -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 ); diff --git a/include/eepp/system/sys.hpp b/include/eepp/system/sys.hpp index 7b156aa0b..5a03e9a3b 100644 --- a/include/eepp/system/sys.hpp +++ b/include/eepp/system/sys.hpp @@ -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 parseArguments( int argc, char* argv[] ); + + /** @return The OS logical drives */ + static std::vector getLogicalDrives(); }; }} // namespace EE::System diff --git a/include/eepp/ui/abstract/uiabstracttableview.hpp b/include/eepp/ui/abstract/uiabstracttableview.hpp index 6e5054c0c..b986024b7 100644 --- a/include/eepp/ui/abstract/uiabstracttableview.hpp +++ b/include/eepp/ui/abstract/uiabstracttableview.hpp @@ -37,7 +37,7 @@ class EE_API UIAbstractTableView : public UIAbstractView { void setColumnHidden( const size_t& column, bool hidden ); - void setColumnsHidden( const std::vector columns, bool hidden ); + void setColumnsHidden( const std::vector& 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 diff --git a/include/eepp/ui/abstract/uiabstractview.hpp b/include/eepp/ui/abstract/uiabstractview.hpp index a2ebc8c48..51f013189 100644 --- a/include/eepp/ui/abstract/uiabstractview.hpp +++ b/include/eepp/ui/abstract/uiabstractview.hpp @@ -45,7 +45,7 @@ class EE_API UIAbstractView : public UIScrollableWidget { bool isType( const Uint32& type ) const; - void setModel( std::shared_ptr ); + void setModel( const std::shared_ptr& ); Model* getModel() { return mModel.get(); } diff --git a/include/eepp/ui/models/filesystemmodel.hpp b/include/eepp/ui/models/filesystemmodel.hpp index 2ea0e73f8..814fa5012 100644 --- a/include/eepp/ui/models/filesystemmodel.hpp +++ b/include/eepp/ui/models/filesystemmodel.hpp @@ -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 create( const std::vector& data ); + + static std::shared_ptr 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& data ) : mData( data ) {} + + std::vector mData; }; }}} // namespace EE::UI::Models diff --git a/include/eepp/ui/models/model.hpp b/include/eepp/ui/models/model.hpp index d1520b4fb..161f1068c 100644 --- a/include/eepp/ui/models/model.hpp +++ b/include/eepp/ui/models/model.hpp @@ -138,9 +138,9 @@ class EE_API Model { Mutex& resourceMutex(); - void acquireResourceMutex() { mResourceLock.lock(); } + void acquireResourceMutex(); - void releaseResourceMutex() { mResourceLock.unlock(); } + void releaseResourceMutex(); protected: Model(){}; diff --git a/include/eepp/ui/uifiledialog.hpp b/include/eepp/ui/uifiledialog.hpp index a291de002..c0a65de36 100644 --- a/include/eepp/ui/uifiledialog.hpp +++ b/include/eepp/ui/uifiledialog.hpp @@ -136,6 +136,8 @@ class EE_API UIFileDialog : public UIWindow { KeyBindings::Shortcut mCloseShortcut; KeyBindings::Shortcut mOpenShortut{ KEY_RETURN, KeyMod::getDefaultModifier() }; std::shared_ptr mModel; + std::shared_ptr 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 diff --git a/include/eepp/ui/uitableview.hpp b/include/eepp/ui/uitableview.hpp index f50f0dd04..a48e2e62d 100644 --- a/include/eepp/ui/uitableview.hpp +++ b/include/eepp/ui/uitableview.hpp @@ -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(); diff --git a/include/eepp/ui/uitreeview.hpp b/include/eepp/ui/uitreeview.hpp index 5d839cdac..9a10b3649 100644 --- a/include/eepp/ui/uitreeview.hpp +++ b/include/eepp/ui/uitreeview.hpp @@ -160,7 +160,7 @@ class EE_API UITreeView : public UIAbstractTableView { UITreeView(); - virtual void createOrUpdateColumns(); + virtual void createOrUpdateColumns( bool resetColumnData ); struct MetadataForIndex { bool open{ false }; diff --git a/premake4.lua b/premake4.lua index c3e1deb28..4335dd82d 100644 --- a/premake4.lua +++ b/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 diff --git a/premake5.lua b/premake5.lua index 18cf5bf37..454474c9f 100644 --- a/premake5.lua +++ b/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" } diff --git a/src/eepp/system/filesystem.cpp b/src/eepp/system/filesystem.cpp index 0f6e2ceaf..d61060419 100644 --- a/src/eepp/system/filesystem.cpp +++ b/src/eepp/system/filesystem.cpp @@ -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 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 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 ) ); } diff --git a/src/eepp/system/pak.cpp b/src/eepp/system/pak.cpp index 00c625adc..bd6baaf6c 100644 --- a/src/eepp/system/pak.cpp +++ b/src/eepp/system/pak.cpp @@ -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; } diff --git a/src/eepp/system/sys.cpp b/src/eepp/system/sys.cpp index 67b1b648d..0b7974187 100644 --- a/src/eepp/system/sys.cpp +++ b/src/eepp/system/sys.cpp @@ -29,6 +29,7 @@ #undef GetTempPath #elif EE_PLATFORM == EE_PLATFORM_LINUX || EE_PLATFORM == EE_PLATFORM_ANDROID #include +#include #include #elif EE_PLATFORM == EE_PLATFORM_HAIKU #include @@ -899,4 +900,60 @@ std::vector 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 Sys::getLogicalDrives() { +#if EE_PLATFORM == EE_PLATFORM_WIN + std::vector 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 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 diff --git a/src/eepp/ui/abstract/uiabstracttableview.cpp b/src/eepp/ui/abstract/uiabstracttableview.cpp index 0ca265c04..7d42a8832 100644 --- a/src/eepp/ui/abstract/uiabstracttableview.cpp +++ b/src/eepp/ui/abstract/uiabstracttableview.cpp @@ -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 columns, bool hidden ) { +void UIAbstractTableView::setColumnsHidden( const std::vector& columns, bool hidden ) { for ( auto col : columns ) columnData( col ).visible = !hidden; - createOrUpdateColumns(); + updateCellsVisibility(); + createOrUpdateColumns( false ); } void UIAbstractTableView::setColumnsVisible( const std::vector 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 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(); diff --git a/src/eepp/ui/abstract/uiabstractview.cpp b/src/eepp/ui/abstract/uiabstractview.cpp index 9c3c796b2..335b1f746 100644 --- a/src/eepp/ui/abstract/uiabstractview.cpp +++ b/src/eepp/ui/abstract/uiabstractview.cpp @@ -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 ) { +void UIAbstractView::setModel( const std::shared_ptr& model ) { if ( model.get() == mModel.get() ) return; if ( mModel ) diff --git a/src/eepp/ui/models/filesystemmodel.cpp b/src/eepp/ui/models/filesystemmodel.cpp index ea357c58f..58559556f 100644 --- a/src/eepp/ui/models/filesystemmodel.cpp +++ b/src/eepp/ui/models/filesystemmodel.cpp @@ -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::create( const std::vector& data ) { + return std::shared_ptr( new DiskDrivesModel( data ) ); +} + +std::shared_ptr 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 diff --git a/src/eepp/ui/models/model.cpp b/src/eepp/ui/models/model.cpp index 6e3aed32f..1bf5e10f7 100644 --- a/src/eepp/ui/models/model.cpp +++ b/src/eepp/ui/models/model.cpp @@ -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; diff --git a/src/eepp/ui/uifiledialog.cpp b/src/eepp/ui/uifiledialog.cpp index f0b27de94..d2b1b1e82 100644 --- a/src/eepp/ui/uifiledialog.cpp +++ b/src/eepp/ui/uifiledialog.cpp @@ -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 flist = FileSystem::filesGetInPath( - String( mCurPath ), getSortAlphabetically(), getFoldersFirst(), !getShowHidden() ); - std::vector files; - std::vector 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 flist = FileSystem::filesGetInPath( + String( mCurPath ), getSortAlphabetically(), getFoldersFirst(), !getShowHidden() ); + std::vector files; + std::vector 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 { diff --git a/src/eepp/ui/uitableview.cpp b/src/eepp/ui/uitableview.cpp index 897af90de..8ce6c28d0 100644 --- a/src/eepp/ui/uitableview.cpp +++ b/src/eepp/ui/uitableview.cpp @@ -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 ) { diff --git a/src/eepp/ui/uitreeview.cpp b/src/eepp/ui/uitreeview.cpp index e12c03c84..1bb33a0e1 100644 --- a/src/eepp/ui/uitreeview.cpp +++ b/src/eepp/ui/uitreeview.cpp @@ -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 { diff --git a/src/eepp/ui/uiwidget.cpp b/src/eepp/ui/uiwidget.cpp index 4d210e288..0a90aaafd 100644 --- a/src/eepp/ui/uiwidget.cpp +++ b/src/eepp/ui/uiwidget.cpp @@ -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(); } diff --git a/src/tools/ecode/appconfig.cpp b/src/tools/ecode/appconfig.cpp index 64d009f58..dcd538215 100644 --- a/src/tools/ecode/appconfig.cpp +++ b/src/tools/ecode/appconfig.cpp @@ -439,7 +439,7 @@ void AppConfig::loadProject( std::string projectFolder, UICodeEditorSplitter* ed size_t i = 0; std::vector 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 ); diff --git a/src/tools/ecode/ecode.cpp b/src/tools/ecode/ecode.cpp index 38e70063b..f0787cef5 100644 --- a/src/tools/ecode/ecode.cpp +++ b/src/tools/ecode/ecode.cpp @@ -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( 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(); diff --git a/src/tools/ecode/terminalmanager.cpp b/src/tools/ecode/terminalmanager.cpp index 5c81c4311..34c9a0e09 100644 --- a/src/tools/ecode/terminalmanager.cpp +++ b/src/tools/ecode/terminalmanager.cpp @@ -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 } );