File indexing completed on 2024-05-05 07:51:47
0001 /*. 0002 SPDX-FileCopyrightText: 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #ifndef STEP_WORLDMODEL_H 0008 #define STEP_WORLDMODEL_H 0009 0010 #include <QAbstractItemModel> 0011 #include <QTime> 0012 #include <QUndoCommand> 0013 #include <QVariant> 0014 0015 #include <KActionCollection> 0016 0017 #include <stepcore/world.h> 0018 0019 namespace StepCore { 0020 class Object; 0021 class World; 0022 class Item; 0023 class Solver; 0024 class CollisionSolver; 0025 class ConstraintSolver; 0026 class MetaProperty; 0027 } 0028 0029 class QIODevice; 0030 class QItemSelectionModel; 0031 class QTimer; 0032 class QMenu; 0033 class QUndoStack; 0034 0035 class Clipboard; 0036 class WorldFactory; 0037 class CommandSimulate; 0038 class SimulationThread; 0039 0040 /** \brief Central class that represents StepCore::World in Step */ 0041 class WorldModel: public QAbstractItemModel 0042 { 0043 Q_OBJECT 0044 public: 0045 enum { FormattedNameRole = Qt::UserRole+1, ClassNameRole }; 0046 enum FormatFlag { FormatEditable = 1, FormatHideUnits = 2 }; 0047 enum UndoFlag { UndoNoMerge = 1 }; 0048 0049 Q_DECLARE_FLAGS(FormatFlags, FormatFlag) 0050 Q_DECLARE_FLAGS(UndoFlags, UndoFlag) 0051 0052 public: 0053 explicit WorldModel(QObject* parent = nullptr); 0054 ~WorldModel(); 0055 0056 /** Get QItemSelectionModel associated with this WorldModel */ 0057 QItemSelectionModel* selectionModel() const { return _selectionModel; } 0058 /** Get WorldFactory associated with this WorldModel */ 0059 const WorldFactory* worldFactory() const { return _worldFactory; } 0060 0061 // QModelIndex quick-access functions 0062 QModelIndex worldIndex() const; ///< Get index of StepCore::World 0063 QModelIndex solverIndex() const; ///< Get index of StepCore::Solver 0064 QModelIndex collisionSolverIndex() const; ///< Get index of StepCore::CollisionSolver 0065 QModelIndex constraintSolverIndex() const; ///< Get index of StepCore::ConstraintSolver 0066 QModelIndex objectIndex(StepCore::Object* obj) const; ///< Get index of given object by pointer 0067 QModelIndex childItemIndex(int n, StepCore::ItemGroup* group = nullptr) const; ///< Get index of n-th child of the group 0068 0069 /** Get StepCore::Object by index. \note Never change returned object directly ! */ 0070 StepCore::Object* object(const QModelIndex& index) const; 0071 /** Find StepCore::Object by name. \note Never change returned object directly ! */ 0072 StepCore::Object* object(const QString& name) const { return _world->object(name); } 0073 0074 /** Get StepCore::World. \note Never change returned object directly ! */ 0075 StepCore::World* world() const { return _world; } 0076 /** Get StepCore::Solver. \note Never change returned object directly ! */ 0077 StepCore::Solver* solver() const { return _world->solver(); } 0078 /** Get StepCore::CollisionSolver. \note Never change returned object directly ! */ 0079 StepCore::CollisionSolver* collisionSolver() const { return _world->collisionSolver(); } 0080 /** Get StepCore::ConstraintSolver. \note Never change returned object directly ! */ 0081 StepCore::ConstraintSolver* constraintSolver() const { return _world->constraintSolver(); } 0082 0083 /** Get StepCore::Item by index. \note Never change returned object directly ! */ 0084 StepCore::Item* item(const QModelIndex& index) const; 0085 0086 /** Get n-th child of the world. \note Never change returned object directly ! */ 0087 StepCore::Item* childItem(int n) const { return _world->items()[n]; } 0088 /** Get count of the children of the world */ 0089 int childItemCount() const { return _world->items().size(); } 0090 0091 /** QAbstractItemModel::data() function */ 0092 QVariant data(const QModelIndex &index, int role) const override; 0093 /** QAbstractItemModel::index() function */ 0094 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override; 0095 /** QAbstractItemModel::parent() function */ 0096 QModelIndex parent(const QModelIndex &index) const override; 0097 /** QAbstractItemModel::rowCount() function */ 0098 int rowCount(const QModelIndex &parent = QModelIndex()) const override; 0099 /** QAbstractItemModel::columnCount() function */ 0100 int columnCount(const QModelIndex &parent = QModelIndex()) const override; 0101 0102 // Add/remove/set functions 0103 /** Generates new unique item name */ 0104 QString newItemName(const QString& className); 0105 StepCore::Item* createItem(const QString& className, StepCore::ItemGroup* parent = nullptr); 0106 /** Creates new item of className with unique name */ 0107 StepCore::Item* newItem(const QString& className, StepCore::ItemGroup* parent = nullptr); 0108 /** Add already created item to the world */ 0109 void addItem(StepCore::Item* item, StepCore::ItemGroup* parent = nullptr); 0110 /** Delete item from the world */ 0111 void deleteItem(StepCore::Item* item); 0112 0113 /** Create new solver of class named className and copy 0114 * similar properties of the old solver into the new solver. */ 0115 StepCore::Solver* newSolver(const QString& name); 0116 0117 // Undo/redo helpers 0118 QUndoStack* undoStack() { return _undoStack; } ///< Get associated QUndoStack 0119 void pushCommand(QUndoCommand* command); ///< Push new undo command 0120 void beginMacro(const QString& text); ///< Begin undo macro 0121 void endMacro(); ///< End undo macro 0122 0123 Clipboard* clipboard() const { return _clipboard; } 0124 0125 // Property edit 0126 /** Modify object property. 0127 * \param object object to modify 0128 * \param property property to modify 0129 * \param value new value for the property 0130 * \param flags UndoFlags 0131 * 0132 * \note Set flags to UndoNoMerge in order to disable merging this 0133 * command with previous on undo history and avoid changing of command order */ 0134 void setProperty(StepCore::Object* object, const StepCore::MetaProperty* property, 0135 const QVariant& value, UndoFlags flags = {}); 0136 0137 /** Modify object property. 0138 * \param object object to modify 0139 * \param propertyName name of the property to modify 0140 * \param value new value for the property 0141 * \param flags UndoFlags 0142 * 0143 * \note Set flags to UndoNoMerge in order to disable merging this 0144 * command with previous on undo history and avoid changing of command order */ 0145 void setProperty(StepCore::Object* object, const QString& propertyName, 0146 const QVariant& value, UndoFlags flags = {}) { 0147 setProperty(object, object->metaObject()->property(propertyName), value, flags); 0148 } 0149 0150 // Format property value for display or edit 0151 /** Format object name using standard formatting */ 0152 QString formatName(const StepCore::Object* object) const; 0153 /** Format object and class name using standard formatting */ 0154 QString formatNameFull(const StepCore::Object* object) const; 0155 /** Format property using standard formatting 0156 * \param object object 0157 * \param objectErrors associated StepCore::ObjecErrors (if required) 0158 * \param property property 0159 * \param flags Format flags */ 0160 QString formatProperty(const StepCore::Object* object, 0161 const StepCore::Object* objectErrors, 0162 const StepCore::MetaProperty* property, 0163 FormatFlags flags = {}) const; 0164 0165 // Tooltip 0166 /** Generate standard tooltip for object given by index */ 0167 QString createToolTip(const QModelIndex& index) const; 0168 0169 // ContextMenu 0170 /** Generate standard context many for object given by index */ 0171 QMenu* createContextMenu(const QModelIndex& index); 0172 0173 // Save/load 0174 /** Clear the world (delete everything in it and reset all settings */ 0175 void clearWorld(); 0176 /** Save the world into device */ 0177 bool saveXml(QIODevice* device); 0178 /** Load the world from device */ 0179 bool loadXml(QIODevice* device); 0180 /** Get last error string */ 0181 QString errorString() const { return _errorString; } 0182 0183 // Names 0184 /** Generate unique object name */ 0185 QString getUniqueName(const QString& className) const; 0186 /** Check is the name is unique */ 0187 bool checkUniqueName(const QString& name) const; 0188 0189 // Simulation 0190 /** Set FPS of simulation */ 0191 void setSimulationFps(int simulationFps); 0192 /** Get FPS of simulation */ 0193 int simulationFps() { return _simulationFps; } 0194 0195 /** Return true if simulation is active */ 0196 bool isSimulationActive(); 0197 0198 /** Pauses the simulation until control returns to event loop */ 0199 void simulationPause(); 0200 0201 void setActions(KActionCollection* actions) { _actions = actions; } 0202 0203 public slots: 0204 void simulationStart(); ///< Start simulation 0205 void simulationStop(); ///< Stop simulation 0206 0207 void cutSelectedItems(); 0208 void copySelectedItems(); 0209 void pasteItems(); 0210 void deleteSelectedItems(); ///< Delete all selected items 0211 0212 protected slots: 0213 void simulationFrameBegin(); 0214 void simulationFrameEnd(int result); 0215 void doEmitChanged(); 0216 0217 signals: 0218 /** This signal is called when the world is changed 0219 * \param dynamicOnly Indicated whether only dynamic variables was changed 0220 * \note Dynamic variables are variables that can change during simulation, 0221 * non-dynamic variables can change only by user action */ 0222 void worldDataChanged(bool dynamicOnly); 0223 0224 /** This signal is called when simulation is stopped. 0225 * \param result simulation result (from StepCore::Solver) */ 0226 void simulationStopped(int result); 0227 0228 protected: 0229 void resetWorld(); 0230 void emitChanged(bool fullUpdate, bool recalcFn); 0231 void addCreatedItem(StepCore::Item* item, StepCore::ItemGroup* parent = nullptr); 0232 void removeCreatedItem(StepCore::Item* item); 0233 StepCore::Solver* swapSolver(StepCore::Solver* solver); 0234 QList<StepCore::Item*> selectedItems(); 0235 0236 // Only for UndoCommand* classes 0237 //void objectChanged(const StepCore::Object* object); 0238 0239 protected: 0240 StepCore::World* _world; 0241 QItemSelectionModel* _selectionModel; 0242 QUndoStack* _undoStack; 0243 Clipboard* _clipboard; 0244 const WorldFactory* _worldFactory; 0245 QString _errorString; 0246 0247 QTimer* _updatingTimer; 0248 bool _updatingFullUpdate; 0249 bool _updatingRecalcFn; 0250 0251 QTimer* _simulationTimer; 0252 QTimer* _simulationTimer0; 0253 int _simulationFps; 0254 CommandSimulate* _simulationCommand; 0255 SimulationThread* _simulationThread; 0256 0257 int _simulationFrames; 0258 QTime _simulationStartTime; 0259 0260 bool _simulationFrameWaiting; 0261 bool _simulationFrameSkipped; 0262 bool _simulationStopping; 0263 bool _simulationPaused; 0264 0265 KActionCollection* _actions; 0266 0267 friend class CommandEditProperty; 0268 friend class CommandNewItem; 0269 friend class CommandSetSolver; 0270 friend class CommandSimulate; 0271 }; 0272 0273 Q_DECLARE_OPERATORS_FOR_FLAGS(WorldModel::FormatFlags) 0274 Q_DECLARE_OPERATORS_FOR_FLAGS(WorldModel::UndoFlags) 0275 0276 #endif 0277