Qucs-GUI  0.0.18
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
schematic_element.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  schematic_element.cpp
3  -----------------------
4  begin : Sat Mar 3 2006
5  copyright : (C) 2006 by Michael Margraf
6  email : michael.margraf@alumni.tu-berlin.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 #include <QtGui>
18 #include <stdlib.h>
19 #include <string>
20 #include <limits.h>
21 
22 #include "schematic.h"
23 #include "node.h"
24 #include "wire.h"
25 #include "diagrams/diagram.h"
26 #include "paintings/painting.h"
27 #include "components/component.h"
28 //Added by qt3to4:
29 #include <Q3PtrList>
30 
31 
32 
33 /* *******************************************************************
34  ***** *****
35  ***** Actions handling the nodes *****
36  ***** *****
37  ******************************************************************* */
38 
39 // Inserts a port into the schematic and connects it to another node if
40 // the coordinates are identical. The node is returned.
42 {
43  Node *pn;
44  // check if new node lies upon existing node
45  for(pn = Nodes->first(); pn != 0; pn = Nodes->next()) // check every node
46  if(pn->cx == x) if(pn->cy == y)
47  {
48  pn->Connections.append(e);
49  break;
50  }
51 
52  if(pn == 0) // create new node, if no existing one lies at this position
53  {
54  pn = new Node(x, y);
55  Nodes->append(pn);
56  pn->Connections.append(e); // connect schematic node to component node
57  }
58  else return pn; // return, if node is not new
59 
60  // check if the new node lies upon an existing wire
61  for(Wire *pw = Wires->first(); pw != 0; pw = Wires->next())
62  {
63  if(pw->x1 == x)
64  {
65  if(pw->y1 > y) continue;
66  if(pw->y2 < y) continue;
67  }
68  else if(pw->y1 == y)
69  {
70  if(pw->x1 > x) continue;
71  if(pw->x2 < x) continue;
72  }
73  else continue;
74 
75  // split the wire into two wires
76  splitWire(pw, pn);
77  return pn;
78  }
79 
80  return pn;
81 }
82 
83 // ---------------------------------------------------
85 {
86  for(Node *pn = Nodes->first(); pn != 0; pn = Nodes->next()) // test nodes
87  if(pn->getSelected(x, y))
88  return pn;
89 
90  return 0;
91 }
92 
93 
94 /* *******************************************************************
95  ***** *****
96  ***** Actions handling the wires *****
97  ***** *****
98  ******************************************************************* */
99 
100 // Inserts a port into the schematic and connects it to another node if the
101 // coordinates are identical. If 0 is returned, no new wire is inserted.
102 // If 2 is returned, the wire line ended.
104 {
105  Node *pn;
106  // check if new node lies upon an existing node
107  for(pn = Nodes->first(); pn != 0; pn = Nodes->next()) // check every node
108  if(pn->cx == w->x1) if(pn->cy == w->y1) break;
109 
110  if(pn != 0)
111  {
112  pn->Connections.append(w);
113  w->Port1 = pn;
114  return 2; // node is not new
115  }
116 
117 
118 
119  // check if the new node lies upon an existing wire
120  for(Wire *ptr2 = Wires->first(); ptr2 != 0; ptr2 = Wires->next())
121  {
122  if(ptr2->x1 == w->x1)
123  {
124  if(ptr2->y1 > w->y1) continue;
125  if(ptr2->y2 < w->y1) continue;
126 
127  if(ptr2->isHorizontal() == w->isHorizontal()) // ptr2-wire is vertical
128  {
129  if(ptr2->y2 >= w->y2)
130  {
131  delete w; // new wire lies within an existing wire
132  return 0;
133  }
134  else
135  {
136  // one part of the wire lies within an existing wire
137  // the other part not
138  if(ptr2->Port2->Connections.count() == 1)
139  {
140  w->y1 = ptr2->y1;
141  w->Port1 = ptr2->Port1;
142  if(ptr2->Label)
143  {
144  w->Label = ptr2->Label;
145  w->Label->pOwner = w;
146  }
147  ptr2->Port1->Connections.removeRef(ptr2); // two -> one wire
148  ptr2->Port1->Connections.append(w);
149  Nodes->removeRef(ptr2->Port2);
150  Wires->removeRef(ptr2);
151  return 2;
152  }
153  else
154  {
155  w->y1 = ptr2->y2;
156  w->Port1 = ptr2->Port2;
157  ptr2->Port2->Connections.append(w); // shorten new wire
158  return 2;
159  }
160  }
161  }
162  }
163  else if(ptr2->y1 == w->y1)
164  {
165  if(ptr2->x1 > w->x1) continue;
166  if(ptr2->x2 < w->x1) continue;
167 
168  if(ptr2->isHorizontal() == w->isHorizontal()) // ptr2-wire is horizontal
169  {
170  if(ptr2->x2 >= w->x2)
171  {
172  delete w; // new wire lies within an existing wire
173  return 0;
174  }
175  else
176  {
177  // one part of the wire lies within an existing wire
178  // the other part not
179  if(ptr2->Port2->Connections.count() == 1)
180  {
181  w->x1 = ptr2->x1;
182  w->Port1 = ptr2->Port1;
183  if(ptr2->Label)
184  {
185  w->Label = ptr2->Label;
186  w->Label->pOwner = w;
187  }
188  ptr2->Port1->Connections.removeRef(ptr2); // two -> one wire
189  ptr2->Port1->Connections.append(w);
190  Nodes->removeRef(ptr2->Port2);
191  Wires->removeRef(ptr2);
192  return 2;
193  }
194  else
195  {
196  w->x1 = ptr2->x2;
197  w->Port1 = ptr2->Port2;
198  ptr2->Port2->Connections.append(w); // shorten new wire
199  return 2;
200  }
201  }
202  }
203  }
204  else continue;
205 
206  pn = new Node(w->x1, w->y1); // create new node
207  Nodes->append(pn);
208  pn->Connections.append(w); // connect schematic node to the new wire
209  w->Port1 = pn;
210 
211  // split the wire into two wires
212  splitWire(ptr2, pn);
213  return 2;
214  }
215 
216  pn = new Node(w->x1, w->y1); // create new node
217  Nodes->append(pn);
218  pn->Connections.append(w); // connect schematic node to the new wire
219  w->Port1 = pn;
220  return 1;
221 }
222 
223 // ---------------------------------------------------
224 // if possible, connect two horizontal wires to one
226 {
227  Wire *pw;
228  Node *n = w->Port1;
229 
230  pw = (Wire*)n->Connections.last(); // last connection is the new wire itself
231  for(pw = (Wire*)n->Connections.prev(); pw!=0; pw = (Wire*)n->Connections.prev())
232  {
233  if(pw->Type != isWire) continue;
234  if(!pw->isHorizontal()) continue;
235  if(pw->x1 < w->x1)
236  {
237  if(n->Connections.count() != 2) continue;
238  if(pw->Label)
239  {
240  w->Label = pw->Label;
241  w->Label->pOwner = w;
242  }
243  else if(n->Label)
244  {
245  w->Label = n->Label;
246  w->Label->pOwner = w;
247  w->Label->Type = isHWireLabel;
248  }
249  w->x1 = pw->x1;
250  w->Port1 = pw->Port1; // new wire lengthens an existing one
251  Nodes->removeRef(n);
252  w->Port1->Connections.removeRef(pw);
253  w->Port1->Connections.append(w);
254  Wires->removeRef(pw);
255  return true;
256  }
257  if(pw->x2 >= w->x2) // new wire lies within an existing one ?
258  {
259  w->Port1->Connections.removeRef(w); // second node not yet made
260  delete w;
261  return false;
262  }
263  if(pw->Port2->Connections.count() < 2)
264  {
265  // existing wire lies within the new one
266  if(pw->Label)
267  {
268  w->Label = pw->Label;
269  w->Label->pOwner = w;
270  }
271  pw->Port1->Connections.removeRef(pw);
272  Nodes->removeRef(pw->Port2);
273  Wires->removeRef(pw);
274  return true;
275  }
276  w->x1 = pw->x2; // shorten new wire according to an existing one
277  w->Port1->Connections.removeRef(w);
278  w->Port1 = pw->Port2;
279  w->Port1->Connections.append(w);
280  return true;
281  }
282 
283  return true;
284 }
285 
286 // ---------------------------------------------------
287 // if possible, connect two vertical wires to one
289 {
290  Wire *pw;
291  Node *n = w->Port1;
292 
293  pw = (Wire*)n->Connections.last(); // last connection is the new wire itself
294  for(pw = (Wire*)n->Connections.prev(); pw!=0; pw = (Wire*)n->Connections.prev())
295  {
296  if(pw->Type != isWire) continue;
297  if(pw->isHorizontal()) continue;
298  if(pw->y1 < w->y1)
299  {
300  if(n->Connections.count() != 2) continue;
301  if(pw->Label)
302  {
303  w->Label = pw->Label;
304  w->Label->pOwner = w;
305  }
306  else if(n->Label)
307  {
308  w->Label = n->Label;
309  w->Label->pOwner = w;
310  w->Label->Type = isVWireLabel;
311  }
312  w->y1 = pw->y1;
313  w->Port1 = pw->Port1; // new wire lengthens an existing one
314  Nodes->removeRef(n);
315  w->Port1->Connections.removeRef(pw);
316  w->Port1->Connections.append(w);
317  Wires->removeRef(pw);
318  return true;
319  }
320  if(pw->y2 >= w->y2) // new wire lies complete within an existing one ?
321  {
322  w->Port1->Connections.removeRef(w); // second node not yet made
323  delete w;
324  return false;
325  }
326  if(pw->Port2->Connections.count() < 2)
327  {
328  // existing wire lies within the new one
329  if(pw->Label)
330  {
331  w->Label = pw->Label;
332  w->Label->pOwner = w;
333  }
334  pw->Port1->Connections.removeRef(pw);
335  Nodes->removeRef(pw->Port2);
336  Wires->removeRef(pw);
337  return true;
338  }
339  w->y1 = pw->y2; // shorten new wire according to an existing one
340  w->Port1->Connections.removeRef(w);
341  w->Port1 = pw->Port2;
342  w->Port1->Connections.append(w);
343  return true;
344  }
345 
346  return true;
347 }
348 
349 // ---------------------------------------------------
350 // Inserts a port into the schematic and connects it to another node if the
351 // coordinates are identical. If 0 is returned, no new wire is inserted.
352 // If 2 is returned, the wire line ended.
354 {
355  Node *pn;
356  // check if new node lies upon an existing node
357  for(pn = Nodes->first(); pn != 0; pn = Nodes->next()) // check every node
358  if(pn->cx == w->x2) if(pn->cy == w->y2) break;
359 
360  if(pn != 0)
361  {
362  pn->Connections.append(w);
363  w->Port2 = pn;
364  return 2; // node is not new
365  }
366 
367 
368 
369  // check if the new node lies upon an existing wire
370  for(Wire *ptr2 = Wires->first(); ptr2 != 0; ptr2 = Wires->next())
371  {
372  if(ptr2->x1 == w->x2)
373  {
374  if(ptr2->y1 > w->y2) continue;
375  if(ptr2->y2 < w->y2) continue;
376 
377  // (if new wire lies within an existing wire, was already check before)
378  if(ptr2->isHorizontal() == w->isHorizontal()) // ptr2-wire is vertical
379  {
380  // one part of the wire lies within an existing wire
381  // the other part not
382  if(ptr2->Port1->Connections.count() == 1)
383  {
384  if(ptr2->Label)
385  {
386  w->Label = ptr2->Label;
387  w->Label->pOwner = w;
388  }
389  w->y2 = ptr2->y2;
390  w->Port2 = ptr2->Port2;
391  ptr2->Port2->Connections.removeRef(ptr2); // two -> one wire
392  ptr2->Port2->Connections.append(w);
393  Nodes->removeRef(ptr2->Port1);
394  Wires->removeRef(ptr2);
395  return 2;
396  }
397  else
398  {
399  w->y2 = ptr2->y1;
400  w->Port2 = ptr2->Port1;
401  ptr2->Port1->Connections.append(w); // shorten new wire
402  return 2;
403  }
404  }
405  }
406  else if(ptr2->y1 == w->y2)
407  {
408  if(ptr2->x1 > w->x2) continue;
409  if(ptr2->x2 < w->x2) continue;
410 
411  // (if new wire lies within an existing wire, was already check before)
412  if(ptr2->isHorizontal() == w->isHorizontal()) // ptr2-wire is horizontal
413  {
414  // one part of the wire lies within an existing wire
415  // the other part not
416  if(ptr2->Port1->Connections.count() == 1)
417  {
418  if(ptr2->Label)
419  {
420  w->Label = ptr2->Label;
421  w->Label->pOwner = w;
422  }
423  w->x2 = ptr2->x2;
424  w->Port2 = ptr2->Port2;
425  ptr2->Port2->Connections.removeRef(ptr2); // two -> one wire
426  ptr2->Port2->Connections.append(w);
427  Nodes->removeRef(ptr2->Port1);
428  Wires->removeRef(ptr2);
429  return 2;
430  }
431  else
432  {
433  w->x2 = ptr2->x1;
434  w->Port2 = ptr2->Port1;
435  ptr2->Port1->Connections.append(w); // shorten new wire
436  return 2;
437  }
438  }
439  }
440  else continue;
441 
442  pn = new Node(w->x2, w->y2); // create new node
443  Nodes->append(pn);
444  pn->Connections.append(w); // connect schematic node to the new wire
445  w->Port2 = pn;
446 
447  // split the wire into two wires
448  splitWire(ptr2, pn);
449  return 2;
450  }
451 
452  pn = new Node(w->x2, w->y2); // create new node
453  Nodes->append(pn);
454  pn->Connections.append(w); // connect schematic node to the new wire
455  w->Port2 = pn;
456  return 1;
457 }
458 
459 // ---------------------------------------------------
460 // if possible, connect two horizontal wires to one
462 {
463  Wire *pw;
464  Node *n = w->Port2;
465 
466  pw = (Wire*)n->Connections.last(); // last connection is the new wire itself
467  for(pw = (Wire*)n->Connections.prev(); pw!=0; pw = (Wire*)n->Connections.prev())
468  {
469  if(pw->Type != isWire) continue;
470  if(!pw->isHorizontal()) continue;
471  if(pw->x2 > w->x2)
472  {
473  if(n->Connections.count() != 2) continue;
474  if(pw->Label)
475  {
476  w->Label = pw->Label;
477  w->Label->pOwner = w;
478  }
479  w->x2 = pw->x2;
480  w->Port2 = pw->Port2; // new wire lengthens an existing one
481  Nodes->removeRef(n);
482  w->Port2->Connections.removeRef(pw);
483  w->Port2->Connections.append(w);
484  Wires->removeRef(pw);
485  return true;
486  }
487  // (if new wire lies complete within an existing one, was already
488  // checked before)
489 
490  if(pw->Port1->Connections.count() < 2)
491  {
492  // existing wire lies within the new one
493  if(pw->Label)
494  {
495  w->Label = pw->Label;
496  w->Label->pOwner = w;
497  }
498  pw->Port2->Connections.removeRef(pw);
499  Nodes->removeRef(pw->Port1);
500  Wires->removeRef(pw);
501  return true;
502  }
503  w->x2 = pw->x1; // shorten new wire according to an existing one
504  w->Port2->Connections.removeRef(w);
505  w->Port2 = pw->Port1;
506  w->Port2->Connections.append(w);
507  return true;
508  }
509 
510  return true;
511 }
512 
513 // ---------------------------------------------------
514 // if possible, connect two vertical wires to one
516 {
517  Wire *pw;
518  Node *n = w->Port2;
519 
520  pw = (Wire*)n->Connections.last(); // last connection is the new wire itself
521  for(pw = (Wire*)n->Connections.prev(); pw!=0; pw = (Wire*)n->Connections.prev())
522  {
523  if(pw->Type != isWire) continue;
524  if(pw->isHorizontal()) continue;
525  if(pw->y2 > w->y2)
526  {
527  if(n->Connections.count() != 2) continue;
528  if(pw->Label)
529  {
530  w->Label = pw->Label;
531  w->Label->pOwner = w;
532  }
533  w->y2 = pw->y2;
534  w->Port2 = pw->Port2; // new wire lengthens an existing one
535  Nodes->removeRef(n);
536  w->Port2->Connections.removeRef(pw);
537  w->Port2->Connections.append(w);
538  Wires->removeRef(pw);
539  return true;
540  }
541  // (if new wire lies complete within an existing one, was already
542  // checked before)
543 
544  if(pw->Port1->Connections.count() < 2)
545  {
546  // existing wire lies within the new one
547  if(pw->Label)
548  {
549  w->Label = pw->Label;
550  w->Label->pOwner = w;
551  }
552  pw->Port2->Connections.removeRef(pw);
553  Nodes->removeRef(pw->Port1);
554  Wires->removeRef(pw);
555  return true;
556  }
557  w->y2 = pw->y1; // shorten new wire according to an existing one
558  w->Port2->Connections.removeRef(w);
559  w->Port2 = pw->Port1;
560  w->Port2->Connections.append(w);
561  return true;
562  }
563 
564  return true;
565 }
566 
567 // ---------------------------------------------------
568 // Inserts a vertical or horizontal wire into the schematic and connects
569 // the ports that hit together. Returns whether the beginning and ending
570 // (the ports of the wire) are connected or not.
572 {
573  int tmp, con = 0;
574  bool ok;
575 
576  // change coordinates if necessary (port 1 coordinates must be less
577  // port 2 coordinates)
578  if(w->x1 > w->x2)
579  {
580  tmp = w->x1;
581  w->x1 = w->x2;
582  w->x2 = tmp;
583  }
584  else if(w->y1 > w->y2)
585  {
586  tmp = w->y1;
587  w->y1 = w->y2;
588  w->y2 = tmp;
589  }
590  else con = 0x100;
591 
592 
593 
594  tmp = insertWireNode1(w);
595  if(tmp == 0) return 3; // no new wire and no open connection
596  if(tmp > 1) con |= 2; // insert node and remember if it remains open
597 
598  if(w->isHorizontal()) ok = connectHWires1(w);
599  else ok = connectVWires1(w);
600  if(!ok) return 3;
601 
602 
603 
604 
605  tmp = insertWireNode2(w);
606  if(tmp == 0) return 3; // no new wire and no open connection
607  if(tmp > 1) con |= 1; // insert node and remember if it remains open
608 
609  if(w->isHorizontal()) ok = connectHWires2(w);
610  else ok = connectVWires2(w);
611  if(!ok) return 3;
612 
613 
614 
615  // change node 1 and 2
616  if(con > 255) con = ((con >> 1) & 1) | ((con << 1) & 2);
617 
618  Wires->append(w); // add wire to the schematic
619 
620 
621 
622 
623  int n1, n2;
624  Wire *pw, *nw;
625  Node *pn, *pn2;
626  Element *pe;
627  // ................................................................
628  // Check if the new line covers existing nodes.
629  // In order to also check new appearing wires -> use "for"-loop
630  for(pw = Wires->current(); pw != 0; pw = Wires->next())
631  for(pn = Nodes->first(); pn != 0; ) // check every node
632  {
633  if(pn->cx == pw->x1)
634  {
635  if(pn->cy <= pw->y1)
636  {
637  pn = Nodes->next();
638  continue;
639  }
640  if(pn->cy >= pw->y2)
641  {
642  pn = Nodes->next();
643  continue;
644  }
645  }
646  else if(pn->cy == pw->y1)
647  {
648  if(pn->cx <= pw->x1)
649  {
650  pn = Nodes->next();
651  continue;
652  }
653  if(pn->cx >= pw->x2)
654  {
655  pn = Nodes->next();
656  continue;
657  }
658  }
659  else
660  {
661  pn = Nodes->next();
662  continue;
663  }
664 
665  n1 = 2;
666  n2 = 3;
667  pn2 = pn;
668  // check all connections of the current node
669  for(pe=pn->Connections.first(); pe!=0; pe=pn->Connections.next())
670  {
671  if(pe->Type != isWire) continue;
672  nw = (Wire*)pe;
673  // wire lies within the new ?
674  if(pw->isHorizontal() != nw->isHorizontal()) continue;
675 
676  pn = nw->Port1;
677  pn2 = nw->Port2;
678  n1 = pn->Connections.count();
679  n2 = pn2->Connections.count();
680  if(n1 == 1)
681  {
682  Nodes->removeRef(pn); // delete node 1 if open
683  pn2->Connections.removeRef(nw); // remove connection
684  pn = pn2;
685  }
686 
687  if(n2 == 1)
688  {
689  pn->Connections.removeRef(nw); // remove connection
690  Nodes->removeRef(pn2); // delete node 2 if open
691  pn2 = pn;
692  }
693 
694  if(pn == pn2)
695  {
696  if(nw->Label)
697  {
698  pw->Label = nw->Label;
699  pw->Label->pOwner = pw;
700  }
701  Wires->removeRef(nw); // delete wire
702  Wires->findRef(pw); // set back to current wire
703  }
704  break;
705  }
706  if(n1 == 1) if(n2 == 1) continue;
707 
708  // split wire into two wires
709  if((pw->x1 != pn->cx) || (pw->y1 != pn->cy))
710  {
711  nw = new Wire(pw->x1, pw->y1, pn->cx, pn->cy, pw->Port1, pn);
712  pn->Connections.append(nw);
713  Wires->append(nw);
714  Wires->findRef(pw);
715  pw->Port1->Connections.append(nw);
716  }
717  pw->Port1->Connections.removeRef(pw);
718  pw->x1 = pn2->cx;
719  pw->y1 = pn2->cy;
720  pw->Port1 = pn2;
721  pn2->Connections.append(pw);
722 
723  pn = Nodes->next();
724  }
725 
726  if (Wires->containsRef (w)) // if two wire lines with different labels ...
727  oneLabel(w->Port1); // ... are connected, delete one label
728  return con | 0x0200; // sent also end flag
729 }
730 
731 // ---------------------------------------------------
732 // Follows a wire line and selects it.
733 void Schematic::selectWireLine(Element *pe, Node *pn, bool ctrl)
734 {
735  Node *pn_1st = pn;
736  while(pn->Connections.count() == 2)
737  {
738  if(pn->Connections.first() == pe) pe = pn->Connections.last();
739  else pe = pn->Connections.first();
740 
741  if(pe->Type != isWire) break;
742  if(ctrl) pe->isSelected ^= ctrl;
743  else pe->isSelected = true;
744 
745  if(((Wire*)pe)->Port1 == pn) pn = ((Wire*)pe)->Port2;
746  else pn = ((Wire*)pe)->Port1;
747  if(pn == pn_1st) break; // avoid endless loop in wire loops
748  }
749 }
750 
751 // ---------------------------------------------------
753 {
754  for(Wire *pw = Wires->first(); pw != 0; pw = Wires->next())
755  if(pw->getSelected(x, y))
756  return pw;
757 
758  return 0;
759 }
760 
761 // ---------------------------------------------------
762 // Splits the wire "*pw" into two pieces by the node "*pn".
764 {
765  Wire *newWire = new Wire(pn->cx, pn->cy, pw->x2, pw->y2, pn, pw->Port2);
766  newWire->isSelected = pw->isSelected;
767 
768  pw->x2 = pn->cx;
769  pw->y2 = pn->cy;
770  pw->Port2 = pn;
771 
772  newWire->Port2->Connections.prepend(newWire);
773  pn->Connections.prepend(pw);
774  pn->Connections.prepend(newWire);
775  newWire->Port2->Connections.removeRef(pw);
776  Wires->append(newWire);
777 
778  if(pw->Label)
779  if((pw->Label->cx > pn->cx) || (pw->Label->cy > pn->cy))
780  {
781  newWire->Label = pw->Label; // label goes to the new wire
782  pw->Label = 0;
783  newWire->Label->pOwner = newWire;
784  }
785 
786  return newWire;
787 }
788 
789 // ---------------------------------------------------
790 // If possible, make one wire out of two wires.
792 {
793  Wire *e3;
794  Wire *e1 = (Wire*)n->Connections.getFirst(); // two wires -> one wire
795  Wire *e2 = (Wire*)n->Connections.getLast();
796 
797  if(e1->Type == isWire) if(e2->Type == isWire)
798  if(e1->isHorizontal() == e2->isHorizontal())
799  {
800  if(e1->x1 == e2->x2) if(e1->y1 == e2->y2)
801  {
802  e3 = e1;
803  e1 = e2;
804  e2 = e3; // e1 must have lesser coordinates
805  }
806  if(e2->Label) // take over the node name label ?
807  {
808  e1->Label = e2->Label;
809  e1->Label->pOwner = e1;
810  }
811  else if(n->Label)
812  {
813  e1->Label = n->Label;
814  e1->Label->pOwner = e1;
815  if(e1->isHorizontal())
816  e1->Label->Type = isHWireLabel;
817  else
818  e1->Label->Type = isVWireLabel;
819  }
820 
821  e1->x2 = e2->x2;
822  e1->y2 = e2->y2;
823  e1->Port2 = e2->Port2;
824  Nodes->removeRef(n); // delete node (is auto delete)
825  e1->Port2->Connections.removeRef(e2);
826  e1->Port2->Connections.append(e1);
827  Wires->removeRef(e2);
828  return true;
829  }
830  return false;
831 }
832 
833 // ---------------------------------------------------
834 // Deletes the wire 'w'.
836 {
837  if(w->Port1->Connections.count() == 1)
838  {
839  if(w->Port1->Label) delete w->Port1->Label;
840  Nodes->removeRef(w->Port1); // delete node 1 if open
841  }
842  else
843  {
844  w->Port1->Connections.removeRef(w); // remove connection
845  if(w->Port1->Connections.count() == 2)
846  oneTwoWires(w->Port1); // two wires -> one wire
847  }
848 
849  if(w->Port2->Connections.count() == 1)
850  {
851  if(w->Port2->Label) delete w->Port2->Label;
852  Nodes->removeRef(w->Port2); // delete node 2 if open
853  }
854  else
855  {
856  w->Port2->Connections.removeRef(w); // remove connection
857  if(w->Port2->Connections.count() == 2)
858  oneTwoWires(w->Port2); // two wires -> one wire
859  }
860 
861  if(w->Label)
862  {
863  delete w->Label;
864  w->Label = 0;
865  }
866  Wires->removeRef(w);
867 }
868 
869 // ---------------------------------------------------
870 int Schematic::copyWires(int& x1, int& y1, int& x2, int& y2,
871  Q3PtrList<Element> *ElementCache)
872 {
873  int count=0;
874  Node *pn;
875  Wire *pw;
876  WireLabel *pl;
877  for(pw = Wires->first(); pw != 0; ) // find bounds of all selected wires
878  if(pw->isSelected)
879  {
880  if(pw->x1 < x1) x1 = pw->x1;
881  if(pw->x2 > x2) x2 = pw->x2;
882  if(pw->y1 < y1) y1 = pw->y1;
883  if(pw->y2 > y2) y2 = pw->y2;
884 
885  count++;
886  ElementCache->append(pw);
887 
888  // rescue non-selected node labels
889  pn = pw->Port1;
890  if(pn->Label)
891  if(pn->Connections.count() < 2)
892  {
893  ElementCache->append(pn->Label);
894 
895  // Don't set pn->Label->pOwner=0 , so text position stays unchanged.
896  // But remember its wire.
897  pn->Label->pOwner = (Node*)pw;
898  pn->Label = 0;
899  }
900  pn = pw->Port2;
901  if(pn->Label)
902  if(pn->Connections.count() < 2)
903  {
904  ElementCache->append(pn->Label);
905 
906  // Don't set pn->Label->pOwner=0 , so text position stays unchanged.
907  // But remember its wire.
908  pn->Label->pOwner = (Node*)pw;
909  pn->Label = 0;
910  }
911 
912  pl = pw->Label;
913  pw->Label = 0;
914  deleteWire(pw);
915  pw->Label = pl; // restore wire label
916  pw = Wires->current();
917  }
918  else pw = Wires->next();
919 
920  return count;
921 }
922 
923 
924 /* *******************************************************************
925  ***** *****
926  ***** Actions with markers *****
927  ***** *****
928  ******************************************************************* */
929 
931 {
932  int n;
933  // test all diagrams
934  for(Diagram *pd = Diagrams->last(); pd != 0; pd = Diagrams->prev())
935  if(pd->getSelected(x, y))
936  {
937 
938  // test all graphs of the diagram
939  for(Graph *pg = pd->Graphs.first(); pg != 0; pg = pd->Graphs.next())
940  {
941  n = pg->getSelected(x-pd->cx, pd->cy-y);
942  if(n >= 0)
943  {
944  Marker *pm = new Marker(pd, pg, n, x-pd->cx, y-pd->cy);
945  pg->Markers.append(pm);
946  setChanged(true, true);
947  return pm;
948  }
949  }
950  }
951 
952  return 0;
953 }
954 
955 // ---------------------------------------------------
956 // Moves the marker pointer left/right on the graph.
957 void Schematic::markerLeftRight(bool left, Q3PtrList<Element> *Elements)
958 {
959  Marker *pm;
960  bool acted = false;
961  for(pm = (Marker*)Elements->first(); pm!=0; pm = (Marker*)Elements->next())
962  {
963  pm->pGraph->Markers.append(pm);
964  if(pm->moveLeftRight(left))
965  acted = true;
966  }
967 
968  if(acted) setChanged(true, true, 'm');
969 }
970 
971 // ---------------------------------------------------
972 // Moves the marker pointer up/down on the more-dimensional graph.
973 void Schematic::markerUpDown(bool up, Q3PtrList<Element> *Elements)
974 {
975  Marker *pm;
976  bool acted = false;
977  for(pm = (Marker*)Elements->first(); pm!=0; pm = (Marker*)Elements->next())
978  {
979  pm->pGraph->Markers.append(pm);
980  if(pm->moveUpDown(up))
981  acted = true;
982  }
983 
984  if(acted) setChanged(true, true, 'm');
985 }
986 
987 
988 /* *******************************************************************
989  ***** *****
990  ***** Actions with all elements *****
991  ***** *****
992  ******************************************************************* */
993 
994 /* Selects the element that contains the coordinates x/y.
995  Returns the pointer to the element.
996 
997  If 'flag' is true, the element can be deselected. If
998  'flag' is false the element cannot be deselected. The
999  purpose of this is to prevent deselection in cases such
1000  as right-clicking on a selected element to get a context
1001  menu.
1002 */
1003 Element* Schematic::selectElement(float fX, float fY, bool flag, int *index)
1004 {
1005  int n, x = int(fX), y = int(fY);
1006  Element *pe_1st = 0;
1007  Element *pe_sel = 0;
1008  WireLabel *pl = 0;
1009  float Corr = textCorr(); // for selecting text
1010 
1011  // test all nodes and their labels
1012  for(Node *pn = Nodes->last(); pn != 0; pn = Nodes->prev())
1013  {
1014  if(!flag)
1015  {
1016  // The element cannot be deselected
1017  if(index)
1018  {
1019  // 'index' is only true if called from MouseActions::MPressSelect()
1020  if(pn->getSelected(x, y))
1021  {
1022  // Return the node pointer, as the selection cannot change
1023  return pn;
1024  }
1025  }
1026  }
1027 
1028  pl = pn->Label; // Get any wire label associated with the Node
1029  if(pl)
1030  {
1031  if(pl->getSelected(x, y))
1032  {
1033  if(flag)
1034  {
1035  // The element can be deselected, so toggle its isSelected member
1036  // TODO: I don't see a need for the xor here, a simple ! on the current value
1037  // would be clearer and have the same effect?
1038  pl->isSelected ^= flag;
1039  return pl;
1040  }
1041  if(pe_sel)
1042  {
1043  // There is another currently
1044  pe_sel->isSelected = false;
1045  return pl;
1046  }
1047  if(pe_1st == 0)
1048  {
1049  // give access to elements lying beneath by storing this label.
1050  // If no label pointer (or other element) has previously been
1051  // stored, the current label pointer is stored here.
1052  // pe_1st is returned if no other selected element
1053  pe_1st = pl;
1054  }
1055  if(pl->isSelected)
1056  {
1057  // if current label is already selected, store a pointer to it.
1058  // This can be used to cycle through
1059  pe_sel = pl;
1060  }
1061  }
1062  }
1063  }
1064 
1065  // test all wires and wire labels
1066  for(Wire *pw = Wires->last(); pw != 0; pw = Wires->prev())
1067  {
1068  if(pw->getSelected(x, y))
1069  {
1070  if(flag)
1071  {
1072  // The element can be deselected
1073  pw->isSelected ^= flag;
1074  return pw;
1075  }
1076  if(pe_sel)
1077  {
1078  pe_sel->isSelected = false;
1079  return pw;
1080  }
1081  if(pe_1st == 0)
1082  {
1083  pe_1st = pw; // give access to elements lying beneath
1084  }
1085  if(pw->isSelected)
1086  {
1087  pe_sel = pw;
1088  }
1089  }
1090  pl = pw->Label; // test any label associated with the wire
1091  if(pl)
1092  {
1093  if(pl->getSelected(x, y))
1094  {
1095  if(flag)
1096  {
1097  // The element can be deselected
1098  pl->isSelected ^= flag;
1099  return pl;
1100  }
1101  if(pe_sel)
1102  {
1103  pe_sel->isSelected = false;
1104  return pl;
1105  }
1106  if(pe_1st == 0)
1107  {
1108  // give access to elements lying beneath
1109  pe_1st = pl;
1110  }
1111  if(pl->isSelected)
1112  {
1113  pe_sel = pl;
1114  }
1115  }
1116  }
1117  }
1118 
1119  // test all components
1120  for(Component *pc = Components->last(); pc != 0; pc = Components->prev())
1121  {
1122  if(pc->getSelected(x, y))
1123  {
1124  if(flag)
1125  {
1126  // The element can be deselected
1127  pc->isSelected ^= flag;
1128  return pc;
1129  }
1130  if(pe_sel)
1131  {
1132  pe_sel->isSelected = false;
1133  return pc;
1134  }
1135  if(pe_1st == 0)
1136  {
1137  pe_1st = pc;
1138  } // give access to elements lying beneath
1139  if(pc->isSelected)
1140  {
1141  pe_sel = pc;
1142  }
1143  }
1144  else
1145  {
1146  n = pc->getTextSelected(x, y, Corr);
1147  if(n >= 0) // was property text clicked ?
1148  {
1149  pc->Type = isComponentText;
1150  if(index) *index = n;
1151  return pc;
1152  }
1153  }
1154  }
1155 
1156  Graph *pg;
1157  Corr = 5.0 / Scale; // size of line select and area for resizing
1158  // test all diagrams
1159  for(Diagram *pd = Diagrams->last(); pd != 0; pd = Diagrams->prev())
1160  {
1161 
1162  for(pg = pd->Graphs.first(); pg != 0; pg = pd->Graphs.next())
1163  {
1164  // test markers of graphs
1165  for(Marker *pm = pg->Markers.first(); pm != 0; pm = pg->Markers.next())
1166  {
1167  if(pm->getSelected(x-pd->cx, y-pd->cy))
1168  {
1169  if(flag)
1170  {
1171  // The element can be deselected
1172  pm->isSelected ^= flag;
1173  return pm;
1174  }
1175  if(pe_sel)
1176  {
1177  pe_sel->isSelected = false;
1178  return pm;
1179  }
1180  if(pe_1st == 0)
1181  {
1182  pe_1st = pm; // give access to elements beneath
1183  }
1184  if(pm->isSelected)
1185  {
1186  pe_sel = pm;
1187  }
1188  }
1189  }
1190  }
1191 
1192  // resize area clicked ?
1193  if(pd->isSelected)
1194  {
1195  if(pd->resizeTouched(fX, fY, Corr))
1196  {
1197  if(pe_1st == 0)
1198  {
1199  pd->Type = isDiagramResize;
1200  return pd;
1201  }
1202  }
1203  }
1204 
1205  if(pd->getSelected(x, y))
1206  {
1207  if(pd->Name[0] == 'T') // tabular, timing diagram or truth table ?
1208  {
1209  if(pd->Name[1] == 'i')
1210  {
1211  if(y > pd->cy)
1212  {
1213  if(x < pd->cx+pd->xAxis.numGraphs) continue;
1214  pd->Type = isDiagramHScroll;
1215  return pd;
1216  }
1217  }
1218  else
1219  {
1220  if(x < pd->cx) // clicked on scroll bar ?
1221  {
1222  pd->Type = isDiagramVScroll;
1223  return pd;
1224  }
1225  }
1226  }
1227 
1228  // test graphs of diagram
1229  for(pg = pd->Graphs.first(); pg != 0; pg = pd->Graphs.next())
1230  {
1231  if(pg->getSelected(x-pd->cx, pd->cy-y) >= 0)
1232  {
1233  if(flag)
1234  {
1235  // The element can be deselected
1236  pg->isSelected ^= flag;
1237  return pg;
1238  }
1239  if(pe_sel)
1240  {
1241  pe_sel->isSelected = false;
1242  return pg;
1243  }
1244  if(pe_1st == 0)
1245  {
1246  pe_1st = pg; // access to elements lying beneath
1247  }
1248  if(pg->isSelected)
1249  {
1250  pe_sel = pg;
1251  }
1252  }
1253  }
1254 
1255  if(flag)
1256  {
1257  // The element can be deselected
1258  pd->isSelected ^= flag;
1259  return pd;
1260  }
1261  if(pe_sel)
1262  {
1263  pe_sel->isSelected = false;
1264  return pd;
1265  }
1266  if(pe_1st == 0)
1267  {
1268  pe_1st = pd; // give access to elements lying beneath
1269  }
1270  if(pd->isSelected)
1271  {
1272  pe_sel = pd;
1273  }
1274  }
1275  }
1276 
1277  // test all paintings
1278  for(Painting *pp = Paintings->last(); pp != 0; pp = Paintings->prev())
1279  {
1280  if(pp->isSelected)
1281  {
1282  if(pp->resizeTouched(fX, fY, Corr))
1283  {
1284  if(pe_1st == 0)
1285  {
1286  pp->Type = isPaintingResize;
1287  return pp;
1288  }
1289  }
1290  }
1291 
1292  if(pp->getSelected(fX, fY, Corr))
1293  {
1294  if(flag)
1295  {
1296  // The element can be deselected
1297  pp->isSelected ^= flag;
1298  return pp;
1299  }
1300  if(pe_sel)
1301  {
1302  pe_sel->isSelected = false;
1303  return pp;
1304  }
1305  if(pe_1st == 0)
1306  {
1307  pe_1st = pp; // give access to elements lying beneath
1308  }
1309  if(pp->isSelected)
1310  {
1311  pe_sel = pp;
1312  }
1313  }
1314  }
1315 
1316  return pe_1st;
1317 }
1318 
1320 {
1321  WireLabel *pltestinner = 0;
1322  WireLabel *pltestouter = 0;
1323 
1324  // First set highlighting for all wire labels to false
1325  for(Wire *pwouter = Wires->last(); pwouter != 0; pwouter = Wires->prev())
1326  {
1327  pltestouter = pwouter->Label; // test any label associated with the wire
1328  if (pltestouter)
1329  {
1330  pltestouter->setHighlighted (false);
1331  }
1332  }
1333 
1334  // Then test every wire's label to see if we need to highlight it
1335  // and matching labels
1336  for(Wire *pwouter = Wires->last(); pwouter != 0; pwouter = Wires->prev())
1337  {
1338  // get any label associated with the wire
1339  pltestouter = pwouter->Label;
1340  if (pltestouter)
1341  {
1342  if (pltestouter->isSelected)
1343  {
1344  // Search for matching labels
1345  for(Wire *pwinner = Wires->last(); pwinner != 0; pwinner = Wires->prev())
1346  {
1347  pltestinner = pwinner->Label; // test any label associated with the wire
1348  if (pltestinner)
1349  {
1350  // Highlight the label if it has the same name as the selected label
1351  if (strcmp(pltestouter->Name, pltestinner->Name) == 0)
1352  {
1353  pltestinner->setHighlighted (true);
1354  }
1355  }
1356  }
1357  }
1358  }
1359  }
1360 }
1361 
1362 // ---------------------------------------------------
1363 // Deselects all elements except 'e'.
1365 {
1366  // test all components
1367  for(Component *pc = Components->first(); pc != 0; pc = Components->next())
1368  if(e != pc) pc->isSelected = false;
1369 
1370  // test all wires
1371  for(Wire *pw = Wires->first(); pw != 0; pw = Wires->next())
1372  {
1373  if(e != pw) pw->isSelected = false;
1374  if(pw->Label) if(pw->Label != e) pw->Label->isSelected = false;
1375  }
1376 
1377  // test all node labels
1378  for(Node *pn = Nodes->first(); pn != 0; pn = Nodes->next())
1379  if(pn->Label) if(pn->Label != e) pn->Label->isSelected = false;
1380 
1381  // test all diagrams
1382  for(Diagram *pd = Diagrams->first(); pd != 0; pd = Diagrams->next())
1383  {
1384  if(e != pd) pd->isSelected = false;
1385 
1386  // test graphs of diagram
1387  for(Graph *pg = pd->Graphs.first(); pg != 0; pg = pd->Graphs.next())
1388  {
1389  if(e != pg) pg->isSelected = false;
1390 
1391  // test markers of graph
1392  for(Marker *pm = pg->Markers.first(); pm != 0; pm = pg->Markers.next())
1393  if(e != pm) pm->isSelected = false;
1394  }
1395 
1396  }
1397 
1398  // test all paintings
1399  for(Painting *pp = Paintings->first(); pp != 0; pp = Paintings->next())
1400  if(e != pp) pp->isSelected = false;
1401 }
1402 
1403 // ---------------------------------------------------
1404 // Selects elements that lie within the rectangle x1/y1, x2/y2.
1405 int Schematic::selectElements(int x1, int y1, int x2, int y2, bool flag)
1406 {
1407  int z=0; // counts selected elements
1408  int cx1, cy1, cx2, cy2;
1409 
1410  // exchange rectangle coordinates to obtain x1 < x2 and y1 < y2
1411  cx1 = (x1 < x2) ? x1 : x2;
1412  cx2 = (x1 > x2) ? x1 : x2;
1413  cy1 = (y1 < y2) ? y1 : y2;
1414  cy2 = (y1 > y2) ? y1 : y2;
1415  x1 = cx1;
1416  x2 = cx2;
1417  y1 = cy1;
1418  y2 = cy2;
1419 
1420  // test all components
1421  for(Component *pc = Components->first(); pc != 0; pc = Components->next())
1422  {
1423  pc->Bounding(cx1, cy1, cx2, cy2);
1424  if(cx1 >= x1) if(cx2 <= x2) if(cy1 >= y1) if(cy2 <= y2)
1425  {
1426  pc->isSelected = true;
1427  z++;
1428  continue;
1429  }
1430  if(pc->isSelected &= flag) z++;
1431  }
1432 
1433 
1434  Wire *pw;
1435  for(pw = Wires->first(); pw != 0; pw = Wires->next()) // test all wires
1436  {
1437  if(pw->x1 >= x1) if(pw->x2 <= x2) if(pw->y1 >= y1) if(pw->y2 <= y2)
1438  {
1439  pw->isSelected = true;
1440  z++;
1441  continue;
1442  }
1443  if(pw->isSelected &= flag) z++;
1444  }
1445 
1446 
1447  // test all wire labels *********************************
1448  WireLabel *pl=0;
1449  for(pw = Wires->first(); pw != 0; pw = Wires->next())
1450  {
1451  if(pw->Label)
1452  {
1453  pl = pw->Label;
1454  if(pl->x1 >= x1) if((pl->x1+pl->x2) <= x2)
1455  if(pl->y1 >= y1) if((pl->y1+pl->y2) <= y2)
1456  {
1457  pl->isSelected = true;
1458  z++;
1459  continue;
1460  }
1461  if(pl->isSelected &= flag) z++;
1462  }
1463  }
1464 
1465 
1466  // test all node labels *************************************
1467  for(Node *pn = Nodes->first(); pn != 0; pn = Nodes->next())
1468  {
1469  pl = pn->Label;
1470  if(pl)
1471  {
1472  if(pl->x1 >= x1) if((pl->x1+pl->x2) <= x2)
1473  if((pl->y1-pl->y2) >= y1) if(pl->y1 <= y2)
1474  {
1475  pl->isSelected = true;
1476  z++;
1477  continue;
1478  }
1479  if(pl->isSelected &= flag) z++;
1480  }
1481  }
1482 
1483 
1484  // test all diagrams *******************************************
1485  for(Diagram *pd = Diagrams->first(); pd != 0; pd = Diagrams->next())
1486  {
1487  // test graphs of diagram
1488  for(Graph *pg = pd->Graphs.first(); pg != 0; pg = pd->Graphs.next())
1489  {
1490  if(pg->isSelected &= flag) z++;
1491 
1492  // test markers of graph
1493  for(Marker *pm = pg->Markers.first(); pm!=0; pm = pg->Markers.next())
1494  {
1495  pm->Bounding(cx1, cy1, cx2, cy2);
1496  if(cx1 >= x1) if(cx2 <= x2) if(cy1 >= y1) if(cy2 <= y2)
1497  {
1498  pm->isSelected = true;
1499  z++;
1500  continue;
1501  }
1502  if(pm->isSelected &= flag) z++;
1503  }
1504  }
1505 
1506  // test diagram itself
1507  pd->Bounding(cx1, cy1, cx2, cy2);
1508  if(cx1 >= x1) if(cx2 <= x2) if(cy1 >= y1) if(cy2 <= y2)
1509  {
1510  pd->isSelected = true;
1511  z++;
1512  continue;
1513  }
1514  if(pd->isSelected &= flag) z++;
1515  }
1516 
1517  // test all paintings *******************************************
1518  for(Painting *pp = Paintings->first(); pp != 0; pp = Paintings->next())
1519  {
1520  pp->Bounding(cx1, cy1, cx2, cy2);
1521  if(cx1 >= x1) if(cx2 <= x2) if(cy1 >= y1) if(cy2 <= y2)
1522  {
1523  pp->isSelected = true;
1524  z++;
1525  continue;
1526  }
1527  if(pp->isSelected &= flag) z++;
1528  }
1529 
1530  return z;
1531 }
1532 
1533 // ---------------------------------------------------
1534 // Selects all markers.
1536 {
1537  for(Diagram *pd = Diagrams->first(); pd != 0; pd = Diagrams->next())
1538  for(Graph *pg = pd->Graphs.first(); pg != 0; pg = pd->Graphs.next())
1539  for(Marker *pm = pg->Markers.first(); pm!=0; pm = pg->Markers.next())
1540  pm->isSelected = true;
1541 }
1542 
1543 // ---------------------------------------------------
1544 // For moving elements: If the moving element is connected to a not
1545 // moving element, insert two wires. If the connected element is already
1546 // a wire, use this wire. Otherwise create new wire.
1547 void Schematic::newMovingWires(Q3PtrList<Element> *p, Node *pn, int pos)
1548 {
1549  Element *pe;
1550 
1551  if(pn->State & 8) // Were new wires already inserted ?
1552  return;
1553  pn->State |= 8;
1554 
1555  for (;;)
1556  {
1557  if(pn->State & 16) // node was already worked on
1558  break;
1559 
1560  pe = pn->Connections.getFirst();
1561  if(pe == 0) return;
1562 
1563  if(pn->Connections.count() > 1)
1564  break;
1565  if(pe->Type != isWire) // is it connected to exactly one wire ?
1566  break;
1567 
1568  // .................................................
1569  long mask = 1, invMask = 3;
1570  Wire *pw2=0, *pw = (Wire*)pe;
1571 
1572  Node *pn2 = pw->Port1;
1573  if(pn2 == pn) pn2 = pw->Port2;
1574 
1575  if(pn2->Connections.count() == 2) // two existing wires connected ?
1576  if((pn2->State & (8+4)) == 0)
1577  {
1578  Element *pe2 = pn2->Connections.getFirst();
1579  if(pe2 == pe) pe2 = pn2->Connections.getLast();
1580  // connected wire connected to exactly one wire ?
1581  if(pe2->Type == isWire)
1582  pw2 = (Wire*)pe2;
1583  }
1584 
1585  // .................................................
1586  // reuse one wire
1587  p->insert(pos, pw);
1588  pw->Port1->Connections.removeRef(pw); // remove connection 1
1589  pw->Port1->State |= 16+4;
1590  pw->Port2->Connections.removeRef(pw); // remove connection 2
1591  pw->Port2->State |= 16+4;
1592  Wires->take(Wires->findRef(pw));
1593 
1594  if(pw->isHorizontal()) mask = 2;
1595 
1596  if(pw2 == 0) // place new wire between component and old wire
1597  {
1598  pn = pn2;
1599  mask ^= 3;
1600  invMask = 0;
1601  }
1602 
1603  if(pw->Port1 != pn)
1604  {
1605  pw->Port1->State |= mask;
1606  pw->Port1 = (Node*)mask;
1607  pw->Port2->State |= invMask;
1608  pw->Port2 = (Node*)invMask; // move port 2 completely
1609  }
1610  else
1611  {
1612  pw->Port1->State |= invMask;
1613  pw->Port1 = (Node*)invMask;
1614  pw->Port2->State |= mask;
1615  pw->Port2 = (Node*)mask;
1616  }
1617 
1618  invMask ^= 3;
1619  // .................................................
1620  // create new wire ?
1621  if(pw2 == 0)
1622  {
1623  if(pw->Port1 != (Node*)mask)
1624  p->insert(pos,
1625  new Wire(pw->x2, pw->y2, pw->x2, pw->y2, (Node*)mask, (Node*)invMask));
1626  else
1627  p->insert(pos,
1628  new Wire(pw->x1, pw->y1, pw->x1, pw->y1, (Node*)mask, (Node*)invMask));
1629  return;
1630  }
1631 
1632 
1633  // .................................................
1634  // reuse a second wire
1635  p->insert(pos, pw2);
1636  pw2->Port1->Connections.removeRef(pw2); // remove connection 1
1637  pw2->Port1->State |= 16+4;
1638  pw2->Port2->Connections.removeRef(pw2); // remove connection 2
1639  pw2->Port2->State |= 16+4;
1640  Wires->take(Wires->findRef(pw2));
1641 
1642  if(pw2->Port1 != pn2)
1643  {
1644  pw2->Port1 = (Node*)0;
1645  pw2->Port2->State |= mask;
1646  pw2->Port2 = (Node*)mask;
1647  }
1648  else
1649  {
1650  pw2->Port1->State |= mask;
1651  pw2->Port1 = (Node*)mask;
1652  pw2->Port2 = (Node*)0;
1653  }
1654  return;
1655  }
1656 
1657  // only x2 moving
1658  p->insert(pos, new Wire(pn->cx, pn->cy, pn->cx, pn->cy, (Node*)0, (Node*)1));
1659  // x1, x2, y2 moving
1660  p->insert(pos, new Wire(pn->cx, pn->cy, pn->cx, pn->cy, (Node*)1, (Node*)3));
1661 }
1662 
1663 // ---------------------------------------------------
1664 // For moving of elements: Copies all selected elements into the
1665 // list 'p' and deletes them from the document.
1666 int Schematic::copySelectedElements(Q3PtrList<Element> *p)
1667 {
1668  int i, count = 0;
1669  Port *pp;
1670  Component *pc;
1671  Wire *pw;
1672  Diagram *pd;
1673  Element *pe;
1674  Node *pn;
1675 
1676 
1677  // test all components *********************************
1678  // Insert components before wires in order to prevent short-cut removal.
1679  for(pc = Components->first(); pc != 0; )
1680  if(pc->isSelected)
1681  {
1682  p->append(pc);
1683  count++;
1684 
1685  // delete all port connections
1686  for(pp = pc->Ports.first(); pp!=0; pp = pc->Ports.next())
1687  {
1688  pp->Connection->Connections.removeRef((Element*)pc);
1689  pp->Connection->State = 4;
1690  }
1691 
1692  Components->take(); // take component out of the document
1693  pc = Components->current();
1694  }
1695  else pc = Components->next();
1696 
1697  // test all wires and wire labels ***********************
1698  for(pw = Wires->first(); pw != 0; )
1699  {
1700  if(pw->Label) if(pw->Label->isSelected)
1701  p->append(pw->Label);
1702 
1703  if(pw->isSelected)
1704  {
1705  p->append(pw);
1706 
1707  pw->Port1->Connections.removeRef(pw); // remove connection 1
1708  pw->Port1->State = 4;
1709  pw->Port2->Connections.removeRef(pw); // remove connection 2
1710  pw->Port2->State = 4;
1711  Wires->take();
1712  pw = Wires->current();
1713  }
1714  else pw = Wires->next();
1715  }
1716 
1717  // ..............................................
1718  // Inserts wires, if a connection to a not moving element is found.
1719  // The order of the "for"-loops is important to guarantee a stable
1720  // operation: components, new wires, old wires
1721  pc = (Component*)p->first();
1722  for(i=0; i<count; i++)
1723  {
1724  for(pp = pc->Ports.first(); pp!=0; pp = pc->Ports.next())
1725  newMovingWires(p, pp->Connection, count);
1726 
1727  p->findRef(pc); // back to the real current pointer
1728  pc = (Component*)p->next();
1729  }
1730 
1731  for(pe = (Element*)pc; pe != 0; pe = p->next()) // new wires
1732  if(pe->isSelected)
1733  break;
1734 
1735  for(pw = (Wire*)pe; pw != 0; pw = (Wire*)p->next())
1736  if(pw->Type == isWire) // not working on labels
1737  {
1738  newMovingWires(p, pw->Port1, count);
1739  newMovingWires(p, pw->Port2, count);
1740  p->findRef(pw); // back to the real current pointer
1741  }
1742 
1743 
1744  // ..............................................
1745  // delete the unused nodes
1746  for(pn = Nodes->first(); pn!=0; )
1747  {
1748  if(pn->State & 8)
1749  if(pn->Connections.count() == 2)
1750  if(oneTwoWires(pn)) // if possible, connect two wires to one
1751  {
1752  pn = Nodes->current();
1753  continue;
1754  }
1755 
1756  if(pn->Connections.count() == 0)
1757  {
1758  if(pn->Label)
1759  {
1760  pn->Label->Type = isMovingLabel;
1761  if(pn->State & 1)
1762  {
1763  if(!(pn->State & 2)) pn->Label->Type = isHMovingLabel;
1764  }
1765  else if(pn->State & 2) pn->Label->Type = isVMovingLabel;
1766  p->append(pn->Label); // do not forget the node labels
1767  }
1768  Nodes->remove();
1769  pn = Nodes->current();
1770  continue;
1771  }
1772 
1773  pn->State = 0;
1774  pn = Nodes->next();
1775  }
1776 
1777  // test all node labels
1778  // do this last to avoid double copying
1779  for(pn = Nodes->first(); pn != 0; pn = Nodes->next())
1780  if(pn->Label) if(pn->Label->isSelected)
1781  p->append(pn->Label);
1782 
1783 
1784  // test all paintings **********************************
1785  for(Painting *ppa = Paintings->first(); ppa != 0; )
1786  if(ppa->isSelected)
1787  {
1788  p->append(ppa);
1789  Paintings->take();
1790  ppa = Paintings->current();
1791  }
1792  else ppa = Paintings->next();
1793 
1794  count = 0; // count markers now
1795  // test all diagrams **********************************
1796  for(pd = Diagrams->first(); pd != 0; )
1797  if(pd->isSelected)
1798  {
1799  p->append(pd);
1800  Diagrams->take();
1801  pd = Diagrams->current();
1802  }
1803  else
1804  {
1805  for(Graph *pg = pd->Graphs.first(); pg!=0; pg = pd->Graphs.next())
1806  for(Marker *pm = pg->Markers.first(); pm != 0; )
1807  if(pm->isSelected)
1808  {
1809  count++;
1810  p->append(pm);
1811  pg->Markers.take();
1812  pm = pg->Markers.current();
1813  }
1814  else pm = pg->Markers.next();
1815 
1816  pd = Diagrams->next();
1817  }
1818 
1819  return count;
1820 }
1821 
1822 // ---------------------------------------------------
1823 bool Schematic::copyComps2WiresPaints(int& x1, int& y1, int& x2, int& y2,
1824  Q3PtrList<Element> *ElementCache)
1825 {
1826  x1=INT_MAX;
1827  y1=INT_MAX;
1828  x2=INT_MIN;
1829  y2=INT_MIN;
1830  copyLabels(x1, y1, x2, y2, ElementCache); // must be first of all !
1831  copyComponents2(x1, y1, x2, y2, ElementCache);
1832  copyWires(x1, y1, x2, y2, ElementCache);
1833  copyPaintings(x1, y1, x2, y2, ElementCache);
1834 
1835  if(y1 == INT_MAX) return false; // no element selected
1836  return true;
1837 }
1838 
1839 // ---------------------------------------------------
1840 // Used in "aligning()", "distributeHorizontal()", "distributeVertical()".
1841 int Schematic::copyElements(int& x1, int& y1, int& x2, int& y2,
1842  Q3PtrList<Element> *ElementCache)
1843 {
1844  int bx1, by1, bx2, by2;
1845  Wires->setAutoDelete(false);
1846  Components->setAutoDelete(false);
1847 
1848  x1=INT_MAX;
1849  y1=INT_MAX;
1850  x2=INT_MIN;
1851  y2=INT_MIN;
1852  // take components and wires out of list, check their boundings
1853  int number = copyComponents(x1, y1, x2, y2, ElementCache);
1854  number += copyWires(x1, y1, x2, y2, ElementCache);
1855 
1856  Wires->setAutoDelete(true);
1857  Components->setAutoDelete(true);
1858 
1859  // find upper most selected diagram
1860  for(Diagram *pd = Diagrams->last(); pd != 0; pd = Diagrams->prev())
1861  if(pd->isSelected)
1862  {
1863  pd->Bounding(bx1, by1, bx2, by2);
1864  if(bx1 < x1) x1 = bx1;
1865  if(bx2 > x2) x2 = bx2;
1866  if(by1 < y1) y1 = by1;
1867  if(by2 > y2) y2 = by2;
1868  ElementCache->append(pd);
1869  number++;
1870  }
1871  // find upper most selected painting
1872  for(Painting *pp = Paintings->last(); pp != 0; pp = Paintings->prev())
1873  if(pp->isSelected)
1874  {
1875  pp->Bounding(bx1, by1, bx2, by2);
1876  if(bx1 < x1) x1 = bx1;
1877  if(bx2 > x2) x2 = bx2;
1878  if(by1 < y1) y1 = by1;
1879  if(by2 > y2) y2 = by2;
1880  ElementCache->append(pp);
1881  number++;
1882  }
1883 
1884  return number;
1885 }
1886 
1887 // ---------------------------------------------------
1888 // Deletes all selected elements.
1890 {
1891  bool sel = false;
1892 
1893  Component *pc = Components->first();
1894  while(pc != 0) // all selected component
1895  if(pc->isSelected)
1896  {
1897  deleteComp(pc);
1898  pc = Components->current();
1899  sel = true;
1900  }
1901  else pc = Components->next();
1902 
1903  Wire *pw = Wires->first();
1904  while(pw != 0) // all selected wires and their labels
1905  {
1906  if(pw->Label)
1907  if(pw->Label->isSelected)
1908  {
1909  delete pw->Label;
1910  pw->Label = 0;
1911  sel = true;
1912  }
1913 
1914  if(pw->isSelected)
1915  {
1916  deleteWire(pw);
1917  pw = Wires->current();
1918  sel = true;
1919  }
1920  else pw = Wires->next();
1921  }
1922 
1923  // all selected labels on nodes ***************************
1924  for(Node *pn = Nodes->first(); pn != 0; pn = Nodes->next())
1925  if(pn->Label)
1926  if(pn->Label->isSelected)
1927  {
1928  delete pn->Label;
1929  pn->Label = 0;
1930  sel = true;
1931  }
1932 
1933  Diagram *pd = Diagrams->first();
1934  while(pd != 0) // test all diagrams
1935  if(pd->isSelected)
1936  {
1937  Diagrams->remove();
1938  pd = Diagrams->current();
1939  sel = true;
1940  }
1941  else
1942  {
1943  bool wasGraphDeleted = false;
1944  // all graphs of diagram
1945  for(Graph *pg = pd->Graphs.first(); pg != 0; )
1946  {
1947  // all markers of diagram
1948  for(Marker *pm = pg->Markers.first(); pm != 0; )
1949  if(pm->isSelected)
1950  {
1951  pg->Markers.remove();
1952  pm = pg->Markers.current();
1953  sel = true;
1954  }
1955  else pm = pg->Markers.next();
1956 
1957  if(pg->isSelected)
1958  {
1959  pd->Graphs.remove();
1960  pg = pd->Graphs.current();
1961  sel = wasGraphDeleted = true;
1962  }
1963  else pg = pd->Graphs.next();
1964  }
1965  if(wasGraphDeleted)
1966  pd->recalcGraphData(); // update diagram (resize etc.)
1967 
1968  pd = Diagrams->next();
1969  }
1970 
1971  Painting *pp = Paintings->first();
1972  while(pp != 0) // test all paintings
1973  {
1974  if(pp->isSelected)
1975  if(pp->Name.at(0) != '.') // do not delete "PortSym", "ID_text"
1976  {
1977  sel = true;
1978  Paintings->remove();
1979  pp = Paintings->current();
1980  continue;
1981  }
1982  pp = Paintings->next();
1983  }
1984 
1985  if(sel)
1986  {
1987  sizeOfAll(UsedX1, UsedY1, UsedX2, UsedY2); // set new document size
1988  setChanged(sel, true);
1989  }
1990  return sel;
1991 }
1992 
1993 // ---------------------------------------------------
1994 bool Schematic::aligning(int Mode)
1995 {
1996  int x1, y1, x2, y2;
1997  int bx1, by1, bx2, by2, *bx=0, *by=0, *ax=0, *ay=0;
1998  Q3PtrList<Element> ElementCache;
1999  int count = copyElements(x1, y1, x2, y2, &ElementCache);
2000  if(count < 1) return false;
2001 
2002 
2003  ax = ay = &x2; // = 0
2004  switch(Mode)
2005  {
2006  case 0: // align top
2007  bx = &x1;
2008  by = &by1;
2009  y2 = 1;
2010  break;
2011  case 1: // align bottom
2012  bx = &x1;
2013  y1 = y2;
2014  by = &by2;
2015  y2 = 1;
2016  break;
2017  case 2: // align left
2018  by = &y1;
2019  bx = &bx1;
2020  y2 = 1;
2021  break;
2022  case 3: // align right
2023  by = &y1;
2024  x1 = x2;
2025  bx = &bx2;
2026  y2 = 1;
2027  break;
2028  case 4: // center horizontally
2029  x1 = (x2+x1) / 2;
2030  by = &x2; // = 0
2031  ax = &bx1;
2032  bx = &bx2;
2033  y1 = 0;
2034  y2 = 2;
2035  break;
2036  case 5: // center vertically
2037  y1 = (y2+y1) / 2;
2038  bx = &x2; // = 0
2039  ay = &by1;
2040  by = &by2;
2041  x1 = 0;
2042  y2 = 2;
2043  break;
2044  }
2045  x2 = 0;
2046 
2047  Wire *pw;
2048  Component *pc;
2049  // re-insert elements
2050  // Go backwards in order to insert node labels before its component.
2051  for(Element *pe = ElementCache.last(); pe != 0; pe = ElementCache.prev())
2052  switch(pe->Type)
2053  {
2054  case isComponent:
2055  case isAnalogComponent:
2056  case isDigitalComponent:
2057  pc = (Component*)pe;
2058  pc->Bounding(bx1, by1, bx2, by2);
2059  pc->setCenter(x1-((*bx)+(*ax))/y2, y1-((*by)+(*ay))/y2, true);
2060  insertRawComponent(pc);
2061  break;
2062 
2063  case isWire:
2064  pw = (Wire*)pe;
2065  bx1 = pw->x1;
2066  by1 = pw->y1;
2067  bx2 = pw->x2;
2068  by2 = pw->y2;
2069  pw->setCenter(x1-((*bx)+(*ax))/y2, y1-((*by)+(*ay))/y2, true);
2070 // if(pw->Label) { }
2071  insertWire(pw);
2072  break;
2073 
2074  case isDiagram:
2075  // Should the axis label be counted for ? I guess everyone
2076  // has a different opinion.
2077 // ((Diagram*)pe)->Bounding(bx1, by1, bx2, by2);
2078 
2079  // Take size without axis label.
2080  bx1 = ((Diagram*)pe)->cx;
2081  by2 = ((Diagram*)pe)->cy;
2082  bx2 = bx1 + ((Diagram*)pe)->x2;
2083  by1 = by2 - ((Diagram*)pe)->y2;
2084  ((Diagram*)pe)->setCenter(x1-((*bx)+(*ax))/y2, y1-((*by)+(*ay))/y2, true);
2085  break;
2086 
2087  case isPainting:
2088  ((Painting*)pe)->Bounding(bx1, by1, bx2, by2);
2089  ((Painting*)pe)->setCenter(x1-((*bx)+(*ax))/y2, y1-((*by)+(*ay))/y2, true);
2090  break;
2091 
2092  case isNodeLabel:
2093  if(((Element*)(((WireLabel*)pe)->pOwner))->Type & isComponent)
2094  {
2095  pc = (Component*)(((WireLabel*)pe)->pOwner);
2096  pc->Bounding(bx1, by1, bx2, by2);
2097  }
2098  else
2099  {
2100  pw = (Wire*)(((WireLabel*)pe)->pOwner);
2101  bx1 = pw->x1;
2102  by1 = pw->y1;
2103  bx2 = pw->x2;
2104  by2 = pw->y2;
2105  }
2106  ((WireLabel*)pe)->cx += x1-((*bx)+(*ax))/y2;
2107  ((WireLabel*)pe)->cy += y1-((*by)+(*ay))/y2;
2108  insertNodeLabel((WireLabel*)pe);
2109  break;
2110 
2111  default:
2112  ;
2113  }
2114 
2115  ElementCache.clear();
2116  if(count < 2) return false;
2117 
2118  setChanged(true, true);
2119  return true;
2120 }
2121 
2122 // ---------------------------------------------------
2124 {
2125  int x1, y1, x2, y2;
2126  int bx1, by1, bx2, by2;
2127  Q3PtrList<Element> ElementCache;
2128  int count = copyElements(x1, y1, x2, y2, &ElementCache);
2129  if(count < 1) return false;
2130 
2131  Element *pe;
2132  WireLabel *pl;
2133  // Node labels are not counted for, so put them to the end.
2134  /* for(pe = ElementCache.last(); pe != 0; pe = ElementCache.prev())
2135  if(pe->Type == isNodeLabel) {
2136  ElementCache.append(pe);
2137  ElementCache.removeRef(pe);
2138  }*/
2139 
2140  // using bubble sort to get elements x ordered
2141  if(count > 1)
2142  for(int i = count-1; i>0; i--)
2143  {
2144  pe = ElementCache.first();
2145  for(int j=0; j<i; j++)
2146  {
2147  pe->getCenter(bx1, by1);
2148  pe=ElementCache.next();
2149  pe->getCenter(bx2, by2);
2150  if(bx1 > bx2) // change two elements ?
2151  {
2152  ElementCache.replace(j+1, ElementCache.prev());
2153  ElementCache.replace(j, pe);
2154  pe = ElementCache.next();
2155  }
2156  }
2157  }
2158 
2159  ElementCache.getLast()->getCenter(x2, y2);
2160  ElementCache.getFirst()->getCenter(x1, y1);
2161  Wire *pw;
2162  int x = x2;
2163  int dx=0;
2164  if(count > 1) dx = (x2-x1)/(count-1);
2165  // re-insert elements and put them at right position
2166  // Go backwards in order to insert node labels before its component.
2167  for(pe = ElementCache.last(); pe != 0; pe = ElementCache.prev())
2168  {
2169  switch(pe->Type)
2170  {
2171  case isComponent:
2172  case isAnalogComponent:
2173  case isDigitalComponent:
2174  pe->cx = x;
2176  break;
2177 
2178  case isWire:
2179  pw = (Wire*)pe;
2180  if(pw->isHorizontal())
2181  {
2182  x1 = pw->x2 - pw->x1;
2183  pw->x1 = x - (x1 >> 1);
2184  pw->x2 = pw->x1 + x1;
2185  }
2186  else pw->x1 = pw->x2 = x;
2187 // if(pw->Label) { }
2188  insertWire(pw);
2189  break;
2190 
2191  case isDiagram:
2192  pe->cx = x - (pe->x2 >> 1);
2193  break;
2194 
2195  case isPainting:
2196  pe->getCenter(bx1, by1);
2197  pe->setCenter(x, by1, false);
2198  break;
2199 
2200  case isNodeLabel:
2201  pl = (WireLabel*)pe;
2202  if(((Element*)(pl->pOwner))->Type & isComponent)
2203  pe->cx += x - ((Component*)(pl->pOwner))->cx;
2204  else
2205  {
2206  pw = (Wire*)(pl->pOwner);
2207  if(pw->isHorizontal())
2208  {
2209  x1 = pw->x2 - pw->x1;
2210  pe->cx += x - (x1 >> 1) - pw->x1;
2211  }
2212  else pe->cx += x - pw->x1;
2213  }
2214  insertNodeLabel(pl);
2215  x += dx;
2216  break;
2217 
2218  default:
2219  ;
2220  }
2221  x -= dx;
2222  }
2223 
2224  ElementCache.clear();
2225  if(count < 2) return false;
2226 
2227  setChanged(true, true);
2228  return true;
2229 }
2230 
2231 // ---------------------------------------------------
2233 {
2234  int x1, y1, x2, y2;
2235  int bx1, by1, bx2, by2;
2236  Q3PtrList<Element> ElementCache;
2237  int count = copyElements(x1, y1, x2, y2, &ElementCache);
2238  if(count < 1) return false;
2239 
2240  // using bubble sort to get elements x ordered
2241  Element *pe;
2242  if(count > 1)
2243  for(int i = count-1; i>0; i--)
2244  {
2245  pe = ElementCache.first();
2246  for(int j=0; j<i; j++)
2247  {
2248  pe->getCenter(bx1, by1);
2249  pe=ElementCache.next();
2250  pe->getCenter(bx2, by2);
2251  if(by1 > by2) // change two elements ?
2252  {
2253  ElementCache.replace(j+1, ElementCache.prev());
2254  ElementCache.replace(j, pe);
2255  pe = ElementCache.next();
2256  }
2257  }
2258  }
2259 
2260  ElementCache.getLast()->getCenter(x2, y2);
2261  ElementCache.getFirst()->getCenter(x1, y1);
2262  Wire *pw;
2263  int y = y2;
2264  int dy=0;
2265  if(count > 1) dy = (y2-y1)/(count-1);
2266  // re-insert elements and put them at right position
2267  // Go backwards in order to insert node labels before its component.
2268  for(pe = ElementCache.last(); pe != 0; pe = ElementCache.prev())
2269  {
2270  switch(pe->Type)
2271  {
2272  case isComponent:
2273  case isAnalogComponent:
2274  case isDigitalComponent:
2275  pe->cy = y;
2277  break;
2278 
2279  case isWire:
2280  pw = (Wire*)pe;
2281  if(pw->isHorizontal()) pw->y1 = pw->y2 = y;
2282  else
2283  {
2284  y1 = pw->y2 - pw->y1;
2285  pw->y1 = y - (y1 >> 1);
2286  pw->y2 = pe->y1 + y1;
2287  }
2288 // if(pw->Label) { }
2289  insertWire(pw);
2290  break;
2291 
2292  case isDiagram:
2293  pe->cy = y + (pe->y2 >> 1);
2294  break;
2295 
2296  case isPainting:
2297  pe->getCenter(bx1, by1);
2298  pe->setCenter(bx1, y, false);
2299  break;
2300 
2301  case isNodeLabel:
2302  if(((Element*)(((WireLabel*)pe)->pOwner))->Type & isComponent)
2303  pe->cy += y - ((Component*)(((WireLabel*)pe)->pOwner))->cy;
2304  else
2305  {
2306  pw = (Wire*)(((WireLabel*)pe)->pOwner);
2307  if(!pw->isHorizontal())
2308  {
2309  y1 = pw->y2 - pw->y1;
2310  pe->cy += y - (y1 >> 1) - pw->y1;
2311  }
2312  else pe->cy += y - pw->y1;
2313  }
2314  insertNodeLabel((WireLabel*)pe);
2315  y += dy;
2316  break;
2317 
2318  default:
2319  ;
2320  }
2321  y -= dy;
2322  }
2323 
2324  ElementCache.clear();
2325  if(count < 2) return false;
2326 
2327  setChanged(true, true);
2328  return true;
2329 }
2330 
2331 
2332 /* *******************************************************************
2333  ***** *****
2334  ***** Actions with components *****
2335  ***** *****
2336  ******************************************************************* */
2337 
2338 // Finds the correct number for power sources, subcircuit ports and
2339 // digital sources and sets them accordingly.
2341 {
2342  Property *pp = c->Props.getFirst();
2343  if(!pp) return;
2344  if(pp->Name != "Num") return;
2345 
2346  int n=1;
2347  QString s = pp->Value;
2348  QString cSign = c->Model;
2349  Component *pc;
2350  // First look, if the port number already exists.
2351  for(pc = Components->first(); pc != 0; pc = Components->next())
2352  if(pc->Model == cSign)
2353  if(pc->Props.getFirst()->Value == s) break;
2354  if(!pc) return; // was port number not yet in use ?
2355 
2356  // Find the first free number.
2357  do
2358  {
2359  s = QString::number(n);
2360  // look for existing ports and their numbers
2361  for(pc = Components->first(); pc != 0; pc = Components->next())
2362  if(pc->Model == cSign)
2363  if(pc->Props.getFirst()->Value == s) break;
2364 
2365  n++;
2366  }
2367  while(pc); // found not used component number
2368  pp->Value = s; // set new number
2369 }
2370 
2371 // ---------------------------------------------------
2373 {
2374  Port *pp;
2375  // connect every node of the component to corresponding schematic node
2376  for(pp = c->Ports.first(); pp != 0; pp = c->Ports.next())
2377  pp->Connection = insertNode(pp->x+c->cx, pp->y+c->cy, c);
2378 
2379  if(noOptimize) return;
2380 
2381  Node *pn;
2382  Element *pe, *pe1;
2383  Q3PtrList<Element> *pL;
2384  // if component over wire then delete this wire
2385  c->Ports.first(); // omit the first element
2386  for(pp = c->Ports.next(); pp != 0; pp = c->Ports.next())
2387  {
2388  pn = pp->Connection;
2389  for(pe = pn->Connections.first(); pe!=0; pe = pn->Connections.next())
2390  if(pe->Type == isWire)
2391  {
2392  if(((Wire*)pe)->Port1 == pn) pL = &(((Wire*)pe)->Port2->Connections);
2393  else pL = &(((Wire*)pe)->Port1->Connections);
2394 
2395  for(pe1 = pL->first(); pe1!=0; pe1 = pL->next())
2396  if(pe1 == c)
2397  {
2398  deleteWire((Wire*)pe);
2399  break;
2400  }
2401  }
2402  }
2403 }
2404 
2405 // ---------------------------------------------------
2406 // Used for example in moving components.
2407 void Schematic::insertRawComponent(Component *c, bool noOptimize)
2408 {
2409  // connect every node of component to corresponding schematic node
2410  insertComponentNodes(c, noOptimize);
2411  Components->append(c);
2412 
2413  // a ground symbol erases an existing label on the wire line
2414  if(c->Model == "GND")
2415  {
2416  c->Model = "x"; // prevent that this ground is found as label
2417  Element *pe = getWireLabel(c->Ports.getFirst()->Connection);
2418  if(pe) if((pe->Type & isComponent) == 0)
2419  {
2420  delete ((Conductor*)pe)->Label;
2421  ((Conductor*)pe)->Label = 0;
2422  }
2423  c->Model = "GND"; // rebuild component model
2424  }
2425 }
2426 
2427 // ---------------------------------------------------
2429 {
2430  Port *pp;
2431  WireLabel **plMem=0, **pl;
2432  int PortCount = Comp->Ports.count();
2433 
2434  if(PortCount > 0)
2435  {
2436  // Save the labels whose node is not connected to somewhere else.
2437  // Otherwise the label would be deleted.
2438  pl = plMem = (WireLabel**)malloc(PortCount * sizeof(WireLabel*));
2439  for(pp = Comp->Ports.first(); pp != 0; pp = Comp->Ports.next())
2440  if(pp->Connection->Connections.count() < 2)
2441  {
2442  *(pl++) = pp->Connection->Label;
2443  pp->Connection->Label = 0;
2444  }
2445  else *(pl++) = 0;
2446  }
2447 
2448 
2449  int x = Comp->tx, y = Comp->ty;
2450  int x1 = Comp->x1, x2 = Comp->x2, y1 = Comp->y1, y2 = Comp->y2;
2451  QString tmp = Comp->Name; // is sometimes changed by "recreate"
2452  Comp->recreate(this); // to apply changes to the schematic symbol
2453  Comp->Name = tmp;
2454  if(x < x1)
2455  x += Comp->x1 - x1;
2456  else if(x > x2)
2457  x += Comp->x2 - x2;
2458  if(y < y1)
2459  y += Comp->y1 - y1;
2460  else if(y > y2)
2461  y += Comp->y2 - y2;
2462  Comp->tx = x;
2463  Comp->ty = y;
2464 
2465 
2466  if(PortCount > 0)
2467  {
2468  // restore node labels
2469  pl = plMem;
2470  for(pp = Comp->Ports.first(); pp != 0; pp = Comp->Ports.next())
2471  {
2472  if(*pl != 0)
2473  {
2474  (*pl)->cx = pp->Connection->cx;
2475  (*pl)->cy = pp->Connection->cy;
2476  placeNodeLabel(*pl);
2477  }
2478  pl++;
2479  if((--PortCount) < 1) break;
2480  }
2481  for( ; PortCount > 0; PortCount--)
2482  {
2483  delete (*pl); // delete not needed labels
2484  pl++;
2485  }
2486  free(plMem);
2487  }
2488 }
2489 
2490 // ---------------------------------------------------
2492 {
2493  // connect every node of component to corresponding schematic node
2494  insertComponentNodes(c, false);
2495 
2496  bool ok;
2497  QString s;
2498  int max=1, len = c->Name.length(), z;
2499  if(c->Name.isEmpty())
2500  {
2501  // a ground symbol erases an existing label on the wire line
2502  if(c->Model == "GND")
2503  {
2504  c->Model = "x"; // prevent that this ground is found as label
2505  Element *pe = getWireLabel(c->Ports.getFirst()->Connection);
2506  if(pe) if((pe->Type & isComponent) == 0)
2507  {
2508  delete ((Conductor*)pe)->Label;
2509  ((Conductor*)pe)->Label = 0;
2510  }
2511  c->Model = "GND"; // rebuild component model
2512  }
2513  }
2514  else
2515  {
2516  // determines the name by looking for names with the same
2517  // prefix and increment the number
2518  for(Component *pc = Components->first(); pc != 0; pc = Components->next())
2519  if(pc->Name.left(len) == c->Name)
2520  {
2521  s = pc->Name.right(pc->Name.length()-len);
2522  z = s.toInt(&ok);
2523  if(ok) if(z >= max) max = z + 1;
2524  }
2525  c->Name += QString::number(max); // create name with new number
2526  }
2527 
2528  setComponentNumber(c); // important for power sources and subcircuit ports
2529  Components->append(c);
2530 }
2531 
2532 // ---------------------------------------------------
2533 void Schematic::activateCompsWithinRect(int x1, int y1, int x2, int y2)
2534 {
2535  bool changed = false;
2536  int cx1, cy1, cx2, cy2, a;
2537  // exchange rectangle coordinates to obtain x1 < x2 and y1 < y2
2538  cx1 = (x1 < x2) ? x1 : x2;
2539  cx2 = (x1 > x2) ? x1 : x2;
2540  cy1 = (y1 < y2) ? y1 : y2;
2541  cy2 = (y1 > y2) ? y1 : y2;
2542  x1 = cx1;
2543  x2 = cx2;
2544  y1 = cy1;
2545  y2 = cy2;
2546 
2547 
2548  for(Component *pc = Components->first(); pc != 0; pc = Components->next())
2549  {
2550  pc->Bounding(cx1, cy1, cx2, cy2);
2551  if(cx1 >= x1) if(cx2 <= x2) if(cy1 >= y1) if(cy2 <= y2)
2552  {
2553  a = pc->isActive - 1;
2554 
2555  if(pc->Ports.count() > 1)
2556  {
2557  if(a < 0) a = 2;
2558  pc->isActive = a; // change "active status"
2559  }
2560  else
2561  {
2562  a &= 1;
2563  pc->isActive = a; // change "active status"
2564  if(a == COMP_IS_ACTIVE) // only for active (not shorten)
2565  if(pc->Model == "GND") // if existing, delete label on wire line
2566  oneLabel(pc->Ports.getFirst()->Connection);
2567  }
2568  changed = true;
2569  }
2570  }
2571 
2572  if(changed) setChanged(true, true);
2573 }
2574 
2575 // ---------------------------------------------------
2577 {
2578  int x1, y1, x2, y2, a;
2579  for(Component *pc = Components->first(); pc != 0; pc = Components->next())
2580  {
2581  pc->Bounding(x1, y1, x2, y2);
2582  if(x >= x1) if(x <= x2) if(y >= y1) if(y <= y2)
2583  {
2584  a = pc->isActive - 1;
2585 
2586  if(pc->Ports.count() > 1)
2587  {
2588  if(a < 0) a = 2;
2589  pc->isActive = a; // change "active status"
2590  }
2591  else
2592  {
2593  a &= 1;
2594  pc->isActive = a; // change "active status"
2595  if(a == COMP_IS_ACTIVE) // only for active (not shorten)
2596  if(pc->Model == "GND") // if existing, delete label on wire line
2597  oneLabel(pc->Ports.getFirst()->Connection);
2598  }
2599  setChanged(true, true);
2600  return true;
2601  }
2602  }
2603  return false;
2604 }
2605 
2606 // ---------------------------------------------------
2608 {
2609  int a;
2610  bool sel = false;
2611  for(Component *pc = Components->first(); pc != 0; pc = Components->next())
2612  if(pc->isSelected)
2613  {
2614  a = pc->isActive - 1;
2615 
2616  if(pc->Ports.count() > 1)
2617  {
2618  if(a < 0) a = 2;
2619  pc->isActive = a; // change "active status"
2620  }
2621  else
2622  {
2623  a &= 1;
2624  pc->isActive = a; // change "active status"
2625  if(a == COMP_IS_ACTIVE) // only for active (not shorten)
2626  if(pc->Model == "GND") // if existing, delete label on wire line
2627  oneLabel(pc->Ports.getFirst()->Connection);
2628  }
2629  sel = true;
2630  }
2631 
2632  if(sel) setChanged(true, true);
2633  return sel;
2634 }
2635 
2636 // ---------------------------------------------------
2637 // Sets the component ports anew. Used after rotate, mirror etc.
2639 {
2640  Port *pp;
2641  WireLabel *pl;
2642  Q3PtrList<WireLabel> LabelCache;
2643 
2644  for(pp = pc->Ports.first(); pp!=0; pp = pc->Ports.next())
2645  {
2646  pp->Connection->Connections.removeRef((Element*)pc);// delete connections
2647  switch(pp->Connection->Connections.count())
2648  {
2649  case 0:
2650  pl = pp->Connection->Label;
2651  if(pl)
2652  {
2653  LabelCache.append(pl);
2654  pl->cx = pp->x + pc->cx;
2655  pl->cy = pp->y + pc->cy;
2656  }
2657  Nodes->removeRef(pp->Connection);
2658  break;
2659  case 2:
2660  oneTwoWires(pp->Connection); // try to connect two wires to one
2661  default:
2662  ;
2663  }
2664  }
2665 
2666  // Re-connect component node to schematic node. This must be done completely
2667  // after the first loop in order to avoid problems with node labels.
2668  for(pp = pc->Ports.first(); pp!=0; pp = pc->Ports.next())
2669  pp->Connection = insertNode(pp->x+pc->cx, pp->y+pc->cy, pc);
2670 
2671  for(pl = LabelCache.first(); pl != 0; pl = LabelCache.next())
2672  insertNodeLabel(pl);
2673 }
2674 
2675 // ---------------------------------------------------
2676 // Returns a pointer of the component on whose text x/y points.
2677 Component* Schematic::selectCompText(int x_, int y_, int& w, int& h)
2678 {
2679  int a, b, dx, dy;
2680  for(Component *pc = Components->first(); pc != 0; pc = Components->next())
2681  {
2682  a = pc->cx + pc->tx;
2683  if(x_ < a) continue;
2684  b = pc->cy + pc->ty;
2685  if(y_ < b) continue;
2686 
2687  pc->textSize(dx, dy);
2688  if(x_ > a+dx) continue;
2689  if(y_ > b+dy) continue;
2690 
2691  w = dx;
2692  h = dy;
2693  return pc;
2694  }
2695 
2696  return 0;
2697 }
2698 
2699 // ---------------------------------------------------
2701 {
2702  Component *sub=0;
2703  // test all components
2704  for(Component *pc = Components->first(); pc != 0; pc = Components->next())
2705  {
2706  if(!pc->isSelected) continue;
2707  if(pc->Model != "Sub")
2708  if(pc->Model != "VHDL")
2709  if(pc->Model != "Verilog") continue;
2710 
2711  if(sub != 0) return 0; // more than one subcircuit selected
2712  sub = pc;
2713  }
2714  return sub;
2715 }
2716 
2717 // ---------------------------------------------------
2719 {
2720  // test all components
2721  for(Component *pc = Components->first(); pc != 0; pc = Components->next())
2722  if(pc->getSelected(x, y))
2723  return pc;
2724 
2725  return 0;
2726 }
2727 
2728 // ---------------------------------------------------
2729 // Deletes the component 'c'.
2731 {
2732  Port *pn;
2733 
2734  // delete all port connections
2735  for(pn = c->Ports.first(); pn!=0; pn = c->Ports.next())
2736  switch(pn->Connection->Connections.count())
2737  {
2738  case 1 :
2739  if(pn->Connection->Label) delete pn->Connection->Label;
2740  Nodes->removeRef(pn->Connection); // delete open nodes
2741  pn->Connection = 0; // (auto-delete)
2742  break;
2743  case 3 :
2744  pn->Connection->Connections.removeRef(c);// delete connection
2745  oneTwoWires(pn->Connection); // two wires -> one wire
2746  break;
2747  default :
2748  pn->Connection->Connections.removeRef(c);// remove connection
2749  break;
2750  }
2751 
2752  Components->removeRef(c); // delete component
2753 }
2754 
2755 // ---------------------------------------------------
2756 int Schematic::copyComponents(int& x1, int& y1, int& x2, int& y2,
2757  Q3PtrList<Element> *ElementCache)
2758 {
2759  Component *pc;
2760  int bx1, by1, bx2, by2, count=0;
2761  // find bounds of all selected components
2762  for(pc = Components->first(); pc != 0; )
2763  {
2764  if(pc->isSelected)
2765  {
2766  pc->Bounding(bx1, by1, bx2, by2); // is needed because of "distribute
2767  if(bx1 < x1) x1 = bx1; // uniformly"
2768  if(bx2 > x2) x2 = bx2;
2769  if(by1 < y1) y1 = by1;
2770  if(by2 > y2) y2 = by2;
2771 
2772  count++;
2773  ElementCache->append(pc);
2774 
2775  Port *pp; // rescue non-selected node labels
2776  for(pp = pc->Ports.first(); pp != 0; pp = pc->Ports.next())
2777  if(pp->Connection->Label)
2778  if(pp->Connection->Connections.count() < 2)
2779  {
2780  ElementCache->append(pp->Connection->Label);
2781 
2782  // Don't set pp->Connection->Label->pOwner=0,
2783  // so text position stays unchanged, but
2784  // remember component for align/distribute.
2785  pp->Connection->Label->pOwner = (Node*)pc;
2786 
2787  pp->Connection->Label = 0;
2788  }
2789 
2790  deleteComp(pc);
2791  pc = Components->current();
2792  continue;
2793  }
2794  pc = Components->next();
2795  }
2796  return count;
2797 }
2798 
2799 // ---------------------------------------------------
2800 void Schematic::copyComponents2(int& x1, int& y1, int& x2, int& y2,
2801  Q3PtrList<Element> *ElementCache)
2802 {
2803  Component *pc;
2804  // find bounds of all selected components
2805  for(pc = Components->first(); pc != 0; )
2806  {
2807  if(pc->isSelected)
2808  {
2809  // is better for unsymmetrical components
2810  if(pc->cx < x1) x1 = pc->cx;
2811  if(pc->cx > x2) x2 = pc->cx;
2812  if(pc->cy < y1) y1 = pc->cy;
2813  if(pc->cy > y2) y2 = pc->cy;
2814 
2815  ElementCache->append(pc);
2816 
2817  Port *pp; // rescue non-selected node labels
2818  for(pp = pc->Ports.first(); pp != 0; pp = pc->Ports.next())
2819  if(pp->Connection->Label)
2820  if(pp->Connection->Connections.count() < 2)
2821  {
2822  ElementCache->append(pp->Connection->Label);
2823  pp->Connection->Label = 0;
2824  // Don't set pp->Connection->Label->pOwner=0,
2825  // so text position stays unchanged.
2826  }
2827 
2828  deleteComp(pc);
2829  pc = Components->current();
2830  continue;
2831  }
2832  pc = Components->next();
2833  }
2834 }
2835 
2836 
2837 /* *******************************************************************
2838  ***** *****
2839  ***** Actions with labels *****
2840  ***** *****
2841  ******************************************************************* */
2842 
2843 // Test, if wire connects wire line with more than one label and delete
2844 // all further labels. Also delete all labels if wire line is grounded.
2846 {
2847  Wire *pw;
2848  Node *pn, *pNode;
2849  Element *pe;
2850  WireLabel *pl = 0;
2851  bool named=false; // wire line already named ?
2852  Q3PtrList<Node> Cons;
2853 
2854  for(pn = Nodes->first(); pn!=0; pn = Nodes->next())
2855  pn->y1 = 0; // mark all nodes as not checked
2856 
2857  Cons.append(n1);
2858  n1->y1 = 1; // mark Node as already checked
2859  for(pn = Cons.first(); pn!=0; pn = Cons.next())
2860  {
2861  if(pn->Label)
2862  {
2863  if(named)
2864  {
2865  delete pn->Label;
2866  pn->Label = 0; // erase double names
2867  }
2868  else
2869  {
2870  named = true;
2871  pl = pn->Label;
2872  }
2873  }
2874 
2875  for(pe = pn->Connections.first(); pe!=0; pe = pn->Connections.next())
2876  {
2877  if(pe->Type != isWire)
2878  {
2879  if(((Component*)pe)->isActive == COMP_IS_ACTIVE)
2880  if(((Component*)pe)->Model == "GND")
2881  {
2882  named = true;
2883  if(pl)
2884  {
2885  pl->pOwner->Label = 0;
2886  delete pl;
2887  }
2888  pl = 0;
2889  }
2890  continue;
2891  }
2892  pw = (Wire*)pe;
2893 
2894  if(pn != pw->Port1) pNode = pw->Port1;
2895  else pNode = pw->Port2;
2896 
2897  if(pNode->y1) continue;
2898  pNode->y1 = 1; // mark Node as already checked
2899  Cons.append(pNode);
2900  Cons.findRef(pn);
2901 
2902  if(pw->Label)
2903  {
2904  if(named)
2905  {
2906  delete pw->Label;
2907  pw->Label = 0; // erase double names
2908  }
2909  else
2910  {
2911  named = true;
2912  pl = pw->Label;
2913  }
2914  }
2915  }
2916  }
2917 }
2918 
2919 // ---------------------------------------------------
2921 {
2922  Node *pn;
2923  int x = pl->cx;
2924  int y = pl->cy;
2925 
2926  // check if new node lies upon an existing node
2927  for(pn = Nodes->first(); pn != 0; pn = Nodes->next())
2928  if(pn->cx == x) if(pn->cy == y) break;
2929 
2930  if(!pn) return -1;
2931 
2932  Element *pe = getWireLabel(pn);
2933  if(pe) // name found ?
2934  {
2935  if(pe->Type & isComponent)
2936  {
2937  delete pl;
2938  return -2; // ground potential
2939  }
2940 
2941  delete ((Conductor*)pe)->Label;
2942  ((Conductor*)pe)->Label = 0;
2943  }
2944 
2945  pn->Label = pl; // insert node label
2946  pl->Type = isNodeLabel;
2947  pl->pOwner = pn;
2948  return 0;
2949 }
2950 
2951 // ---------------------------------------------------
2952 // Test, if wire line is already labeled and returns a pointer to the
2953 // labeled element.
2955 {
2956  Wire *pw;
2957  Node *pn, *pNode;
2958  Element *pe;
2959  Q3PtrList<Node> Cons;
2960 
2961  for(pn = Nodes->first(); pn!=0; pn = Nodes->next())
2962  pn->y1 = 0; // mark all nodes as not checked
2963 
2964  Cons.append(pn_);
2965  pn_->y1 = 1; // mark Node as already checked
2966  for(pn = Cons.first(); pn!=0; pn = Cons.next())
2967  if(pn->Label) return pn;
2968  else
2969  for(pe = pn->Connections.first(); pe!=0; pe = pn->Connections.next())
2970  {
2971  if(pe->Type != isWire)
2972  {
2973  if(((Component*)pe)->isActive == COMP_IS_ACTIVE)
2974  if(((Component*)pe)->Model == "GND") return pe;
2975  continue;
2976  }
2977 
2978  pw = (Wire*)pe;
2979  if(pw->Label) return pw;
2980 
2981  if(pn != pw->Port1) pNode = pw->Port1;
2982  else pNode = pw->Port2;
2983 
2984  if(pNode->y1) continue;
2985  pNode->y1 = 1; // mark Node as already checked
2986  Cons.append(pNode);
2987  Cons.findRef(pn);
2988  }
2989  return 0; // no wire label found
2990 }
2991 
2992 // ---------------------------------------------------
2993 // Inserts a node label.
2995 {
2996  if(placeNodeLabel(pl) != -1)
2997  return;
2998 
2999  // Go on, if label don't lie on existing node.
3000 
3001  Wire *pw = selectedWire(pl->cx, pl->cy);
3002  if(pw) // lies label on existing wire ?
3003  {
3004  if(getWireLabel(pw->Port1) == 0) // wire not yet labeled ?
3005  pw->setName(pl->Name, pl->initValue, 0, pl->cx, pl->cy);
3006 
3007  delete pl;
3008  return;
3009  }
3010 
3011 
3012  Node *pn = new Node(pl->cx, pl->cy);
3013  Nodes->append(pn);
3014 
3015  pn->Label = pl;
3016  pl->Type = isNodeLabel;
3017  pl->pOwner = pn;
3018 }
3019 
3020 // ---------------------------------------------------
3021 void Schematic::copyLabels(int& x1, int& y1, int& x2, int& y2,
3022  Q3PtrList<Element> *ElementCache)
3023 {
3024  WireLabel *pl;
3025  // find bounds of all selected wires
3026  for(Wire *pw = Wires->first(); pw != 0; pw = Wires->next())
3027  {
3028  pl = pw->Label;
3029  if(pl) if(pl->isSelected)
3030  {
3031  if(pl->x1 < x1) x1 = pl->x1;
3032  if(pl->y1-pl->y2 < y1) y1 = pl->y1-pl->y2;
3033  if(pl->x1+pl->x2 > x2) x2 = pl->x1+pl->x2;
3034  if(pl->y1 > y2) y2 = pl->y1;
3035  ElementCache->append(pl);
3036  }
3037  }
3038 
3039  for(Node *pn = Nodes->first(); pn != 0; pn = Nodes->next())
3040  {
3041  pl = pn->Label;
3042  if(pl) if(pl->isSelected)
3043  {
3044  if(pl->x1 < x1) x1 = pl->x1;
3045  if(pl->y1-pl->y2 < y1) y1 = pl->y1-pl->y2;
3046  if(pl->x1+pl->x2 > x2) x2 = pl->x1+pl->x2;
3047  if(pl->y1 > y2) y2 = pl->y1;
3048  ElementCache->append(pl);
3049  pl->pOwner->Label = 0; // erase connection
3050  pl->pOwner = 0;
3051  }
3052  }
3053 }
3054 
3055 
3056 /* *******************************************************************
3057  ***** *****
3058  ***** Actions with paintings *****
3059  ***** *****
3060  ******************************************************************* */
3061 
3063 {
3064  float Corr = 5.0 / Scale; // size of line select
3065 
3066  for(Painting *pp = Paintings->first(); pp != 0; pp = Paintings->next())
3067  if(pp->getSelected(fX, fY, Corr))
3068  return pp;
3069 
3070  return 0;
3071 }
3072 
3073 // ---------------------------------------------------
3074 void Schematic::copyPaintings(int& x1, int& y1, int& x2, int& y2,
3075  Q3PtrList<Element> *ElementCache)
3076 {
3077  Painting *pp;
3078  int bx1, by1, bx2, by2;
3079  // find boundings of all selected paintings
3080  for(pp = Paintings->first(); pp != 0; )
3081  if(pp->isSelected)
3082  {
3083  pp->Bounding(bx1, by1, bx2, by2);
3084  if(bx1 < x1) x1 = bx1;
3085  if(bx2 > x2) x2 = bx2;
3086  if(by1 < y1) y1 = by1;
3087  if(by2 > y2) y2 = by2;
3088 
3089  ElementCache->append(pp);
3090  Paintings->take();
3091  pp = Paintings->current();
3092  }
3093  else pp = Paintings->next();
3094 }
Q3PtrList< Marker > Markers
Definition: graph.h:79
void deleteComp(Component *)
int insertWireNode2(Wire *)
bool distributeVertical()
bool getSelected(int, int)
Definition: wirelabel.cpp:97
bool connectHWires2(Wire *)
void recalcGraphData()
Definition: diagram.cpp:769
int Type
Definition: element.h:152
float textCorr()
Definition: schematic.cpp:922
bool moveUpDown(bool)
Definition: marker.cpp:331
Node * Connection
Definition: element.h:79
bool connectHWires1(Wire *)
Definition: node.h:30
bool aligning(int)
int y1
Definition: element.h:153
Marker * setMarker(int, int)
Definition: wire.h:31
int copyElements(int &, int &, int &, int &, Q3PtrList< Element > *)
label for Node and Wire classes
Definition: element.h:161
#define isNodeLabel
Definition: element.h:126
float Scale
Definition: qucsdoc.h:58
Definition: graph.h:57
int State
Definition: node.h:42
#define isDiagram
Definition: element.h:131
Node * selectedNode(int, int)
int insertWireNode1(Wire *)
int tx
Definition: component.h:78
int selectElements(int, int, int, int, bool)
int y2
Definition: element.h:153
Definition: element.h:72
Definition: marker.h:31
int x1
Definition: element.h:153
int insertWire(Wire *)
void copyPaintings(int &, int &, int &, int &, Q3PtrList< Element > *)
void deleteWire(Wire *)
bool activateSelectedComponents()
int copyWires(int &, int &, int &, int &, Q3PtrList< Element > *)
Node * insertNode(int, int, Element *)
void insertRawComponent(Component *, bool noOptimize=true)
int getSelected(int, int)
Definition: graph.cpp:148
void setHighlighted(bool newval)
Definition: wirelabel.h:42
Painting * selectedPainting(float, float)
#define isDigitalComponent
Definition: element.h:113
Q3PtrList< Diagram > * Diagrams
Definition: schematic.h:121
bool copyComps2WiresPaints(int &, int &, int &, int &, Q3PtrList< Element > *)
int ty
Definition: component.h:78
Wire * splitWire(Wire *, Node *)
QString Value
Definition: element.h:97
bool isHorizontal()
Definition: wire.cpp:123
bool connectVWires1(Wire *)
int cx
Definition: element.h:153
int copySelectedElements(Q3PtrList< Element > *)
#define isPaintingResize
Definition: element.h:121
Q3PtrList< Component > * Components
Definition: schematic.h:123
Element * selectElement(float, float, bool, int *index=0)
Q3PtrList< Property > Props
Definition: component.h:72
int y
Definition: element.h:75
bool isSelected
Definition: element.h:151
#define isVMovingLabel
Definition: element.h:129
Component * selectCompText(int, int, int &, int &)
Component * selectedComponent(int, int)
int UsedX2
Definition: schematic.h:133
Q3PtrList< Element > Connections
Definition: node.h:39
int placeNodeLabel(WireLabel *)
Q3PtrList< Node > * Nodes
Definition: schematic.h:120
bool oneTwoWires(Node *)
bool distributeHorizontal()
Q3PtrList< Graph > Graphs
Definition: diagram.h:95
QString Name
Definition: painting.h:55
void copyComponents2(int &, int &, int &, int &, Q3PtrList< Element > *)
void newMovingWires(Q3PtrList< Element > *, Node *, int)
void setCompPorts(Component *)
virtual void getCenter(int &, int &)
Definition: element.cpp:39
#define isAnalogComponent
Definition: element.h:112
Superclass of all schematic drawing elements.
Definition: element.h:142
#define isDiagramVScroll
Definition: element.h:134
void setCenter(int, int, bool relative=false)
Definition: wire.cpp:67
void insertComponentNodes(Component *, bool)
#define isDiagramHScroll
Definition: element.h:133
#define isHWireLabel
Definition: element.h:124
void Bounding(int &, int &, int &, int &)
Definition: component.cpp:76
bool connectVWires2(Wire *)
Q3PtrList< Port > Ports
Definition: component.h:70
bool moveLeftRight(bool)
Definition: marker.cpp:302
QString Name
Definition: element.h:97
#define isVWireLabel
Definition: element.h:125
bool activateSpecifiedComponent(int, int)
#define isPainting
Definition: element.h:120
QString Name
Definition: component.h:80
int copyComponents(int &, int &, int &, int &, Q3PtrList< Element > *)
void markerLeftRight(bool, Q3PtrList< Element > *)
QString Name
Definition: wirelabel.h:46
Element * getWireLabel(Node *)
#define isDiagramResize
Definition: element.h:132
QString Model
Definition: component.h:80
int UsedY2
Definition: schematic.h:133
Component * searchSelSubcircuit()
void markerUpDown(bool, Q3PtrList< Element > *)
Conductor * pOwner
Definition: wirelabel.h:42
int cy
Definition: element.h:153
#define isComponentText
Definition: element.h:111
void copyLabels(int &, int &, int &, int &, Q3PtrList< Element > *)
Wire * selectedWire(int, int)
WireLabel * Label
Definition: element.h:163
void selectWireLine(Element *, Node *, bool)
#define isMovingLabel
Definition: element.h:127
#define isComponent
Definition: element.h:110
Node * Port1
Definition: wire.h:43
void setComponentNumber(Component *)
#define isHMovingLabel
Definition: element.h:128
void setCenter(int, int, bool relative=false)
Definition: component.cpp:129
void activateCompsWithinRect(int, int, int, int)
int UsedX1
Definition: schematic.h:133
void recreateComponent(Component *)
void sizeOfAll(int &, int &, int &, int &)
Definition: schematic.cpp:931
void deselectElements(Element *)
void oneLabel(Node *)
#define isWire
Definition: element.h:118
int x2
Definition: element.h:153
Q3PtrList< Painting > * Paintings
Definition: schematic.h:122
#define COMP_IS_ACTIVE
Definition: component.h:75
Node * Port2
Definition: wire.h:43
Q3PtrList< Wire > * Wires
Definition: schematic.h:119
int UsedY1
Definition: schematic.h:133
virtual void Bounding(int &, int &, int &, int &)
Definition: painting.cpp:33
int x
Definition: element.h:75
void insertComponent(Component *)
void setName(const QString &, const QString &, int delta_=0, int x_=0, int y_=0)
Definition: wire.cpp:129
bool getSelected(int, int)
Definition: marker.cpp:569
QString initValue
Definition: wirelabel.h:46
virtual void recreate(Schematic *)
Definition: component.h:39
void highlightWireLabels(void)
virtual void setCenter(int, int, bool relative=false)
Definition: element.cpp:35
void setChanged(bool, bool fillStack=false, char Op='*')
Definition: schematic.cpp:278
void insertNodeLabel(WireLabel *)
Graph * pGraph
Definition: marker.h:52