File indexing completed on 2024-12-08 08:10:40
0001 /*************************************************************************** 0002 * Copyright (C) 2005 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #ifndef ICNDOCUMENT_H 0012 #define ICNDOCUMENT_H 0013 0014 #include "itemdocument.h" 0015 0016 #include <QMap> 0017 0018 class Cells; 0019 class CNItem; 0020 class CNItemGroup; 0021 class Connector; 0022 class ECNode; 0023 class FlowContainer; 0024 class Node; 0025 class NodeGroup; 0026 0027 typedef QMap<QString, Node *> NodeMap; 0028 typedef QList<QPointer<Connector>> ConnectorList; 0029 typedef QList<QPointer<Node>> NodeList; 0030 typedef QList<NodeGroup *> NodeGroupList; 0031 typedef QList<QPointer<NodeGroup>> GuardedNodeGroupList; 0032 0033 /** 0034 @author David Saxton 0035 */ 0036 class ICNDocument : public ItemDocument 0037 { 0038 Q_OBJECT 0039 public: 0040 ICNDocument(const QString &caption); 0041 0042 ~ICNDocument() override; 0043 0044 enum hit_score { hs_none = 0, hs_connector = 4, hs_item = 1000 }; 0045 0046 View *createView(ViewContainer *viewContainer, uint viewAreaId) override; 0047 0048 /** 0049 * Will attempt to create an item with the given id at position p. Some item 0050 * (such as PIC/START) have restrictions, and can only have one instance of 0051 * themselves on the canvas, and adds the operation to the undo list 0052 */ 0053 Item *addItem(const QString &id, const QPoint &p, bool newItem) override; 0054 0055 /** 0056 * short for casting whatever itemWithID(id) returns 0057 */ 0058 CNItem *cnItemWithID(const QString &id); 0059 /** 0060 * Returns a pointer to a node on the canvas with the given id, 0061 * or nullptr if no such node exists 0062 */ 0063 virtual Node *nodeWithID(const QString &id) = 0; 0064 /** 0065 * Returns a pointer to a Connector on the canvas with the given id, 0066 * or nullptr if no such Connector exists 0067 */ 0068 Connector *connectorWithID(const QString &id); 0069 /** 0070 * Adds a KtlQCanvasItem to the delete list to be deleted, 0071 * when flushDeleteList() is called 0072 */ 0073 void appendDeleteList(KtlQCanvasItem *qcanvasItem) override; 0074 /** 0075 * Permantly deletes all items that have been added to the delete list with 0076 * the appendDeleteList( KtlQCanvasItem *qcanvasItem ) function. 0077 */ 0078 void flushDeleteList() override = 0; 0079 /** 0080 * Reinherit this function to perform special checks on whether the two 0081 * given QCanvasItems (either nodes or connectors or both) can be 0082 * connected together. 0083 */ 0084 virtual bool canConnect(KtlQCanvasItem *qcanvasItem1, KtlQCanvasItem *qcanvasItem2) const; 0085 /** 0086 * copies the selected items to the clipboard, in an XML text form 0087 */ 0088 void copy() override; 0089 /** 0090 * selects everything in the current document 0091 */ 0092 void selectAll() override; 0093 0094 /** 0095 * registers (adds to the document) an item (a connector or a node) 0096 * @param qcanvasItem the item to be registered 0097 * @return true if succeeded, false if it didn't 0098 */ 0099 bool registerItem(KtlQCanvasItem *qcanvasItem) override; 0100 /** 0101 * Returns a pointer to the 2-dimension array of ICNDocument cells. 0102 */ 0103 Cells *cells() const 0104 { 0105 return m_cells; 0106 } 0107 /** 0108 * Adds score to the cells at the given cell referece 0109 */ 0110 void addCPenalty(int x, int y, int score); 0111 /** 0112 * If there are two connectors joined to a node, then they can be merged 0113 * into one connector. The node will not be removed. 0114 * @param node The node between the two connectors 0115 * @param noCreate If true, no new connectors will be created 0116 * @returns true if it was successful in merging the connectors 0117 */ 0118 // bool joinConnectors( Node *node ); 0119 /** 0120 * Snaps a coordinate in the document to the grid 0121 * @param pos The coordinate 0122 * @return The snapped to grid coordinate 0123 */ 0124 static int gridSnap(int pos); /// Returns 'pos' when snapped to grid 0125 /** 0126 * Snaps a point to the grid 0127 * @param pos The point 0128 * @return The adjusted coordinate 0129 */ 0130 static QPoint gridSnap(const QPoint &pos); 0131 /** 0132 * Returns true if the CNItem is valid - e.g. will return true for a 0133 * component in a circuit, but not in a pic program 0134 */ 0135 bool isValidItem(Item *item) override = 0; 0136 bool isValidItem(const QString &itemId) override = 0; 0137 0138 // TODO to document 0139 virtual ConnectorList getCommonConnectors(const ItemList &list); 0140 virtual NodeList getCommonNodes(const ItemList &list); 0141 0142 /** 0143 * returns all the nodes contained by the document. Note that this function is inefficient, 0144 * so don't use it in loops 0145 * @return all the nodes contained by the document 0146 */ 0147 virtual NodeList nodeList() const = 0; 0148 0149 /** 0150 * @return all the connectors from the document 0151 */ 0152 const ConnectorList &connectorList() const 0153 { 0154 return m_connectorList; 0155 } 0156 0157 /** 0158 * @return all the nodegroups from the document 0159 */ 0160 const GuardedNodeGroupList &nodeGroupList() const 0161 { 0162 return m_nodeGroupList; 0163 } 0164 0165 /** 0166 * @return the selected items from the document 0167 */ 0168 ItemGroup *selectList() const override; 0169 0170 /** 0171 * Creates a connector between two nodes, and returns a pointer to it 0172 * and adds the operation to the undo list 0173 */ 0174 virtual Connector *createConnector(const QString &startNodeId, const QString &endNodeId, QPointList *pointList = nullptr) = 0; 0175 /** 0176 * Creates a connector from node1 to node2. If pointList is non-null, then the 0177 * connector will be assigned those points 0178 */ 0179 // virtual 0180 0181 Connector *createConnector(Node *node1, Node *node2, QPointList *pointList = nullptr); 0182 /** 0183 * Splits Connector con into two connectors at point pos2, and creates a connector from the node 0184 * to the intersection of the two new connectors. If pointList is non-null, then the new connector 0185 * from the node will be assigned those points 0186 */ 0187 virtual Connector *createConnector(Node *node, Connector *con, const QPoint &pos2, QPointList *pointList = nullptr) = 0; 0188 /** 0189 * Splits con1 and con2 into two new connectors each at points pos1 and pos2, and creates a new connector 0190 * between the two points of intersection given by pos1 and pos2. If pointList is non-null, then the new 0191 * connector between the two points will be assigned those points 0192 */ 0193 virtual Connector *createConnector(Connector *con1, Connector *con2, const QPoint &pos1, const QPoint &pos2, QPointList *pointList = nullptr) = 0; 0194 /** 0195 * Returns the flowcontainer at the given position at the highest level that 0196 * is not in the current select list, or nullptr if there isn't one 0197 */ 0198 FlowContainer *flowContainer(const QPoint &pos); 0199 /** 0200 * Sets the drag (e.g. horizontal arrow) cursor for resizing a CNItem, depending on the corner clicked on 0201 */ 0202 void setItemResizeCursor(int cornerType); 0203 0204 void getTranslatable(const ItemList &itemList, ConnectorList *fixedConnectors = nullptr, ConnectorList *translatableConnectors = nullptr, NodeGroupList *translatableNodeGroups = nullptr); 0205 0206 /** 0207 * Reroutes invalidated directors. You shouldn't call this function 0208 * directly - instead use ItemDocument::requestEvent. 0209 */ 0210 void rerouteInvalidatedConnectors(); 0211 /** 0212 * Assigns the orphan nodes into NodeGroups. You shouldn't call this 0213 * function directly - instead use ItemDocument::requestEvent. 0214 */ 0215 virtual void slotAssignNodeGroups(); 0216 0217 void unregisterUID(const QString &uid) override; 0218 0219 public slots: 0220 /** 0221 * Deletes all items in the selected item list, along with associated 0222 * connectors, etc, and adds the operation to the undo list 0223 */ 0224 void deleteSelection() override; 0225 /** 0226 * This function looks at all the connectors and the nodes, determines 0227 * which ones need rerouting, and then reroutes them 0228 */ 0229 void requestRerouteInvalidatedConnectors(); 0230 /** 0231 * Remaps the 2-dimension array of ICNDocument cells, and the various 0232 * hitscores / etc associated with them. This is used for connector 0233 * routing, and should be called after e.g. items have been moved 0234 */ 0235 void createCellMap(); 0236 /** 0237 * Call this to request NodeGroup reassignment. 0238 */ 0239 void slotRequestAssignNG(); 0240 0241 signals: 0242 /** 0243 * Emitted when a Connector is added 0244 */ 0245 void connectorAdded(Connector *connector); 0246 /** 0247 * Emitted when a Node is added 0248 */ 0249 void nodeAdded(Node *node); 0250 0251 protected: 0252 /** 0253 * Adds all connector points from the items (used in connector routing). 0254 * This only needs to be called when connector(s) need routing. 0255 */ 0256 void addAllItemConnectorPoints(); 0257 0258 void fillContextMenu(const QPoint &pos) override; 0259 /** 0260 * Creates a new NodeGroup to control the node, if there does not already 0261 * exist a NodeGroup containing the given node. The associated nodes will 0262 * also be added to the NodeGroup. 0263 * @returns a pointer to the NodeGroup if one was created, or a pointer to the existing one containing that node 0264 */ 0265 NodeGroup *createNodeGroup(Node *node); 0266 /** 0267 * Finds (and deletes if found) the NodeGroup containing the given node. 0268 * @returns true if the NodeGroup was found and deleted 0269 */ 0270 bool deleteNodeGroup(Node *node); 0271 0272 friend class CanvasEditor; 0273 0274 /** 0275 * deletes all the elements containde in the nodeList. Should be overridden. 0276 */ 0277 virtual void deleteAllNodes() = 0; 0278 0279 /** 0280 * Selects all nodes on the document. Should be overridden. 0281 */ 0282 virtual void selectAllNodes() = 0; 0283 0284 // this should be overridden in {Flow|Circuit}ICNDocument 0285 ConnectorList m_connectorList; 0286 CNItemGroup *m_selectList; // Selected objects 0287 0288 // OVERLOADED 0289 KtlQCanvasItemList m_itemDeleteList; // List of canvas items to be deleted 0290 0291 private: 0292 Cells *m_cells; 0293 GuardedNodeGroupList m_nodeGroupList; 0294 }; 0295 0296 /** 0297 @author David Saxton 0298 */ 0299 class DirCursor 0300 { 0301 public: 0302 static DirCursor *self(); 0303 ~DirCursor(); 0304 0305 static QPixmap leftArrow() 0306 { 0307 return self()->m_leftArrow; 0308 } 0309 0310 static QPixmap rightArrow() 0311 { 0312 return self()->m_rightArrow; 0313 } 0314 0315 static QPixmap upArrow() 0316 { 0317 return self()->m_upArrow; 0318 } 0319 0320 static QPixmap downArrow() 0321 { 0322 return self()->m_downArrow; 0323 } 0324 0325 protected: 0326 DirCursor(); 0327 void initCursors(); 0328 0329 static DirCursor *m_self; 0330 QPixmap m_leftArrow; 0331 QPixmap m_rightArrow; 0332 QPixmap m_upArrow; 0333 QPixmap m_downArrow; 0334 }; 0335 0336 #endif