2025-01-17 23:13:42 +00:00
# include "explorermodel.h"
# include "objects/base/instance.h"
2025-01-20 10:25:04 +00:00
# include "qabstractitemmodel.h"
2025-01-17 23:13:42 +00:00
# include "qcontainerfwd.h"
2025-01-18 17:50:56 +00:00
# include "qicon.h"
# include "qimage.h"
# include "qnamespace.h"
2025-01-17 23:13:42 +00:00
# include "qobject.h"
# include "qwidget.h"
2025-01-18 15:27:43 +00:00
# include "common.h"
# include <algorithm>
2025-01-20 10:25:04 +00:00
# include <cstdio>
# include <memory>
2025-01-18 15:27:43 +00:00
# include <optional>
2025-01-18 17:50:56 +00:00
# include "objects/base/instance.h"
2025-01-17 23:13:42 +00:00
// https://doc.qt.io/qt-6/qtwidgets-itemviews-simpletreemodel-example.html#testing-the-model
2025-01-18 17:50:56 +00:00
std : : map < std : : string , QImage > instanceIconCache ;
2025-01-17 23:13:42 +00:00
ExplorerModel : : ExplorerModel ( InstanceRef dataRoot , QWidget * parent )
: QAbstractItemModel ( parent )
, rootItem ( dataRoot ) {
2025-01-18 15:27:43 +00:00
// TODO: Don't use lambdas and handlers like that
hierarchyPreUpdateHandler = [ & ] ( InstanceRef object , std : : optional < InstanceRef > oldParent , std : : optional < InstanceRef > newParent ) {
if ( oldParent . has_value ( ) ) {
auto children = oldParent . value ( ) - > GetChildren ( ) ;
size_t idx = std : : find ( children . begin ( ) , children . end ( ) , object ) - children . end ( ) ;
beginRemoveRows ( toIndex ( oldParent . value ( ) ) , idx , idx ) ;
}
if ( newParent . has_value ( ) ) {
size_t size = newParent . value ( ) - > GetChildren ( ) . size ( ) ;
beginInsertRows ( toIndex ( newParent . value ( ) ) , size , size ) ;
} else {
// TODO:
}
} ;
hierarchyPostUpdateHandler = [ & ] ( InstanceRef object , std : : optional < InstanceRef > oldParent , std : : optional < InstanceRef > newParent ) {
if ( newParent . has_value ( ) ) endInsertRows ( ) ;
if ( oldParent . has_value ( ) ) endRemoveRows ( ) ;
} ;
2025-01-17 23:13:42 +00:00
}
ExplorerModel : : ~ ExplorerModel ( ) = default ;
QModelIndex ExplorerModel : : index ( int row , int column , const QModelIndex & parent ) const {
if ( ! hasIndex ( row , column , parent ) )
return { } ;
Instance * parentItem = parent . isValid ( )
? static_cast < Instance * > ( parent . internalPointer ( ) )
: rootItem . get ( ) ;
if ( parentItem - > GetChildren ( ) . size ( ) > = row )
return createIndex ( row , column , parentItem - > GetChildren ( ) [ row ] . get ( ) ) ;
return { } ;
}
2025-01-18 15:27:43 +00:00
QModelIndex ExplorerModel : : toIndex ( InstanceRef item ) {
if ( item = = rootItem )
return { } ;
InstanceRef parentItem = item - > GetParent ( ) . value ( ) ;
// Check above ensures this item is not root, so value() must be valid
for ( int i = 0 ; i < parentItem - > GetChildren ( ) . size ( ) ; i + + )
if ( parentItem - > GetChildren ( ) [ i ] = = item )
return createIndex ( i , 0 , item . get ( ) ) ;
return QModelIndex { } ;
}
2025-01-17 23:13:42 +00:00
QModelIndex ExplorerModel : : parent ( const QModelIndex & index ) const {
if ( ! index . isValid ( ) )
return { } ;
Instance * childItem = static_cast < Instance * > ( index . internalPointer ( ) ) ;
// NORISK: The parent must exist if the child was obtained from it during this frame
InstanceRef parentItem = childItem - > GetParent ( ) . value ( ) ;
if ( parentItem = = rootItem )
return { } ;
// Check above ensures this item is not root, so value() must be valid
InstanceRef parentParent = parentItem - > GetParent ( ) . value ( ) ;
for ( int i = 0 ; i < parentParent - > GetChildren ( ) . size ( ) ; i + + )
if ( parentParent - > GetChildren ( ) [ i ] = = parentItem )
return createIndex ( i , 0 , parentItem . get ( ) ) ;
return QModelIndex { } ;
}
int ExplorerModel : : rowCount ( const QModelIndex & parent ) const {
if ( parent . column ( ) > 0 )
return 0 ;
Instance * parentItem = parent . isValid ( )
? static_cast < Instance * > ( parent . internalPointer ( ) )
: rootItem . get ( ) ;
return parentItem - > GetChildren ( ) . size ( ) ;
}
int ExplorerModel : : columnCount ( const QModelIndex & parent ) const {
return 1 ;
}
QVariant ExplorerModel : : data ( const QModelIndex & index , int role ) const {
2025-01-18 17:50:56 +00:00
if ( ! index . isValid ( ) )
2025-01-17 23:13:42 +00:00
return { } ;
2025-01-18 17:50:56 +00:00
Instance * item = static_cast < Instance * > ( index . internalPointer ( ) ) ;
switch ( role ) {
case Qt : : DisplayRole :
return QString : : fromStdString ( item - > name ) ;
case Qt : : DecorationRole :
return iconOf ( item - > GetClass ( ) ) ;
}
return { } ;
2025-01-17 23:13:42 +00:00
}
2025-01-20 10:25:04 +00:00
bool ExplorerModel : : setData ( const QModelIndex & index , const QVariant & value , int role ) {
if ( ! index . isValid ( ) | | role ! = Qt : : EditRole ) return false ;
Instance * inst = static_cast < Instance * > ( index . internalPointer ( ) ) ;
inst - > name = value . toString ( ) . toStdString ( ) ;
return true ;
}
2025-01-17 23:13:42 +00:00
QVariant ExplorerModel : : headerData ( int section , Qt : : Orientation orientation ,
int role ) const
{
return QString ( " Idk lol \u00AF \u005C \u005F \u0028 \u30C4 \u0029 \u005F \u002F \u00AF " ) ;
}
Qt : : ItemFlags ExplorerModel : : flags ( const QModelIndex & index ) const
{
2025-01-20 10:25:04 +00:00
//return index.isValid()
// ? QAbstractItemModel::flags(index) : Qt::ItemFlags(Qt::NoItemFlags);
2025-01-17 23:13:42 +00:00
return index . isValid ( )
2025-01-20 10:25:04 +00:00
? QAbstractItemModel : : flags ( index ) | Qt : : ItemIsEditable | Qt : : ItemIsDragEnabled | Qt : : ItemIsDropEnabled
: Qt : : NoItemFlags | Qt : : ItemIsDropEnabled ;
2025-01-18 17:50:56 +00:00
}
QImage ExplorerModel : : iconOf ( InstanceType * type ) const {
if ( instanceIconCache . count ( type - > className ) ) return instanceIconCache [ type - > className ] ;
InstanceType * currentClass = type ;
while ( currentClass - > explorerIcon . empty ( ) ) currentClass = currentClass - > super ;
QImage icon ( " assets/icons/ " + QString : : fromStdString ( currentClass - > explorerIcon ) ) ;
instanceIconCache [ type - > className ] = icon ;
return icon ;
2025-01-20 10:25:04 +00:00
}
bool ExplorerModel : : moveRows ( const QModelIndex & sourceParentIdx , int sourceRow , int count , const QModelIndex & destinationParentIdx , int destinationChild ) {
Instance * sourceParent = sourceParentIdx . isValid ( ) ? static_cast < Instance * > ( sourceParentIdx . internalPointer ( ) ) : workspace . get ( ) ;
Instance * destinationParent = destinationParentIdx . isValid ( ) ? static_cast < Instance * > ( destinationParentIdx . internalPointer ( ) ) : workspace . get ( ) ;
printf ( " Moved %d from %s \n " , count , sourceParent - > name . c_str ( ) ) ;
if ( ( sourceRow + count ) > = sourceParent - > GetChildren ( ) . size ( ) ) {
fprintf ( stderr , " Attempt to move rows %d-%d from %s (%s) while it only has %d children. \n " , sourceRow , sourceRow + count , sourceParent - > name . c_str ( ) , sourceParent - > GetClass ( ) - > className . c_str ( ) , sourceParent - > GetChildren ( ) . size ( ) ) ;
return false ;
}
for ( int i = sourceRow ; i < ( sourceRow + count ) ; i + + ) {
sourceParent - > GetChildren ( ) [ i ] - > SetParent ( destinationParent - > shared_from_this ( ) ) ;
}
return true ;
}
bool ExplorerModel : : removeRows ( int row , int count , const QModelIndex & parentIdx ) {
Instance * parent = parentIdx . isValid ( ) ? static_cast < Instance * > ( parentIdx . internalPointer ( ) ) : workspace . get ( ) ;
for ( int i = row ; i < ( row + count ) ; i + + ) {
//parent->GetChildren()[i]->SetParent(nullptr);
}
return true ;
}
bool ExplorerModel : : insertRows ( int row , int count , const QModelIndex & parentIdx ) {
//Instance* parent = parentIdx.isValid() ? static_cast<Instance*>(parentIdx.internalPointer()) : workspace.get();
//beginInsertRows(parentIdx, parent->GetChildren().size(), parent->GetChildren().size() + count);
//for ()
//endInsertRows();
//return true;
return false ;
}
Qt : : DropActions ExplorerModel : : supportedDragActions ( ) const {
return Qt : : DropAction : : MoveAction ;
}
Qt : : DropActions ExplorerModel : : supportedDropActions ( ) const {
return Qt : : DropAction : : MoveAction ;
}
InstanceRef ExplorerModel : : fromIndex ( const QModelIndex index ) {
if ( ! index . isValid ( ) ) return workspace ;
return static_cast < Instance * > ( index . internalPointer ( ) ) - > shared_from_this ( ) ;
2025-01-17 23:13:42 +00:00
}