1 /*************************************************************************** 2 * Copyright (C) 2005 by David Saxton * 3 * david@bluehaze.org * 4 * * 5 * This program is free software; you can redistribute it and/or modify * 6 * it under the terms of the GNU General Public License as published by * 7 * the Free Software Foundation; either version 2 of the License, or * 8 * (at your option) any later version. * 9 ***************************************************************************/ 10 11 #ifndef ICNDOCUMENT_H 12 #define ICNDOCUMENT_H 13 14 #include "itemdocument.h" 15 16 #include <QMap> 17 18 class Cells; 19 class CNItem; 20 class CNItemGroup; 21 class Connector; 22 class ECNode; 23 class FlowContainer; 24 class Node; 25 class NodeGroup; 26 27 typedef QMap< QString, Node* > NodeMap; 28 typedef QList<QPointer<Connector> > ConnectorList; 29 typedef QList<QPointer<Node> > NodeList; 30 typedef QList<NodeGroup*> NodeGroupList; 31 typedef QList<QPointer<NodeGroup> > GuardedNodeGroupList; 32 33 /** 34 @author David Saxton 35 */ 36 class ICNDocument : public ItemDocument 37 { 38 Q_OBJECT 39 public: 40 ICNDocument( const QString &caption, const char *name ); 41 42 ~ICNDocument() override; 43 44 enum hit_score 45 { 46 hs_none = 0, 47 hs_connector = 4, 48 hs_item = 1000 49 }; 50 51 View *createView( ViewContainer *viewContainer, uint viewAreaId, const char *name = nullptr ) override; 52 53 /** 54 * Will attempt to create an item with the given id at position p. Some item 55 * (such as PIC/START) have restrictions, and can only have one instance of 56 * themselves on the canvas, and adds the operation to the undo list 57 */ 58 Item* addItem( const QString &id, const QPoint &p, bool newItem ) override; 59 60 /** 61 * short for casting whatever itemWithID(id) returns 62 */ 63 CNItem* cnItemWithID( const QString &id ); 64 /** 65 * Returns a pointer to a node on the canvas with the given id, 66 * or nullptr if no such node exists 67 */ 68 virtual Node* nodeWithID( const QString &id ) = 0; 69 /** 70 * Returns a pointer to a Connector on the canvas with the given id, 71 * or nullptr if no such Connector exists 72 */ 73 Connector* connectorWithID( const QString &id ); 74 /** 75 * Adds a KtlQCanvasItem to the delete list to be deleted, 76 * when flushDeleteList() is called 77 */ 78 void appendDeleteList( KtlQCanvasItem *qcanvasItem ) override; 79 /** 80 * Permantly deletes all items that have been added to the delete list with 81 * the appendDeleteList( KtlQCanvasItem *qcanvasItem ) function. 82 */ 83 void flushDeleteList() override = 0; 84 /** 85 * Reinherit this function to perform special checks on whether the two 86 * given QCanvasItems (either nodes or connectors or both) can be 87 * connected together. 88 */ 89 virtual bool canConnect( KtlQCanvasItem *qcanvasItem1, KtlQCanvasItem *qcanvasItem2 ) const; 90 /** 91 * copies the selected items to the clipboard, in an XML text form 92 */ 93 void copy() override; 94 /** 95 * selects everything in the current document 96 */ 97 void selectAll() override; 98 99 /** 100 * registers (adds to the document) an item (a connector or a node) 101 * @param qcanvasItem the item to be registered 102 * @return true if succeeded, false if it didn't 103 */ 104 bool registerItem( KtlQCanvasItem *qcanvasItem ) override; 105 /** 106 * Returns a pointer to the 2-dimension array of ICNDocument cells. 107 */ cells()108 Cells *cells() const { return m_cells; } 109 /** 110 * Adds score to the cells at the given cell referece 111 */ 112 void addCPenalty( int x, int y, int score ); 113 /** 114 * If there are two connectors joined to a node, then they can be merged 115 * into one connector. The node will not be removed. 116 * @param node The node between the two connectors 117 * @param noCreate If true, no new connectors will be created 118 * @returns true if it was successful in merging the connectors 119 */ 120 // bool joinConnectors( Node *node ); 121 /** 122 * Snaps a coordinate in the document to the grid 123 * @param pos The coordinate 124 * @return The snapped to grid coordinate 125 */ 126 static int gridSnap( int pos ); /// Returns 'pos' when snapped to grid 127 /** 128 * Snaps a point to the grid 129 * @param pos The point 130 * @return The adjusted coordinate 131 */ 132 static QPoint gridSnap( const QPoint &pos ); 133 /** 134 * Returns true if the CNItem is valid - e.g. will return true for a 135 * component in a circuit, but not in a pic program 136 */ 137 bool isValidItem( Item *item ) override = 0; 138 bool isValidItem( const QString &itemId ) override = 0; 139 140 // TODO to document 141 virtual ConnectorList getCommonConnectors( const ItemList &list ); 142 virtual NodeList getCommonNodes( const ItemList &list ); 143 144 /** 145 * returns all the nodes contained by the document. Note that this function is inefficient, 146 * so don't use it in loops 147 * @return all the nodes contained by the document 148 */ 149 virtual NodeList nodeList() const = 0; 150 151 /** 152 * @return all the connectors from the document 153 */ connectorList()154 const ConnectorList & connectorList() const { return m_connectorList; } 155 156 /** 157 * @return all the nodegroups from the document 158 */ nodeGroupList()159 const GuardedNodeGroupList & nodeGroupList() const { return m_nodeGroupList; } 160 161 /** 162 * @return the selected items from the document 163 */ 164 ItemGroup *selectList() const override; 165 166 /** 167 * Creates a connector between two nodes, and returns a pointer to it 168 * and adds the operation to the undo list 169 */ 170 virtual Connector* createConnector( const QString &startNodeId, const QString &endNodeId, QPointList *pointList = nullptr ) = 0; 171 /** 172 * Creates a connector from node1 to node2. If pointList is non-null, then the 173 * connector will be assigned those points 174 */ 175 //virtual 176 177 Connector *createConnector( Node *node1, Node *node2, QPointList *pointList = nullptr); 178 /** 179 * Splits Connector con into two connectors at point pos2, and creates a connector from the node 180 * to the intersection of the two new connectors. If pointList is non-null, then the new connector 181 * from the node will be assigned those points 182 */ 183 virtual Connector * createConnector( Node *node, Connector *con, const QPoint &pos2, QPointList *pointList = nullptr ) = 0; 184 /** 185 * Splits con1 and con2 into two new connectors each at points pos1 and pos2, and creates a new connector 186 * between the two points of intersection given by pos1 and pos2. If pointList is non-null, then the new 187 * connector between the two points will be assigned those points 188 */ 189 virtual Connector * createConnector( Connector *con1, Connector *con2, const QPoint &pos1, const QPoint &pos2, QPointList *pointList = nullptr ) = 0; 190 /** 191 * Returns the flowcontainer at the given position at the highest level that 192 * is not in the current select list, or nullptr if there isn't one 193 */ 194 FlowContainer *flowContainer( const QPoint &pos ); 195 /** 196 * Sets the drag (e.g. horizontal arrow) cursor for resizing a CNItem, depending on the corner clicked on 197 */ 198 void setItemResizeCursor( int cornerType ); 199 200 void getTranslatable( const ItemList & itemList, ConnectorList * fixedConnectors = nullptr, ConnectorList * translatableConnectors = nullptr, NodeGroupList * translatableNodeGroups = nullptr ); 201 202 /** 203 * Reroutes invalidated directors. You shouldn't call this function 204 * directly - instead use ItemDocument::requestEvent. 205 */ 206 void rerouteInvalidatedConnectors(); 207 /** 208 * Assigns the orphan nodes into NodeGroups. You shouldn't call this 209 * function directly - instead use ItemDocument::requestEvent. 210 */ 211 virtual void slotAssignNodeGroups(); 212 213 void unregisterUID( const QString & uid ) override; 214 215 public slots: 216 /** 217 * Deletes all items in the selected item list, along with associated 218 * connectors, etc, and adds the operation to the undo list 219 */ 220 void deleteSelection() override; 221 /** 222 * This function looks at all the connectors and the nodes, determines 223 * which ones need rerouting, and then reroutes them 224 */ 225 void requestRerouteInvalidatedConnectors(); 226 /** 227 * Remaps the 2-dimension array of ICNDocument cells, and the various 228 * hitscores / etc associated with them. This is used for connector 229 * routing, and should be called after e.g. items have been moved 230 */ 231 void createCellMap(); 232 /** 233 * Call this to request NodeGroup reassignment. 234 */ 235 void slotRequestAssignNG(); 236 237 signals: 238 /** 239 * Emitted when a Connector is added 240 */ 241 void connectorAdded( Connector *connector ); 242 /** 243 * Emitted when a Node is added 244 */ 245 void nodeAdded( Node *node ); 246 247 protected: 248 /** 249 * Adds all connector points from the items (used in connector routing). 250 * This only needs to be called when connector(s) need routing. 251 */ 252 void addAllItemConnectorPoints(); 253 254 void fillContextMenu( const QPoint &pos ) override; 255 /** 256 * Creates a new NodeGroup to control the node, if there does not already 257 * exist a NodeGroup containing the given node. The associated nodes will 258 * also be added to the NodeGroup. 259 * @returns a pointer to the NodeGroup if one was created, or a pointer to the existing one containing that node 260 */ 261 NodeGroup* createNodeGroup( Node *node ); 262 /** 263 * Finds (and deletes if found) the NodeGroup containing the given node. 264 * @returns true if the NodeGroup was found and deleted 265 */ 266 bool deleteNodeGroup( Node *node ); 267 268 friend class CanvasEditor; 269 270 /** 271 * deletes all the elements containde in the nodeList. Should be overridden. 272 */ 273 virtual void deleteAllNodes() = 0; 274 275 /** 276 * Selects all nodes on the document. Should be overridden. 277 */ 278 virtual void selectAllNodes() = 0; 279 280 // this should be overridden in {Flow|Circuit}ICNDocument 281 ConnectorList m_connectorList; 282 CNItemGroup *m_selectList; // Selected objects 283 284 // OVERLOADED 285 KtlQCanvasItemList m_itemDeleteList; // List of canvas items to be deleted 286 287 private: 288 Cells *m_cells; 289 GuardedNodeGroupList m_nodeGroupList; 290 291 }; 292 293 /** 294 @author David Saxton 295 */ 296 class DirCursor 297 { 298 public: 299 static DirCursor* self(); 300 ~DirCursor(); 301 leftArrow()302 static QPixmap leftArrow() 303 { 304 return self()->m_leftArrow; 305 } 306 rightArrow()307 static QPixmap rightArrow() 308 { 309 return self()->m_rightArrow; 310 } 311 upArrow()312 static QPixmap upArrow() 313 { 314 return self()->m_upArrow; 315 } 316 downArrow()317 static QPixmap downArrow() 318 { 319 return self()->m_downArrow; 320 } 321 322 protected: 323 DirCursor(); 324 void initCursors(); 325 326 static DirCursor *m_self; 327 QPixmap m_leftArrow; 328 QPixmap m_rightArrow; 329 QPixmap m_upArrow; 330 QPixmap m_downArrow; 331 }; 332 333 334 #endif 335