Qucs-GUI  0.0.18
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
schematic.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  schematic.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 
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include <QtGui>
22 #include <stdlib.h>
23 #include <limits.h>
24 
25 #include <QImage>
26 #include <QAction>
27 #include <QRegExp>
28 #include <QIcon>
29 #include <QPrinter>
30 #include <QLineEdit>
31 #include <QFileInfo>
32 #include <Q3IconView>
33 #include <QTabWidget>
34 #include <Q3DragObject>
35 #include <Q3PaintDeviceMetrics>
36 #include <QDir>
37 
38 #include "qucs.h"
39 //Added by qt3to4:
40 #include <QTextStream>
41 #include <QDragLeaveEvent>
42 #include <Q3StrList>
43 #include <Q3PtrList>
44 #include <QPixmap>
45 #include <QDragEnterEvent>
46 #include <QDragMoveEvent>
47 #include <QDropEvent>
48 #include <QMouseEvent>
49 #include <QEvent>
50 #include <QWheelEvent>
51 #include "main.h"
52 #include "node.h"
53 #include "schematic.h"
54 #include "textdoc.h"
55 #include "viewpainter.h"
56 #include "mouseactions.h"
57 #include "diagrams/diagrams.h"
58 #include "paintings/paintings.h"
59 #include "components/vhdlfile.h"
60 #include "components/verilogfile.h"
61 #include "components/vafile.h"
62 
63 // just dummies for empty lists
64 Q3PtrList<Wire> SymbolWires;
65 Q3PtrList<Node> SymbolNodes;
66 Q3PtrList<Diagram> SymbolDiags;
67 Q3PtrList<Component> SymbolComps;
68 
69 
70 Schematic::Schematic(QucsApp *App_, const QString& Name_)
71  : QucsDoc(App_, Name_)
72 {
73  symbolMode = false;
74 
75  // ...........................................................
76  GridX = GridY = 10;
77  ViewX1=ViewY1=0;
78  ViewX2=ViewY2=800;
79  UsedX1 = UsedY1 = INT_MAX;
80  UsedX2 = UsedY2 = INT_MIN;
81 
82  tmpPosX = tmpPosY = -100;
85  tmpScale = 1.0;
86 
87  DocComps.setAutoDelete(true);
88  DocWires.setAutoDelete(true);
89  DocNodes.setAutoDelete(true);
90  DocDiags.setAutoDelete(true);
91  DocPaints.setAutoDelete(true);
92  SymbolPaints.setAutoDelete(true);
93 
94  UndoStack.setAutoDelete(true);
95  UndoSymbol.setAutoDelete(true);
96  // The 'i' means state for being unchanged.
97  UndoStack.append(new QString(" i\n</>\n</>\n</>\n</>\n"));
98  UndoSymbol.append(new QString(" i\n</>\n</>\n</>\n</>\n"));
99 
100  isVerilog = false;
101  creatingLib = false;
102  FileInfo = QFileInfo (Name_);
103  if(App) {
104  if(Name_.isEmpty())
105  App->DocumentTab->addTab(this, QPixmap(empty_xpm),
106  QObject::tr("untitled"));
107  else
108  App->DocumentTab->addTab(this, QPixmap(empty_xpm),
109  FileInfo.fileName());
110 
111  // calls indirectly "becomeCurrent"
112  App->DocumentTab->setCurrentPage(App->DocumentTab->indexOf(this));
113 
114  showFrame = 0; // don't show
115  Frame_Text0 = tr("Title");
116  Frame_Text1 = tr("Drawn By:");
117  Frame_Text2 = tr("Date:");
118  Frame_Text3 = tr("Revision:");
119 
120  setVScrollBarMode(Q3ScrollView::AlwaysOn);
121  setHScrollBarMode(Q3ScrollView::AlwaysOn);
122  viewport()->setPaletteBackgroundColor(QucsSettings.BGColor);
123  viewport()->setMouseTracking(true);
124  viewport()->setAcceptDrops(true); // enable drag'n drop
125 // FIXME #warning removed those signals, crashes on it...
126  /*connect(horizontalScrollBar(),
127  SIGNAL(prevLine()), SLOT(slotScrollLeft()));
128  connect(horizontalScrollBar(),
129  SIGNAL(nextLine()), SLOT(slotScrollRight()));
130  connect(verticalScrollBar(),
131  SIGNAL(prevLine()), SLOT(slotScrollUp()));
132  connect(verticalScrollBar(),
133  SIGNAL(nextLine()), SLOT(slotScrollDown()));*/
134 
135  // ...........................................................
136 
137  // to repair some strange scrolling artefacts
138  connect(this, SIGNAL(horizontalSliderReleased()),
139  viewport(), SLOT(update()));
140  connect(this, SIGNAL(verticalSliderReleased()),
141  viewport(), SLOT(update()));
142 
143  // to prevent user from editing something that he doesn't see
144  connect(this, SIGNAL(horizontalSliderPressed()), App, SLOT(slotHideEdit()));
145  connect(this, SIGNAL(verticalSliderPressed()), App, SLOT(slotHideEdit()));
146  } // of "if(App)"
147 }
148 
150 {
151  if(App) {
152  App->editText->reparent(App, 0, QPoint(0, 0));
153  App->DocumentTab->removePage(this); // delete tab in TabBar
154  }
155 }
156 
157 // ---------------------------------------------------
159 {
160  // If the number of ports is not equal, remove or add some.
161  unsigned int countPort = adjustPortNumbers();
162 
163  // If a symbol does not yet exist, create one.
164  if(SymbolPaints.count() != countPort)
165  return false;
166 
167  int h = 30*((countPort-1)/2) + 10;
168  SymbolPaints.prepend(new ID_Text(-20, h+4));
169 
170  SymbolPaints.append(
171  new GraphicLine(-20, -h, 40, 0, QPen(Qt::darkBlue,2)));
172  SymbolPaints.append(
173  new GraphicLine( 20, -h, 0,2*h, QPen(Qt::darkBlue,2)));
174  SymbolPaints.append(
175  new GraphicLine(-20, h, 40, 0, QPen(Qt::darkBlue,2)));
176  SymbolPaints.append(
177  new GraphicLine(-20, -h, 0,2*h, QPen(Qt::darkBlue,2)));
178 
179  unsigned int i=0, y = 10-h;
180  while(i<countPort) {
181  i++;
182  SymbolPaints.append(
183  new GraphicLine(-30, y, 10, 0, QPen(Qt::darkBlue,2)));
184  SymbolPaints.at(i)->setCenter(-30, y);
185 
186  if(i == countPort) break;
187  i++;
188  SymbolPaints.append(
189  new GraphicLine( 20, y, 10, 0, QPen(Qt::darkBlue,2)));
190  SymbolPaints.at(i)->setCenter(30, y);
191  y += 60;
192  }
193  return true;
194 }
195 
196 // ---------------------------------------------------
197 void Schematic::becomeCurrent(bool update)
198 {
199  QString *ps;
200  App->printCursorPosition(0, 0);
201 
202  // update appropriate menu entry
203  if (symbolMode) {
204  if (DocName.right(4) == ".sym") {
205  App->symEdit->setMenuText(tr("Edit Text"));
206  App->symEdit->setStatusTip(tr("Edits the Text"));
207  App->symEdit->setWhatsThis(tr("Edit Text\n\nEdits the text file"));
208  }
209  else {
210  App->symEdit->setMenuText(tr("Edit Schematic"));
211  App->symEdit->setStatusTip(tr("Edits the schematic"));
212  App->symEdit->setWhatsThis(tr("Edit Schematic\n\nEdits the schematic"));
213  }
214  }
215  else {
216  App->symEdit->setMenuText(tr("Edit Circuit Symbol"));
217  App->symEdit->setStatusTip(tr("Edits the symbol for this schematic"));
218  App->symEdit->setWhatsThis(
219  tr("Edit Circuit Symbol\n\nEdits the symbol for this schematic"));
220  }
221 
222  if(symbolMode) {
223  Nodes = &SymbolNodes;
224  Wires = &SymbolWires;
228 
229  // if no symbol yet exists -> create one
230  if(createSubcircuitSymbol()) {
232  setChanged(true, true);
233  }
234 
235  ps = UndoSymbol.current();
236  if(ps != UndoSymbol.getFirst()) App->undo->setEnabled(true);
237  else App->undo->setEnabled(false);
238  if(ps != UndoSymbol.getLast()) App->redo->setEnabled(true);
239  else App->redo->setEnabled(false);
240  }
241  else {
242  Nodes = &DocNodes;
243  Wires = &DocWires;
244  Diagrams = &DocDiags;
245  Paintings = &DocPaints;
246  Components = &DocComps;
247 
248  ps = UndoStack.current();
249  if(ps != UndoStack.getFirst()) App->undo->setEnabled(true);
250  else App->undo->setEnabled(false);
251  if(ps != UndoStack.getLast()) App->redo->setEnabled(true);
252  else App->redo->setEnabled(false);
253 
254  if(update)
255  reloadGraphs(); // load recent simulation data
256  }
257 }
258 
259 // ---------------------------------------------------
260 void Schematic::setName (const QString& Name_)
261 {
262  DocName = Name_;
263  QFileInfo Info (DocName);
264  if (App) App->DocumentTab->setTabLabel (this, Info.fileName ());
265 
266  QString base = Info.baseName (true);
267  QString ext = Info.extension (false);
268  DataSet = base + ".dat";
269  Script = base + ".m";
270  if (ext != "dpl")
271  DataDisplay = base + ".dpl";
272  else
273  DataDisplay = base + ".sch";
274 }
275 
276 // ---------------------------------------------------
277 // Sets the document to be changed or not to be changed.
278 void Schematic::setChanged(bool c, bool fillStack, char Op)
279 {
280  if((!DocChanged) && c)
281  App->DocumentTab->setTabIconSet(this, QPixmap(smallsave_xpm));
282  else if(DocChanged && (!c))
283  App->DocumentTab->setTabIconSet(this, QPixmap(empty_xpm));
284  DocChanged = c;
285 
286  showBias = -1; // schematic changed => bias points may be invalid
287 
288  if(!fillStack)
289  return;
290 
291 
292  // ................................................
293  if(symbolMode) { // for symbol edit mode
294  QString *Curr = UndoSymbol.current();
295  while(Curr != UndoSymbol.last())
296  UndoSymbol.remove(); // remove "Redo" items
297 
298  UndoSymbol.append(new QString(createSymbolUndoString(Op)));
299 
300  if(!App->undo->isEnabled()) App->undo->setEnabled(true);
301  if(App->redo->isEnabled()) App->redo->setEnabled(false);
302 
303  while(UndoSymbol.count() > QucsSettings.maxUndo) { // "while..." because
304  UndoSymbol.removeFirst(); // "maxUndo" could be decreased meanwhile
305  UndoSymbol.last();
306  }
307  return;
308  }
309 
310  // ................................................
311  // for schematic edit mode
312  QString *Curr = UndoStack.current();
313  while(Curr != UndoStack.last())
314  UndoStack.remove(); // remove "Redo" items
315 
316  if(Op == 'm') // only one for move marker
317  if(UndoStack.current()->at(0) == Op)
318  UndoStack.remove();
319 
320  UndoStack.append(new QString(createUndoString(Op)));
321 
322  if(!App->undo->isEnabled()) App->undo->setEnabled(true);
323  if(App->redo->isEnabled()) App->redo->setEnabled(false);
324 
325  while(UndoStack.count() > QucsSettings.maxUndo) { // "while..." because
326  UndoStack.removeFirst(); // "maxUndo" could be decreased meanwhile
327  UndoStack.last();
328  }
329 }
330 
331 // -----------------------------------------------------------
332 bool Schematic::sizeOfFrame(int& xall, int& yall)
333 {
334  // Values exclude border of 1.5cm at each side.
335  switch(showFrame) {
336  case 1: xall = 1020; yall = 765; break; // DIN A5 landscape
337  case 2: xall = 765; yall = 1020; break; // DIN A5 portrait
338  case 3: xall = 1530; yall = 1020; break; // DIN A4 landscape
339  case 4: xall = 1020; yall = 1530; break; // DIN A4 portrait
340  case 5: xall = 2295; yall = 1530; break; // DIN A3 landscape
341  case 6: xall = 1530; yall = 2295; break; // DIN A3 portrait
342  case 7: xall = 1414; yall = 1054; break; // letter landscape
343  case 8: xall = 1054; yall = 1414; break; // letter portrait
344  default: return false;
345  }
346 
347  return true;
348 }
349 
350 // -----------------------------------------------------------
352 {
353  // dimensions: X cm / 2.54 * 144
354  int xall, yall;
355  if(!sizeOfFrame(xall, yall))
356  return;
357  p->Painter->setPen(QPen(Qt::darkGray,1));
358  //p->Painter->setPen(QPen(Qt::black,0));
359  int d = p->LineSpacing + int(4.0 * p->Scale);
360  int x1_, y1_, x2_, y2_;
361  p->map(xall, yall, x1_, y1_);
362  x2_ = int(xall * p->Scale) + 1;
363  y2_ = int(yall * p->Scale) + 1;
364  p->Painter->drawRect(x1_, y1_, -x2_, -y2_);
365  p->Painter->drawRect(x1_-d, y1_-d, 2*d-x2_, 2*d-y2_);
366 
367  int z;
368  int step = xall / ((xall+127) / 255);
369  for(z=step; z<=xall-step; z+=step) {
370  p->map(z, 0, x2_, y2_);
371  p->Painter->drawLine(x2_, y2_, x2_, y2_+d);
372  p->Painter->drawLine(x2_, y1_-d, x2_, y1_);
373  }
374  char Letter[2] = "1";
375  for(z=step/2+5; z<xall; z+=step) {
376  p->drawText(Letter, z, 3, 0);
377  p->map(z, yall+3, x2_, y2_);
378  p->Painter->drawText(x2_, y2_-d, 0, 0, Qt::TextDontClip, Letter);
379  Letter[0]++;
380  }
381 
382  step = yall / ((yall+127) / 255);
383  for(z=step; z<=yall-step; z+=step) {
384  p->map(0, z, x2_, y2_);
385  p->Painter->drawLine(x2_, y2_, x2_+d, y2_);
386  p->Painter->drawLine(x1_-d, y2_, x1_, y2_);
387  }
388  Letter[0] = 'A';
389  for(z=step/2+5; z<yall; z+=step) {
390  p->drawText(Letter, 5, z, 0);
391  p->map(xall+5, z, x2_, y2_);
392  p->Painter->drawText(x2_-d, y2_, 0, 0, Qt::TextDontClip, Letter);
393  Letter[0]++;
394  }
395 
396  // draw text box with text
397  p->map(xall-340, yall-3, x1_, y1_);
398  p->map(xall-3, yall-3, x2_, y2_);
399  x1_ -= d; x2_ -= d;
400  y1_ -= d; y2_ -= d;
401  d = int(6.0 * p->Scale);
402  z = int(200.0 * p->Scale);
403  y1_ -= p->LineSpacing + d;
404  p->Painter->drawLine(x1_, y1_, x2_, y1_);
405  p->Painter->drawText(x1_+d, y1_+(d>>1), 0, 0, Qt::TextDontClip, Frame_Text2);
406  p->Painter->drawLine(x1_+z, y1_, x1_+z, y1_ + p->LineSpacing+d);
407  p->Painter->drawText(x1_+d+z, y1_+(d>>1), 0, 0, Qt::TextDontClip, Frame_Text3);
408  y1_ -= p->LineSpacing + d;
409  p->Painter->drawLine(x1_, y1_, x2_, y1_);
410  p->Painter->drawText(x1_+d, y1_+(d>>1), 0, 0, Qt::TextDontClip, Frame_Text1);
411  y1_ -= (Frame_Text0.count('\n')+1) * p->LineSpacing + d;
412  p->Painter->drawRect(x2_, y2_, x1_-x2_-1, y1_-y2_-1);
413  p->Painter->drawText(x1_+d, y1_+(d>>1), 0, 0, Qt::TextDontClip, Frame_Text0);
414 }
415 
416 // -----------------------------------------------------------
417 // Is called when the content (schematic or data display) has to be drawn.
418 void Schematic::drawContents(QPainter *p, int, int, int, int)
419 {
420  ViewPainter Painter;
421  Painter.init(p, Scale, -ViewX1, -ViewY1, contentsX(), contentsY());
422 
423  paintGrid(&Painter, contentsX(), contentsY(),
424  visibleWidth(), visibleHeight());
425 
426  if(!symbolMode)
427  paintFrame(&Painter);
428 
429  for(Component *pc = Components->first(); pc != 0; pc = Components->next())
430  pc->paint(&Painter);
431 
432  for(Wire *pw = Wires->first(); pw != 0; pw = Wires->next()) {
433  pw->paint(&Painter);
434  if(pw->Label)
435  pw->Label->paint(&Painter); // separate because of paintSelected
436  }
437 
438  Node *pn;
439  for(pn = Nodes->first(); pn != 0; pn = Nodes->next()) {
440  pn->paint(&Painter);
441  if(pn->Label)
442  pn->Label->paint(&Painter); // separate because of paintSelected
443  }
444 
445  // FIXME disable here, issue with select box goes away
446  // also, instead of red, line turns blue
447  for(Diagram *pd = Diagrams->first(); pd != 0; pd = Diagrams->next())
448  pd->paint(&Painter);
449 
450  for(Painting *pp = Paintings->first(); pp != 0; pp = Paintings->next())
451  pp->paint(&Painter);
452 
453  if(showBias > 0) { // show DC bias points in schematic ?
454  int x, y, z;
455  for(pn = Nodes->first(); pn != 0; pn = Nodes->next()) {
456  if(pn->Name.isEmpty()) continue;
457  x = pn->cx;
458  y = pn->cy + 4;
459  z = pn->x1;
460  if(z & 1) x -= Painter.Painter->fontMetrics().width(pn->Name);
461  if(!(z & 2)) {
462  y -= (Painter.LineSpacing>>1) + 4;
463  if(z & 1) x -= 4;
464  else x += 4;
465  }
466  if(z & 0x10)
467  Painter.Painter->setPen(Qt::darkGreen); // green for currents
468  else
469  Painter.Painter->setPen(Qt::blue); // blue for voltages
470  Painter.drawText(pn->Name, x, y);
471  }
472  }
473 
474  /*
475  * The following events used to be drawn from mouseactions.cpp, but since Qt4
476  * Paint actions can only be called from within the paint event, so they
477  * are put into a QList (PostedPaintEvents) and processed here
478  */
479  for(int i=0;i<PostedPaintEvents.size();i++)
480  {
482  QPainter painter2(viewport());
483 
484  switch(p.pe)
485  {
486  case _NotRop:
487  if(p.PaintOnViewport)
488  painter2.setCompositionMode(QPainter::RasterOp_SourceAndNotDestination);
489  else
490  Painter.Painter->setCompositionMode(QPainter::RasterOp_SourceAndNotDestination);
491  break;
492  case _Rect:
493  if(p.PaintOnViewport)
494  painter2.drawRect(p.x1, p.y1, p.x2, p.y2);
495  else
496  Painter.drawRect(p.x1, p.y1, p.x2, p.y2);
497  break;
498  case _Line:
499  if(p.PaintOnViewport)
500  painter2.drawLine(p.x1, p.y1, p.x2, p.y2);
501  else
502  Painter.drawLine(p.x1, p.y1, p.x2, p.y2);
503  break;
504  case _Ellipse:
505  if(p.PaintOnViewport)
506  painter2.drawEllipse(p.x1, p.y1, p.x2, p.y2);
507  else
508  Painter.drawEllipse(p.x1, p.y1, p.x2, p.y2);
509  break;
510  case _Arc:
511  if(p.PaintOnViewport)
512  painter2.drawArc(p.x1, p.y1, p.x2, p.y2, p.a, p.b);
513  else
514  Painter.drawArc(p.x1, p.y1, p.x2, p.y2, p.a, p.b);
515  break;
516  case _DotLine:
517  Painter.Painter->setPen(Qt::DotLine);
518  break;
519  case _Translate:
520 
521  painter2.translate(p.x1, p.y1);
522  break;
523  case _Scale:
524  painter2.scale(p.x1,p.y1);
525  break;
526  }
527 
528  }
529  PostedPaintEvents.clear();
530 
531 }
532 
533 void Schematic::PostPaintEvent (PE pe, int x1, int y1, int x2, int y2, int a, int b, bool PaintOnViewport)
534 {
535  PostedPaintEvent p = {pe, x1,y1,x2,y2,a,b,PaintOnViewport};
536  PostedPaintEvents.push_back(p);
537  viewport()->update();
538  update();
539 }
540 
541 
542 // ---------------------------------------------------
543 void Schematic::contentsMouseMoveEvent(QMouseEvent *Event)
544 {
545  if(App->MouseMoveAction)
546  (App->view->*(App->MouseMoveAction))(this, Event);
547 }
548 
549 // -----------------------------------------------------------
550 void Schematic::contentsMousePressEvent(QMouseEvent *Event)
551 {
552  App->editText->setHidden(true); // disable text edit of component property
554  return;
555 
556  float x = float(Event->pos().x())/Scale + float(ViewX1);
557  float y = float(Event->pos().y())/Scale + float(ViewY1);
558 
559  if(Event->button() != Qt::LeftButton)
562  // show menu on right mouse button
563  App->view->rightPressMenu(this, Event, x, y);
565  // Is not called automatically because menu has focus.
566  (App->view->*(App->MouseReleaseAction))(this, Event);
567  return;
568  }
569 
570  if(App->MousePressAction)
571  (App->view->*(App->MousePressAction))(this, Event, x, y);
572 }
573 
574 // -----------------------------------------------------------
575 void Schematic::contentsMouseReleaseEvent(QMouseEvent *Event)
576 {
578  (App->view->*(App->MouseReleaseAction))(this, Event);
579 }
580 
581 // -----------------------------------------------------------
583 {
585  (App->view->*(App->MouseDoubleClickAction))(this, Event);
586 }
587 
588 // -----------------------------------------------------------
589 void Schematic::print(QPrinter*, QPainter *Painter, bool printAll, bool fitToPage)
590 {
591  Q3PaintDeviceMetrics pmetrics(Painter->device());
592  float printerDpiX = (float)pmetrics.logicalDpiX();
593  float printerDpiY = (float)pmetrics.logicalDpiY();
594  float printerW = (float)pmetrics.width();
595  float printerH = (float)pmetrics.height();
596  QPainter pa(viewport());
597  Q3PaintDeviceMetrics smetrics(pa.device());
598  float screenDpiX = (float)smetrics.logicalDpiX();
599  float screenDpiY = (float)smetrics.logicalDpiY();
600  float PrintScale = 0.5;
602  int marginX = (int)(40 * printerDpiX / screenDpiX);
603  int marginY = (int)(40 * printerDpiY / screenDpiY);
604 
605  if(fitToPage) {
606 
607  float ScaleX = float((printerW - 2*marginX) /
608  float((UsedX2-UsedX1) * printerDpiX)) * screenDpiX;
609  float ScaleY = float((printerH - 2*marginY) /
610  float((UsedY2-UsedY1) * printerDpiY)) * screenDpiY;
611 
612  if(showFrame){
613  int xall, yall;
614  sizeOfFrame(xall, yall);
615  ScaleX = ((float)(printerW - 2*marginX) /
616  (float)(xall * printerDpiX)) * screenDpiX;
617  ScaleY = ((float)(printerH - 2*marginY) /
618  (float)(yall * printerDpiY)) * screenDpiY;
619  }
620 
621  if(ScaleX > ScaleY)
622  PrintScale = ScaleY;
623  else
624  PrintScale = ScaleX;
625  }
626 
627 
628  //bool selected;
629  ViewPainter p;
630  int StartX = UsedX1;
631  int StartY = UsedY1;
632  if(showFrame) {
633  if(UsedX1 > 0) StartX = 0;
634  if(UsedY1 > 0) StartY = 0;
635  }
636 
637  float PrintRatio = printerDpiX / screenDpiX;
638  QFont oldFont = Painter->font();
639  QFont printFont = Painter->font();
640 #ifdef __MINGW32__
641  printFont.setPointSizeF(printFont.pointSizeF()/PrintRatio);
642  Painter->setFont(printFont);
643 #endif
644  p.init(Painter, PrintScale * PrintRatio,
645  -StartX, -StartY, -marginX, -marginY,
646  PrintScale, PrintRatio);
647 
648  if(!symbolMode)
649  paintFrame(&p);
650 
651  paintSchToViewpainter(&p,printAll,false,screenDpiX,printerDpiX);
652 
653  Painter->setFont(oldFont);
654 }
655 
656 
657 void Schematic::paintSchToViewpainter(ViewPainter *p, bool printAll, bool toImage, int screenDpiX, int printerDpiX)
658 {
659  bool selected;
660 
661  for(Component *pc = Components->first(); pc != 0; pc = Components->next())
662  if(pc->isSelected || printAll) {
663  selected = pc->isSelected;
664  pc->isSelected = false;
665  if (toImage) {
666  pc->paint(p);
667  } else {
668  pc->print(p, (float)screenDpiX / (float)printerDpiX);
669  }
670  pc->isSelected = selected;
671  }
672 
673  for(Wire *pw = Wires->first(); pw != 0; pw = Wires->next()) {
674  if(pw->isSelected || printAll) {
675  selected = pw->isSelected;
676  pw->isSelected = false;
677  pw->paint(p); // paint all selected wires
678  pw->isSelected = selected;
679  }
680  if(pw->Label)
681  if(pw->Label->isSelected || printAll) {
682  selected = pw->Label->isSelected;
683  pw->Label->isSelected = false;
684  pw->Label->paint(p);
685  pw->Label->isSelected = selected;
686  }
687  }
688 
689  Element *pe;
690  for(Node *pn = Nodes->first(); pn != 0; pn = Nodes->next()) {
691  for(pe = pn->Connections.first(); pe != 0; pe = pn->Connections.next())
692  if(pe->isSelected || printAll) {
693  pn->paint(p); // paint all nodes with selected elements
694  break;
695  }
696  if(pn->Label)
697  if(pn->Label->isSelected || printAll) {
698  selected = pn->Label->isSelected;
699  pn->Label->isSelected = false;
700  pn->Label->paint(p);
701  pn->Label->isSelected = selected;
702  }
703  }
704 
705  for(Painting *pp = Paintings->first(); pp != 0; pp = Paintings->next())
706  if(pp->isSelected || printAll) {
707  selected = pp->isSelected;
708  pp->isSelected = false;
709  pp->paint(p); // paint all selected paintings
710  pp->isSelected = selected;
711  }
712 
713  Graph *pg;
714  Marker *pm;
715  for(Diagram *pd = Diagrams->first(); pd != 0; pd = Diagrams->next())
716  if(pd->isSelected || printAll) {
717  // if graph or marker is selected, deselect during printing
718  for(pg = pd->Graphs.first(); pg != 0; pg = pd->Graphs.next()) {
719  if(pg->isSelected) pg->Type |= 1; // remember selection
720  pg->isSelected = false;
721  for(pm = pg->Markers.first(); pm != 0; pm = pg->Markers.next()) {
722  if(pm->isSelected) pm->Type |= 1; // remember selection
723  pm->isSelected = false;
724  }
725  }
726 
727  selected = pd->isSelected;
728  pd->isSelected = false;
729  pd->paint(p); // paint all selected diagrams with graphs and markers
730  pd->isSelected = selected;
731 
732  // revert selection of graphs and markers
733  for(pg = pd->Graphs.first(); pg != 0; pg = pd->Graphs.next()) {
734  if(pg->Type & 1) pg->isSelected = true;
735  pg->Type &= -2;
736  for(pm = pg->Markers.first(); pm != 0; pm = pg->Markers.next()) {
737  if(pm->Type & 1) pm->isSelected = true;
738  pm->Type &= -2;
739  }
740  }
741  }
742 }
743 
744 // -----------------------------------------------------------
745 float Schematic::zoom(float s)
746 {
747  Scale *= s;
748  if(Scale > 10.0) Scale = 10.0f;
749  if(Scale < 0.1) Scale = 0.1f;
750 
751  // "resizeContents()" performs an immediate repaint. So, set widget
752  // to hidden. This causes some flicker, but it is still nicer.
753  viewport()->setHidden(true);
754 // setHidden(true);
755  resizeContents(int(Scale*float(ViewX2 - ViewX1)),
756  int(Scale*float(ViewY2 - ViewY1)));
757 // setHidden(false);
758  viewport()->setHidden(false);
759 
760  viewport()->update();
761  App->view->drawn = false;
762  return Scale;
763 }
764 
765 // -----------------------------------------------------------
766 float Schematic::zoomBy(float s)
767 {
768  zoom(s);
769  s -= 1.0;
770  scrollBy( int(s * float(contentsX()+visibleWidth()/2)),
771  int(s * float(contentsY()+visibleHeight()/2)) );
772  return Scale;
773 }
774 
775 // ---------------------------------------------------
777 {
779  if(UsedX1 == 0)
780  if(UsedX2 == 0)
781  if(UsedY1 == 0)
782  if(UsedY2 == 0) {
783  UsedX1 = UsedY1 = INT_MAX;
784  UsedX2 = UsedY2 = INT_MIN;
785  return;
786  }
787 
788  float xScale = float(visibleWidth()) / float(UsedX2-UsedX1+80);
789  float yScale = float(visibleHeight()) / float(UsedY2-UsedY1+80);
790  if(xScale > yScale) xScale = yScale;
791  xScale /= Scale;
792 
793  ViewX1 = UsedX1 - 40;
794  ViewY1 = UsedY1 - 40;
795  ViewX2 = UsedX2 + 40;
796  ViewY2 = UsedY2 + 40;
797  zoom(xScale);
798 }
799 
800 // ---------------------------------------------------
802 {
803  Scale = 1.0;
804 
805  int x1 = UsedX1;
806  int y1 = UsedY1;
807  int x2 = UsedX2;
808  int y2 = UsedY2;
809 
810  if(x1 > x2) { // happens e.g. if untitled without changes
811  x1 = 0;
812  x2 = 800;
813  }
814  if(y1 > y2) {
815  y1 = 0;
816  y2 = 800;
817  }
818  if(x2==0) if(y2==0) if(x1==0) if(y1==0) x2 = y2 = 800;
819 
820  ViewX1 = x1-40;
821  ViewY1 = y1-40;
822  ViewX2 = x2+40;
823  ViewY2 = y2+40;
824  resizeContents(x2-x1+80, y2-y1+80);
825  viewport()->update();
826  App->view->drawn = false;
827 }
828 
829 // -----------------------------------------------------------
830 // Enlarge the viewport area if the coordinates x1-x2/y1-y2 exceed the
831 // visible area.
832 void Schematic::enlargeView(int x1, int y1, int x2, int y2)
833 {
834  int dx=0, dy=0;
835  if(x1 < UsedX1) UsedX1 = x1;
836  if(y1 < UsedY1) UsedY1 = y1;
837  if(x2 > UsedX2) UsedX2 = x2;
838  if(y2 > UsedY2) UsedY2 = y2;
839 
840  if(x1 < ViewX1) {
841  dx = int(Scale * float(ViewX1-x1+40));
842  ViewX1 = x1-40;
843  }
844  if(y1 < ViewY1) {
845  dy = int(Scale * float(ViewY1-y1+40));
846  ViewY1 = y1-40;
847  }
848  if(x2 > ViewX2) ViewX2 = x2+40;
849  if(y2 > ViewY2) ViewY2 = y2+40;
850 
851  resizeContents(int(Scale*float(ViewX2 - ViewX1)),
852  int(Scale*float(ViewY2 - ViewY1)));
853  scrollBy(dx,dy);
854 }
855 
856 // ---------------------------------------------------
857 // Sets an arbitrary coordinate onto the next grid coordinate.
858 void Schematic::setOnGrid(int& x, int& y)
859 {
860  if(x<0) x -= (GridX >> 1) - 1;
861  else x += GridX >> 1;
862  x -= x % GridX;
863 
864  if(y<0) y -= (GridY >> 1) - 1;
865  else y += GridY >> 1;
866  y -= y % GridY;
867 }
868 
869 // ---------------------------------------------------
870 void Schematic::paintGrid(ViewPainter *p, int cX, int cY, int Width, int Height)
871 {
872  if(!GridOn) return;
873 
874  p->Painter->setPen(QPen(Qt::black,0));
875  int dx = -int(Scale*float(ViewX1)) - cX;
876  int dy = -int(Scale*float(ViewY1)) - cY;
877  p->Painter->drawLine(-3+dx, dy, 4+dx, dy); // small cross at origin
878  p->Painter->drawLine( dx,-3+dy, dx, 4+dy);
879 
880 
881  int x1 = int(float(cX)/Scale) + ViewX1;
882  int y1 = int(float(cY)/Scale) + ViewY1;
883 
884  // setOnGrid(x1, y1) for 2*Grid
885  if(x1<0) x1 -= GridX - 1;
886  else x1 += GridX;
887  x1 -= x1 % (GridX << 1);
888 
889  if(y1<0) y1 -= GridY - 1;
890  else y1 += GridY;
891  y1 -= y1 % (GridY << 1);
892 
893  float X, Y, Y0, DX, DY;
894  X = float(x1)*Scale + p->DX;
895  Y = Y0 = float(y1)*Scale + p->DY;
896  x1 = X > 0.0 ? int(X + 0.5) : int(X - 0.5);
897  y1 = Y > 0.0 ? int(Y + 0.5) : int(Y - 0.5);
898 
899 
900  int xEnd = x1 + Width;
901  int yEnd = y1 + Height;
902  DX = float(GridX << 1) * Scale; // every second grid a point
903  DY = float(GridY << 1) * Scale;
904  while(DX <= 8.0) DX *= 1.5; // if too narrow, every third grid a point
905  while(DY <= 8.0) DY *= 1.5; // if too narrow, every third grid a point
906 
907  while(x1 < xEnd) {
908  Y = Y0;
909  y1 = Y > 0.0 ? int(Y + 0.5) : int(Y - 0.5);
910  while(y1 < yEnd) {
911  p->Painter->drawPoint(x1, y1); // paint grid
912  Y += DY;
913  y1 = Y > 0.0 ? int(Y + 0.5) : int(Y - 0.5);
914  }
915  X += DX;
916  x1 = X > 0.0 ? int(X + 0.5) : int(X - 0.5);
917  }
918 }
919 
920 // ---------------------------------------------------
921 // Correction factor for unproportional font scaling.
923 {
924  QFont Font = QucsSettings.font;
925  Font.setPointSizeFloat( Scale * float(Font.pointSize()) );
926  QFontMetrics metrics(Font);
927  return (Scale / float(metrics.lineSpacing()));
928 }
929 
930 // ---------------------------------------------------
931 void Schematic::sizeOfAll(int& xmin, int& ymin, int& xmax, int& ymax)
932 {
933  xmin=INT_MAX;
934  ymin=INT_MAX;
935  xmax=INT_MIN;
936  ymax=INT_MIN;
937  Component *pc;
938  Diagram *pd;
939  Wire *pw;
940  WireLabel *pl;
941  Painting *pp;
942 
943  if(Components->isEmpty())
944  if(Wires->isEmpty())
945  if(Diagrams->isEmpty())
946  if(Paintings->isEmpty()) {
947  xmin = xmax = 0;
948  ymin = ymax = 0;
949  return;
950  }
951 
952 
953  float Corr = textCorr();
954  int x1, y1, x2, y2;
955  // find boundings of all components
956  for(pc = Components->first(); pc != 0; pc = Components->next()) {
957  pc->entireBounds(x1, y1, x2, y2, Corr);
958  if(x1 < xmin) xmin = x1;
959  if(x2 > xmax) xmax = x2;
960  if(y1 < ymin) ymin = y1;
961  if(y2 > ymax) ymax = y2;
962  }
963 
964  // find boundings of all wires
965  for(pw = Wires->first(); pw != 0; pw = Wires->next()) {
966  if(pw->x1 < xmin) xmin = pw->x1;
967  if(pw->x2 > xmax) xmax = pw->x2;
968  if(pw->y1 < ymin) ymin = pw->y1;
969  if(pw->y2 > ymax) ymax = pw->y2;
970 
971  pl = pw->Label;
972  if(pl) { // check position of wire label
973  if(pl->x1 < xmin) xmin = pl->x1;
974  if((pl->x1+pl->x2) > xmax) xmax = pl->x1 + pl->x2;
975  if(pl->y1 > ymax) ymax = pl->y1;
976  if((pl->y1-pl->y2) < ymin) ymin = pl->y1 - pl->y2;
977  }
978  }
979 
980  // find boundings of all node labels
981  for(Node *pn = Nodes->first(); pn != 0; pn = Nodes->next()) {
982  pl = pn->Label;
983  if(pl) { // check position of node label
984  if(pl->x1 < xmin) xmin = pl->x1;
985  if((pl->x1+pl->x2) > xmax) xmax = pl->x1 + pl->x2;
986  if(pl->y1 > ymax) ymax = pl->y1;
987  if((pl->y1-pl->y2) < ymin) ymin = pl->y1 - pl->y2;
988  }
989  }
990 
991  // find boundings of all diagrams
992  for(pd = Diagrams->first(); pd != 0; pd = Diagrams->next()) {
993  pd->Bounding(x1, y1, x2, y2);
994  if(x1 < xmin) xmin = x1;
995  if(x2 > xmax) xmax = x2;
996  if(y1 < ymin) ymin = y1;
997  if(y2 > ymax) ymax = y2;
998 
999  for(Graph *pg = pd->Graphs.first(); pg!=0; pg = pd->Graphs.next())
1000  // test all markers of diagram
1001  for(Marker *pm = pg->Markers.first(); pm!=0; pm = pg->Markers.next()) {
1002  pm->Bounding(x1, y1, x2, y2);
1003  if(x1 < xmin) xmin = x1;
1004  if(x2 > xmax) xmax = x2;
1005  if(y1 < ymin) ymin = y1;
1006  if(y2 > ymax) ymax = y2;
1007  }
1008  }
1009 
1010  // find boundings of all Paintings
1011  for(pp = Paintings->first(); pp != 0; pp = Paintings->next()) {
1012  pp->Bounding(x1, y1, x2, y2);
1013  if(x1 < xmin) xmin = x1;
1014  if(x2 > xmax) xmax = x2;
1015  if(y1 < ymin) ymin = y1;
1016  if(y2 > ymax) ymax = y2;
1017  }
1018 }
1019 
1020 // ---------------------------------------------------
1021 // Rotates all selected components around their midpoint.
1023 {
1024  Wires->setAutoDelete(false);
1025  Components->setAutoDelete(false);
1026 
1027  int x1=INT_MAX, y1=INT_MAX;
1028  int x2=INT_MIN, y2=INT_MIN;
1029  Q3PtrList<Element> ElementCache;
1030  copyLabels(x1, y1, x2, y2, &ElementCache); // must be first of all !
1031  copyComponents(x1, y1, x2, y2, &ElementCache);
1032  copyWires(x1, y1, x2, y2, &ElementCache);
1033  copyPaintings(x1, y1, x2, y2, &ElementCache);
1034  if(y1 == INT_MAX) return false; // no element selected
1035 
1036  Wires->setAutoDelete(true);
1037  Components->setAutoDelete(true);
1038 
1039  x1 = (x1+x2) >> 1; // center for rotation
1040  y1 = (y1+y2) >> 1;
1041  setOnGrid(x1, y1);
1042 
1043 
1044  Wire *pw;
1045  Painting *pp;
1046  Component *pc;
1047  WireLabel *pl;
1048  // re-insert elements
1049  for(Element *pe = ElementCache.first(); pe != 0; pe = ElementCache.next())
1050  switch(pe->Type) {
1051  case isComponent:
1052  case isAnalogComponent:
1053  case isDigitalComponent:
1054  pc = (Component*)pe;
1055  pc->rotate(); //rotate component !before! rotating its center
1056  pc->setCenter(pc->cy - y1 + x1, x1 - pc->cx + y1);
1057  insertRawComponent(pc);
1058  break;
1059 
1060  case isWire:
1061  pw = (Wire*)pe;
1062  x2 = pw->x1;
1063  pw->x1 = pw->y1 - y1 + x1;
1064  pw->y1 = x1 - x2 + y1;
1065  x2 = pw->x2;
1066  pw->x2 = pw->y2 - y1 + x1;
1067  pw->y2 = x1 - x2 + y1;
1068  pl = pw->Label;
1069  if(pl) {
1070  x2 = pl->cx;
1071  pl->cx = pl->cy - y1 + x1;
1072  pl->cy = x1 - x2 + y1;
1073  if(pl->Type == isHWireLabel)
1074  pl->Type = isVWireLabel;
1075  else pl->Type = isHWireLabel;
1076  }
1077  insertWire(pw);
1078  break;
1079 
1080  case isHWireLabel:
1081  case isVWireLabel:
1082  pl = (WireLabel*)pe;
1083  x2 = pl->x1;
1084  pl->x1 = pl->y1 - y1 + x1;
1085  pl->y1 = x1 - x2 + y1;
1086  break;
1087  case isNodeLabel:
1088  pl = (WireLabel*)pe;
1089  if(pl->pOwner == 0) {
1090  x2 = pl->x1;
1091  pl->x1 = pl->y1 - y1 + x1;
1092  pl->y1 = x1 - x2 + y1;
1093  }
1094  x2 = pl->cx;
1095  pl->cx = pl->cy - y1 + x1;
1096  pl->cy = x1 - x2 + y1;
1097  insertNodeLabel(pl);
1098  break;
1099 
1100  case isPainting:
1101  pp = (Painting*)pe;
1102  pp->rotate(); // rotate painting !before! rotating its center
1103  pp->getCenter(x2, y2);
1104  pp->setCenter(y2-y1 + x1, x1-x2 + y1);
1105  Paintings->append(pp);
1106  break;
1107  default: ;
1108  }
1109 
1110  ElementCache.clear();
1111 
1112  setChanged(true, true);
1113  return true;
1114 }
1115 
1116 // ---------------------------------------------------
1117 // Mirrors all selected components.
1118 // First copy them to 'ElementCache', then mirror and insert again.
1120 {
1121  Wires->setAutoDelete(false);
1122  Components->setAutoDelete(false);
1123 
1124  int x1, y1, x2, y2;
1125  Q3PtrList<Element> ElementCache;
1126  if(!copyComps2WiresPaints(x1, y1, x2, y2, &ElementCache))
1127  return false;
1128  Wires->setAutoDelete(true);
1129  Components->setAutoDelete(true);
1130 
1131  y1 = (y1+y2) >> 1; // axis for mirroring
1132  setOnGrid(y2, y1);
1133  y1 <<= 1;
1134 
1135 
1136  Wire *pw;
1137  Painting *pp;
1138  Component *pc;
1139  WireLabel *pl;
1140  // re-insert elements
1141  for(Element *pe = ElementCache.first(); pe != 0; pe = ElementCache.next())
1142  switch(pe->Type) {
1143  case isComponent:
1144  case isAnalogComponent:
1145  case isDigitalComponent:
1146  pc = (Component*)pe;
1147  pc->mirrorX(); // mirror component !before! mirroring its center
1148  pc->setCenter(pc->cx, y1 - pc->cy);
1149  insertRawComponent(pc);
1150  break;
1151  case isWire:
1152  pw = (Wire*)pe;
1153  pw->y1 = y1 - pw->y1;
1154  pw->y2 = y1 - pw->y2;
1155  pl = pw->Label;
1156  if(pl) pl->cy = y1 - pl->cy;
1157  insertWire(pw);
1158  break;
1159  case isHWireLabel:
1160  case isVWireLabel:
1161  pl = (WireLabel*)pe;
1162  pl->y1 = y1 - pl->y1;
1163  break;
1164  case isNodeLabel:
1165  pl = (WireLabel*)pe;
1166  if(pl->pOwner == 0)
1167  pl->y1 = y1 - pl->y1;
1168  pl->cy = y1 - pl->cy;
1169  insertNodeLabel(pl);
1170  break;
1171  case isPainting:
1172  pp = (Painting*)pe;
1173  pp->getCenter(x2, y2);
1174  pp->mirrorX(); // mirror painting !before! mirroring its center
1175  pp->setCenter(x2, y1 - y2);
1176  Paintings->append(pp);
1177  break;
1178  default: ;
1179  }
1180 
1181  ElementCache.clear();
1182  setChanged(true, true);
1183  return true;
1184 }
1185 
1186 // ---------------------------------------------------
1187 // Mirrors all selected components. First copy them to 'ElementCache', then mirror and insert again.
1189 {
1190  Wires->setAutoDelete(false);
1191  Components->setAutoDelete(false);
1192 
1193  int x1, y1, x2, y2;
1194  Q3PtrList<Element> ElementCache;
1195  if(!copyComps2WiresPaints(x1, y1, x2, y2, &ElementCache))
1196  return false;
1197  Wires->setAutoDelete(true);
1198  Components->setAutoDelete(true);
1199 
1200  x1 = (x1+x2) >> 1; // axis for mirroring
1201  setOnGrid(x1, x2);
1202  x1 <<= 1;
1203 
1204  Wire *pw;
1205  Painting *pp;
1206  Component *pc;
1207  WireLabel *pl;
1208  // re-insert elements
1209  for(Element *pe = ElementCache.first(); pe != 0; pe = ElementCache.next())
1210  switch(pe->Type) {
1211  case isComponent:
1212  case isAnalogComponent:
1213  case isDigitalComponent:
1214  pc = (Component*)pe;
1215  pc->mirrorY(); // mirror component !before! mirroring its center
1216  pc->setCenter(x1 - pc->cx, pc->cy);
1217  insertRawComponent(pc);
1218  break;
1219  case isWire:
1220  pw = (Wire*)pe;
1221  pw->x1 = x1 - pw->x1;
1222  pw->x2 = x1 - pw->x2;
1223  pl = pw->Label;
1224  if(pl) pl->cx = x1 - pl->cx;
1225  insertWire(pw);
1226  break;
1227  case isHWireLabel:
1228  case isVWireLabel:
1229  pl = (WireLabel*)pe;
1230  pl->x1 = x1 - pl->x1;
1231  break;
1232  case isNodeLabel:
1233  pl = (WireLabel*)pe;
1234  if(pl->pOwner == 0)
1235  pl->x1 = x1 - pl->x1;
1236  pl->cx = x1 - pl->cx;
1237  insertNodeLabel(pl);
1238  break;
1239  case isPainting:
1240  pp = (Painting*)pe;
1241  pp->getCenter(x2, y2);
1242  pp->mirrorY(); // mirror painting !before! mirroring its center
1243  pp->setCenter(x1 - x2, y2);
1244  Paintings->append(pp);
1245  break;
1246  default: ;
1247  }
1248 
1249  ElementCache.clear();
1250  setChanged(true, true);
1251  return true;
1252 }
1253 
1254 // ---------------------------------------------------
1255 // Updates the graph data of all diagrams (load from data files).
1257 {
1258  QFileInfo Info(DocName);
1259  for(Diagram *pd = Diagrams->first(); pd != 0; pd = Diagrams->next())
1260  pd->loadGraphData(Info.dirPath()+QDir::separator()+DataSet);
1261 }
1262 
1263 // ---------------------------------------------------
1264 // Performs copy or cut functions for clipboard.
1265 QString Schematic::copySelected(bool cut)
1266 {
1267  QString s = createClipboardFile();
1268  if(cut) deleteElements(); // delete selected elements if wanted
1269  return s;
1270 }
1271 
1272 // ---------------------------------------------------
1273 // Performs paste function from clipboard
1274 bool Schematic::paste(QTextStream *stream, Q3PtrList<Element> *pe)
1275 {
1276  return pasteFromClipboard(stream, pe);
1277 }
1278 
1279 // ---------------------------------------------------
1280 // Loads this Qucs document.
1282 {
1283  DocComps.clear();
1284  DocWires.clear();
1285  DocNodes.clear();
1286  DocDiags.clear();
1287  DocPaints.clear();
1288  SymbolPaints.clear();
1289 
1290  if(!loadDocument()) return false;
1291  lastSaved = QDateTime::currentDateTime();
1292  UndoStack.clear();
1293  UndoSymbol.clear();
1294  symbolMode = true;
1295  setChanged(false, true); // "not changed" state, but put on undo stack
1296  UndoSymbol.current()->replace(1,1,'i');
1297  symbolMode = false;
1298  setChanged(false, true); // "not changed" state, but put on undo stack
1299  UndoStack.current()->replace(1,1,'i');// state of being unchanged
1300 
1301  // The undo stack of the circuit symbol is initialized when first
1302  // entering its edit mode.
1303 
1305  if(ViewX1 > UsedX1) ViewX1 = UsedX1;
1306  if(ViewY1 > UsedY1) ViewY1 = UsedY1;
1307  if(ViewX2 < UsedX2) ViewX2 = UsedX2;
1308  if(ViewY2 < UsedY2) ViewY2 = UsedY2;
1309  zoom(1.0f);
1310  setContentsPos(tmpViewX1, tmpViewY1);
1311  tmpViewX1 = tmpViewY1 = -200; // was used as temporary cache
1312  return true;
1313 }
1314 
1315 // ---------------------------------------------------
1316 // Saves this Qucs document. Returns the number of subcircuit ports.
1318 {
1319  int result = adjustPortNumbers();// same port number for schematic and symbol
1320  if(saveDocument() < 0)
1321  return -1;
1322 
1323  QFileInfo Info(DocName);
1324  lastSaved = Info.lastModified();
1325 
1326  if(result >= 0) {
1327  setChanged(false);
1328  QString *p, *ps = UndoStack.current();
1329  for(p = UndoStack.first(); p != 0; p = UndoStack.next())
1330  p->replace(1,1,' ');//at(1) = ' '; // state of being changed
1331  ps->replace(1,1,'i');//(1) = 'i'; // state of being unchanged
1332  UndoStack.findRef(ps); // back to current
1333 
1334  ps = UndoSymbol.current();
1335  for(p = UndoSymbol.first(); p != 0; p = UndoSymbol.next())
1336  p->replace(1,1,' ');//at(1) = ' '; // state of being changed
1337  ps->replace(1,1,'i');//at(1) = 'i'; // state of being unchanged
1338  UndoSymbol.findRef(ps); // back to current
1339  }
1340  // update the subcircuit file lookup hashes
1343 
1344  return result;
1345 }
1346 
1347 // ---------------------------------------------------
1348 // If the port number of the schematic and of the symbol are not
1349 // equal add or remove some in the symbol.
1351 {
1352  int x1, x2, y1, y2;
1353  // get size of whole symbol to know where to place new ports
1354  if(symbolMode) sizeOfAll(x1, y1, x2, y2);
1355  else {
1357  Wires = &SymbolWires;
1358  Nodes = &SymbolNodes;
1359  Diagrams = &SymbolDiags;
1361  sizeOfAll(x1, y1, x2, y2);
1362  Components = &DocComps;
1363  Wires = &DocWires;
1364  Nodes = &DocNodes;
1365  Diagrams = &DocDiags;
1366  Paintings = &DocPaints;
1367  }
1368  x1 += 40;
1369  y2 += 20;
1370  setOnGrid(x1, y2);
1371 
1372 
1373  Painting *pp;
1374  // delete all port names in symbol
1375  for(pp = SymbolPaints.first(); pp!=0; pp = SymbolPaints.next())
1376  if(pp->Name == ".PortSym ")
1377  ((PortSymbol*)pp)->nameStr = "";
1378 
1379  QString Str;
1380  int countPort = 0;
1381 
1382  QFileInfo Info (DataDisplay);
1383  QString Suffix = Info.extension (false);
1384 
1385  // handle VHDL file symbol
1386  if (Suffix == "vhd" || Suffix == "vhdl") {
1387  QStringList::iterator it;
1388  QStringList Names, GNames, GTypes, GDefs;
1389  int Number;
1390 
1391  // get ports from VHDL file
1392  QFileInfo Info(DocName);
1393  QString Name = Info.dirPath() + QDir::separator() + DataDisplay;
1394 
1395  // obtain VHDL information either from open text document or the
1396  // file directly
1397  VHDL_File_Info VInfo;
1398  TextDoc * d = (TextDoc*)App->findDoc (Name);
1399  if (d)
1400  VInfo = VHDL_File_Info (d->document()->toPlainText());
1401  else
1402  VInfo = VHDL_File_Info (Name, true);
1403  Names = QStringList::split(",",VInfo.PortNames);
1404 
1405  for(pp = SymbolPaints.first(); pp!=0; pp = SymbolPaints.next())
1406  if(pp->Name == ".ID ") {
1407  ID_Text * id = (ID_Text *) pp;
1408  id->Prefix = VInfo.EntityName.upper();
1409  id->Parameter.clear();
1410  GNames = QStringList::split(",",VInfo.GenNames);
1411  GTypes = QStringList::split(",",VInfo.GenTypes);
1412  GDefs = QStringList::split(",",VInfo.GenDefs);
1413  for(Number = 1, it = GNames.begin(); it != GNames.end(); ++it) {
1414  id->Parameter.append(new SubParameter(
1415  true,
1416  *it+"="+GDefs[Number-1],
1417  tr("generic")+" "+QString::number(Number),
1418  GTypes[Number-1]));
1419  Number++;
1420  }
1421  }
1422 
1423  for(Number = 1, it = Names.begin(); it != Names.end(); ++it, Number++) {
1424  countPort++;
1425 
1426  Str = QString::number(Number);
1427  // search for matching port symbol
1428  for(pp = SymbolPaints.first(); pp!=0; pp = SymbolPaints.next())
1429  if(pp->Name == ".PortSym ")
1430  if(((PortSymbol*)pp)->numberStr == Str) break;
1431 
1432  if(pp)
1433  ((PortSymbol*)pp)->nameStr = *it;
1434  else {
1435  SymbolPaints.append(new PortSymbol(x1, y2, Str, *it));
1436  y2 += 40;
1437  }
1438  }
1439  }
1440  // handle Verilog-HDL file symbol
1441  else if (Suffix == "v") {
1442 
1443  QStringList::iterator it;
1444  QStringList Names;
1445  int Number;
1446 
1447  // get ports from Verilog-HDL file
1448  QFileInfo Info (DocName);
1449  QString Name = Info.dirPath() + QDir::separator() + DataDisplay;
1450 
1451  // obtain Verilog-HDL information either from open text document or the
1452  // file directly
1453  Verilog_File_Info VInfo;
1454  TextDoc * d = (TextDoc*)App->findDoc (Name);
1455  if (d)
1456  VInfo = Verilog_File_Info (d->document()->toPlainText());
1457  else
1458  VInfo = Verilog_File_Info (Name, true);
1459  Names = QStringList::split(",",VInfo.PortNames);
1460 
1461  for(pp = SymbolPaints.first(); pp!=0; pp = SymbolPaints.next())
1462  if(pp->Name == ".ID ") {
1463  ID_Text * id = (ID_Text *) pp;
1464  id->Prefix = VInfo.ModuleName.upper();
1465  id->Parameter.clear();
1466  }
1467 
1468  for(Number = 1, it = Names.begin(); it != Names.end(); ++it, Number++) {
1469  countPort++;
1470 
1471  Str = QString::number(Number);
1472  // search for matching port symbol
1473  for(pp = SymbolPaints.first(); pp!=0; pp = SymbolPaints.next())
1474  if(pp->Name == ".PortSym ")
1475  if(((PortSymbol*)pp)->numberStr == Str) break;
1476 
1477  if(pp)
1478  ((PortSymbol*)pp)->nameStr = *it;
1479  else {
1480  SymbolPaints.append(new PortSymbol(x1, y2, Str, *it));
1481  y2 += 40;
1482  }
1483  }
1484  }
1485  // handle Verilog-A file symbol
1486  else if (Suffix == "va") {
1487 
1488  QStringList::iterator it;
1489  QStringList Names;
1490  int Number;
1491 
1492  // get ports from Verilog-A file
1493  QFileInfo Info (DocName);
1494  QString Name = Info.dirPath() + QDir::separator() + DataDisplay;
1495 
1496  // obtain Verilog-A information either from open text document or the
1497  // file directly
1498  VerilogA_File_Info VInfo;
1499  TextDoc * d = (TextDoc*)App->findDoc (Name);
1500  if (d)
1501  VInfo = VerilogA_File_Info (d->toPlainText());
1502  else
1503  VInfo = VerilogA_File_Info (Name, true);
1504  Names = QStringList::split(",",VInfo.PortNames);
1505 
1506  for(pp = SymbolPaints.first(); pp!=0; pp = SymbolPaints.next())
1507  if(pp->Name == ".ID ") {
1508  ID_Text * id = (ID_Text *) pp;
1509  id->Prefix = VInfo.ModuleName.upper();
1510  id->Parameter.clear();
1511  }
1512 
1513  for(Number = 1, it = Names.begin(); it != Names.end(); ++it, Number++) {
1514  countPort++;
1515 
1516  Str = QString::number(Number);
1517  // search for matching port symbol
1518  for(pp = SymbolPaints.first(); pp!=0; pp = SymbolPaints.next())
1519  if(pp->Name == ".PortSym ")
1520  if(((PortSymbol*)pp)->numberStr == Str) break;
1521 
1522  if(pp)
1523  ((PortSymbol*)pp)->nameStr = *it;
1524  else {
1525  SymbolPaints.append(new PortSymbol(x1, y2, Str, *it));
1526  y2 += 40;
1527  }
1528  }
1529  }
1530  // handle schematic symbol
1531  else
1532  {
1533  // go through all components in a schematic
1534  for(Component *pc = DocComps.first(); pc!=0; pc = DocComps.next())
1535  {
1536  if(pc->Model == "Port")
1537  {
1538  countPort++;
1539 
1540  Str = pc->Props.getFirst()->Value;
1541  // search for matching port symbol
1542  for(pp = SymbolPaints.first(); pp!=0; pp = SymbolPaints.next())
1543  {
1544  if(pp->Name == ".PortSym ")
1545  {
1546  if(((PortSymbol*)pp)->numberStr == Str) break;
1547  }
1548  }
1549 
1550  if(pp)
1551  {
1552  ((PortSymbol*)pp)->nameStr = pc->Name;
1553  }
1554  else
1555  {
1556  SymbolPaints.append(new PortSymbol(x1, y2, Str, pc->Name));
1557  y2 += 40;
1558  }
1559  }
1560  }
1561  }
1562 
1563  // delete not accounted port symbols
1564  for(pp = SymbolPaints.first(); pp!=0; ) {
1565  if(pp->Name == ".PortSym ")
1566  if(((PortSymbol*)pp)->nameStr.isEmpty()) {
1567  SymbolPaints.remove();
1568  pp = SymbolPaints.current();
1569  continue;
1570  }
1571  pp = SymbolPaints.next();
1572  }
1573 
1574  return countPort;
1575 }
1576 
1577 // ---------------------------------------------------
1579 {
1580  if(symbolMode) {
1581  if(UndoSymbol.current() == UndoSymbol.getFirst()) return false;
1582 
1583  rebuildSymbol(UndoSymbol.prev());
1584  adjustPortNumbers(); // set port names
1585 
1586  QString *ps = UndoSymbol.current();
1587  if(ps != UndoSymbol.getFirst()) App->undo->setEnabled(true);
1588  else App->undo->setEnabled(false);
1589  if(ps != UndoSymbol.getLast()) App->redo->setEnabled(true);
1590  else App->redo->setEnabled(false);
1591 
1592  if(ps->at(1) == 'i')
1593  if(UndoStack.current()->at(1) == 'i') {
1594  setChanged(false, false);
1595  return true;
1596  }
1597 
1598  setChanged(true, false);
1599  return true;
1600  }
1601 
1602 
1603  // ...... for schematic edit mode .......
1604  if(UndoStack.current() == UndoStack.getFirst()) return false;
1605 
1606  rebuild(UndoStack.prev());
1607  reloadGraphs(); // load recent simulation data
1608 
1609  QString *ps = UndoStack.current();
1610  if(ps != UndoStack.getFirst()) App->undo->setEnabled(true);
1611  else App->undo->setEnabled(false);
1612  if(ps != UndoStack.getLast()) App->redo->setEnabled(true);
1613  else App->redo->setEnabled(false);
1614 
1615  if(ps->at(1) == 'i') {
1616  if(UndoSymbol.isEmpty()) {
1617  setChanged(false, false);
1618  return true;
1619  }
1620  else if(UndoSymbol.current()->at(1) == 'i') {
1621  setChanged(false, false);
1622  return true;
1623  }
1624  }
1625 
1626  setChanged(true, false);
1627  return true;
1628 }
1629 
1630 // ---------------------------------------------------
1632 {
1633  if(symbolMode) {
1634  if(UndoSymbol.current() == UndoSymbol.getLast()) return false;
1635 
1636  rebuildSymbol(UndoSymbol.next());
1637  adjustPortNumbers(); // set port names
1638 
1639  QString *ps = UndoSymbol.current();
1640  if(ps != UndoSymbol.getFirst()) App->undo->setEnabled(true);
1641  else App->undo->setEnabled(false);
1642  if(ps != UndoSymbol.getLast()) App->redo->setEnabled(true);
1643  else App->redo->setEnabled(false);
1644 
1645  if(ps->at(1) == 'i')
1646  if(UndoStack.current()->at(1) == 'i') {
1647  setChanged(false, false);
1648  return true;
1649  }
1650 
1651  setChanged(true, false);
1652  return true;
1653  }
1654 
1655 
1656  // ...... for schematic edit mode .......
1657  if(UndoStack.current() == UndoStack.getLast()) return false;
1658 
1659  rebuild(UndoStack.next());
1660  reloadGraphs(); // load recent simulation data
1661 
1662  QString *ps = UndoStack.current();
1663  if(ps != UndoStack.getFirst()) App->undo->setEnabled(true);
1664  else App->undo->setEnabled(false);
1665  if(ps != UndoStack.getLast()) App->redo->setEnabled(true);
1666  else App->redo->setEnabled(false);
1667 
1668  if(ps->at(1) == 'i') {
1669  if(UndoSymbol.isEmpty()) {
1670  setChanged(false, false);
1671  return true;
1672  }
1673  else if(UndoSymbol.current()->at(1) == 'i') {
1674  setChanged(false, false);
1675  return true;
1676  }
1677  }
1678 
1679  setChanged(true, false);
1680  return true;
1681 }
1682 
1683 // ---------------------------------------------------
1684 // Sets selected elements on grid.
1686 {
1687  int x, y, No;
1688  bool count = false;
1689  Port *pp;
1690  WireLabel *pl, *pLabel;
1691  Q3PtrList<WireLabel> LabelCache;
1692 
1693  // test all components
1694  Components->setAutoDelete(false);
1695  for(Component *pc = Components->last(); pc != 0; pc = Components->prev())
1696  if(pc->isSelected) {
1697 
1698  // rescue non-selected node labels
1699  for(pp = pc->Ports.first(); pp != 0; pp = pc->Ports.next())
1700  if(pp->Connection->Label)
1701  if(pp->Connection->Connections.count() < 2) {
1702  LabelCache.append(pp->Connection->Label);
1703  pp->Connection->Label->pOwner = 0;
1704  pp->Connection->Label = 0;
1705  }
1706 
1707  x = pc->cx;
1708  y = pc->cy;
1709  No = Components->at();
1710  deleteComp(pc);
1711  setOnGrid(pc->cx, pc->cy);
1712  insertRawComponent(pc);
1713  Components->at(No); // restore current list position
1714  pc->isSelected = false;
1715  count = true;
1716 
1717  x -= pc->cx;
1718  y -= pc->cy; // re-insert node labels and correct position
1719  for(pl = LabelCache.first(); pl != 0; pl = LabelCache.next()) {
1720  pl->cx -= x;
1721  pl->cy -= y;
1722  insertNodeLabel(pl);
1723  }
1724  LabelCache.clear();
1725  }
1726  Components->setAutoDelete(true);
1727 
1728  Wires->setAutoDelete(false);
1729  // test all wires and wire labels
1730  for(Wire *pw = Wires->last(); pw != 0; pw = Wires->prev()) {
1731  pl = pw->Label;
1732  pw->Label = 0;
1733 
1734  if(pw->isSelected) {
1735  // rescue non-selected node label
1736  pLabel = 0;
1737  if(pw->Port1->Label) {
1738  if(pw->Port1->Connections.count() < 2) {
1739  pLabel = pw->Port1->Label;
1740  pw->Port1->Label = 0;
1741  }
1742  }
1743  else if(pw->Port2->Label) {
1744  if(pw->Port2->Connections.count() < 2) {
1745  pLabel = pw->Port2->Label;
1746  pw->Port2->Label = 0;
1747  }
1748  }
1749 
1750  No = Wires->at();
1751  deleteWire(pw);
1752  setOnGrid(pw->x1, pw->y1);
1753  setOnGrid(pw->x2, pw->y2);
1754  insertWire(pw);
1755  Wires->at(No); // restore current list position
1756  pw->isSelected = false;
1757  count = true;
1758  if(pl)
1759  setOnGrid(pl->cx, pl->cy);
1760 
1761  if(pLabel) {
1762  setOnGrid(pLabel->cx, pLabel->cy);
1763  insertNodeLabel(pLabel);
1764  }
1765  }
1766 
1767  if(pl) {
1768  pw->Label = pl;
1769  if(pl->isSelected) {
1770  setOnGrid(pl->x1, pl->y1);
1771  pl->isSelected = false;
1772  count = true;
1773  }
1774  }
1775  }
1776  Wires->setAutoDelete(true);
1777 
1778  // test all node labels
1779  for(Node *pn = Nodes->first(); pn != 0; pn = Nodes->next())
1780  if(pn->Label)
1781  if(pn->Label->isSelected) {
1782  setOnGrid(pn->Label->x1, pn->Label->y1);
1783  pn->Label->isSelected = false;
1784  count = true;
1785  }
1786 
1787  // test all diagrams
1788  for(Diagram *pd = Diagrams->last(); pd != 0; pd = Diagrams->prev()) {
1789  if(pd->isSelected) {
1790  setOnGrid(pd->cx, pd->cy);
1791  pd->isSelected = false;
1792  count = true;
1793  }
1794 
1795  for(Graph *pg = pd->Graphs.first(); pg != 0; pg = pd->Graphs.next())
1796  // test markers of diagram
1797  for(Marker *pm = pg->Markers.first(); pm != 0; pm = pg->Markers.next())
1798  if(pm->isSelected) {
1799  x = pm->x1 + pd->cx;
1800  y = pm->y1 + pd->cy;
1801  setOnGrid(x, y);
1802  pm->x1 = x - pd->cx;
1803  pm->y1 = y - pd->cy;
1804  pm->isSelected = false;
1805  count = true;
1806  }
1807  }
1808 
1809  // test all paintings
1810  for(Painting *pa = Paintings->last(); pa != 0; pa = Paintings->prev())
1811  if(pa->isSelected) {
1812  setOnGrid(pa->cx, pa->cy);
1813  pa->isSelected = false;
1814  count = true;
1815  }
1816 
1817  if(count) setChanged(true, true);
1818  return count;
1819 }
1820 
1821 // ---------------------------------------------------
1823 {
1824  symbolMode = !symbolMode; // change mode
1825 
1826  int tmp, t2;
1827  float temp;
1828  temp = Scale; Scale = tmpScale; tmpScale = temp;
1829  tmp = contentsX();
1830  t2 = contentsY();
1831  setContentsPos(tmpPosX, tmpPosY);
1832  tmpPosX = tmp;
1833  tmpPosY = t2;
1834  tmp = ViewX1; ViewX1 = tmpViewX1; tmpViewX1 = tmp;
1835  tmp = ViewY1; ViewY1 = tmpViewY1; tmpViewY1 = tmp;
1836  tmp = ViewX2; ViewX2 = tmpViewX2; tmpViewX2 = tmp;
1837  tmp = ViewY2; ViewY2 = tmpViewY2; tmpViewY2 = tmp;
1838  tmp = UsedX1; UsedX1 = tmpUsedX1; tmpUsedX1 = tmp;
1839  tmp = UsedY1; UsedY1 = tmpUsedY1; tmpUsedY1 = tmp;
1840  tmp = UsedX2; UsedX2 = tmpUsedX2; tmpUsedX2 = tmp;
1841  tmp = UsedY2; UsedY2 = tmpUsedY2; tmpUsedY2 = tmp;
1842 }
1843 
1844 
1845 // *********************************************************************
1846 // ********** **********
1847 // ********** Function for serving mouse wheel moving **********
1848 // ********** **********
1849 // *********************************************************************
1850 void Schematic::contentsWheelEvent(QWheelEvent *Event)
1851 {
1852  App->editText->setHidden(true); // disable edit of component property
1853  int delta = Event->delta() >> 1; // use smaller steps
1854 
1855  // ...................................................................
1856  if((Event->state() & Qt::ShiftModifier) ||
1857  (Event->orientation() == Qt::Horizontal)) { // scroll horizontally ?
1858  if(delta > 0) { if(scrollLeft(delta)) scrollBy(-delta, 0); }
1859  else { if(scrollRight(delta)) scrollBy(-delta, 0); }
1860  viewport()->update(); // because QScrollView thinks nothing has changed
1861  App->view->drawn = false;
1862  }
1863  // ...................................................................
1864  else if(Event->state() & Qt::ControlModifier) { // use mouse wheel to zoom ?
1865  float Scaling;
1866  if(delta < 0) Scaling = float(delta)/-60.0/1.1;
1867  else Scaling = 1.1*60.0/float(delta);
1868  zoom(Scaling);
1869  Scaling -= 1.0;
1870  scrollBy( int(Scaling * float(Event->pos().x())),
1871  int(Scaling * float(Event->pos().y())) );
1872  }
1873  // ...................................................................
1874  else { // scroll vertically !
1875  if(delta > 0) { if(scrollUp(delta)) scrollBy(0, -delta); }
1876  else { if(scrollDown(delta)) scrollBy(0, -delta); }
1877  viewport()->update(); // because QScrollView thinks nothing has changed
1878  App->view->drawn = false;
1879  }
1880 
1881  Event->accept(); // QScrollView must not handle this event
1882 }
1883 
1884 // -----------------------------------------------------------
1885 // Scrolls the visible area upwards and enlarges or reduces the view
1886 // area accordingly.
1887 bool Schematic::scrollUp(int step)
1888 {
1889  int diff;
1890 
1891  diff = contentsY() - step;
1892  if(diff < 0) { // scroll outside the active area ? (upwards)
1893  resizeContents(contentsWidth(), contentsHeight()-diff);
1894  ViewY1 += diff;
1895  scrollBy(0, diff);
1896  return false;
1897  }
1898 
1899  diff = ViewY2 - UsedY2 - 20; // keep border of 20
1900  if(diff > 0) { // make active area smaller ?
1901  if(step < diff) diff = step;
1902  resizeContents(contentsWidth(), contentsHeight()-diff);
1903  ViewY2 -= diff;
1904  }
1905 
1906  return true;
1907 }
1908 
1909 // -----------------------------------------------------------
1910 // Scrolls the visible area downwards and enlarges or reduces the view
1911 // area accordingly. ("step" must be negative!)
1913 {
1914  int diff;
1915 
1916  diff = contentsHeight() - contentsY()-visibleHeight() + step;
1917  if(diff < 0) { // scroll outside the active area ? (downwards)
1918  resizeContents(contentsWidth(), contentsHeight()-diff);
1919  ViewY2 -= diff;
1920  scrollBy(0, -step);
1921  return false;
1922  }
1923 
1924  diff = ViewY1 - UsedY1 + 20; // keep border of 20
1925  if(diff < 0) { // make active area smaller ?
1926  if(step > diff) diff = step;
1927  resizeContents(contentsWidth(), contentsHeight()+diff);
1928  ViewY1 -= diff;
1929  return false;
1930  }
1931 
1932  return true;
1933 }
1934 
1935 // -----------------------------------------------------------
1936 // Scrolls the visible area to the left and enlarges or reduces the view
1937 // area accordingly.
1939 {
1940  int diff;
1941 
1942  diff = contentsX() - step;
1943  if(diff < 0) { // scroll outside the active area ? (to the left)
1944  resizeContents(contentsWidth()-diff, contentsHeight());
1945  ViewX1 += diff;
1946  scrollBy(diff, 0);
1947  return false;
1948  }
1949 
1950  diff = ViewX2 - UsedX2 - 20; // keep border of 20
1951  if(diff > 0) { // make active area smaller ?
1952  if(step < diff) diff = step;
1953  resizeContents(contentsWidth()-diff, contentsHeight());
1954  ViewX2 -= diff;
1955  }
1956 
1957  return true;
1958 }
1959 
1960 // -----------------------------------------------------------
1961 // Scrolls the visible area to the right and enlarges or reduces the
1962 // view area accordingly. ("step" must be negative!)
1964 {
1965  int diff;
1966 
1967  diff = contentsWidth() - contentsX()-visibleWidth() + step;
1968  if(diff < 0) { // scroll outside the active area ? (to the right)
1969  resizeContents(contentsWidth()-diff, contentsHeight());
1970  ViewX2 -= diff;
1971  scrollBy(-step, 0);
1972  return false;
1973  }
1974 
1975  diff = ViewX1 - UsedX1 + 20; // keep border of 20
1976  if(diff < 0) { // make active area smaller ?
1977  if(step > diff) diff = step;
1978  resizeContents(contentsWidth()+diff, contentsHeight());
1979  ViewX1 -= diff;
1980  return false;
1981  }
1982 
1983  return true;
1984 }
1985 
1986 // -----------------------------------------------------------
1987 // Is called if the scroll arrow of the ScrollBar is pressed.
1989 {
1990  App->editText->setHidden(true); // disable edit of component property
1991  scrollUp(verticalScrollBar()->lineStep());
1992  viewport()->update(); // because QScrollView thinks nothing has changed
1993  App->view->drawn = false;
1994 }
1995 
1996 // -----------------------------------------------------------
1997 // Is called if the scroll arrow of the ScrollBar is pressed.
1999 {
2000  App->editText->setHidden(true); // disable edit of component property
2001  scrollDown(-verticalScrollBar()->lineStep());
2002  viewport()->update(); // because QScrollView thinks nothing has changed
2003  App->view->drawn = false;
2004 }
2005 
2006 // -----------------------------------------------------------
2007 // Is called if the scroll arrow of the ScrollBar is pressed.
2009 {
2010  App->editText->setHidden(true); // disable edit of component property
2011  scrollLeft(horizontalScrollBar()->lineStep());
2012  viewport()->update(); // because QScrollView thinks nothing has changed
2013  App->view->drawn = false;
2014 }
2015 
2016 // -----------------------------------------------------------
2017 // Is called if the scroll arrow of the ScrollBar is pressed.
2019 {
2020  App->editText->setHidden(true); // disable edit of component property
2021  scrollRight(-horizontalScrollBar()->lineStep());
2022  viewport()->update(); // because QScrollView thinks nothing has changed
2023  App->view->drawn = false;
2024 }
2025 
2026 
2027 // *********************************************************************
2028 // ********** **********
2029 // ********** Function for serving drag'n drop **********
2030 // ********** **********
2031 // *********************************************************************
2032 
2033 // Is called if an object is dropped (after drag'n drop).
2034 void Schematic::contentsDropEvent(QDropEvent *Event)
2035 {
2036  if(dragIsOkay) {
2037  Q3StrList List;
2038  Q3UriDrag::decode(Event, List);
2039 
2040  // do not close untitled document to avoid segfault
2041  QucsDoc *d = QucsMain->getDoc(0);
2042  bool changed = d->DocChanged;
2043  d->DocChanged = true;
2044 
2045  // URI: file:/home/linuxuser/Desktop/example.sch
2046  for(unsigned int i=0; i < List.count(); i++)
2047  App->gotoPage(QDir::convertSeparators(Q3UriDrag::uriToLocalFile(List.at(i))));
2048 
2049  d->DocChanged = changed;
2050  return;
2051  }
2052 
2053 
2054  QMouseEvent e(QEvent::MouseButtonPress, Event->pos(),
2055  Qt::LeftButton, Qt::NoButton);
2056  int x = int(Event->pos().x()/Scale) + ViewX1;
2057  int y = int(Event->pos().y()/Scale) + ViewY1;
2058 
2059  App->view->MPressElement(this, &e, x, y);
2060 
2061  if(App->view->selElem) delete App->view->selElem;
2062  App->view->selElem = 0; // no component selected
2063 
2064  if(formerAction)
2065  formerAction->setOn(true); // restore old action
2066 }
2067 
2068 // ---------------------------------------------------
2069 void Schematic::contentsDragEnterEvent(QDragEnterEvent *Event)
2070 {
2071 
2072  //qDebug() << Event->mimeData()->formats();
2073  formerAction = 0;
2074  dragIsOkay = false;
2075 
2076  // file dragged in ?
2077  if(Event->provides("text/uri-list"))
2078  if(Q3UriDrag::canDecode(Event)) {
2079  dragIsOkay = true;
2080  Event->accept();
2081  return;
2082  }
2083 
2084  // drag library component
2085  if(Event->provides("text/plain")) {
2086  QString s;
2087  if(Q3TextDrag::decode(Event, s))
2088  if(s.left(15) == "QucsComponent:<") {
2089  s = s.mid(14);
2091  if(App->view->selElem) {
2092  Event->accept();
2093  return;
2094  }
2095  }
2096  Event->ignore();
2097  return;
2098  }
2099 
2100 
2101  if(Event->format(1) == 0) { // only one MIME type ?
2102 
2103  // drag component from listview
2104  if(Event->provides("application/x-qabstractitemmodeldatalist")) {
2105  //Q3IconViewItem *Item = App->CompComps->currentItem();
2106  QListWidgetItem *Item = App->CompComps->currentItem();
2107  if(Item) {
2109  App->slotSelectComponent(Item); // also sets drawn=false
2110  App->MouseMoveAction = 0;
2111  App->MousePressAction = 0;
2112 
2113  Event->accept();
2114  return;
2115  }
2116  }
2117  }
2118 
2119  Event->ignore();
2120 }
2121 
2122 // ---------------------------------------------------
2124 {
2125  if(App->view->selElem)
2126  if(App->view->selElem->Type & isComponent)
2127  if(App->view->drawn) {
2128 
2129  QPainter painter(viewport());
2130  App->view->setPainter(this);
2131  ((Component*)App->view->selElem)->paintScheme(this);
2132  App->view->drawn = false;
2133  }
2134 
2135  if(formerAction)
2136  formerAction->setOn(true); // restore old action
2137 }
2138 
2139 // ---------------------------------------------------
2140 void Schematic::contentsDragMoveEvent(QDragMoveEvent *Event)
2141 {
2142  if(!dragIsOkay) {
2143  if(App->view->selElem == 0) {
2144  Event->ignore();
2145  return;
2146  }
2147 
2148  QMouseEvent e(QEvent::MouseMove, Event->pos(), Qt::NoButton, Qt::NoButton);
2149  App->view->MMoveElement(this, &e);
2150  }
2151 
2152  Event->accept();
2153 }
2154 
2155 void Schematic::getSchWidthAndHeight(int &w, int &h, int& xmin_, int& ymin_)
2156 {
2157  int xmin= INT_MAX,
2158  ymin= INT_MAX,
2159  xmax= INT_MIN,
2160  ymax= INT_MIN;
2161 
2162  for(Component *pc = Components->first(); pc != 0; pc = Components->next()) {
2163  int x1,y1,x2,y2,d1,d2,d3,d4;
2164  pc->entireBounds(x1,y1,x2,y2,this->textCorr());
2165 
2166  d1 = std::min(x1,x2);
2167  if (d1<xmin) xmin = d1;
2168  d2 = std::max(x2,x1);
2169  if (d2>xmax) xmax = d2;
2170  d3 = std::min(y1,y2);
2171  if (d3<ymin) ymin = d3;
2172  d4 = std::max(y2,y1);
2173  if (d4>ymax) ymax = d4;
2174  }
2175 
2176  for(Wire *pw = Wires->first(); pw != 0; pw = Wires->next()) {
2177  int xc,yc;
2178  pw->getCenter(xc,yc);
2179 
2180  if (xc<xmin) xmin = xc;
2181  if (xc>xmax) xmax = xc;
2182  if (yc<ymin) ymin = yc;
2183  if (yc>ymax) ymax = yc;
2184  }
2185 
2186  for(Diagram *pd = Diagrams->first(); pd != 0; pd = Diagrams->next()) {
2187 
2188  int x1,y1,x2,y2,d1,d2,d3,d4;
2189  pd->Bounding(x1,y1,x2,y2);
2190 
2191  d1 = std::min(x1,x2);
2192  if (d1<xmin) xmin = d1;
2193  d2 = std::max(x2,x1);
2194  if (d2>xmax) xmax = d2;
2195  d3 = std::min(y1,y2);
2196  if (d3<ymin) ymin = d3;
2197  d4 = std::max(y2,y1);
2198  if (d4>ymax) ymax = d4;
2199  }
2200 
2201  for(Painting *pp = Paintings->first(); pp != 0; pp = Paintings->next()) {
2202  int x1,y1,x2,y2,d1,d2,d3,d4;
2203  pp->Bounding(x1,y1,x2,y2);
2204 
2205  d1 = std::min(x1,x2);
2206  if (d1<xmin) xmin = d1;
2207  d2 = std::max(x2,x1);
2208  if (d2>xmax) xmax = d2;
2209  d3 = std::min(y1,y2);
2210  if (d3<ymin) ymin = d3;
2211  d4 = std::max(y2,y1);
2212  if (d4>ymax) ymax = d4;
2213  }
2214 
2215  w = abs(xmax - xmin);
2216  h = abs(ymax - ymin);
2217  xmin_ = xmin;
2218  ymin_ = ymin;
2219 }
2220 
2221 void Schematic::getSelAreaWidthAndHeight(int &wsel, int &hsel, int& xmin_sel_, int& ymin_sel_)
2222 {
2223  int xmin= INT_MAX,
2224  ymin= INT_MAX,
2225  xmax= INT_MIN,
2226  ymax= INT_MIN;
2227 
2228  for(Component *pc = Components->first(); pc != 0; pc = Components->next()) {
2229  if (pc->isSelected) {
2230  int x1,y1,x2,y2,d1,d2,d3,d4;
2231  pc->entireBounds(x1,y1,x2,y2,this->textCorr());
2232  d1 = std::min(x1,x2);
2233  if (d1<xmin) xmin = d1;
2234  d2 = std::max(x2,x1);
2235  if (d2>xmax) xmax = d2;
2236  d3 = std::min(y1,y2);
2237  if (d3<ymin) ymin = d3;
2238  d4 = std::max(y2,y1);
2239  if (d4>ymax) ymax = d4;
2240  }
2241  }
2242 
2243  for(Wire *pw = Wires->first(); pw != 0; pw = Wires->next()) {
2244 
2245  if (pw->isSelected) {
2246  int xc,yc;
2247  pw->getCenter(xc,yc);
2248 
2249  if (xc<xmin) xmin = xc;
2250  if (xc>xmax) xmax = xc;
2251  if (yc<ymin) ymin = yc;
2252  if (yc>ymax) ymax = yc;
2253  }
2254  }
2255 
2256  for(Diagram *pd = Diagrams->first(); pd != 0; pd = Diagrams->next()) {
2257 
2258 
2259 
2260  if (pd->isSelected) {
2261  int x1,y1,x2,y2,d1,d2,d3,d4;
2262  pd->Bounding(x1,y1,x2,y2);
2263 
2264  d1 = std::min(x1,x2);
2265  if (d1<xmin) xmin = d1;
2266  d2 = std::max(x2,x1);
2267  if (d2>xmax) xmax = d2;
2268  d3 = std::min(y1,y2);
2269  if (d3<ymin) ymin = d3;
2270  d4 = std::max(y2,y1);
2271  if (d4>ymax) ymax = d4;
2272  }
2273  }
2274 
2275  for(Painting *pp = Paintings->first(); pp != 0; pp = Paintings->next()) {
2276 
2277  if (pp->isSelected) {
2278  int x1,y1,x2,y2,d1,d2,d3,d4;
2279  pp->Bounding(x1,y1,x2,y2);
2280  d1 = std::min(x1,x2);
2281  if (d1<xmin) xmin = d1;
2282  d2 = std::max(x2,x1);
2283  if (d2>xmax) xmax = d2;
2284  d3 = std::min(y1,y2);
2285  if (d3<ymin) ymin = d3;
2286  d4 = std::max(y2,y1);
2287  if (d4>ymax) ymax = d4;
2288  }
2289  }
2290 
2291  wsel = abs(xmax - xmin);
2292  hsel = abs(ymax - ymin);
2293  xmin_sel_ = xmin;
2294  ymin_sel_ = ymin;
2295 }
bool scrollRight(int)
Definition: schematic.cpp:1963
QString EntityName
Definition: vhdlfile.h:59
int tmpUsedY2
Definition: schematic.h:142
Q3PtrList< Marker > Markers
Definition: graph.h:79
void contentsMouseMoveEvent(QMouseEvent *)
Definition: schematic.cpp:543
void deleteComp(Component *)
bool undo()
Definition: schematic.cpp:1578
int saveDocument()
void MPressElement(Schematic *, QMouseEvent *, float, float)
QPainter * Painter
Definition: viewpainter.h:58
Q3PtrList< Painting > DocPaints
Definition: schematic.h:122
int Type
Definition: element.h:152
QString Frame_Text0
Definition: schematic.h:136
QString Script
Definition: qucsdoc.h:54
void updateSpiceNameHash(void)
Definition: qucs.cpp:3018
float textCorr()
Definition: schematic.cpp:922
bool GridOn
Definition: qucsdoc.h:64
Definition of the TextDoc class.
Node * Connection
Definition: element.h:79
const char * smallsave_xpm[]
Definition: qucsdoc.cpp:28
Definition: node.h:30
bool gotoPage(const QString &)
Definition: qucs.cpp:1527
int y1
Definition: element.h:153
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)
Definition: schematic.cpp:533
void slotScrollRight()
Definition: schematic.cpp:2018
Definition: wire.h:31
void(MouseActions::* MouseMoveAction)(Schematic *, QMouseEvent *)
Definition: qucs.h:85
int tmpViewX2
Definition: schematic.h:141
#define isNodeLabel
Definition: element.h:126
void MMoveElement(Schematic *, QMouseEvent *)
QFont font
Definition: main.h:46
float Scale
Definition: qucsdoc.h:58
Q3PtrList< Component > SymbolComps
Definition: schematic.cpp:67
Definition: graph.h:57
void paint(ViewPainter *)
Definition: node.cpp:39
void switchPaintMode()
Definition: schematic.cpp:1822
int tmpUsedY1
Definition: schematic.h:142
float Scale
Definition: viewpainter.h:59
void map(int, int, int &, int &)
Definition: viewpainter.cpp:63
tQucsSettings QucsSettings
Definition: main.cpp:52
int tmpViewY1
Definition: schematic.h:141
QString ModuleName
Definition: verilogfile.h:54
void(MouseActions::* MousePressAction)(Schematic *, QMouseEvent *, float, float)
Definition: qucs.h:86
Q3PtrList< Wire > SymbolWires
Definition: schematic.cpp:64
Component * getComponentFromName(QString &Line, Schematic *p)
Definition: component.cpp:1532
QString createSymbolUndoString(char)
int showBias
Definition: qucsdoc.h:63
bool rotateElements()
Definition: schematic.cpp:1022
int adjustPortNumbers()
Definition: schematic.cpp:1350
int y2
Definition: element.h:153
Definition: element.h:72
Definition: marker.h:31
void becomeCurrent(bool)
Definition: schematic.cpp:197
int x1
Definition: element.h:153
int LineSpacing
Definition: viewpainter.h:60
void drawLine(int, int, int, int)
Definition: viewpainter.cpp:85
bool paste(QTextStream *, Q3PtrList< Element > *)
Definition: schematic.cpp:1274
int insertWire(Wire *)
QString createClipboardFile()
void contentsMouseReleaseEvent(QMouseEvent *)
Definition: schematic.cpp:575
void setOnGrid(int &, int &)
Definition: schematic.cpp:858
virtual void rotate()
Definition: painting.h:48
bool creatingLib
Definition: schematic.h:298
void showAll()
Definition: schematic.cpp:776
void copyPaintings(int &, int &, int &, int &, Q3PtrList< Element > *)
bool isVerilog
Definition: schematic.h:297
void deleteWire(Wire *)
void contentsWheelEvent(QWheelEvent *)
Definition: schematic.cpp:1850
void mirrorX()
Definition: component.cpp:490
int copyWires(int &, int &, int &, int &, Q3PtrList< Element > *)
void mirrorY()
Definition: component.cpp:552
QString PortNames
Definition: vhdlfile.h:60
QucsDoc * getDoc(int No=-1)
Definition: qucs.cpp:562
bool createSubcircuitSymbol()
Definition: schematic.cpp:158
Definition: schematic.h:55
bool DocChanged
Definition: qucsdoc.h:60
QucsDoc * findDoc(QString, int *Pos=0)
Definition: qucs.cpp:582
QString PortNames
Definition: vafile.h:30
void insertRawComponent(Component *, bool noOptimize=true)
QLineEdit * editText
Definition: qucs.h:81
#define isDigitalComponent
Definition: element.h:113
bool dragIsOkay
Definition: schematic.h:172
void enlargeView(int, int, int, int)
Definition: schematic.cpp:832
PE
Definition: schematic.h:55
float zoom(float)
Definition: schematic.cpp:745
Q3PtrList< Diagram > * Diagrams
Definition: schematic.h:121
void slotScrollLeft()
Definition: schematic.cpp:2008
QString ModuleName
Definition: vafile.h:29
int ViewY1
Definition: schematic.h:132
Definitions and declarations for the main application.
bool copyComps2WiresPaints(int &, int &, int &, int &, Q3PtrList< Element > *)
void paint(ViewPainter *)
Definition: wirelabel.cpp:109
QucsApp * QucsMain
Definition: main.cpp:54
const char * empty_xpm[]
Definition: qucsdoc.cpp:65
int tmpViewY2
Definition: schematic.h:141
void contentsMousePressEvent(QMouseEvent *)
Definition: schematic.cpp:550
int cx
Definition: element.h:153
void entireBounds(int &, int &, int &, int &, float)
Definition: component.cpp:109
void setPainter(Schematic *)
void print(QPrinter *, QPainter *, bool, bool)
Definition: schematic.cpp:589
Q3PtrList< Component > * Components
Definition: schematic.h:123
void printCursorPosition(int, int)
Definition: qucs_init.cpp:980
bool mirrorYComponents()
Definition: schematic.cpp:1188
virtual void mirrorX()
Definition: painting.h:49
bool symbolMode
Definition: schematic.h:128
bool load()
Definition: schematic.cpp:1281
bool isSelected
Definition: element.h:151
int drawText(const QString &, int, int, int *Height=0)
bool PaintOnViewport
Definition: schematic.h:56
Q3PtrList< Diagram > DocDiags
Definition: schematic.h:121
void drawContents(QPainter *, int, int, int, int)
Definition: schematic.cpp:418
bool rebuild(QString *)
bool scrollDown(int)
Definition: schematic.cpp:1912
int UsedX2
Definition: schematic.h:133
Q3PtrList< Element > Connections
Definition: node.h:39
QString createUndoString(char)
void slotScrollDown()
Definition: schematic.cpp:1998
Q3PtrList< Node > * Nodes
Definition: schematic.h:120
Element * selElem
Definition: mouseactions.h:50
QucsApp * App
Definition: qucsdoc.h:59
Q3PtrList< Graph > Graphs
Definition: diagram.h:95
int ViewY2
Definition: schematic.h:132
void Bounding(int &, int &, int &, int &)
Definition: diagram.cpp:622
QAction * undo
Definition: qucs.h:174
QListWidget * CompComps
Definition: qucs.h:165
QString Name
Definition: painting.h:55
float tmpScale
Definition: schematic.h:140
bool pasteFromClipboard(QTextStream *, Q3PtrList< Element > *)
void paintGrid(ViewPainter *, int, int, int, int)
Definition: schematic.cpp:870
MouseActions * view
Definition: qucs.h:163
virtual void getCenter(int &, int &)
Definition: painting.h:32
QDateTime lastSaved
Definition: qucsdoc.h:56
void drawArc(int, int, int, int, int, int)
int GridX
Definition: schematic.h:131
QList< PostedPaintEvent > PostedPaintEvents
Definition: schematic.h:127
QAction * redo
Definition: qucs.h:174
QAction * symEdit
Definition: qucs.h:174
void(MouseActions::* MouseReleaseAction)(Schematic *, QMouseEvent *)
Definition: qucs.h:88
#define isAnalogComponent
Definition: element.h:112
bool sizeOfFrame(int &, int &)
Definition: schematic.cpp:332
QString Frame_Text1
Definition: schematic.h:136
QString copySelected(bool)
Definition: schematic.cpp:1265
int ViewX1
Definition: schematic.h:132
Q3PtrList< Node > SymbolNodes
Definition: schematic.cpp:65
void drawRect(int, int, int, int)
Superclass of all schematic drawing elements.
Definition: element.h:142
int tmpUsedX1
Definition: schematic.h:142
int save()
Definition: schematic.cpp:1317
#define isHWireLabel
Definition: element.h:124
int ViewX2
Definition: schematic.h:132
bool rebuildSymbol(QString *)
QString Frame_Text2
Definition: schematic.h:136
int showFrame
Definition: schematic.h:135
QAction * formerAction
void getSelAreaWidthAndHeight(int &wsel, int &hsel, int &xmin_sel_, int &ymin_sel_)
Definition: schematic.cpp:2221
QString DataSet
Definition: qucsdoc.h:52
void rotate()
Definition: component.cpp:390
void slotScrollUp()
Definition: schematic.cpp:1988
#define isVWireLabel
Definition: element.h:125
void paintSchToViewpainter(ViewPainter *p, bool printAll, bool toImage, int screenDpiX=96, int printerDpiX=300)
Definition: schematic.cpp:657
#define isPainting
Definition: element.h:120
void paintFrame(ViewPainter *)
Definition: schematic.cpp:351
float zoomBy(float)
Definition: schematic.cpp:766
int GridY
Definition: schematic.h:131
QTabWidget * DocumentTab
Definition: qucs.h:164
int copyComponents(int &, int &, int &, int &, Q3PtrList< Element > *)
QAction * activeAction
Definition: qucs.h:182
QFileInfo FileInfo
Definition: schematic.h:173
void reloadGraphs()
Definition: schematic.cpp:1256
void MPressWire2(Schematic *, QMouseEvent *, float, float)
MouseActions::MPressWire2 Is called if ending point of wire is pressed.
Q3PtrList< Diagram > SymbolDiags
Definition: schematic.cpp:66
int UsedY2
Definition: schematic.h:133
Schematic(QucsApp *, const QString &)
Definition: schematic.cpp:70
QString Name
Definition: node.h:40
QString GenNames
Definition: vhdlfile.h:63
void contentsDragMoveEvent(QDragMoveEvent *)
Definition: schematic.cpp:2140
void MReleasePaste(Schematic *, QMouseEvent *)
Conductor * pOwner
Definition: wirelabel.h:42
int cy
Definition: element.h:153
Q3PtrList< Painting > SymbolPaints
Definition: schematic.h:125
QString GenTypes
Definition: vhdlfile.h:62
void copyLabels(int &, int &, int &, int &, Q3PtrList< Element > *)
WireLabel * Label
Definition: element.h:163
unsigned int maxUndo
Definition: main.h:55
QString DocName
Definition: qucsdoc.h:51
Q3PtrList< QString > UndoSymbol
Definition: schematic.h:145
int tmpPosY
Definition: qucsdoc.h:65
void(MouseActions::* MouseDoubleClickAction)(Schematic *, QMouseEvent *)
Definition: qucs.h:87
The TextDoc class definition.
Definition: textdoc.h:49
bool mirrorXComponents()
Definition: schematic.cpp:1119
void contentsDragEnterEvent(QDragEnterEvent *)
Definition: schematic.cpp:2069
void contentsMouseDoubleClickEvent(QMouseEvent *)
Definition: schematic.cpp:582
#define isComponent
Definition: element.h:110
Q3PtrList< Wire > DocWires
Definition: schematic.h:119
void setCenter(int, int, bool relative=false)
Definition: component.cpp:129
Definition: qucs.h:61
void init(QPainter *, float, int, int, int, int, float FontScale_=0.0, float PrintScale_=1.0)
Definition: viewpainter.cpp:36
int UsedX1
Definition: schematic.h:133
void sizeOfAll(int &, int &, int &, int &)
Definition: schematic.cpp:931
void rightPressMenu(Schematic *, QMouseEvent *, float, float)
int tmpPosX
Definition: qucsdoc.h:65
bool redo()
Definition: schematic.cpp:1631
Q3PtrList< QString > UndoStack
Definition: schematic.h:144
#define isWire
Definition: element.h:118
QString Frame_Text3
Definition: schematic.h:136
bool scrollLeft(int)
Definition: schematic.cpp:1938
void contentsDropEvent(QDropEvent *)
Definition: schematic.cpp:2034
int x2
Definition: element.h:153
void showNoZoom()
Definition: schematic.cpp:801
void setName(const QString &)
Definition: schematic.cpp:260
Q3PtrList< Node > DocNodes
Definition: schematic.h:120
Q3PtrList< Painting > * Paintings
Definition: schematic.h:122
bool loadDocument()
Q3PtrList< Wire > * Wires
Definition: schematic.h:119
int UsedY1
Definition: schematic.h:133
virtual void mirrorY()
Definition: painting.h:50
virtual void Bounding(int &, int &, int &, int &)
Definition: painting.cpp:33
QColor BGColor
Definition: main.h:48
int tmpUsedX2
Definition: schematic.h:142
void getSchWidthAndHeight(int &w, int &h, int &xmin_, int &ymin_)
Definition: schematic.cpp:2155
QString DataDisplay
Definition: qucsdoc.h:53
QString GenDefs
Definition: vhdlfile.h:64
void updateSchNameHash(void)
Definition: qucs.cpp:2958
void drawEllipse(int, int, int, int)
void slotSelectComponent(QListWidgetItem *)
Definition: qucs.cpp:713
bool elementsOnGrid()
Definition: schematic.cpp:1685
bool scrollUp(int)
Definition: schematic.cpp:1887
virtual void setCenter(int, int, bool relative=false)
Definition: element.cpp:35
void setChanged(bool, bool fillStack=false, char Op='*')
Definition: schematic.cpp:278
int tmpViewX1
Definition: schematic.h:141
void insertNodeLabel(WireLabel *)
Q3PtrList< Component > DocComps
Definition: schematic.h:123
void contentsDragLeaveEvent(QDragLeaveEvent *)
Definition: schematic.cpp:2123