mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-27 16:38:20 +03:00
Some improvements. Functional.
This commit is contained in:
@@ -166,6 +166,7 @@ class EE_API FileSystemModel : public Model {
|
||||
void handleFileEvent( const FileEvent& event );
|
||||
|
||||
~FileSystemModel();
|
||||
|
||||
protected:
|
||||
std::atomic<bool> mInitOK;
|
||||
std::string mRootPath;
|
||||
@@ -181,6 +182,7 @@ class EE_API FileSystemModel : public Model {
|
||||
FileSystemModel( const std::string& rootPath, const Mode& mode,
|
||||
const DisplayConfig displayConfig );
|
||||
|
||||
size_t getFileIndex( Node* parent, const FileInfo& file );
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Models
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef EE_UI_MODELS_MODEL_HPP
|
||||
#define EE_UI_MODELS_MODEL_HPP
|
||||
|
||||
#include <eepp/system/lock.hpp>
|
||||
#include <eepp/system/mutex.hpp>
|
||||
#include <eepp/ui/models/modelindex.hpp>
|
||||
#include <eepp/ui/models/modelrole.hpp>
|
||||
#include <eepp/ui/models/variant.hpp>
|
||||
@@ -120,10 +122,10 @@ class EE_API Model {
|
||||
|
||||
void beginInsertRows( ModelIndex const& parent, int first, int last );
|
||||
void beginInsertColumns( ModelIndex const& parent, int first, int last );
|
||||
void beginMoveRows( ModelIndex const& source_parent, int first, int last,
|
||||
ModelIndex const& target_parent, int target_index );
|
||||
void beginMoveColumns( ModelIndex const& source_parent, int first, int last,
|
||||
ModelIndex const& target_parent, int target_index );
|
||||
void beginMoveRows( ModelIndex const& sourceParent, int first, int last,
|
||||
ModelIndex const& targetParent, int target_index );
|
||||
void beginMoveColumns( ModelIndex const& sourceParent, int first, int last,
|
||||
ModelIndex const& targetParent, int target_index );
|
||||
void beginDeleteRows( ModelIndex const& parent, int first, int last );
|
||||
void beginDeleteColumns( ModelIndex const& parent, int first, int last );
|
||||
|
||||
@@ -134,6 +136,12 @@ class EE_API Model {
|
||||
void endDeleteRows();
|
||||
void endDeleteColumns();
|
||||
|
||||
Mutex& resourceLock();
|
||||
|
||||
void acquireResourceLock() { mResourceLock.lock(); }
|
||||
|
||||
void releaseResourceLock() { mResourceLock.unlock(); }
|
||||
|
||||
protected:
|
||||
Model(){};
|
||||
|
||||
@@ -150,10 +158,10 @@ class EE_API Model {
|
||||
struct Operation {
|
||||
OperationType type{ OperationType::Invalid };
|
||||
Direction direction{ Direction::Row };
|
||||
ModelIndex source_parent;
|
||||
ModelIndex sourceParent;
|
||||
int first{ 0 };
|
||||
int last{ 0 };
|
||||
ModelIndex target_parent;
|
||||
ModelIndex targetParent;
|
||||
int target{ 0 };
|
||||
|
||||
Operation( OperationType type ) : type( type ) {}
|
||||
@@ -162,7 +170,7 @@ class EE_API Model {
|
||||
int last ) :
|
||||
type( type ),
|
||||
direction( direction ),
|
||||
source_parent( parent ),
|
||||
sourceParent( parent ),
|
||||
first( first ),
|
||||
last( last ) {}
|
||||
|
||||
@@ -170,10 +178,10 @@ class EE_API Model {
|
||||
int first, int last, ModelIndex const& targetParent, int target ) :
|
||||
type( type ),
|
||||
direction( direction ),
|
||||
source_parent( sourceParent ),
|
||||
sourceParent( sourceParent ),
|
||||
first( first ),
|
||||
last( last ),
|
||||
target_parent( targetParent ),
|
||||
targetParent( targetParent ),
|
||||
target( target ) {}
|
||||
};
|
||||
|
||||
@@ -195,6 +203,7 @@ class EE_API Model {
|
||||
std::unordered_set<UIAbstractView*> mViews;
|
||||
std::unordered_set<Client*> mClients;
|
||||
std::function<void()> mOnUpdate;
|
||||
Mutex mResourceLock;
|
||||
};
|
||||
|
||||
inline ModelIndex ModelIndex::parent() const {
|
||||
|
||||
@@ -13,9 +13,9 @@ class PersistentHandle {
|
||||
friend class Model;
|
||||
friend class PersistentModelIndex;
|
||||
|
||||
PersistentHandle( ModelIndex const& index ) : m_index( index ) {}
|
||||
PersistentHandle( ModelIndex const& index ) : mIndex( index ) {}
|
||||
|
||||
ModelIndex m_index;
|
||||
ModelIndex mIndex;
|
||||
};
|
||||
|
||||
class PersistentModelIndex {
|
||||
@@ -28,8 +28,8 @@ class PersistentModelIndex {
|
||||
PersistentModelIndex& operator=( PersistentModelIndex const& ) = default;
|
||||
PersistentModelIndex& operator=( PersistentModelIndex&& ) = default;
|
||||
|
||||
bool isValid() const { return hasValidHandle() && m_handle.lock()->m_index.isValid(); }
|
||||
bool hasValidHandle() const { return !m_handle.expired(); }
|
||||
bool isValid() const { return hasValidHandle() && mHandle.lock()->mIndex.isValid(); }
|
||||
bool hasValidHandle() const { return !mHandle.expired(); }
|
||||
|
||||
int row() const;
|
||||
int column() const;
|
||||
@@ -39,7 +39,7 @@ class PersistentModelIndex {
|
||||
|
||||
void* internalData() const {
|
||||
if ( hasValidHandle() )
|
||||
return m_handle.lock()->m_index.internalData();
|
||||
return mHandle.lock()->mIndex.internalData();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
@@ -51,7 +51,7 @@ class PersistentModelIndex {
|
||||
bool operator!=( ModelIndex const& ) const;
|
||||
|
||||
private:
|
||||
std::weak_ptr<PersistentHandle> m_handle;
|
||||
std::weak_ptr<PersistentHandle> mHandle;
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Models
|
||||
|
||||
@@ -37,10 +37,6 @@ EventDispatcher::~EventDispatcher() {
|
||||
void EventDispatcher::inputCallback( InputEvent* event ) {
|
||||
switch ( event->Type ) {
|
||||
case InputEvent::Window: {
|
||||
if ( event->window.type == InputEvent::WindowKeyboardFocusGain ) {
|
||||
mMousePosi = mInput->queryMousePos();
|
||||
mMousePos = mMousePosi.asFloat();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case InputEvent::KeyUp:
|
||||
|
||||
@@ -394,13 +394,86 @@ void FileSystemModel::setPreviouslySelectedIndex( const ModelIndex& previouslySe
|
||||
mPreviouslySelectedIndex = previouslySelectedIndex;
|
||||
}
|
||||
|
||||
size_t FileSystemModel::getFileIndex( Node* parent, const FileInfo& file ) {
|
||||
std::vector<FileInfo> files;
|
||||
|
||||
for ( const auto& nodeFile : parent->mChildren ) {
|
||||
files.emplace_back( nodeFile.info() );
|
||||
}
|
||||
|
||||
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;
|
||||
} );
|
||||
|
||||
if ( getDisplayConfig().foldersFirst ) {
|
||||
std::vector<FileInfo> folders;
|
||||
std::vector<FileInfo> file;
|
||||
for ( size_t i = 0; i < files.size(); i++ ) {
|
||||
if ( files[i].isDirectory() ) {
|
||||
folders.push_back( files[i] );
|
||||
} else {
|
||||
file.push_back( files[i] );
|
||||
}
|
||||
}
|
||||
files.clear();
|
||||
for ( auto& folder : folders )
|
||||
files.push_back( folder );
|
||||
for ( auto& f : file )
|
||||
files.push_back( f );
|
||||
}
|
||||
|
||||
size_t pos = parent->childCount();
|
||||
|
||||
for ( size_t i = 0; i < files.size(); ++i ) {
|
||||
if ( file.getFileName() == files[i].getFileName() ) {
|
||||
pos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
std::string getFileSystemEventTypeName( FileSystemEventType action ) {
|
||||
switch ( action ) {
|
||||
case FileSystemEventType::Add:
|
||||
return "Add";
|
||||
case FileSystemEventType::Modified:
|
||||
return "Modified";
|
||||
case FileSystemEventType::Delete:
|
||||
return "Delete";
|
||||
case FileSystemEventType::Moved:
|
||||
return "Moved";
|
||||
default:
|
||||
return "Bad Action";
|
||||
}
|
||||
}
|
||||
|
||||
void FileSystemModel::handleFileEvent( const FileEvent& event ) {
|
||||
if ( !mInitOK )
|
||||
return;
|
||||
|
||||
Lock l( resourceLock() );
|
||||
|
||||
if ( Log::instance() && Log::instance()->getLogLevelThreshold() == LogLevel::Debug ) {
|
||||
Log::debug(
|
||||
"DIR ( %s ) FILE ( %s ) has event %s", event.directory.c_str(),
|
||||
( ( event.oldFilename.empty() ? "" : "from file " + event.oldFilename + " to " ) +
|
||||
event.filename )
|
||||
.c_str(),
|
||||
getFileSystemEventTypeName( event.type ).c_str() );
|
||||
}
|
||||
|
||||
switch ( event.type ) {
|
||||
case FileSystemEventType::Add: {
|
||||
FileInfo file( event.directory + event.filename );
|
||||
|
||||
if ( ( getMode() == Mode::DirectoriesOnly && !file.isDirectory() ) ||
|
||||
( getDisplayConfig().ignoreHidden && file.isHidden() ) )
|
||||
return;
|
||||
|
||||
auto* parent = getNodeFromPath(
|
||||
file.isDirectory() ? FileSystem::removeLastFolderFromPath( file.getDirectoryPath() )
|
||||
: file.getDirectoryPath(),
|
||||
@@ -412,14 +485,19 @@ void FileSystemModel::handleFileEvent( const FileEvent& event ) {
|
||||
if ( childNodeExists )
|
||||
return;
|
||||
|
||||
size_t childCount = parent->childCount();
|
||||
|
||||
Node childNode = parent->createChild( file.getFilepath(), *this );
|
||||
|
||||
if ( !childNode.getName().empty() ) {
|
||||
beginInsertRows( parent->index( *this, 0 ), childCount, childCount );
|
||||
size_t pos = getFileIndex( parent, file );
|
||||
|
||||
parent->mChildren.emplace_back( std::move( childNode ) );
|
||||
beginInsertRows( parent->index( *this, 0 ), pos, pos );
|
||||
|
||||
if ( pos == SIZE_MAX ) {
|
||||
parent->mChildren.emplace_back( std::move( childNode ) );
|
||||
} else {
|
||||
parent->mChildren.insert( parent->mChildren.begin() + pos,
|
||||
std::move( childNode ) );
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
} else {
|
||||
@@ -459,12 +537,47 @@ void FileSystemModel::handleFileEvent( const FileEvent& event ) {
|
||||
}
|
||||
case FileSystemEventType::Moved: {
|
||||
FileInfo file( event.directory + event.filename );
|
||||
|
||||
if ( file.exists() ) {
|
||||
auto* node = getNodeFromPath( event.directory + event.oldFilename,
|
||||
file.isDirectory(), false );
|
||||
if ( node ) {
|
||||
node->mInfo = std::move( file );
|
||||
node->mName = FileSystem::fileNameFromPath( node->mInfo.getFilepath() );
|
||||
ModelIndex index = node->index( *this, 0 );
|
||||
if ( !index.isValid() )
|
||||
return;
|
||||
|
||||
Node* parent = node->mParent;
|
||||
if ( !parent )
|
||||
return;
|
||||
|
||||
if ( ( getMode() == Mode::DirectoriesOnly && !file.isDirectory() ) )
|
||||
return;
|
||||
|
||||
if ( !node->info().isHidden() && getDisplayConfig().ignoreHidden &&
|
||||
file.isHidden() ) {
|
||||
handleFileEvent(
|
||||
{ FileSystemEventType::Delete, event.directory, event.oldFilename } );
|
||||
return;
|
||||
}
|
||||
|
||||
size_t pos = getFileIndex( node->getParent(), file );
|
||||
|
||||
if ( pos != SIZE_MAX )
|
||||
beginMoveRows( index.parent(), index.row(), index.row(), index.parent(),
|
||||
pos );
|
||||
|
||||
parent->mChildren.erase( parent->mChildren.begin() + index.row() );
|
||||
Node childNode = parent->createChild( file.getFilepath(), *this );
|
||||
|
||||
if ( pos == SIZE_MAX ) {
|
||||
parent->mChildren.emplace_back( std::move( childNode ) );
|
||||
} else {
|
||||
parent->mChildren.insert( parent->mChildren.begin() + pos,
|
||||
std::move( childNode ) );
|
||||
}
|
||||
|
||||
if ( pos != SIZE_MAX )
|
||||
endMoveRows();
|
||||
} else {
|
||||
handleFileEvent(
|
||||
{ FileSystemEventType::Add, event.directory, event.filename } );
|
||||
|
||||
+115
-112
@@ -75,22 +75,22 @@ void Model::beginInsertColumns( ModelIndex const& parent, int first, int last )
|
||||
mOperationStack.push( { OperationType::Insert, Direction::Column, parent, first, last } );
|
||||
}
|
||||
|
||||
void Model::beginMoveRows( ModelIndex const& source_parent, int first, int last,
|
||||
ModelIndex const& target_parent, int target_index ) {
|
||||
void Model::beginMoveRows( ModelIndex const& sourceParent, int first, int last,
|
||||
ModelIndex const& targetParent, int targetIndex ) {
|
||||
eeASSERT( first >= 0 );
|
||||
eeASSERT( first <= last );
|
||||
eeASSERT( target_index >= 0 );
|
||||
mOperationStack.push( { OperationType::Move, Direction::Row, source_parent, first, last,
|
||||
target_parent, target_index } );
|
||||
eeASSERT( targetIndex >= 0 );
|
||||
mOperationStack.push( { OperationType::Move, Direction::Row, sourceParent, first, last,
|
||||
targetParent, targetIndex } );
|
||||
}
|
||||
|
||||
void Model::beginMoveColumns( ModelIndex const& source_parent, int first, int last,
|
||||
ModelIndex const& target_parent, int target_index ) {
|
||||
void Model::beginMoveColumns( ModelIndex const& sourceParent, int first, int last,
|
||||
ModelIndex const& targetParent, int targetIndex ) {
|
||||
eeASSERT( first >= 0 );
|
||||
eeASSERT( first <= last );
|
||||
eeASSERT( target_index >= 0 );
|
||||
mOperationStack.push( { OperationType::Move, Direction::Column, source_parent, first, last,
|
||||
target_parent, target_index } );
|
||||
eeASSERT( targetIndex >= 0 );
|
||||
mOperationStack.push( { OperationType::Move, Direction::Column, sourceParent, first, last,
|
||||
targetParent, targetIndex } );
|
||||
}
|
||||
|
||||
void Model::beginDeleteRows( ModelIndex const& parent, int first, int last ) {
|
||||
@@ -131,31 +131,31 @@ std::weak_ptr<PersistentHandle> Model::registerPersistentIndex( ModelIndex const
|
||||
|
||||
template <bool IsRow>
|
||||
void Model::saveDeletedIndices( ModelIndex const& parent, int first, int last ) {
|
||||
std::vector<ModelIndex> deleted_indices;
|
||||
std::vector<ModelIndex> deletedIndices;
|
||||
|
||||
for ( auto& entry : mPersistentHandles ) {
|
||||
auto current_index = entry.first;
|
||||
auto currentIndex = entry.first;
|
||||
|
||||
// Walk up the persistent handle's parents to see if it is contained
|
||||
// within the range that is being deleted.
|
||||
while ( current_index.isValid() ) {
|
||||
auto current_parent = current_index.parent();
|
||||
while ( currentIndex.isValid() ) {
|
||||
auto currentParent = currentIndex.parent();
|
||||
|
||||
if ( current_parent == parent ) {
|
||||
if ( currentParent == parent ) {
|
||||
if ( IsRow ) {
|
||||
if ( current_index.row() >= first && current_index.row() <= last )
|
||||
deleted_indices.emplace_back( current_index );
|
||||
if ( currentIndex.row() >= first && currentIndex.row() <= last )
|
||||
deletedIndices.emplace_back( currentIndex );
|
||||
} else {
|
||||
if ( current_index.column() >= first && current_index.column() <= last )
|
||||
deleted_indices.emplace_back( current_index );
|
||||
if ( currentIndex.column() >= first && currentIndex.column() <= last )
|
||||
deletedIndices.emplace_back( currentIndex );
|
||||
}
|
||||
}
|
||||
|
||||
current_index = current_parent;
|
||||
currentIndex = currentParent;
|
||||
}
|
||||
}
|
||||
|
||||
mDeletedIndicesStack.push( std::move( deleted_indices ) );
|
||||
mDeletedIndicesStack.push( std::move( deletedIndices ) );
|
||||
}
|
||||
|
||||
void Model::endInsertRows() {
|
||||
@@ -166,7 +166,7 @@ void Model::endInsertRows() {
|
||||
handleInsert( operation );
|
||||
|
||||
for ( auto& client : mClients ) {
|
||||
client->modelDidInsertRows( operation.source_parent, operation.first, operation.last );
|
||||
client->modelDidInsertRows( operation.sourceParent, operation.first, operation.last );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ void Model::endInsertColumns() {
|
||||
handleInsert( operation );
|
||||
|
||||
for ( auto& client : mClients )
|
||||
client->modelDidInsertColumns( operation.source_parent, operation.first, operation.last );
|
||||
client->modelDidInsertColumns( operation.sourceParent, operation.first, operation.last );
|
||||
}
|
||||
|
||||
void Model::endMoveRows() {
|
||||
@@ -189,8 +189,8 @@ void Model::endMoveRows() {
|
||||
handleMove( operation );
|
||||
|
||||
for ( auto& client : mClients )
|
||||
client->modelDidMoveRows( operation.source_parent, operation.first, operation.last,
|
||||
operation.target_parent, operation.target );
|
||||
client->modelDidMoveRows( operation.sourceParent, operation.first, operation.last,
|
||||
operation.targetParent, operation.target );
|
||||
}
|
||||
|
||||
void Model::endMoveColumns() {
|
||||
@@ -201,8 +201,8 @@ void Model::endMoveColumns() {
|
||||
handleMove( operation );
|
||||
|
||||
for ( auto& client : mClients ) {
|
||||
client->modeldidMoveColumns( operation.source_parent, operation.first, operation.last,
|
||||
operation.target_parent, operation.target );
|
||||
client->modeldidMoveColumns( operation.sourceParent, operation.first, operation.last,
|
||||
operation.targetParent, operation.target );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ void Model::endDeleteRows() {
|
||||
handleDelete( operation );
|
||||
|
||||
for ( auto& client : mClients ) {
|
||||
client->modelDidDeleteRows( operation.source_parent, operation.first, operation.last );
|
||||
client->modelDidDeleteRows( operation.sourceParent, operation.first, operation.last );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,61 +226,61 @@ void Model::endDeleteColumns() {
|
||||
handleDelete( operation );
|
||||
|
||||
for ( auto& client : mClients ) {
|
||||
client->modelDidDeleteColumns( operation.source_parent, operation.first, operation.last );
|
||||
client->modelDidDeleteColumns( operation.sourceParent, operation.first, operation.last );
|
||||
}
|
||||
}
|
||||
|
||||
void Model::handleInsert( Operation const& operation ) {
|
||||
bool is_row = operation.direction == Direction::Row;
|
||||
std::vector<const ModelIndex*> to_shift;
|
||||
bool isRow = operation.direction == Direction::Row;
|
||||
std::vector<const ModelIndex*> toShift;
|
||||
|
||||
for ( auto& entry : mPersistentHandles ) {
|
||||
if ( entry.first.parent() == operation.source_parent ) {
|
||||
if ( is_row && entry.first.row() >= operation.first ) {
|
||||
to_shift.emplace_back( &entry.first );
|
||||
} else if ( !is_row && entry.first.column() >= operation.first ) {
|
||||
to_shift.emplace_back( &entry.first );
|
||||
if ( entry.first.parent() == operation.sourceParent ) {
|
||||
if ( isRow && entry.first.row() >= operation.first ) {
|
||||
toShift.emplace_back( &entry.first );
|
||||
} else if ( !isRow && entry.first.column() >= operation.first ) {
|
||||
toShift.emplace_back( &entry.first );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int offset = operation.last - operation.first + 1;
|
||||
|
||||
for ( auto current_index : to_shift ) {
|
||||
int new_row = is_row ? current_index->row() + offset : current_index->row();
|
||||
int new_column = is_row ? current_index->column() : current_index->column() + offset;
|
||||
auto new_index = createIndex( new_row, new_column, current_index->internalData() );
|
||||
for ( auto currentIndex : toShift ) {
|
||||
int newRow = isRow ? currentIndex->row() + offset : currentIndex->row();
|
||||
int newColumn = isRow ? currentIndex->column() : currentIndex->column() + offset;
|
||||
auto newIndex = createIndex( newRow, newColumn, currentIndex->internalData() );
|
||||
|
||||
auto it = mPersistentHandles.find( *current_index );
|
||||
auto it = mPersistentHandles.find( *currentIndex );
|
||||
auto handle = std::move( it->second );
|
||||
|
||||
handle->m_index = new_index;
|
||||
handle->mIndex = newIndex;
|
||||
|
||||
mPersistentHandles.erase( it );
|
||||
mPersistentHandles[std::move( new_index )] = std::move( handle );
|
||||
mPersistentHandles[std::move( newIndex )] = std::move( handle );
|
||||
}
|
||||
}
|
||||
|
||||
void Model::handleDelete( Operation const& operation ) {
|
||||
bool is_row = operation.direction == Direction::Row;
|
||||
std::vector<ModelIndex> deleted_indices = mDeletedIndicesStack.top();
|
||||
bool isRow = operation.direction == Direction::Row;
|
||||
std::vector<ModelIndex> deletedIndices = mDeletedIndicesStack.top();
|
||||
mDeletedIndicesStack.pop();
|
||||
std::vector<const ModelIndex*> to_shift;
|
||||
std::vector<const ModelIndex*> toShift;
|
||||
|
||||
// Get rid of all persistent handles which have been marked for death
|
||||
for ( auto& deleted_index : deleted_indices ) {
|
||||
mPersistentHandles.erase( deleted_index );
|
||||
for ( auto& deletedIndex : deletedIndices ) {
|
||||
mPersistentHandles.erase( deletedIndex );
|
||||
}
|
||||
|
||||
for ( auto& entry : mPersistentHandles ) {
|
||||
if ( entry.first.parent() == operation.source_parent ) {
|
||||
if ( is_row ) {
|
||||
if ( entry.first.parent() == operation.sourceParent ) {
|
||||
if ( isRow ) {
|
||||
if ( entry.first.row() > operation.last ) {
|
||||
to_shift.emplace_back( &entry.first );
|
||||
toShift.emplace_back( &entry.first );
|
||||
}
|
||||
} else {
|
||||
if ( entry.first.column() > operation.last ) {
|
||||
to_shift.emplace_back( &entry.first );
|
||||
toShift.emplace_back( &entry.first );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -288,118 +288,121 @@ void Model::handleDelete( Operation const& operation ) {
|
||||
|
||||
int offset = operation.last - operation.first + 1;
|
||||
|
||||
for ( auto current_index : to_shift ) {
|
||||
int new_row = is_row ? current_index->row() - offset : current_index->row();
|
||||
int new_column = is_row ? current_index->column() : current_index->column() - offset;
|
||||
auto new_index = createIndex( new_row, new_column, current_index->internalData() );
|
||||
for ( auto currentIndex : toShift ) {
|
||||
int newRow = isRow ? currentIndex->row() - offset : currentIndex->row();
|
||||
int newColumn = isRow ? currentIndex->column() : currentIndex->column() - offset;
|
||||
auto newIndex = createIndex( newRow, newColumn, currentIndex->internalData() );
|
||||
|
||||
auto it = mPersistentHandles.find( *current_index );
|
||||
auto it = mPersistentHandles.find( *currentIndex );
|
||||
auto handle = std::move( it->second );
|
||||
|
||||
handle->m_index = new_index;
|
||||
handle->mIndex = newIndex;
|
||||
|
||||
mPersistentHandles.erase( it );
|
||||
mPersistentHandles[std::move( new_index )] = std::move( handle );
|
||||
mPersistentHandles[std::move( newIndex )] = std::move( handle );
|
||||
}
|
||||
}
|
||||
|
||||
void Model::handleMove( Operation const& operation ) {
|
||||
bool is_row = operation.direction == Direction::Row;
|
||||
bool move_within = operation.source_parent == operation.target_parent;
|
||||
bool moving_down = operation.target > operation.first;
|
||||
Mutex& Model::resourceLock() {
|
||||
return mResourceLock;
|
||||
}
|
||||
|
||||
if ( move_within && operation.first == operation.target )
|
||||
void Model::handleMove( Operation const& operation ) {
|
||||
bool isRow = operation.direction == Direction::Row;
|
||||
bool moveWithin = operation.sourceParent == operation.targetParent;
|
||||
bool movingDown = operation.target > operation.first;
|
||||
|
||||
if ( moveWithin && operation.first == operation.target )
|
||||
return;
|
||||
|
||||
if ( is_row ) {
|
||||
eeASSERT( operation.target <= (int)rowCount( operation.target_parent ) );
|
||||
eeASSERT( operation.last < (int)rowCount( operation.source_parent ) );
|
||||
if ( isRow ) {
|
||||
eeASSERT( operation.target <= (int)rowCount( operation.targetParent ) );
|
||||
eeASSERT( operation.last < (int)rowCount( operation.sourceParent ) );
|
||||
} else {
|
||||
eeASSERT( operation.target <= (int)columnCount( operation.target_parent ) );
|
||||
eeASSERT( operation.last < (int)columnCount( operation.source_parent ) );
|
||||
eeASSERT( operation.target <= (int)columnCount( operation.targetParent ) );
|
||||
eeASSERT( operation.last < (int)columnCount( operation.sourceParent ) );
|
||||
}
|
||||
|
||||
// NOTE: to_shift_down is used as a generic "to shift" when move_within is true.
|
||||
std::vector<const ModelIndex*> to_move; // Items to be moved between the source and target
|
||||
std::vector<const ModelIndex*> to_shift_down; // Items to be shifted down after a move-to
|
||||
std::vector<const ModelIndex*> to_shift_up; // Items to be shifted up after a move-from
|
||||
std::vector<const ModelIndex*> toMove; // Items to be moved between the source and target
|
||||
std::vector<const ModelIndex*> toShiftDown; // Items to be shifted down after a move-to
|
||||
std::vector<const ModelIndex*> toShiftUp; // Items to be shifted up after a move-from
|
||||
|
||||
int count = operation.last - operation.first + 1;
|
||||
// [start, end)
|
||||
int work_area_start = std::min( operation.first, operation.target );
|
||||
int workAreaStart = std::min( operation.first, operation.target );
|
||||
int work_area_end = std::max( operation.last + 1, operation.target + count );
|
||||
|
||||
for ( auto& entry : mPersistentHandles ) {
|
||||
int dimension = is_row ? entry.first.row() : entry.first.column();
|
||||
int dimension = isRow ? entry.first.row() : entry.first.column();
|
||||
|
||||
if ( move_within ) {
|
||||
if ( entry.first.parent() == operation.source_parent ) {
|
||||
if ( moveWithin ) {
|
||||
if ( entry.first.parent() == operation.sourceParent ) {
|
||||
if ( dimension >= operation.first && dimension <= operation.last ) {
|
||||
to_move.emplace_back( &entry.first );
|
||||
} else if ( moving_down && dimension > operation.last &&
|
||||
toMove.emplace_back( &entry.first );
|
||||
} else if ( movingDown && dimension > operation.last &&
|
||||
dimension < work_area_end ) {
|
||||
to_shift_down.emplace_back( &entry.first );
|
||||
} else if ( !moving_down && dimension >= work_area_start &&
|
||||
toShiftDown.emplace_back( &entry.first );
|
||||
} else if ( !movingDown && dimension >= workAreaStart &&
|
||||
dimension < operation.first ) {
|
||||
to_shift_down.emplace_back( &entry.first );
|
||||
toShiftDown.emplace_back( &entry.first );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( entry.first.parent() == operation.source_parent ) {
|
||||
if ( entry.first.parent() == operation.sourceParent ) {
|
||||
if ( dimension >= operation.first && dimension <= operation.last ) {
|
||||
to_move.emplace_back( &entry.first );
|
||||
toMove.emplace_back( &entry.first );
|
||||
} else if ( dimension > operation.last ) {
|
||||
to_shift_up.emplace_back( &entry.first );
|
||||
toShiftUp.emplace_back( &entry.first );
|
||||
}
|
||||
} else if ( entry.first.parent() == operation.target_parent ) {
|
||||
} else if ( entry.first.parent() == operation.targetParent ) {
|
||||
if ( dimension >= operation.target ) {
|
||||
to_shift_down.emplace_back( &entry.first );
|
||||
toShiftDown.emplace_back( &entry.first );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto replace_handle = [&]( ModelIndex const& current_index, int new_dimension, bool relative ) {
|
||||
int new_row = is_row ? ( relative ? current_index.row() + new_dimension : new_dimension )
|
||||
: current_index.row();
|
||||
int new_column = !is_row
|
||||
? ( relative ? current_index.column() + new_dimension : new_dimension )
|
||||
: current_index.column();
|
||||
auto new_index = index( new_row, new_column, operation.target_parent );
|
||||
auto replaceHandle = [&]( ModelIndex const& currentIndex, int newDimension, bool relative ) {
|
||||
int newRow = isRow ? ( relative ? currentIndex.row() + newDimension : newDimension )
|
||||
: currentIndex.row();
|
||||
int newColumn = !isRow ? ( relative ? currentIndex.column() + newDimension : newDimension )
|
||||
: currentIndex.column();
|
||||
auto newIndex = index( newRow, newColumn, operation.targetParent );
|
||||
|
||||
auto it = mPersistentHandles.find( current_index );
|
||||
auto it = mPersistentHandles.find( currentIndex );
|
||||
auto handle = std::move( it->second );
|
||||
|
||||
handle->m_index = new_index;
|
||||
handle->mIndex = newIndex;
|
||||
|
||||
mPersistentHandles.erase( it );
|
||||
mPersistentHandles[std::move( new_index )] = std::move( handle );
|
||||
mPersistentHandles[std::move( newIndex )] = std::move( handle );
|
||||
};
|
||||
|
||||
for ( auto current_index : to_move ) {
|
||||
int dimension = is_row ? current_index->row() : current_index->column();
|
||||
int target_offset = dimension - operation.first;
|
||||
int new_dimension = operation.target + target_offset;
|
||||
for ( auto currentIndex : toMove ) {
|
||||
int dimension = isRow ? currentIndex->row() : currentIndex->column();
|
||||
int targetOffset = dimension - operation.first;
|
||||
int newDimension = operation.target + targetOffset;
|
||||
|
||||
replace_handle( *current_index, new_dimension, false );
|
||||
replaceHandle( *currentIndex, newDimension, false );
|
||||
}
|
||||
|
||||
if ( move_within ) {
|
||||
for ( auto current_index : to_shift_down ) {
|
||||
int dimension = is_row ? current_index->row() : current_index->column();
|
||||
int target_offset = moving_down ? dimension - ( operation.last + 1 )
|
||||
: dimension - work_area_start + count;
|
||||
int new_dimension = work_area_start + target_offset;
|
||||
if ( moveWithin ) {
|
||||
for ( auto currentIndex : toShiftDown ) {
|
||||
int dimension = isRow ? currentIndex->row() : currentIndex->column();
|
||||
int targetOffset =
|
||||
movingDown ? dimension - ( operation.last + 1 ) : dimension - workAreaStart + count;
|
||||
int newDimension = workAreaStart + targetOffset;
|
||||
|
||||
replace_handle( *current_index, new_dimension, false );
|
||||
replaceHandle( *currentIndex, newDimension, false );
|
||||
}
|
||||
} else {
|
||||
for ( auto current_index : to_shift_down ) {
|
||||
replace_handle( *current_index, count, true );
|
||||
for ( auto currentIndex : toShiftDown ) {
|
||||
replaceHandle( *currentIndex, count, true );
|
||||
}
|
||||
|
||||
for ( auto current_index : to_shift_up ) {
|
||||
replace_handle( *current_index, count, true );
|
||||
for ( auto currentIndex : toShiftUp ) {
|
||||
replaceHandle( *currentIndex, count, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,57 +7,57 @@ PersistentModelIndex::PersistentModelIndex( ModelIndex const& index ) {
|
||||
return;
|
||||
|
||||
auto* model = const_cast<Model*>( index.model() );
|
||||
m_handle = model->registerPersistentIndex( index );
|
||||
mHandle = model->registerPersistentIndex( index );
|
||||
}
|
||||
|
||||
int PersistentModelIndex::row() const {
|
||||
if ( !hasValidHandle() )
|
||||
return -1;
|
||||
return m_handle.lock()->m_index.row();
|
||||
return mHandle.lock()->mIndex.row();
|
||||
}
|
||||
|
||||
int PersistentModelIndex::column() const {
|
||||
if ( !hasValidHandle() )
|
||||
return -1;
|
||||
return m_handle.lock()->m_index.column();
|
||||
return mHandle.lock()->mIndex.column();
|
||||
}
|
||||
|
||||
PersistentModelIndex PersistentModelIndex::parent() const {
|
||||
if ( !hasValidHandle() )
|
||||
return {};
|
||||
return { m_handle.lock()->m_index.parent() };
|
||||
return { mHandle.lock()->mIndex.parent() };
|
||||
}
|
||||
|
||||
PersistentModelIndex PersistentModelIndex::siblingAtColumn( int column ) const {
|
||||
if ( !hasValidHandle() )
|
||||
return {};
|
||||
|
||||
return { m_handle.lock()->m_index.siblingAtColumn( column ) };
|
||||
return { mHandle.lock()->mIndex.siblingAtColumn( column ) };
|
||||
}
|
||||
|
||||
Variant PersistentModelIndex::data( ModelRole role ) const {
|
||||
if ( !hasValidHandle() )
|
||||
return {};
|
||||
return { m_handle.lock()->m_index.data( role ) };
|
||||
return { mHandle.lock()->mIndex.data( role ) };
|
||||
}
|
||||
|
||||
PersistentModelIndex::operator ModelIndex() const {
|
||||
if ( !hasValidHandle() )
|
||||
return {};
|
||||
else
|
||||
return m_handle.lock()->m_index;
|
||||
return mHandle.lock()->mIndex;
|
||||
}
|
||||
|
||||
bool PersistentModelIndex::operator==( PersistentModelIndex const& other ) const {
|
||||
bool is_this_valid = hasValidHandle();
|
||||
bool is_other_valid = other.hasValidHandle();
|
||||
bool isThisValid = hasValidHandle();
|
||||
bool isOtherValid = other.hasValidHandle();
|
||||
|
||||
if ( !is_this_valid && !is_other_valid )
|
||||
if ( !isThisValid && !isOtherValid )
|
||||
return true;
|
||||
if ( is_this_valid != is_other_valid )
|
||||
if ( isThisValid != isOtherValid )
|
||||
return false;
|
||||
|
||||
return m_handle.lock()->m_index == other.m_handle.lock()->m_index;
|
||||
return mHandle.lock()->mIndex == other.mHandle.lock()->mIndex;
|
||||
}
|
||||
|
||||
bool PersistentModelIndex::operator!=( PersistentModelIndex const& other ) const {
|
||||
@@ -69,7 +69,7 @@ bool PersistentModelIndex::operator==( ModelIndex const& other ) const {
|
||||
return !other.isValid();
|
||||
}
|
||||
|
||||
return m_handle.lock()->m_index == other;
|
||||
return mHandle.lock()->mIndex == other;
|
||||
}
|
||||
|
||||
bool PersistentModelIndex::operator!=( ModelIndex const& other ) const {
|
||||
|
||||
@@ -26,7 +26,7 @@ bool UITableView::isType( const Uint32& type ) const {
|
||||
|
||||
void UITableView::drawChilds() {
|
||||
int realIndex = 0;
|
||||
|
||||
Lock l( const_cast<Model*>( getModel() )->resourceLock() );
|
||||
size_t start = mScrollOffset.y / getRowHeight();
|
||||
size_t end =
|
||||
eemin<size_t>( (size_t)eeceil( ( mScrollOffset.y + mSize.getHeight() ) / getRowHeight() ),
|
||||
@@ -62,6 +62,8 @@ Node* UITableView::overFind( const Vector2f& point ) {
|
||||
|
||||
Node* pOver = NULL;
|
||||
if ( mEnabled && mVisible ) {
|
||||
Lock l( const_cast<Model*>( getModel() )->resourceLock() );
|
||||
|
||||
updateWorldPolygon();
|
||||
if ( mWorldBounds.contains( point ) && mPoly.pointInside( point ) ) {
|
||||
writeNodeFlag( NODE_FLAG_MOUSEOVER_ME_OR_CHILD, 1 );
|
||||
@@ -108,6 +110,7 @@ Node* UITableView::overFind( const Vector2f& point ) {
|
||||
|
||||
Float UITableView::getMaxColumnContentWidth( const size_t& colIndex, bool bestGuess ) {
|
||||
Float lWidth = 0;
|
||||
Lock l( const_cast<Model*>( getModel() )->resourceLock() );
|
||||
if ( getModel()->rowCount() == 0 )
|
||||
return lWidth;
|
||||
getUISceneNode()->setIsLoading( true );
|
||||
@@ -170,6 +173,7 @@ void UITableView::onColumnSizeChange( const size_t& colIndex, bool fromUserInter
|
||||
Uint32 UITableView::onKeyDown( const KeyEvent& event ) {
|
||||
auto curIndex = getSelection().first();
|
||||
int pageSize = eefloor( getVisibleArea().getHeight() / getRowHeight() ) - 1;
|
||||
Lock l( const_cast<Model*>( getModel() )->resourceLock() );
|
||||
|
||||
switch ( event.getKeyCode() ) {
|
||||
case KEY_PAGEUP: {
|
||||
@@ -268,6 +272,7 @@ Uint32 UITableView::onKeyDown( const KeyEvent& event ) {
|
||||
ModelIndex UITableView::findRowWithText( const std::string& text, const bool& caseSensitive,
|
||||
const bool& exactMatch ) const {
|
||||
const Model* model = getModel();
|
||||
Lock l( const_cast<Model*>( getModel() )->resourceLock() );
|
||||
if ( !model || model->rowCount() == 0 )
|
||||
return {};
|
||||
size_t rc = model->rowCount();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <deque>
|
||||
#include <eepp/graphics/renderer/renderer.hpp>
|
||||
#include <eepp/system/lock.hpp>
|
||||
#include <eepp/ui/uilinearlayout.hpp>
|
||||
#include <eepp/ui/uipushbutton.hpp>
|
||||
#include <eepp/ui/uiscenenode.hpp>
|
||||
@@ -43,6 +44,7 @@ void UITreeView::traverseTree( TreeViewCallback callback ) const {
|
||||
if ( !getModel() )
|
||||
return;
|
||||
auto& model = *getModel();
|
||||
Lock l( const_cast<Model*>( getModel() )->resourceLock() );
|
||||
int indentLevel = 0;
|
||||
Float yOffset = getHeaderHeight();
|
||||
int rowIndex = -1;
|
||||
@@ -116,6 +118,7 @@ void UITreeView::bindNavigationClick( UIWidget* widget ) {
|
||||
auto mouseEvent = static_cast<const MouseEvent*>( event );
|
||||
auto idx = mouseEvent->getNode()->getParent()->asType<UITableRow>()->getCurIndex();
|
||||
if ( mouseEvent->getFlags() & EE_BUTTON_LMASK ) {
|
||||
Lock l( const_cast<Model*>( getModel() )->resourceLock() );
|
||||
if ( getModel()->rowCount( idx ) ) {
|
||||
auto& data = getIndexMetadata( idx );
|
||||
data.open = !data.open;
|
||||
@@ -146,6 +149,7 @@ UIWidget* UITreeView::setupCell( UITableCell* widget, UIWidget* rowWidget,
|
||||
if ( icon ) {
|
||||
Vector2f pos( icon->convertToNodeSpace( mouseEvent->getPosition().asFloat() ) );
|
||||
if ( pos >= Vector2f::Zero && pos <= icon->getPixelsSize() ) {
|
||||
Lock l( const_cast<Model*>( getModel() )->resourceLock() );
|
||||
auto idx =
|
||||
mouseEvent->getNode()->getParent()->asType<UITableRow>()->getCurIndex();
|
||||
if ( getModel()->rowCount( idx ) ) {
|
||||
@@ -627,6 +631,7 @@ void UITreeView::onSortColumn( const size_t& ) {
|
||||
ModelIndex UITreeView::findRowWithText( const std::string& text, const bool& caseSensitive,
|
||||
const bool& exactMatch ) const {
|
||||
const Model* model = getModel();
|
||||
Lock l( const_cast<Model*>( getModel() )->resourceLock() );
|
||||
if ( !model || model->rowCount() == 0 )
|
||||
return {};
|
||||
ModelIndex foundIndex = {};
|
||||
@@ -670,7 +675,12 @@ ModelIndex UITreeView::selectRowWithPath( std::string path ) {
|
||||
if ( foundIndex == ModelIndex() )
|
||||
break;
|
||||
|
||||
if ( getModel()->rowCount( foundIndex ) ) {
|
||||
size_t rowCount = 0;
|
||||
{
|
||||
Lock l( const_cast<Model*>( getModel() )->resourceLock() );
|
||||
rowCount = getModel()->rowCount( foundIndex );
|
||||
}
|
||||
if ( rowCount ) {
|
||||
auto& data = getIndexMetadata( foundIndex );
|
||||
if ( !data.open ) {
|
||||
data.open = true;
|
||||
|
||||
@@ -65,10 +65,12 @@ Vector2i InputSDL::queryMousePos() {
|
||||
SDL_Window* sdlw = reinterpret_cast<WindowSDL*>( mWindow )->GetSDLWindow();
|
||||
SDL_GetGlobalMouseState( &tempMouse.x, &tempMouse.y );
|
||||
SDL_GetWindowPosition( sdlw, &tempWinPos.x, &tempWinPos.y );
|
||||
SDL_GetWindowBordersSize( sdlw, &bordersSize.Top, &bordersSize.Left, &bordersSize.Bottom,
|
||||
&bordersSize.Right );
|
||||
mousePos.x = (int)tempMouse.x - tempWinPos.x - bordersSize.Left;
|
||||
mousePos.y = (int)tempMouse.y - tempWinPos.y - bordersSize.Top;
|
||||
// Since an unknown version the window position includes the margin from the border size.
|
||||
// So we don't need to compute that manually.
|
||||
/*SDL_GetWindowBordersSize( sdlw, &bordersSize.Top, &bordersSize.Left, &bordersSize.Bottom,
|
||||
&bordersSize.Right );*/
|
||||
mousePos.x = (int)tempMouse.x - tempWinPos.x /* - bordersSize.Left*/;
|
||||
mousePos.y = (int)tempMouse.y - tempWinPos.y /* - bordersSize.Top*/;
|
||||
return mousePos;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,9 +51,6 @@ void Input::sendEvent( InputEvent* Event ) {
|
||||
void Input::processEvent( InputEvent* Event ) {
|
||||
switch ( Event->Type ) {
|
||||
case InputEvent::Window: {
|
||||
if ( Event->window.type == InputEvent::WindowKeyboardFocusGain ) {
|
||||
mMousePos = queryMousePos();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case InputEvent::KeyDown: {
|
||||
|
||||
@@ -13,15 +13,6 @@ void FileSystemListener::handleFileAction( efsw::WatchID, const std::string& dir
|
||||
case efsw::Actions::Add:
|
||||
case efsw::Actions::Delete:
|
||||
case efsw::Actions::Moved: {
|
||||
/*auto* node = mFileSystemModel.get()->getNodeFromPath(
|
||||
file.isDirectory() ? FileSystem::removeLastFolderFromPath( file.getDirectoryPath() )
|
||||
: file.getDirectoryPath(),
|
||||
true, false );
|
||||
if ( node && ( !mFileSystemModel.get()->getDisplayConfig().ignoreHidden ||
|
||||
!file.isHidden() ) ) {
|
||||
node->invalidate();
|
||||
mFileSystemModel.get()->invalidate();
|
||||
}*/
|
||||
FileEvent event( (FileSystemEventType)action, dir, filename, oldFilename );
|
||||
mFileSystemModel.get()->handleFileEvent( event );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user