File indexing completed on 2024-10-13 10:59:26
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 ITEMDOCUMENT_H 0012 #define ITEMDOCUMENT_H 0013 0014 #include "canvasitems.h" 0015 #include <canvas.h> 0016 #include <document.h> 0017 #include <set> 0018 0019 #include <QMap> 0020 #include <QStack> 0021 // #include <q3valuevector.h> 0022 0023 class Canvas; 0024 class CanvasTip; 0025 class Connector; 0026 class CMManager; 0027 class ECNode; 0028 class Item; 0029 class ItemDocumentData; 0030 class ItemGroup; 0031 class KTechlab; 0032 class Operation; 0033 0034 class KActionMenu; 0035 class KtlQCanvasItem; 0036 0037 typedef QStack<ItemDocumentData *> IDDStack; 0038 typedef QPointer<Item> GuardedItem; 0039 typedef QMap<int, GuardedItem> IntItemMap; 0040 typedef QMap<QString, Item *> ItemMap; 0041 typedef QList<GuardedItem> ItemList; 0042 typedef QList<QPoint> QPointList; 0043 0044 /** 0045 @author David Saxton 0046 */ 0047 class ItemDocument : public Document 0048 { 0049 Q_OBJECT 0050 0051 friend class KtlTestsAppFixture; 0052 0053 public: 0054 ItemDocument(const QString &caption); 0055 ~ItemDocument() override; 0056 0057 class Z 0058 { 0059 public: 0060 enum { 0061 Select = 10000000, 0062 Connector = 20000000, 0063 Item = 30000000, 0064 RaisedItem = 40000000, 0065 ResizeHandle = 50000000, 0066 Tip = 60000000, 0067 ConnectorCreateLine = 70000000, 0068 0069 // How much "Z" separates items stacked on each other 0070 DeltaItem = 10000 0071 }; 0072 }; 0073 0074 /** 0075 * Some things (such as the canvas getting resized, connectors being 0076 * invalidated, need to be done after editing operations have finished, 0077 * etc, and they also need to be done in the order given in the 0078 * enumeration below. 0079 */ 0080 class ItemDocumentEvent 0081 { 0082 public: 0083 enum type { ResizeCanvasToItems = 1 << 0, UpdateNodeGroups = 1 << 1, RerouteInvalidatedConnectors = 1 << 2, UpdateZOrdering = 1 << 3 }; 0084 }; 0085 0086 void fileSave() override; 0087 void fileSaveAs() override; 0088 void print() override; 0089 bool openURL(const QUrl &url) override; 0090 /** 0091 * Attempt to register the item, returning true iff successful 0092 */ 0093 virtual bool registerItem(KtlQCanvasItem *qcanvasItem); 0094 /** 0095 * Will attempt to create an item with the given id at position p. Some item 0096 * (such as PIC/START) have restrictions, and can only have one instance of 0097 * themselves on the canvas, and adds the operation to the undo list 0098 */ 0099 virtual Item *addItem(const QString &id, const QPoint &p, bool newItem) = 0; 0100 /** 0101 * @returns A pointer to the canvas 0102 */ 0103 Canvas *canvas() const 0104 { 0105 return m_canvas; 0106 } 0107 /** 0108 * Attemtps to register a unique id for the canvas view of an item on the 0109 * canvas. If the id does not already exist, will return true; otherwise 0110 * the function will return false. 0111 */ 0112 bool registerUID(const QString &uid); 0113 /** 0114 * Generates a unique id based on a possibly unique component name. 0115 */ 0116 QString generateUID(QString name); 0117 /** 0118 * Unlists the given id as one that is used. 0119 * @see registerUID 0120 */ 0121 virtual void unregisterUID(const QString &uid); 0122 /** 0123 * @return Whether or not the item is valid; i.e. is appropriate to the 0124 * document being edited, and does not have other special restrictions 0125 * on it (such as only allowing one instance of the Start part in 0126 * FlowCode). 0127 */ 0128 virtual bool isValidItem(Item *item) = 0; 0129 /** 0130 * @return Whether or not the item is valid; i.e. is appropriate to the 0131 * document being edited, and does not have other special restrictions 0132 * on it (such as only allowing one instance of the Start part in 0133 * FlowCode). 0134 */ 0135 virtual bool isValidItem(const QString &itemId) = 0; 0136 /** 0137 * Increases the "height" of the given list of items by "one". 0138 */ 0139 void raiseZ(const ItemList &itemList); 0140 /** 0141 * Decreases the "height" of the given list of items by "one". 0142 */ 0143 void lowerZ(const ItemList &itemList); 0144 /** 0145 * @return ItemGroup that is used as the select list for this document. 0146 */ 0147 virtual ItemGroup *selectList() const = 0; 0148 /** 0149 * Deselects any currently selected items 0150 */ 0151 void unselectAll(); 0152 /** 0153 * Select a list of KtlQCanvasItem's 0154 */ 0155 void select(const KtlQCanvasItemList &list); 0156 /** 0157 * Select a KtlQCanvasItem 0158 */ 0159 void select(KtlQCanvasItem *item); 0160 /** 0161 * Unselects the item 0162 */ 0163 void unselect(KtlQCanvasItem *qcanvasItem); 0164 /** 0165 * Deletes anything waiting to be deleted. 0166 */ 0167 virtual void flushDeleteList() = 0; 0168 /** 0169 * Returns a rubber-band rectangle that contains all of the items on the 0170 * canvas, padded out by a small border. 0171 */ 0172 QRect canvasBoundingRect() const; 0173 /** 0174 * Returns a pointer to a Item on the canvas with the given id, 0175 * or nullptr if no such Item exists. 0176 */ 0177 Item *itemWithID(const QString &); 0178 /** 0179 * Returns true if the user can perform an undo action 0180 * (i.e. the undo stack is not empty) 0181 */ 0182 bool isUndoAvailable() const override; 0183 /** 0184 * Returns true if the user can perform an redo action 0185 * (i.e. the redo stack is not empty) 0186 */ 0187 bool isRedoAvailable() const override; 0188 /** 0189 * Returns the top item at point (x, y), or nullptr if there is no item there 0190 */ 0191 KtlQCanvasItem *itemAtTop(const QPoint &pos) const; 0192 /** 0193 * Called when the canvas is clicked on with the right mouse button. 0194 * Popups up a menu for editing operations 0195 */ 0196 virtual void canvasRightClick(const QPoint &pos, KtlQCanvasItem *item); 0197 /** 0198 * List of items in the ItemDocument 0199 */ 0200 ItemList itemList() const; 0201 /** 0202 * Set the given KtlQCanvasItem (which will attempt to be casted to known 0203 * items to be deleted. 0204 */ 0205 virtual void appendDeleteList(KtlQCanvasItem *) = 0; 0206 /** 0207 * Save the current state of the document to the undo/redo history. 0208 * @param actionTicket if this is non-negative, and the last state save 0209 * also had the same actionTicket, then the next state save will 0210 * overwrite the previous state save. 0211 * @see getActionTicket 0212 */ 0213 void requestStateSave(int actionTicket = -1); 0214 0215 /** 0216 * Clears the undo / redo history 0217 */ 0218 void clearHistory(); 0219 /** 0220 * Requests an event to be done after other stuff (editing, etc) is finished. 0221 */ 0222 void requestEvent(ItemDocumentEvent::type type); 0223 /** 0224 * Called from Canvas (when KtlQCanvas::advance is called). 0225 */ 0226 virtual void update(); 0227 0228 /** 0229 * Returns a unique id, for use in requestStateSave 0230 */ 0231 int getActionTicket() const 0232 { 0233 return m_nextActionTicket++; 0234 } 0235 0236 public slots: 0237 void undo() override; 0238 void redo() override; 0239 void cut() override; 0240 void paste() override; 0241 /** 0242 * Ask the canvas to be resized to the current items on the canvas. 0243 */ 0244 void requestCanvasResize(); 0245 /** 0246 * Selects everything in the view. 0247 */ 0248 void selectAll() override = 0; 0249 /** 0250 * Increases the "height" of the selected items. 0251 */ 0252 void raiseZ(); 0253 /** 0254 * Decreases the "height" of the selected items. 0255 */ 0256 void lowerZ(); 0257 /** 0258 * Brings up a file dialog requesting the location of the file to export 0259 * to, and then exports an image of the canvas. 0260 */ 0261 void exportToImage(); 0262 0263 protected: 0264 void exportToImageDraw(const QRect &saveArea, QPaintDevice &pDev); 0265 public slots: 0266 /** 0267 * Deletes whatever is selected. 0268 */ 0269 virtual void deleteSelection() {}; 0270 /** 0271 * Called when the user presses Escape (or similar) 0272 */ 0273 void cancelCurrentOperation(); 0274 /** 0275 * Sets the y-positions of the selected items to the average of the 0276 * initial y-positions. 0277 */ 0278 0279 // TODO: decide whether these should be moved to ICNdocument... 0280 void alignHorizontally(); 0281 /** 0282 * Sets the x-positions of the selected items to the average of the 0283 * initial x-positions. 0284 */ 0285 void alignVertically(); 0286 /** 0287 * Averages out the horizontal spacing between the selected items. 0288 */ 0289 void distributeHorizontally(); 0290 /** 0291 * Averages out the vertical spacing between the selected items. 0292 */ 0293 void distributeVertically(); 0294 /** 0295 * Adds an items not in the Z ordering to the ordering, and removes any 0296 * items from the Z ordering if they have parents. Then, calls all items 0297 * found in the ordering to tell them their Z position. 0298 */ 0299 // ################## 0300 0301 void slotUpdateZOrdering(); 0302 /** 0303 * Call this with ItemDocument::DrawAction to start drawing the given thing 0304 */ 0305 void slotSetDrawAction(QAction *selected); 0306 /** 0307 * Sets the editing mode to repeatedly creating a CNItem 0308 * with the given id. Usually called when the user double-clicks on 0309 * the component box. 0310 */ 0311 void slotSetRepeatedItemId(const QString &id); 0312 /** 0313 * Unsets the editing mode from repeatedly creating a CNItem 0314 */ 0315 void slotUnsetRepeatedItemId(); 0316 /** 0317 * Called when the user changes the configuration. 0318 * This, for example, will tell the CNItems on the canvas to update 0319 * their configuration. 0320 */ 0321 void slotUpdateConfiguration() override; 0322 /** 0323 * Enables / disables / selects various actions depending on 0324 * what is selected or not. 0325 */ 0326 virtual void slotInitItemActions(); 0327 /** 0328 * Process queued events (see ItemDocument::ItemDocumentEvent). 0329 */ 0330 void processItemDocumentEvents(); 0331 0332 signals: 0333 /** 0334 * Emitted when the selection changes. 0335 */ 0336 void selectionChanged(); 0337 0338 protected slots: 0339 /** 0340 * Called after the canvas is resized to set the scrollbars of the 0341 * ItemViews to either always show or always hidden. 0342 */ 0343 void updateItemViewScrollbars(); 0344 0345 protected: 0346 /** 0347 * Called from registerItem when a new item is added. 0348 */ 0349 virtual void itemAdded(Item *item); 0350 void handleNewView(View *view) override; 0351 /** 0352 * Set to true to remove buttons and grid and so on from the canvas, set false to put them back 0353 */ 0354 void setSVGExport(bool svgExport); 0355 void writeFile(); 0356 /** 0357 * Reinherit this if you want to add any options to the right-click context 0358 */ 0359 virtual void fillContextMenu(const QPoint &pos); 0360 /** 0361 * Reads the background settings (grid-colour, underlying colour) from the Config settings, 0362 * and generates the background pixmap from those settings 0363 */ 0364 void updateBackground(); 0365 /** 0366 * Sets the canvas size to both (a) containing all items present on the 0367 * canvas, and (b) no smaller than the smallest view of the canvas. This 0368 * function should only be called by processItemDocumentEvents - a resize 0369 * request must be made with requestEvent. 0370 */ 0371 void resizeCanvasToItems(); 0372 0373 Canvas *m_canvas; 0374 0375 CMManager *m_cmManager; 0376 CanvasTip *m_canvasTip; 0377 0378 ItemList m_itemDeleteList; 0379 ItemMap m_itemList; 0380 0381 QString m_fileExtensionInfo; // For displaying in the save file dialog 0382 QString m_fileExtensionValue; // saving files enforces this file extension 0383 0384 private: 0385 /** 0386 * This clears a given stack and deletes all pointers, but the one to m_currentState. 0387 */ 0388 void cleanClearStack(IDDStack &stack); 0389 0390 static int m_nextActionTicket; 0391 0392 unsigned m_queuedEvents; // OR'ed together list of ItemDocumentEvent::type 0393 unsigned m_nextIdNum; 0394 int m_currentActionTicket; 0395 bool m_bIsLoading; 0396 0397 ItemDocumentData *m_currentState; 0398 ItemDocumentData *m_savedState; // Pointer to the document data that holds the state when it saved 0399 0400 KActionMenu *m_pAlignmentAction; 0401 0402 IntItemMap m_zOrder; 0403 0404 std::set<QString> m_idList; // used to ensure unique IDs to try to make sure save files are valid. 0405 0406 QTimer *m_pEventTimer; 0407 QTimer *m_pUpdateItemViewScrollbarsTimer; 0408 0409 IDDStack m_undoStack; 0410 IDDStack m_redoStack; 0411 0412 friend class ICNView; 0413 friend class ItemView; 0414 }; 0415 0416 /** 0417 @author David Saxton 0418 */ 0419 class Canvas : public KtlQCanvas 0420 { 0421 Q_OBJECT 0422 public: 0423 Canvas(ItemDocument *itemDocument); 0424 0425 /** 0426 * Sets a message to be displayed on the canvas for a brief period of 0427 * time. If this is called with an empty message, then any existing 0428 * message will be removed. 0429 */ 0430 void setMessage(const QString &message); 0431 void update() override; 0432 void resize(const QRect &size) override; 0433 0434 signals: 0435 /** 0436 * Emitted when the canvas rectangle-size changes. 0437 */ 0438 void resized(const QRect &oldSize, const QRect &newSize); 0439 0440 public slots: 0441 void slotSetAllChanged() 0442 { 0443 setAllChanged(); 0444 } 0445 0446 protected: 0447 void drawBackground(QPainter &painter, const QRect &clip) override; 0448 void drawForeground(QPainter &painter, const QRect &clip) override; 0449 0450 ItemDocument *p_itemDocument; 0451 0452 QString m_message; 0453 QTimer *m_pMessageTimeout; 0454 }; 0455 0456 /** 0457 @author David Saxton 0458 */ 0459 class CanvasTip : public KtlQCanvasRectangle 0460 { 0461 public: 0462 CanvasTip(ItemDocument *itemDocument, KtlQCanvas *qcanvas); 0463 ~CanvasTip() override; 0464 0465 void displayVI(ECNode *node, const QPoint &pos); 0466 void displayVI(Connector *connector, const QPoint &pos); 0467 0468 protected: 0469 void draw(QPainter &p) override; 0470 void setText(const QString &text); 0471 bool updateVI(); 0472 void display(const QPoint &pos); 0473 QString displayText(unsigned num) const; 0474 0475 QVector<double> m_v; 0476 QVector<double> m_i; 0477 ItemDocument *p_itemDocument; 0478 QString m_text; 0479 }; 0480 0481 #endif