Warning, file /education/step/step/worldmodel.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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