1 /* This file is part of Step. 2 Copyright (C) 2007 Vladimir Kuznetsov <ks.vladimir@gmail.com> 3 4 Step is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2 of the License, or 7 (at your option) any later version. 8 9 Step is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with Step; if not, write to the Free Software 16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 */ 18 19 #ifndef STEP_WORLDSCENE_H 20 #define STEP_WORLDSCENE_H 21 22 #include <QGraphicsScene> 23 #include <QGraphicsView> 24 #include <QList> 25 #include <QHash> 26 27 #include "messageframe.h" 28 29 class WorldModel; 30 //class ItemCreator; 31 32 class QUrl; 33 class QModelIndex; 34 class QGraphicsItem; 35 class QItemSelection; 36 class StepGraphicsItem; 37 class WorldGraphicsView; 38 class ItemCreator; 39 class WorldSceneAxes; 40 41 namespace StepCore { 42 class Item; 43 class MetaObject; 44 } 45 46 /** \brief World scene class */ 47 class WorldScene: public QGraphicsScene 48 { 49 Q_OBJECT 50 51 public: 52 typedef QList<const StepCore::MetaObject*> SnapList; 53 54 /** Flags for controlling item snapping behavior */ 55 enum SnapFlag { 56 SnapOnCenter = 1, ///< Snap to the center of the body 57 SnapSetPosition = 2, ///< Set position property 58 SnapSetAngle = 4, ///< Set angle property 59 SnapSetLocalPosition = 8, ///< Set localPosition property 60 SnapParticle = 256, ///< Allow snapping to Particle 61 SnapRigidBody = 512 ///< Allow snapping to RigidBody 62 }; 63 Q_DECLARE_FLAGS(SnapFlags, SnapFlag) 64 65 /** Construct WorldScene */ 66 explicit WorldScene(WorldModel* worldModel, QObject* parent = 0); 67 ~WorldScene(); 68 69 /** Get StepCore::Item by QGraphicsItem */ 70 StepCore::Item* itemFromGraphics(const QGraphicsItem* graphicsItem) const; 71 /** Get StepGraphicsItem for given StepCore::Item */ 72 StepGraphicsItem* graphicsFromItem(const StepCore::Item* item) const; 73 74 /** Called by WorldView when view scale is updated */ 75 void updateViewScale(); // Qt4.3 can help here 76 /** Get current view scale of the scene */ currentViewScale()77 double currentViewScale() { return _currentViewScale; } 78 79 /** Calculate united bounding rect of all items 80 * (not taking into account WorldSceneAxes */ 81 QRectF calcItemsBoundingRect(); 82 83 /** Highlight item at given position 84 * \param pos position 85 * \param flags snap flags 86 * \param moreTypes additional item types to snap */ 87 StepCore::Item* snapHighlight(QPointF pos, SnapFlags flags, const SnapList* moreTypes = 0); 88 89 /** Remove highlighting */ 90 void snapClear(); 91 92 /** Attach item to another item at given position 93 * \param pos position 94 * \param flags snap flags 95 * \param moreTypes additional item types to snap 96 * \param movingState moving state of the item 97 * \param item StepCore::Item to attach 98 * \param num Num of the end to attach (or -1) 99 * 100 * If movingState equals Started or Moving this function 101 * will only highlight potential body to attach and leave current 102 * body detaches. It movingState equals Finished the function 103 * will actually attach the body. 104 * 105 * This function sets "body" property of the item to snapped item 106 * and "position" and/or "localPosition" property to the position 107 * on snapped item. If num >=0 then QString::number(num) is added 108 * to property names */ 109 StepCore::Item* snapItem(QPointF pos, SnapFlags flags, const SnapList* moreTypes, 110 int movingState, StepCore::Item* item, int num = -1); 111 112 /** Get associated WorldModel */ worldModel()113 WorldModel* worldModel() const { return _worldModel; } 114 115 /** Check if scene has an active item creator */ 116 bool hasItemCreator() const; 117 118 public slots: 119 /** Begin adding new item. Creates appropriate ItemCreator */ 120 void beginAddItem(const QString& name); 121 122 /** Shows a message to the user 123 * \param type message type 124 * \param text message text 125 * \param flags message flags 126 * \return message id of the created message */ 127 int showMessage(MessageFrame::Type type, const QString& text, MessageFrame::Flags flags = {}) { 128 return _messageFrame->showMessage(type, text, flags); 129 } 130 /** Changed existing message 131 * \param id message id 132 * \param type message type 133 * \param text message text 134 * \param flags message flags 135 * \return new message id */ 136 int changeMessage(int id, MessageFrame::Type type, const QString& text, MessageFrame::Flags flags = {}) { 137 return _messageFrame->changeMessage(id, type, text, flags); 138 } 139 /** Close message 140 * \param id message id */ closeMessage(int id)141 void closeMessage(int id) { _messageFrame->closeMessage(id); } 142 143 /** Reload application settings */ 144 void settingsChanged(); 145 146 signals: 147 /** This signal is emitted when item creation is finished or canceled */ 148 void endAddItem(const QString& name, bool success); 149 /** This signal is emitted when a link in the message is activated */ 150 void linkActivated(const QUrl& url); 151 152 protected slots: 153 void worldModelReset(); 154 void worldDataChanged(bool dynamicOnly); 155 void worldCurrentChanged(const QModelIndex& current, const QModelIndex& previous); 156 void worldSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); 157 158 void worldRowsInserted(const QModelIndex& parent, int start, int end); 159 void worldRowsAboutToBeRemoved(const QModelIndex& parent, int start, int end); 160 161 void messageLinkActivated(const QString& link); 162 163 void snapUpdateToolTip(); 164 165 protected: 166 bool event(QEvent* event) override; 167 void mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent) override; 168 void helpEvent(QGraphicsSceneHelpEvent *helpEvent) override; 169 //void contextMenuEvent(QGraphicsSceneContextMenuEvent* contextMenuEvent); 170 171 void worldGetItemsRecursive(const QModelIndex& parent); 172 173 protected: 174 WorldModel* _worldModel; 175 WorldGraphicsView* _worldView; 176 QHash<const StepCore::Item*, StepGraphicsItem*> _itemsHash; 177 double _currentViewScale; 178 ItemCreator* _itemCreator; 179 QRgb _bgColor; 180 181 MessageFrame *_messageFrame; 182 WorldSceneAxes *_sceneAxes; 183 StepGraphicsItem *_snapItem; 184 QPointF _snapPos; 185 QString _snapToolTip; 186 QTimer* _snapTimer; 187 188 friend class WorldGraphicsView; 189 }; 190 191 /** \brief World view */ 192 class WorldGraphicsView: public QGraphicsView 193 { 194 Q_OBJECT 195 196 public: 197 WorldGraphicsView(WorldScene* worldScene, QWidget* parent); 198 199 public slots: 200 void zoomIn(); ///< Zoom scene in 201 void zoomOut(); ///< Zoom scene out 202 void fitToPage(); ///< Ensure that all objects are visible 203 void actualSize(); ///< Set zoom to 100% 204 205 /** Reload application settings */ 206 void settingsChanged(); 207 208 protected slots: 209 void sceneRectChanged(const QRectF& rect); 210 211 protected: 212 void mousePressEvent(QMouseEvent* e) override; 213 void mouseReleaseEvent(QMouseEvent* e) override; 214 void wheelEvent(QWheelEvent* e) override; 215 void scrollContentsBy(int dx, int dy) override; 216 void updateSceneRect(); 217 218 static const int SCENE_LENGTH = 2000; 219 220 QRectF _sceneRect; 221 }; 222 223 Q_DECLARE_OPERATORS_FOR_FLAGS(WorldScene::SnapFlags) 224 225 #endif 226 227