-
-
Notifications
You must be signed in to change notification settings - Fork 118
/
Copy pathschematic.h
573 lines (490 loc) · 21 KB
/
schematic.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
/***************************************************************************
schematic.h
-------------
begin : Sat Mar 11 2006
copyright : (C) 2006 by Michael Margraf
email : michael.margraf@alumni.tu-berlin.de
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef SCHEMATIC_H
#define SCHEMATIC_H
// maybe in another place...
#ifdef NDEBUG
// cast without overhead
# define prechecked_cast static_cast
#else
// cast safely, for debugging purposes
# define prechecked_cast dynamic_cast
#endif
#include "wire.h"
#include "node.h"
#include "qucsdoc.h"
#include "diagrams/diagram.h"
#include "paintings/painting.h"
#include "components/component.h"
#include "wire_planner.h"
#include "qt3_compat/qt_compat.h"
#include "qt3_compat/q3scrollview.h"
#include <QVector>
#include <QStringList>
#include <QFileInfo>
class QTextStream;
class QTextEdit;
class QPlainTextEdit;
class QDragMoveEvent;
class QDropEvent;
class QDragLeaveEvent;
class QWheelEvent;
class QMouseEvent;
class QDragEnterEvent;
class QPainter;
// digital signal data
struct DigSignal {
DigSignal() { Name=""; Type=""; }
DigSignal(const QString& _Name, const QString& _Type = "")
: Name(_Name), Type(_Type) {}
QString Name; // name
QString Type; // type of signal
};
typedef QMap<QString, DigSignal> DigMap;
typedef enum {_NotRop, _Rect, _SelectionRect, _Line, _Ellipse, _Arc, _DotLine, _DotRect, _Translate, _Scale} PE;
typedef struct {PE pe; int x1; int y1;int x2;int y2;int a; int b; bool PaintOnViewport;}PostedPaintEvent;
// subcircuit, vhdl, etc. file structure
struct SubFile {
SubFile() { Type=""; File=""; PortTypes.clear(); }
SubFile(const QString& _Type, const QString& _File)
: Type(_Type), File(_File) { PortTypes.clear(); }
QString Type; // type of file
QString File; // file name identifier
QStringList PortTypes; // data types of in/out signals
};
typedef QMap<QString, SubFile> SubMap;
class Schematic : public Q3ScrollView, public QucsDoc {
Q_OBJECT
public:
Schematic(QucsApp*, const QString&);
~Schematic();
void setName(const QString&);
void setChanged(bool, bool fillStack=false, char Op='*');
void print(QPrinter*, QPainter*, bool printAll, bool fitToPage, QMargins margins={});
void paintSchToViewpainter(QPainter* painter, bool printAll);
void PostPaintEvent(PE pe, int x1=0, int y1=0, int x2=0, int y2=0, int a=0, int b=0,bool PaintOnViewport=false);
bool sizeOfFrame(int&, int&);
/**
Iterates over all elements of schematic to find the size of the smallest
rectangle able to fit all elements. The bounds are then stored in members
@c UsedX1, @c UsedY1, @c UsedX2, @c UsedY2 , i.e. the internal state
of schematic is updated.
*/
void updateAllBoundingRect();
/**
Returns the smallest rectangle enclosing all elements of schematic
*/
QRect allBoundingRect();
struct Selection {
QRect bounds;
std::vector<Component*> components;
std::vector<Wire*> wires;
std::vector<Painting*> paintings;
std::vector<Diagram*> diagrams;
std::vector<WireLabel*> labels;
std::vector<Marker*> markers;
std::vector<Node*> nodes;
};
Selection currentSelection() const;
bool rotateElements();
bool mirrorXComponents();
bool mirrorYComponents();
QPoint setOnGrid(const QPoint& p);
void setOnGrid(int&, int&);
bool elementsOnGrid();
/**
Zoom around a "zooming center". Zooming center is a point on the canvas,
which doesn't move relative to a viewport while canvas is being zoomed in or
out.
This produces the effect of "concentrating" on a zooming center: with each
zoom-in step one would get closer and closer to the point, while point's
surroundings would go "out of sight", beyound the viewport's borders.
Zooming out works in backwards order: everything is like being "sucked into"
the zooming center.
If param \c viewportRelative is \c true then the given coordinates are
treated as relative to the viewport top-left corner. Otherwise they're
considered to be absolute i.e. relative to canvas top-left corner.
@param scaleChange a multiplier for a current scale value
@param coords coordinates of the "zooming center"
@param viewportRelative tells if coordinates are absolute or relative to viewport
*/
void zoomAroundPoint(double scaleChange, QPoint coords, bool viewportRelative);
float zoomBy(float);
void showAll();
void zoomToSelection();
void showNoZoom();
void enlargeView(int, int, int, int);
void switchPaintMode();
int adjustPortNumbers();
int orderSymbolPorts();
void reloadGraphs();
bool createSubcircuitSymbol();
/**
@brief Given cordinates of a model point returns coordinates of this point
relative to viewport. It's a reverse of @ref Schematic::viewportToModel
*/
QPoint modelToViewport(const QPoint& modelCoordinates);
/**
Given a coordinates of viewport point returns coordinates of the model plane point
displayed at given location of the viewport.
*/
QPoint viewportToModel(const QPoint& viewportCoordinates);
/**
Given coordinates of a point on the view plane (schematic's canvas), this method
returns coordinates of a corresponding point on the model plane.
@param viewCoordinates a point on the view plane
@return a corresponding point on the model plane
*/
QPoint contentsToModel(const QPoint& viewCoordinates);
/**
Given coordinates of a point on the model plane, this method returns coordinates
of a corresponding point on the view plane (schematic's canvas).
@param modelCoordinates a point on the model plane
@return a corresponding point on the view plane
*/
QPoint modelToContents(const QPoint& modelCoordinates);
void cut();
void copy();
bool paste(QTextStream*, QList<Element*>*);
bool load();
int save();
int saveSymbolCpp (void);
int saveSymbolJSON (void);
int savePropsJSON (void);
void becomeCurrent(bool);
bool undo();
bool redo();
void scrollUp(int);
void scrollDown(int);
void scrollLeft(int);
void scrollRight(int);
bool checkDplAndDatNames();
/*! \brief Get (schematic) file reference */
QFileInfo getFileInfo (void) { return a_FileInfo; }
/*! \brief Set reference to file (schematic) */
void setFileInfo(QString FileName) { a_FileInfo = QFileInfo(FileName); }
QString getFrame_Text0() const { return a_Frame_Text0; }
void setFrame_Text0(const QString value) { a_Frame_Text0 = value; }
QString getFrame_Text1() const { return a_Frame_Text1; }
void setFrame_Text1(const QString value) { a_Frame_Text1 = value; }
QString getFrame_Text2() const { return a_Frame_Text2; }
void setFrame_Text2(const QString value) { a_Frame_Text2 = value; }
QString getFrame_Text3() const { return a_Frame_Text3; }
void setFrame_Text3(const QString value) { a_Frame_Text3 = value; }
int getShowFrame() const { return a_showFrame; }
void setShowFrame(int value) { a_showFrame = value; }
int getViewX1() const { return a_ViewX1; }
int getViewY1() const { return a_ViewY1; }
int getGridX() const { return a_GridX; }
void setGridX(int value) { a_GridX = value; }
int getGridY() const { return a_GridY; }
void setGridY(int value) { a_GridY = value; }
void setGridColor(const QColor& color) { a_GridColor = color; }
QColor getGridColor() const { return a_GridColor; }
bool getSymbolMode() const { return a_symbolMode; }
void setSymbolMode(bool value) { a_symbolMode = value; }
bool getIsSymbolOnly() const { return a_isSymbolOnly; }
void setIsSymbolOnly(bool value) { a_isSymbolOnly = value; }
void clearPostedPaintEvents() { a_PostedPaintEvents.clear(); }
// The pointers points to the current lists, either to the schematic
// elements "Doc..." or to the symbol elements "SymbolPaints".
Q3PtrList<Wire> *a_Wires;
Q3PtrList<Wire> a_DocWires;
Q3PtrList<Node>* a_Nodes;
Q3PtrList<Node> a_DocNodes;
Q3PtrList<Diagram>* a_Diagrams;
Q3PtrList<Diagram> a_DocDiags;
Q3PtrList<Painting>* a_Paintings;
Q3PtrList<Painting> a_DocPaints;
Q3PtrList<Component>* a_Components;
Q3PtrList<Component> a_DocComps;
Q3PtrList<Painting> a_SymbolPaints; // symbol definition for subcircuit
private:
QList<PostedPaintEvent> a_PostedPaintEvents;
bool a_symbolMode; // true if in symbol painting mode
bool a_isSymbolOnly;
// Horizontal and vertical grid step, grid color.
int a_GridX;
int a_GridY;
QColor a_GridColor;
// Variables View* are the coordinates of top-level and bottom-right corners
// of a rectangle representing the schematic "model". This
// rectangle may grow and shrink when user scrolls the view, and its
// coordinates change accordingly. Everything (elements, wires, etc.) lies
// inside this rectangle. The size of this rectangle is the "logical" size
// of the schematic. The comment in "renderModel" method describes how
// these variables ("model") is used to draw the scematic.
int a_ViewX1;
int a_ViewY1;
int a_ViewX2;
int a_ViewY2;
int a_showFrame;
QString a_Frame_Text0;
QString a_Frame_Text1;
QString a_Frame_Text2;
QString a_Frame_Text3;
// Two of those data sets are needed for Schematic and for symbol.
// Which one is in "tmp..." depends on "symbolMode".
float a_tmpScale;
int a_tmpViewX1;
int a_tmpViewY1;
int a_tmpViewX2;
int a_tmpViewY2;
int a_tmpUsedX1;
int a_tmpUsedY1;
int a_tmpUsedX2;
int a_tmpUsedY2;
int a_undoActionIdx;
QVector<QString *> a_undoAction;
int a_undoSymbolIdx;
QVector<QString *> a_undoSymbol; // undo stack for circuit symbol
signals:
void signalCursorPosChanged(int, int, QString);
void signalUndoState(bool);
void signalRedoState(bool);
void signalFileChanged(bool);
void signalComponentDeleted(Component *);
protected:
// overloaded function to get actions of user
void drawContents(QPainter*, int, int, int, int)override;
void contentsMouseMoveEvent(QMouseEvent*)override;
void contentsMousePressEvent(QMouseEvent*)override;
void contentsMouseDoubleClickEvent(QMouseEvent*)override;
void contentsMouseReleaseEvent(QMouseEvent*)override;
void contentsWheelEvent(QWheelEvent*)override;
void contentsDropEvent(QDropEvent*)override;
void contentsDragEnterEvent(QDragEnterEvent*)override;
void contentsDragLeaveEvent(QDragLeaveEvent*)override;
void contentsDragMoveEvent(QDragMoveEvent*)override;
void contentsNativeGestureZoomEvent( QNativeGestureEvent* ) override;
protected slots:
void slotScrollUp();
void slotScrollDown();
void slotScrollLeft();
void slotScrollRight();
private:
// Variables Used* hold the coordinates of top-left and bottom-right corners
// of a smallest rectangle which can fit all elements of the schematic.
// This rectangle exists in the same coordinate system as View*-rectangle
int a_UsedX1;
int a_UsedY1;
int a_UsedX2;
int a_UsedY2;
void sizeOfAll(int&, int&, int&, int&);
// Viewport-realative coordinates of the cursor between mouse movements.
// Used in "pan with mouse" feature.
QPoint a_previousCursorPosition;
bool a_dragIsOkay;
/*! \brief hold system-independent information about a schematic file */
QFileInfo a_FileInfo;
/**
Minimum scale at which schematic could be drawn.
*/
static constexpr double a_minScale = 0.1;
/**
Maximum scale at which schematic could be drawn.
*/
static constexpr double a_maxScale = 10.0;
/**
Returns a rectangle which describes the model plane of the schematic.
The rectangle is a copy, changes made to it do not affect schematic state.
*/
QRect modelRect();
/**
Returns a rectangle which describes the viewport. Top-left corner is (0,0),
width and height are equal to viewport's width and height.
*/
QRect viewportRect();
/**
If given value violates lower or upper scale limit, then returns
the limit value, original value otherwise.
*/
static double clipScale(double);
/**
Tells whether the model should be rerendered. Model should be rendered
if the given scale differs from the current one or if the point displayed
at \a viewportCoords in the viewport differs from the point \a modelCoords.
Otherwise there is no changes and no need to rerender.
@param scale desired scale
@param newModelBounds a rectangle describing the desired model bounds
@param modelCoords coordinates of a point on the model plane
@param viewportCoords coordinates of a point in the viewport.
*/
bool shouldRender(const double& scale, const QRect& newModelBounds, const QPoint& modelCoords, const QPoint& viewportCoords);
/**
Renders schematic model on Q3ScrollView's contents at a given scale,
and positions the contents so that the point \a modelPlaneCoords of the
model is displayed at location \a viewportCoords of the viewport.
There is no need to call "update" on Q3ScrollView after using this method.
It is done as a part of rendering process.
Usage examples:
1. Imagine you want to handle user's right scroll and you want scrolling
to be infinite. Each scroll has to "stretch" schematic model to the right.
First step is to take current model and create a new desired
model size from it by shifting its right bound.
After scrolling you want rightmost point of the model to be diplayed
at right bound of the viewport. Then second step is to take coordinates
of top-right corner of @b new @b desired model and coordinates of top-rigth
corner of viewport and pass to @c renderModel along with new model:
@code
renderModel(sameScale, newModel, newModel.topRight(), viewportRect().topRight());
@endcode
2. Suppose you want to zoom at some element, so that its center would be
displayed at the center of the viewport after zooming.
First, find coordinates of the element center
Second, find coordinates of the viewport center
Third, call @c renderModel:
@code
renderModel(zoomScale, sameModel, elementCenter, viewportRect().center());
@endcode
3. Imagine you want to scroll and zoom so that the point currently
displayed at the center of the viewport would be at the viewport
top-left corner after.
@code
renderModel(zoomScale, sameModel, viewportToModel(viewportRect().center()), viewportRect.topLeft());
@endcode
@param scale desired new scale. It is clipped when exceeds
a lower or upperlimit
@param newModelBounds a rectangle describing the desired model bounds
@param modelPlaneCoords coordinates of a point somewhere within
\a newModelBounds
@param viewportCoords coordinates of the point on the viewport where
\a modelPlaneCoords should be placed after rendering
@return new scale value
*/
double renderModel(double scale, QRect newModelBounds, QPoint modelPlaneCoords, QPoint viewportCoords);
void drawElements(QPainter* painter);
void drawDcBiasPoints(QPainter* painter);
void drawPostPaintEvents(QPainter* painter);
void paintFrame(QPainter* painter);
void drawGrid(QPainter* painter);
void relativeRotation(int &x, int &y, int comX, int comY, int posX, int posY);
/* ********************************************************************
***** The following methods are in the file *****
***** "schematic_element.cpp". They only access the QPtrList *****
***** pointers "Wires", "Nodes", "Diagrams", "Paintings" and *****
***** "Components". *****
******************************************************************** */
public:
Node* insertNode(int, int, Element*);
Node* selectedNode(int, int);
qucs_s::wire::Planner a_wirePlanner;
std::pair<bool,Node*> connectWithWire(const QPoint& a, const QPoint& b) noexcept;
void showEphemeralWire(const QPoint& a, const QPoint& b) noexcept;
int insertWireNode1(Wire*);
bool connectHWires1(Wire*);
bool connectVWires1(Wire*);
int insertWireNode2(Wire*);
bool connectHWires2(Wire*);
bool connectVWires2(Wire*);
int insertWire(Wire*);
void selectWireLine(Element*, Node*, bool);
Wire* selectedWire(int, int);
Wire* splitWire(Wire*, Node*);
bool oneTwoWires(Node*);
void deleteWire(Wire*);
Marker* setMarker(int, int);
void markerLeftRight(bool, QList<Element*>*);
void markerUpDown(bool, QList<Element*>*);
Element* selectElement(float, float, bool, int *index=0);
void deselectElements(Element*) const;
int selectElements(const QRect&, bool, bool) const;
void selectMarkers() const;
void newMovingWires(Q3PtrList<Element>*, Node*, int) const;
int copySelectedElements(Q3PtrList<Element>*);
bool deleteElements();
bool aligning(int);
bool distributeHorizontal();
bool distributeVertical();
void setComponentNumber(Component*);
void insertRawComponent(Component*, bool noOptimize=true);
void recreateComponent(Component*);
void insertComponent(Component*);
void activateCompsWithinRect(int, int, int, int);
bool activateSpecifiedComponent(int, int);
bool activateSelectedComponents();
void setCompPorts(Component*);
Component* selectCompText(int, int, int&, int&) const;
Component* searchSelSubcircuit();
Component* selectedComponent(int, int);
void deleteComp(Component*);
Component* getComponentByName(const QString& compname) const;
void oneLabel(Node*);
int placeNodeLabel(WireLabel*);
Element* getWireLabel(Node*);
void insertNodeLabel(WireLabel*);
void copyLabels(int&, int&, int&, int&, QList<Element *> *);
Painting* selectedPainting(float, float);
void copyPaintings(int&, int&, int&, int&, QList<Element *> *);
private:
void insertComponentNodes(Component*, bool);
int copyWires(int&, int&, int&, int&, QList<Element *> *);
int copyComponents(int&, int&, int&, int&, QList<Element *> *);
void copyComponents2(int&, int&, int&, int&, QList<Element *> *);
bool copyComps2WiresPaints(int&, int&, int&, int&, QList<Element *> *);
int copyElements(int&, int&, int&, int&, QList<Element *> *);
/* ********************************************************************
***** The following methods are in the file *****
***** "schematic_file.cpp". They only access the QPtrLists *****
***** and their pointers. ("DocComps", "Components" etc.) *****
******************************************************************** */
public:
static int testFile(const QString &);
bool createLibNetlist(QTextStream*, QPlainTextEdit*, int);
bool createSubNetlist(QTextStream *, int&, QStringList&, QPlainTextEdit*, int);
void createSubNetlistPlain(QTextStream*, QPlainTextEdit*, int);
int prepareNetlist(QTextStream&, QStringList&, QPlainTextEdit*);
QString createNetlist(QTextStream&, int);
bool isDigitalCircuit();
bool loadDocument();
void highlightWireLabels (void);
void clearSignalsAndFileList();
void clearSignals();
void setIsAnalog(bool value) { a_isAnalog = value; }
bool getIsAnalog() const { return a_isAnalog; }
void setIsVerilog(bool value) { a_isVerilog = value; }
bool getIsVerilog() const { return a_isVerilog; }
bool giveNodeNames(QTextStream *, int&, QStringList&, QPlainTextEdit*, int);
private:
int saveDocument();
bool loadProperties(QTextStream*);
void simpleInsertComponent(Component*);
bool loadComponents(QTextStream*, QList<Component*> *List=0);
void simpleInsertWire(Wire*);
bool loadWires(QTextStream*, QList<Element*> *List=0);
bool loadDiagrams(QTextStream*, QList<Diagram*>*);
bool loadPaintings(QTextStream*, QList<Painting*>*);
bool loadIntoNothing(QTextStream*);
QString createClipboardFile();
bool pasteFromClipboard(QTextStream *, QList<Element*>*);
QString createUndoString(char);
bool rebuild(QString *);
QString createSymbolUndoString(char);
bool rebuildSymbol(QString *);
static void createNodeSet(QStringList&, int&, Conductor*, Node*);
void throughAllNodes(bool, QStringList&, int&);
void propagateNode(QStringList&, int&, Node*);
void collectDigitalSignals(void);
void beginNetlistDigital(QTextStream &);
void endNetlistDigital(QTextStream &);
bool throughAllComps(QTextStream *, int&, QStringList&, QPlainTextEdit *, int);
DigMap a_Signals; // collecting node names for VHDL signal declarations
QStringList a_PortTypes;
bool a_isAnalog;
bool a_isVerilog;
bool a_creatingLib;
};
#endif