File indexing completed on 2024-04-28 07:39:43
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_WORLDSCENE_H 0008 #define STEP_WORLDSCENE_H 0009 0010 #include <QGraphicsScene> 0011 #include <QGraphicsView> 0012 #include <QList> 0013 #include <QHash> 0014 0015 #include "messageframe.h" 0016 0017 class WorldModel; 0018 //class ItemCreator; 0019 0020 class QUrl; 0021 class QModelIndex; 0022 class QGraphicsItem; 0023 class QItemSelection; 0024 class StepGraphicsItem; 0025 class WorldGraphicsView; 0026 class ItemCreator; 0027 class WorldSceneAxes; 0028 0029 namespace StepCore { 0030 class Item; 0031 class MetaObject; 0032 } 0033 0034 /** \brief World scene class */ 0035 class WorldScene: public QGraphicsScene 0036 { 0037 Q_OBJECT 0038 0039 public: 0040 typedef QList<const StepCore::MetaObject*> SnapList; 0041 0042 /** Flags for controlling item snapping behavior */ 0043 enum SnapFlag { 0044 SnapOnCenter = 1, ///< Snap to the center of the body 0045 SnapSetPosition = 2, ///< Set position property 0046 SnapSetAngle = 4, ///< Set angle property 0047 SnapSetLocalPosition = 8, ///< Set localPosition property 0048 SnapParticle = 256, ///< Allow snapping to Particle 0049 SnapRigidBody = 512 ///< Allow snapping to RigidBody 0050 }; 0051 Q_DECLARE_FLAGS(SnapFlags, SnapFlag) 0052 0053 /** Construct WorldScene */ 0054 explicit WorldScene(WorldModel* worldModel, QObject* parent = nullptr); 0055 ~WorldScene(); 0056 0057 /** Get StepCore::Item by QGraphicsItem */ 0058 StepCore::Item* itemFromGraphics(const QGraphicsItem* graphicsItem) const; 0059 /** Get StepGraphicsItem for given StepCore::Item */ 0060 StepGraphicsItem* graphicsFromItem(const StepCore::Item* item) const; 0061 0062 /** Called by WorldView when view scale is updated */ 0063 void updateViewScale(); // Qt4.3 can help here 0064 /** Get current view scale of the scene */ 0065 double currentViewScale() { return _currentViewScale; } 0066 0067 /** Calculate united bounding rect of all items 0068 * (not taking into account WorldSceneAxes */ 0069 QRectF calcItemsBoundingRect(); 0070 0071 /** Highlight item at given position 0072 * \param pos position 0073 * \param flags snap flags 0074 * \param moreTypes additional item types to snap */ 0075 StepCore::Item* snapHighlight(QPointF pos, SnapFlags flags, const SnapList* moreTypes = nullptr); 0076 0077 /** Remove highlighting */ 0078 void snapClear(); 0079 0080 /** Attach item to another item at given position 0081 * \param pos position 0082 * \param flags snap flags 0083 * \param moreTypes additional item types to snap 0084 * \param movingState moving state of the item 0085 * \param item StepCore::Item to attach 0086 * \param num Num of the end to attach (or -1) 0087 * 0088 * If movingState equals Started or Moving this function 0089 * will only highlight potential body to attach and leave current 0090 * body detaches. It movingState equals Finished the function 0091 * will actually attach the body. 0092 * 0093 * This function sets "body" property of the item to snapped item 0094 * and "position" and/or "localPosition" property to the position 0095 * on snapped item. If num >=0 then QString::number(num) is added 0096 * to property names */ 0097 StepCore::Item* snapItem(QPointF pos, SnapFlags flags, const SnapList* moreTypes, 0098 int movingState, StepCore::Item* item, int num = -1); 0099 0100 /** Get associated WorldModel */ 0101 WorldModel* worldModel() const { return _worldModel; } 0102 0103 /** Check if scene has an active item creator */ 0104 bool hasItemCreator() const; 0105 0106 public slots: 0107 /** Begin adding new item. Creates appropriate ItemCreator */ 0108 void beginAddItem(const QString& name); 0109 0110 /** Shows a message to the user 0111 * \param type message type 0112 * \param text message text 0113 * \param flags message flags 0114 * \return message id of the created message */ 0115 int showMessage(MessageFrame::Type type, const QString& text, MessageFrame::Flags flags = {}) { 0116 return _messageFrame->showMessage(type, text, flags); 0117 } 0118 /** Changed existing message 0119 * \param id message id 0120 * \param type message type 0121 * \param text message text 0122 * \param flags message flags 0123 * \return new message id */ 0124 int changeMessage(int id, MessageFrame::Type type, const QString& text, MessageFrame::Flags flags = {}) { 0125 return _messageFrame->changeMessage(id, type, text, flags); 0126 } 0127 /** Close message 0128 * \param id message id */ 0129 void closeMessage(int id) { _messageFrame->closeMessage(id); } 0130 0131 /** Reload application settings */ 0132 void settingsChanged(); 0133 0134 signals: 0135 /** This signal is emitted when item creation is finished or canceled */ 0136 void endAddItem(const QString& name, bool success); 0137 /** This signal is emitted when a link in the message is activated */ 0138 void linkActivated(const QUrl& url); 0139 0140 protected slots: 0141 void worldModelReset(); 0142 void worldDataChanged(bool dynamicOnly); 0143 void worldCurrentChanged(const QModelIndex& current, const QModelIndex& previous); 0144 void worldSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); 0145 0146 void worldRowsInserted(const QModelIndex& parent, int start, int end); 0147 void worldRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); 0148 0149 void messageLinkActivated(const QString& link); 0150 0151 void snapUpdateToolTip(); 0152 0153 protected: 0154 bool event(QEvent* event) override; 0155 void mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent) override; 0156 void helpEvent(QGraphicsSceneHelpEvent *helpEvent) override; 0157 //void contextMenuEvent(QGraphicsSceneContextMenuEvent* contextMenuEvent); 0158 0159 void worldGetItemsRecursive(const QModelIndex& parent); 0160 0161 protected: 0162 WorldModel* _worldModel; 0163 WorldGraphicsView* _worldView; 0164 QHash<const StepCore::Item*, StepGraphicsItem*> _itemsHash; 0165 double _currentViewScale; 0166 ItemCreator* _itemCreator; 0167 QRgb _bgColor; 0168 0169 MessageFrame *_messageFrame; 0170 WorldSceneAxes *_sceneAxes; 0171 StepGraphicsItem *_snapItem; 0172 QPointF _snapPos; 0173 QString _snapToolTip; 0174 QTimer* _snapTimer; 0175 0176 friend class WorldGraphicsView; 0177 }; 0178 0179 /** \brief World view */ 0180 class WorldGraphicsView: public QGraphicsView 0181 { 0182 Q_OBJECT 0183 0184 public: 0185 WorldGraphicsView(WorldScene* worldScene, QWidget* parent); 0186 0187 public slots: 0188 void zoomIn(); ///< Zoom scene in 0189 void zoomOut(); ///< Zoom scene out 0190 void fitToPage(); ///< Ensure that all objects are visible 0191 void actualSize(); ///< Set zoom to 100% 0192 0193 /** Reload application settings */ 0194 void settingsChanged(); 0195 0196 protected slots: 0197 void sceneRectChanged(const QRectF& rect); 0198 0199 protected: 0200 void mousePressEvent(QMouseEvent* e) override; 0201 void mouseReleaseEvent(QMouseEvent* e) override; 0202 void wheelEvent(QWheelEvent* e) override; 0203 void scrollContentsBy(int dx, int dy) override; 0204 void updateSceneRect(); 0205 0206 static const int SCENE_LENGTH = 2000; 0207 0208 QRectF _sceneRect; 0209 }; 0210 0211 Q_DECLARE_OPERATORS_FOR_FLAGS(WorldScene::SnapFlags) 0212 0213 #endif 0214