Qucs-GUI  0.0.18
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
component.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  component.cpp
3  ---------------
4  begin : Sat Aug 23 2003
5  copyright : (C) 2003 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 
20 #include <QDir>
21 #include <QPen>
22 #include <QPoint>
23 #include <QString>
24 #include <QPainter>
25 #include <QTabWidget>
26 #include <QMessageBox>
27 #include <QtXml>
28 #include <Q3Dict>
29 
30 #include "components.h"
31 #include "node.h"
32 #include "main.h"
33 #include "qucs.h"
34 #include "schematic.h"
35 #include "viewpainter.h"
36 #include "module.h"
37 
38 // ***********************************************************************
39 // ********** **********
40 // ********** class "Component" **********
41 // ********** **********
42 // ***********************************************************************
44 {
46 
47  mirroredX = false;
48  rotated = 0;
49  isSelected = false;
51  showName = true;
52 
53  cx = 0;
54  cy = 0;
55  tx = 0;
56  ty = 0;
57 
58  Arcs.setAutoDelete(true);
59  Lines.setAutoDelete(true);
60  Rects.setAutoDelete(true);
61  Ellips.setAutoDelete(true);
62  Ports.setAutoDelete(true);
63  Texts.setAutoDelete(true);
64  Props.setAutoDelete(true);
65 
66  containingSchematic = NULL;
67 }
68 
69 // -------------------------------------------------------
71 {
72  return new Component();
73 }
74 
75 // -------------------------------------------------------
76 void Component::Bounding(int& _x1, int& _y1, int& _x2, int& _y2)
77 {
78  _x1 = x1+cx;
79  _y1 = y1+cy;
80  _x2 = x2+cx;
81  _y2 = y2+cy;
82 }
83 
84 // -------------------------------------------------------
85 // Size of component text.
86 int Component::textSize(int& _dx, int& _dy)
87 {
88  QFontMetrics metrics(QucsSettings.font); // get size of text
89  int tmp, count=0;
90  _dx = _dy = 0;
91  if(showName) {
92  _dx = metrics.width(Name);
93  _dy = metrics.height();
94  count++;
95  }
96  for(Property *pp = Props.first(); pp != 0; pp = Props.next())
97  if(pp->display) {
98  // get width of text
99  tmp = metrics.width(pp->Name+"="+pp->Value);
100  if(tmp > _dx) _dx = tmp;
101  _dy += metrics.height();
102  count++;
103  }
104  return count;
105 }
106 
107 // -------------------------------------------------------
108 // Boundings including the component text.
109 void Component::entireBounds(int& _x1, int& _y1, int& _x2, int& _y2, float Corr)
110 {
111  _x1 = x1+cx;
112  _y1 = y1+cy;
113  _x2 = x2+cx;
114  _y2 = y2+cy;
115 
116  // text boundings
117  if(tx < x1) _x1 = tx+cx;
118  if(ty < y1) _y1 = ty+cy;
119 
120  int dx, dy, ny;
121  ny = textSize(dx, dy);
122  dy = int(float(ny) / Corr); // correction for unproportional font scaling
123 
124  if((tx+dx) > x2) _x2 = tx+dx+cx;
125  if((ty+dy) > y2) _y2 = ty+dy+cy;
126 }
127 
128 // -------------------------------------------------------
129 void Component::setCenter(int x, int y, bool relative)
130 {
131  if(relative) { cx += x; cy += y; }
132  else { cx = x; cy = y; }
133 }
134 
135 // -------------------------------------------------------
136 void Component::getCenter(int& x, int& y)
137 {
138  x = cx;
139  y = cy;
140 }
141 
142 // -------------------------------------------------------
143 int Component::getTextSelected(int x_, int y_, float Corr)
144 {
145  x_ -= cx;
146  y_ -= cy;
147  if(x_ < tx) return -1;
148  if(y_ < ty) return -1;
149 
150  x_ -= tx;
151  y_ -= ty;
152  int w, dy = int(float(y_) * Corr); // correction for font scaling
153  QFontMetrics metrics(QucsSettings.font);
154  if(showName) {
155  w = metrics.width(Name);
156  if(dy < 1) {
157  if(x_ < w) return 0;
158  return -1;
159  }
160  dy--;
161  }
162 
163  Property *pp;
164  for(pp = Props.first(); pp != 0; pp = Props.next())
165  if(pp->display)
166  if((dy--) < 1) break;
167  if(!pp) return -1;
168 
169  // get width of text
170  w = metrics.width(pp->Name+"="+pp->Value);
171  if(x_ > w) return -1;
172  return Props.at()+1; // number the property
173 }
174 
175 // -------------------------------------------------------
176 bool Component::getSelected(int x_, int y_)
177 {
178  x_ -= cx;
179  y_ -= cy;
180  if(x_ >= x1) if(x_ <= x2) if(y_ >= y1) if(y_ <= y2)
181  return true;
182 
183  return false;
184 }
185 
186 // -------------------------------------------------------
188 {
189  Text *pt;
190  int x, y, a, b, xb, yb;
191  QFont f = p->Painter->font(); // save current font
192  QFont newFont = f;
193  if(Model.at(0) == '.') { // is simulation component (dc, ac, ...)
194  newFont.setPointSizeFloat(p->Scale * Texts.getFirst()->Size);
195  newFont.setWeight(QFont::DemiBold);
196  p->Painter->setFont(newFont);
197  p->map(cx, cy, x, y);
198 
199  p->Painter->setPen(QPen(Qt::darkBlue,2));
200  a = b = 0;
201  QRect r, t;
202  for(pt = Texts.first(); pt != 0; pt = Texts.next()) {
203  t.setRect(x, y+b, 0, 0);
204  p->Painter->drawText(t, Qt::AlignLeft|Qt::TextDontClip, pt->s, -1, &r);
205  b += r.height();
206  if(a < r.width()) a = r.width();
207  }
208  xb = a + int(12.0*p->Scale);
209  yb = b + int(10.0*p->Scale);
210  x2 = x1+25 + int(float(a) / p->Scale);
211  y2 = y1+23 + int(float(b) / p->Scale);
212  if(ty < y2+1) if(ty > y1-r.height()) ty = y2 + 1;
213 
214  p->map(cx-1, cy, x, y);
215  p->map(cx-6, cy-5, a, b);
216  p->Painter->drawRect(a, b, xb, yb);
217  p->Painter->drawLine(x, y+yb, a, b+yb);
218  p->Painter->drawLine(x+xb-1, y+yb, x, y+yb);
219  p->Painter->drawLine(x+xb-1, y+yb, a+xb, b+yb);
220  p->Painter->drawLine(x+xb-1, y+yb, x+xb-1, y);
221  p->Painter->drawLine(x+xb-1, y, a+xb, b);
222  }
223  else { // normal components go here
224 
225  // paint all lines
226  for(Line *p1 = Lines.first(); p1 != 0; p1 = Lines.next()) {
227  p->Painter->setPen(p1->style);
228  p->drawLine(cx+p1->x1, cy+p1->y1, cx+p1->x2, cy+p1->y2);
229  }
230 
231  // paint all arcs
232  for(Arc *p3 = Arcs.first(); p3 != 0; p3 = Arcs.next()) {
233  p->Painter->setPen(p3->style);
234  p->drawArc(cx+p3->x, cy+p3->y, p3->w, p3->h, p3->angle, p3->arclen);
235  }
236 
237  // paint all rectangles
238  Area *pa;
239  for(pa = Rects.first(); pa != 0; pa = Rects.next()) {
240  p->Painter->setPen(pa->Pen);
241  p->Painter->setBrush(pa->Brush);
242  p->drawRect(cx+pa->x, cy+pa->y, pa->w, pa->h);
243  }
244 
245  // paint all ellipses
246  for(pa = Ellips.first(); pa != 0; pa = Ellips.next()) {
247  p->Painter->setPen(pa->Pen);
248  p->Painter->setBrush(pa->Brush);
249  p->drawEllipse(cx+pa->x, cy+pa->y, pa->w, pa->h);
250  }
251  p->Painter->setBrush(Qt::NoBrush);
252 
253  newFont.setWeight(QFont::Light);
254 
255  // keep track of painter state
256  p->Painter->save();
257 
258  QMatrix wm = p->Painter->worldMatrix();
259  // write all text
260  for(pt = Texts.first(); pt != 0; pt = Texts.next()) {
261  p->Painter->setWorldMatrix(
262  QMatrix(pt->mCos, -pt->mSin, pt->mSin, pt->mCos,
263  p->DX + float(cx+pt->x) * p->Scale,
264  p->DY + float(cy+pt->y) * p->Scale));
265  newFont.setPointSizeFloat(p->Scale * pt->Size);
266  newFont.setOverline(pt->over);
267  newFont.setUnderline(pt->under);
268  p->Painter->setFont(newFont);
269  p->Painter->setPen(pt->Color);
270  if (0) {
271  p->Painter->drawText(0, 0, 0, 0, Qt::AlignLeft|Qt::TextDontClip, pt->s);
272  } else {
273  int w, h;
274  w = p->drawTextMapped (pt->s, 0, 0, &h);
275  }
276  }
277  p->Painter->setWorldMatrix(wm);
278  p->Painter->setWorldXForm(false);
279 
280  // restore painter state
281  p->Painter->restore();
282  }
283 
284  // restore old font
285  p->Painter->setFont(f);
286 
287  p->Painter->setPen(QPen(Qt::black,1));
288  p->map(cx+tx, cy+ty, x, y);
289  if(showName) {
290  p->Painter->drawText(x, y, 0, 0, Qt::TextDontClip, Name);
291  y += p->LineSpacing;
292  }
293  // write all properties
294  for(Property *p4 = Props.first(); p4 != 0; p4 = Props.next())
295  if(p4->display) {
296  p->Painter->drawText(x, y, 0, 0, Qt::TextDontClip, p4->Name+"="+p4->Value);
297  y += p->LineSpacing;
298  }
299 
300  if(isActive == COMP_IS_OPEN)
301  p->Painter->setPen(QPen(Qt::red,0));
302  else if(isActive & COMP_IS_SHORTEN)
303  p->Painter->setPen(QPen(Qt::darkGreen,0));
304  if(isActive != COMP_IS_ACTIVE) {
305  p->drawRect(cx+x1, cy+y1, x2-x1+1, y2-y1+1);
306  p->drawLine(cx+x1, cy+y1, cx+x2, cy+y2);
307  p->drawLine(cx+x1, cy+y2, cx+x2, cy+y1);
308  }
309 
310  // draw component bounding box
311  if(isSelected) {
312  p->Painter->setPen(QPen(Qt::darkGray,3));
313  p->drawRoundRect(cx+x1, cy+y1, x2-x1, y2-y1);
314  }
315 }
316 
317 // -------------------------------------------------------
318 // Paints the component when moved with the mouse.
320 {
321  // qDebug() << "paintScheme" << Model;
322  if(Model.at(0) == '.') { // is simulation component (dc, ac, ...)
323  Text *pt;
324  int a, b, xb, yb;
325  QFont newFont = p->font();
326 
327  float Scale =
328  ((Schematic*)QucsMain->DocumentTab->currentPage())->Scale;
329  newFont.setPointSizeFloat(float(Scale) * QucsSettings.largeFontSize);
330  newFont.setWeight(QFont::DemiBold);
331  QFontMetrics metrics(newFont);
332 
333  a = b = 0;
334  QSize r;
335  for(pt = Texts.first(); pt != 0; pt = Texts.next()) {
336  r = metrics.size(0, pt->s);
337  b += r.height();
338  if(a < r.width()) a = r.width();
339  }
340  xb = a + int(12.0*Scale);
341  yb = b + int(10.0*Scale);
342  x2 = x1+25 + int(float(a) / Scale);
343  y2 = y1+23 + int(float(b) / Scale);
344  if(ty < y2+1) if(ty > y1-r.height()) ty = y2 + 1;
345 
346  p->PostPaintEvent(_Rect,cx-6, cy-5, xb, yb);
347  p->PostPaintEvent(_Line,cx-1, cy+yb, cx-6, cy+yb-5);
348  p->PostPaintEvent(_Line,cx+xb-2, cy+yb, cx-1, cy+yb);
349  p->PostPaintEvent(_Line,cx+xb-2, cy+yb, cx+xb-6, cy+yb-5);
350  p->PostPaintEvent(_Line,cx+xb-2, cy+yb, cx+xb-2, cy);
351  p->PostPaintEvent(_Line,cx+xb-2, cy, cx+xb-6, cy-5);
352  return;
353  }
354 
355  // paint all lines
356  for(Line *p1 = Lines.first(); p1 != 0; p1 = Lines.next())
357  p->PostPaintEvent(_Line,cx+p1->x1, cy+p1->y1, cx+p1->x2, cy+p1->y2);
358 
359  // paint all ports
360  for(Port *p2 = Ports.first(); p2 != 0; p2 = Ports.next())
361  if(p2->avail) p->PostPaintEvent(_Ellipse,cx+p2->x-4, cy+p2->y-4, 8, 8);
362 
363  for(Arc *p3 = Arcs.first(); p3 != 0; p3 = Arcs.next()) // paint all arcs
364  p->PostPaintEvent(_Arc,cx+p3->x, cy+p3->y, p3->w, p3->h, p3->angle, p3->arclen);
365 
366  Area *pa;
367  for(pa = Rects.first(); pa != 0; pa = Rects.next()) // paint all rectangles
368  p->PostPaintEvent(_Rect,cx+pa->x, cy+pa->y, pa->w, pa->h);
369 
370  for(pa = Ellips.first(); pa != 0; pa = Ellips.next()) // paint all ellipses
371  p->PostPaintEvent(_Ellipse,cx+pa->x, cy+pa->y, pa->w, pa->h);
372 }
373 
374 // -------------------------------------------------------
375 // For output on a printer device.
376 void Component::print(ViewPainter *p, float FontScale)
377 {
378  Text *pt;
379  for(pt = Texts.first(); pt != 0; pt = Texts.next())
380  pt->Size *= FontScale;
381 
382  paint(p);
383 
384  for(pt = Texts.first(); pt != 0; pt = Texts.next())
385  pt->Size /= FontScale;
386 }
387 
388 // -------------------------------------------------------
389 // Rotates the component 90 counter-clockwise around its center
391 {
392  // Port count only available after recreate, createSymbol
393  if ((Model != "Sub") && (Model !="VHDL") && (Model != "Verilog")) // skip port count
394  if(Ports.count() < 1) return; // do not rotate components without ports
395  int tmp, dx, dy;
396 
397  // rotate all lines
398  for(Line *p1 = Lines.first(); p1 != 0; p1 = Lines.next()) {
399  tmp = -p1->x1;
400  p1->x1 = p1->y1;
401  p1->y1 = tmp;
402  tmp = -p1->x2;
403  p1->x2 = p1->y2;
404  p1->y2 = tmp;
405  }
406 
407  // rotate all ports
408  for(Port *p2 = Ports.first(); p2 != 0; p2 = Ports.next()) {
409  tmp = -p2->x;
410  p2->x = p2->y;
411  p2->y = tmp;
412  }
413 
414  // rotate all arcs
415  for(Arc *p3 = Arcs.first(); p3 != 0; p3 = Arcs.next()) {
416  tmp = -p3->x;
417  p3->x = p3->y;
418  p3->y = tmp - p3->w;
419  tmp = p3->w;
420  p3->w = p3->h;
421  p3->h = tmp;
422  p3->angle += 16*90;
423  if(p3->angle >= 16*360) p3->angle -= 16*360;;
424  }
425 
426  Area *pa;
427  // rotate all rectangles
428  for(pa = Rects.first(); pa != 0; pa = Rects.next()) {
429  tmp = -pa->x;
430  pa->x = pa->y;
431  pa->y = tmp - pa->w;
432  tmp = pa->w;
433  pa->w = pa->h;
434  pa->h = tmp;
435  }
436 
437  // rotate all ellipses
438  for(pa = Ellips.first(); pa != 0; pa = Ellips.next()) {
439  tmp = -pa->x;
440  pa->x = pa->y;
441  pa->y = tmp - pa->w;
442  tmp = pa->w;
443  pa->w = pa->h;
444  pa->h = tmp;
445  }
446 
447  // rotate all text
448  float ftmp;
449  for(Text *pt = Texts.first(); pt != 0; pt = Texts.next()) {
450  tmp = -pt->x;
451  pt->x = pt->y;
452  pt->y = tmp;
453 
454  ftmp = -pt->mSin;
455  pt->mSin = pt->mCos;
456  pt->mCos = ftmp;
457  }
458 
459  tmp = -x1; // rotate boundings
460  x1 = y1; y1 = -x2;
461  x2 = y2; y2 = tmp;
462 
463  tmp = -tx; // rotate text position
464  tx = ty;
465  ty = tmp;
466  QFontMetrics metrics(QucsSettings.font); // get size of text
467  dx = dy = 0;
468  if(showName) {
469  dx = metrics.width(Name);
470  dy = metrics.lineSpacing();
471  }
472  for(Property *pp = Props.first(); pp != 0; pp = Props.next())
473  if(pp->display) {
474  // get width of text
475  tmp = metrics.width(pp->Name+"="+pp->Value);
476  if(tmp > dx) dx = tmp;
477  dy += metrics.lineSpacing();
478  }
479  if(tx > x2) ty = y1-ty+y2; // rotate text position
480  else if(ty < y1) ty -= dy;
481  else if(tx < x1) { tx += dy-dx; ty = y1-ty+y2; }
482  else ty -= dx;
483 
484  rotated++; // keep track of what's done
485  rotated &= 3;
486 }
487 
488 // -------------------------------------------------------
489 // Mirrors the component about the x-axis.
491 {
492  // Port count only available after recreate, createSymbol
493  if ((Model != "Sub") && (Model !="VHDL") && (Model != "Verilog")) // skip port count
494  if(Ports.count() < 1) return; // do not rotate components without ports
495 
496  // mirror all lines
497  for(Line *p1 = Lines.first(); p1 != 0; p1 = Lines.next()) {
498  p1->y1 = -p1->y1;
499  p1->y2 = -p1->y2;
500  }
501 
502  // mirror all ports
503  for(Port *p2 = Ports.first(); p2 != 0; p2 = Ports.next())
504  p2->y = -p2->y;
505 
506  // mirror all arcs
507  for(Arc *p3 = Arcs.first(); p3 != 0; p3 = Arcs.next()) {
508  p3->y = -p3->y - p3->h;
509  if(p3->angle > 16*180) p3->angle -= 16*360;
510  p3->angle = -p3->angle; // mirror
511  p3->angle -= p3->arclen; // go back to end of arc
512  if(p3->angle < 0) p3->angle += 16*360; // angle has to be > 0
513  }
514 
515  Area *pa;
516  // mirror all rectangles
517  for(pa = Rects.first(); pa != 0; pa = Rects.next())
518  pa->y = -pa->y - pa->h;
519 
520  // mirror all ellipses
521  for(pa = Ellips.first(); pa != 0; pa = Ellips.next())
522  pa->y = -pa->y - pa->h;
523 
524  QFont f = QucsSettings.font;
525  // mirror all text
526  for(Text *pt = Texts.first(); pt != 0; pt = Texts.next()) {
527  f.setPointSizeFloat(pt->Size);
528  QFontMetrics smallMetrics(f);
529  QSize s = smallMetrics.size(0, pt->s); // use size for more lines
530  pt->y = -pt->y - int(pt->mCos)*s.height() + int(pt->mSin)*s.width();
531  }
532 
533  int tmp = y1;
534  y1 = -y2; y2 = -tmp; // mirror boundings
535 
536  QFontMetrics metrics(QucsSettings.font); // get size of text
537  int dy = 0;
538  if(showName)
539  dy = metrics.lineSpacing(); // for "Name"
540  for(Property *pp = Props.first(); pp != 0; pp = Props.next())
541  if(pp->display) dy += metrics.lineSpacing();
542  if((tx > x1) && (tx < x2)) ty = -ty-dy; // mirror text position
543  else ty = y1+ty+y2;
544 
545  mirroredX = !mirroredX; // keep track of what's done
546  rotated += rotated << 1;
547  rotated &= 3;
548 }
549 
550 // -------------------------------------------------------
551 // Mirrors the component about the y-axis.
553 {
554  // Port count only available after recreate, createSymbol
555  if ((Model != "Sub") && (Model !="VHDL") && (Model != "Verilog")) // skip port count
556  if(Ports.count() < 1) return; // do not rotate components without ports
557 
558  // mirror all lines
559  for(Line *p1 = Lines.first(); p1 != 0; p1 = Lines.next()) {
560  p1->x1 = -p1->x1;
561  p1->x2 = -p1->x2;
562  }
563 
564  // mirror all ports
565  for(Port *p2 = Ports.first(); p2 != 0; p2 = Ports.next())
566  p2->x = -p2->x;
567 
568  // mirror all arcs
569  for(Arc *p3 = Arcs.first(); p3 != 0; p3 = Arcs.next()) {
570  p3->x = -p3->x - p3->w;
571  p3->angle = 16*180 - p3->angle - p3->arclen; // mirror
572  if(p3->angle < 0) p3->angle += 16*360; // angle has to be > 0
573  }
574 
575  Area *pa;
576  // mirror all rectangles
577  for(pa = Rects.first(); pa != 0; pa = Rects.next())
578  pa->x = -pa->x - pa->w;
579 
580  // mirror all ellipses
581  for(pa = Ellips.first(); pa != 0; pa = Ellips.next())
582  pa->x = -pa->x - pa->w;
583 
584  int tmp;
585  QFont f = QucsSettings.font;
586  // mirror all text
587  for(Text *pt = Texts.first(); pt != 0; pt = Texts.next()) {
588  f.setPointSizeFloat(pt->Size);
589  QFontMetrics smallMetrics(f);
590  QSize s = smallMetrics.size(0, pt->s); // use size for more lines
591  pt->x = -pt->x - int(pt->mSin)*s.height() - int(pt->mCos)*s.width();
592  }
593 
594  tmp = x1;
595  x1 = -x2; x2 = -tmp; // mirror boundings
596 
597  QFontMetrics metrics(QucsSettings.font); // get size of text
598  int dx = 0;
599  if(showName)
600  dx = metrics.width(Name);
601  for(Property *pp = Props.first(); pp != 0; pp = Props.next())
602  if(pp->display) {
603  // get width of text
604  tmp = metrics.width(pp->Name+"="+pp->Value);
605  if(tmp > dx) dx = tmp;
606  }
607  if((ty > y1) && (ty < y2)) tx = -tx-dx; // mirror text position
608  else tx = x1+tx+x2;
609 
610  mirroredX = !mirroredX; // keep track of what's done
611  rotated += rotated << 1;
612  rotated += 2;
613  rotated &= 3;
614 }
615 
616 // -------------------------------------------------------
618 {
619  QString s = Model+":"+Name;
620 
621  // output all node names
622  for(Port *p1 = Ports.first(); p1 != 0; p1 = Ports.next())
623  s += " "+p1->Connection->Name; // node names
624 
625  // output all properties
626  for(Property *p2 = Props.first(); p2 != 0; p2 = Props.next())
627  if(p2->Name != "Symbol")
628  s += " "+p2->Name+"=\""+p2->Value+"\"";
629 
630  return s + '\n';
631 }
632 
633 // -------------------------------------------------------
635 {
636  switch(isActive) {
637  case COMP_IS_ACTIVE:
638  return netlist();
639  case COMP_IS_OPEN:
640  return QString("");
641  }
642 
643  // Component is shortened.
644  int z=0;
645  QString s;
646  QString Node1 = Ports.first()->Connection->Name;
647  for(Port *pp = Ports.next(); pp != 0; pp = Ports.next())
648  s += "R:" + Name + "." + QString::number(z++) + " " +
649  Node1 + " " + pp->Connection->Name + " R=\"0\"\n";
650  return s;
651 }
652 
653 // -------------------------------------------------------
655 {
656  return QString(""); // no digital model
657 }
658 
659 // -------------------------------------------------------
660 QString Component::get_Verilog_Code(int NumPorts)
661 {
662  switch(isActive) {
663  case COMP_IS_OPEN:
664  return QString("");
665  case COMP_IS_ACTIVE:
666  return verilogCode(NumPorts);
667  }
668 
669  // Component is shortened.
670  Port *p = Ports.first();
671  QString Node1 = p->Connection->Name;
672  QString s = "";
673  for(p = Ports.next(); p != 0; p = Ports.next())
674  s += " assign " + p->Connection->Name + " = " + Node1 + ";\n";
675  return s;
676 }
677 
678 // -------------------------------------------------------
680 {
681  return QString(""); // no digital model
682 }
683 
684 // -------------------------------------------------------
685 QString Component::get_VHDL_Code(int NumPorts)
686 {
687  switch(isActive) {
688  case COMP_IS_OPEN:
689  return QString("");
690  case COMP_IS_ACTIVE:
691  return vhdlCode(NumPorts);
692  }
693 
694  // Component is shortened.
695  // This puts the signal of the second port onto the first port.
696  // This is locigally correct for the inverter only, but makes
697  // some sense for the gates (OR, AND etc.).
698  // Has anyone a better idea?
699  QString Node1 = Ports.first()->Connection->Name;
700  return " " + Node1 + " <= " + Ports.next()->Connection->Name + ";\n";
701 }
702 
703 // -------------------------------------------------------
705 {
706 #if XML
707  QDomDocument doc;
708  QDomElement el = doc.createElement (Model);
709  doc.appendChild (el);
710  el.setTagName (Model);
711  el.setAttribute ("inst", Name.isEmpty() ? "*" : Name);
712  el.setAttribute ("display", isActive | (showName ? 4 : 0));
713  el.setAttribute ("cx", cx);
714  el.setAttribute ("cy", cy);
715  el.setAttribute ("tx", tx);
716  el.setAttribute ("ty", ty);
717  el.setAttribute ("mirror", mirroredX);
718  el.setAttribute ("rotate", rotated);
719 
720  for (Property *pr = Props.first(); pr != 0; pr = Props.next()) {
721  el.setAttribute (pr->Name, (pr->display ? "1@" : "0@") + pr->Value);
722  }
723  qDebug (doc.toString());
724 #endif
725  QString s = "<" + Model;
726 
727  if(Name.isEmpty()) s += " * ";
728  else s += " "+Name+" ";
729 
730  int i=0;
731  if(!showName)
732  i = 4;
733  i |= isActive;
734  s += QString::number(i);
735  s += " "+QString::number(cx)+" "+QString::number(cy);
736  s += " "+QString::number(tx)+" "+QString::number(ty);
737  if(mirroredX) s += " 1";
738  else s += " 0";
739  s += " "+QString::number(rotated);
740 
741  // write all properties
742  for(Property *p1 = Props.first(); p1 != 0; p1 = Props.next()) {
743  if(p1->Description.isEmpty())
744  s += " \""+p1->Name+"="+p1->Value+"\""; // e.g. for equations
745  else s += " \""+p1->Value+"\"";
746  if(p1->display) s += " 1";
747  else s += " 0";
748  }
749 
750  return s+">";
751 }
752 
753 // -------------------------------------------------------
754 bool Component::load(const QString& _s)
755 {
756  bool ok;
757  int ttx, tty, tmp;
758  QString s = _s;
759 
760  if(s.at(0) != '<') return false;
761  if(s.at(s.length()-1) != '>') return false;
762  s = s.mid(1, s.length()-2); // cut off start and end character
763 
764  QString n;
765  Name = s.section(' ',1,1); // Name
766  if(Name == "*") Name = "";
767 
768  n = s.section(' ',2,2); // isActive
769  tmp = n.toInt(&ok);
770  if(!ok) return false;
771  isActive = tmp & 3;
772 
773  if(tmp & 4)
774  showName = false;
775  else
776  showName = true;
777 
778  n = s.section(' ',3,3); // cx
779  cx = n.toInt(&ok);
780  if(!ok) return false;
781 
782  n = s.section(' ',4,4); // cy
783  cy = n.toInt(&ok);
784  if(!ok) return false;
785 
786  n = s.section(' ',5,5); // tx
787  ttx = n.toInt(&ok);
788  if(!ok) return false;
789 
790  n = s.section(' ',6,6); // ty
791  tty = n.toInt(&ok);
792  if(!ok) return false;
793 
794  if(Model.at(0) != '.') { // is simulation component (dc, ac, ...) ?
795 
796  n = s.section(' ',7,7); // mirroredX
797  if(n.toInt(&ok) == 1) mirrorX();
798  if(!ok) return false;
799 
800  n = s.section(' ',8,8); // rotated
801  tmp = n.toInt(&ok);
802  if(!ok) return false;
803  if(rotated > tmp) // neccessary because of historical flaw in ...
804  tmp += 4; // ... components like "volt_dc"
805  for(int z=rotated; z<tmp; z++) rotate();
806 
807  }
808 
809  tx = ttx; ty = tty; // restore text position (was changed by rotate/mirror)
810 
811  unsigned int z=0, counts = s.count('"');
812  if(Model == "Sub")
813  tmp = 2; // first property (File) already exists
814  else if(Model == "Lib")
815  tmp = 3;
816  else if(Model == "EDD")
817  tmp = 5;
818  else if(Model == "RFEDD")
819  tmp = 8;
820  else if(Model == "VHDL")
821  tmp = 2;
822  else tmp = counts + 1; // "+1" because "counts" could be zero
823 
824  for(; tmp<=(int)counts/2; tmp++)
825  Props.append(new Property("p", "", true, " "));
826 
827  // load all properties
828  Property *p1;
829  for(p1 = Props.first(); p1 != 0; p1 = Props.next()) {
830  z++;
831  n = s.section('"',z,z); // property value
832  z++;
833  // not all properties have to be mentioned (backward compatible)
834  if(z > counts) {
835  if(p1->Description.isEmpty())
836  Props.remove(); // remove if allocated in vain
837 
838  if(Model == "Diode") {
839  if(counts < 56) { // backward compatible
840  counts >>= 1;
841  p1 = Props.at(counts-1);
842  for(; p1 != 0; p1 = Props.current()) {
843  if(counts-- < 19)
844  break;
845 
846  n = Props.prev()->Value;
847  p1->Value = n;
848  }
849 
850  p1 = Props.at(17);
851  p1->Value = Props.at(11)->Value;
852  Props.current()->Value = "0";
853  }
854  }
855  else if(Model == "AND" || Model == "NAND" || Model == "NOR" ||
856  Model == "OR" || Model == "XNOR"|| Model == "XOR") {
857  if(counts < 10) { // backward compatible
858  counts >>= 1;
859  p1 = Props.at(counts);
860  for(; p1 != 0; p1 = Props.current()) {
861  if(counts-- < 4)
862  break;
863  n = Props.prev()->Value;
864  p1->Value = n;
865  }
866  Props.current()->Value = "10";
867  }
868  }
869  else if(Model == "Buf" || Model == "Inv") {
870  if(counts < 8) { // backward compatible
871  counts >>= 1;
872  p1 = Props.at(counts);
873  for(; p1 != 0; p1 = Props.current()) {
874  if(counts-- < 3)
875  break;
876  n = Props.prev()->Value;
877  p1->Value = n;
878  }
879  Props.current()->Value = "10";
880  }
881  }
882 
883  return true;
884  }
885 
886  // for equations
887  if(Model != "EDD" && Model != "RFEDD" && Model != "RFEDD2P")
888  if(p1->Description.isEmpty()) { // unknown number of properties ?
889  p1->Name = n.section('=',0,0);
890  n = n.section('=',1);
891  // allocate memory for a new property (e.g. for equations)
892  if(Props.count() < (counts>>1)) {
893  Props.insert(z >> 1, new Property("y", "1", true));
894  Props.prev();
895  }
896  }
897  if(z == 6) if(counts == 6) // backward compatible
898  if(Model == "R") {
899  Props.getLast()->Value = n;
900  return true;
901  }
902  p1->Value = n;
903 
904  n = s.section('"',z,z); // display
905  p1->display = (n.at(1) == '1');
906  }
907 
908  return true;
909 }
910 
911 // *******************************************************************
912 // *** The following functions are used to load the schematic symbol
913 // *** from file. (e.g. subcircuit, library component)
914 
915 int Component::analyseLine(const QString& Row, int numProps)
916 {
917  QPen Pen;
918  QBrush Brush;
919  QColor Color;
920  QString s;
921  int i1, i2, i3, i4, i5, i6;
922 
923  s = Row.section(' ',0,0); // component type
924  if((s == "PortSym") || (s == ".PortSym")) { // backward compatible
925  if(!getIntegers(Row, &i1, &i2, &i3))
926  return -1;
927  for(i6 = Ports.count(); i6<i3; i6++) // if ports not in numerical order
928  Ports.append(new Port(0, 0, false));
929 
930  Ports.at(i3-1)->x = i1;
931  Ports.current()->y = i2;
932  Ports.current()->avail = true;
933 
934  if(i1 < x1) x1 = i1; // keep track of component boundings
935  if(i1 > x2) x2 = i1;
936  if(i2 < y1) y1 = i2;
937  if(i2 > y2) y2 = i2;
938  return 0; // do not count Ports
939  }
940  else if(s == "Line") {
941  if(!getIntegers(Row, &i1, &i2, &i3, &i4)) return -1;
942  if(!getPen(Row, Pen, 5)) return -1;
943  i3 += i1;
944  i4 += i2;
945  Lines.append(new Line(i1, i2, i3, i4, Pen));
946 
947  if(i1 < x1) x1 = i1; // keep track of component boundings
948  if(i1 > x2) x2 = i1;
949  if(i2 < y1) y1 = i2;
950  if(i2 > y2) y2 = i2;
951  if(i3 < x1) x1 = i3;
952  if(i3 > x2) x2 = i3;
953  if(i4 < y1) y1 = i4;
954  if(i4 > y2) y2 = i4;
955  return 1;
956  }
957  else if(s == "EArc") {
958  if(!getIntegers(Row, &i1, &i2, &i3, &i4, &i5, &i6))
959  return -1;
960  if(!getPen(Row, Pen, 7)) return -1;
961  Arcs.append(new struct Arc(i1, i2, i3, i4, i5, i6, Pen));
962 
963  if(i1 < x1) x1 = i1; // keep track of component boundings
964  if(i1+i3 > x2) x2 = i1+i3;
965  if(i2 < y1) y1 = i2;
966  if(i2+i4 > y2) y2 = i2+i4;
967  return 1;
968  }
969  else if(s == ".ID") {
970  if(!getIntegers(Row, &i1, &i2)) return -1;
971  tx = i1;
972  ty = i2;
973  Name = Row.section(' ',3,3);
974  if(Name.isEmpty()) Name = "SUB";
975 
976  i1 = 1;
977  Property *pp = Props.at(numProps-1);
978  for(;;) {
979  s = Row.section('"', i1,i1);
980  if(s.isEmpty()) break;
981 
982  pp = Props.next();
983  if(pp == 0) {
984  pp = new Property();
985  Props.append(pp);
986 
987  pp->display = (s.at(0) == '1');
988  pp->Value = s.section('=', 2,2);
989  }
990 
991  pp->Name = s.section('=', 1,1);
992  pp->Description = s.section('=', 3,3);
993  if(pp->Description.isEmpty())
994  pp->Description = " ";
995 
996  i1 += 2;
997  }
998 
999  while(pp != Props.last())
1000  Props.remove();
1001  return 0; // do not count IDs
1002  }
1003  else if(s == "Arrow") {
1004  if(!getIntegers(Row, &i1, &i2, &i3, &i4, &i5, &i6)) return -1;
1005  if(!getPen(Row, Pen, 7)) return -1;
1006 
1007  double beta = atan2(double(i6), double(i5));
1008  double phi = atan2(double(i4), double(i3));
1009  double Length = sqrt(double(i6*i6 + i5*i5));
1010 
1011  i3 += i1;
1012  i4 += i2;
1013  if(i1 < x1) x1 = i1; // keep track of component boundings
1014  if(i1 > x2) x2 = i1;
1015  if(i3 < x1) x1 = i3;
1016  if(i3 > x2) x2 = i3;
1017  if(i2 < y1) y1 = i2;
1018  if(i2 > y2) y2 = i2;
1019  if(i4 < y1) y1 = i4;
1020  if(i4 > y2) y2 = i4;
1021 
1022  Lines.append(new Line(i1, i2, i3, i4, Pen)); // base line
1023 
1024  double w = beta+phi;
1025  i5 = i3-int(Length*cos(w));
1026  i6 = i4-int(Length*sin(w));
1027  Lines.append(new Line(i3, i4, i5, i6, Pen)); // arrow head
1028  if(i5 < x1) x1 = i5; // keep track of component boundings
1029  if(i5 > x2) x2 = i5;
1030  if(i6 < y1) y1 = i6;
1031  if(i6 > y2) y2 = i6;
1032 
1033  w = phi-beta;
1034  i5 = i3-int(Length*cos(w));
1035  i6 = i4-int(Length*sin(w));
1036  Lines.append(new Line(i3, i4, i5, i6, Pen));
1037  if(i5 < x1) x1 = i5; // keep track of component boundings
1038  if(i5 > x2) x2 = i5;
1039  if(i6 < y1) y1 = i6;
1040  if(i6 > y2) y2 = i6;
1041 
1042  return 1;
1043  }
1044  else if(s == "Ellipse") {
1045  if(!getIntegers(Row, &i1, &i2, &i3, &i4)) return -1;
1046  if(!getPen(Row, Pen, 5)) return -1;
1047  if(!getBrush(Row, Brush, 8)) return -1;
1048  Ellips.append(new Area(i1, i2, i3, i4, Pen, Brush));
1049 
1050  if(i1 < x1) x1 = i1; // keep track of component boundings
1051  if(i1 > x2) x2 = i1;
1052  if(i2 < y1) y1 = i2;
1053  if(i2 > y2) y2 = i2;
1054  if(i1+i3 < x1) x1 = i1+i3;
1055  if(i1+i3 > x2) x2 = i1+i3;
1056  if(i2+i4 < y1) y1 = i2+i4;
1057  if(i2+i4 > y2) y2 = i2+i4;
1058  return 1;
1059  }
1060  else if(s == "Rectangle") {
1061  if(!getIntegers(Row, &i1, &i2, &i3, &i4)) return -1;
1062  if(!getPen(Row, Pen, 5)) return -1;
1063  if(!getBrush(Row, Brush, 8)) return -1;
1064  Rects.append(new Area(i1, i2, i3, i4, Pen, Brush));
1065 
1066  if(i1 < x1) x1 = i1; // keep track of component boundings
1067  if(i1 > x2) x2 = i1;
1068  if(i2 < y1) y1 = i2;
1069  if(i2 > y2) y2 = i2;
1070  if(i1+i3 < x1) x1 = i1+i3;
1071  if(i1+i3 > x2) x2 = i1+i3;
1072  if(i2+i4 < y1) y1 = i2+i4;
1073  if(i2+i4 > y2) y2 = i2+i4;
1074  return 1;
1075  }
1076  else if(s == "Text") { // must be last in order to reuse "s" *********
1077  if(!getIntegers(Row, &i1, &i2, &i3, 0, &i4)) return -1;
1078  Color.setNamedColor(Row.section(' ',4,4));
1079  if(!Color.isValid()) return -1;
1080 
1081  s = Row.mid(Row.find('"')+1); // Text (can contain " !!!)
1082  s = s.left(s.length()-1);
1083  if(s.isEmpty()) return -1;
1084  convert2Unicode(s);
1085 
1086  Texts.append(new Text(i1, i2, s, Color, float(i3),
1087  float(cos(float(i4)*M_PI/180.0)),
1088  float(sin(float(i4)*M_PI/180.0))));
1089 
1090  QFont Font(QucsSettings.font);
1091  Font.setPointSizeFloat(float(i3));
1092  QFontMetrics metrics(Font);
1093  QSize r = metrics.size(0, s); // get size of text
1094  i3 = i1 + int(float(r.width()) * Texts.current()->mCos)
1095  + int(float(r.height()) * Texts.current()->mSin);
1096  i4 = i2 + int(float(r.width()) * -Texts.current()->mSin)
1097  + int(float(r.height()) * Texts.current()->mCos);
1098 
1099  if(i1 < x1) x1 = i1; // keep track of component boundings
1100  if(i2 < y1) y1 = i2;
1101  if(i1 > x2) x2 = i1;
1102  if(i2 > y2) y2 = i2;
1103 
1104  if(i3 < x1) x1 = i3;
1105  if(i4 < y1) y1 = i4;
1106  if(i3 > x2) x2 = i3;
1107  if(i4 > y2) y2 = i4;
1108  return 1;
1109  }
1110 
1111  return 0;
1112 }
1113 
1114 // ---------------------------------------------------------------------
1115 bool Component::getIntegers(const QString& s, int *i1, int *i2, int *i3,
1116  int *i4, int *i5, int *i6)
1117 {
1118  bool ok;
1119  QString n;
1120 
1121  if(!i1) return true;
1122  n = s.section(' ',1,1);
1123  *i1 = n.toInt(&ok);
1124  if(!ok) return false;
1125 
1126  if(!i2) return true;
1127  n = s.section(' ',2,2);
1128  *i2 = n.toInt(&ok);
1129  if(!ok) return false;
1130 
1131  if(!i3) return true;
1132  n = s.section(' ',3,3);
1133  *i3 = n.toInt(&ok);
1134  if(!ok) return false;
1135 
1136  if(i4) {
1137  n = s.section(' ',4,4);
1138  *i4 = n.toInt(&ok);
1139  if(!ok) return false;
1140  }
1141 
1142  if(!i5) return true;
1143  n = s.section(' ',5,5);
1144  *i5 = n.toInt(&ok);
1145  if(!ok) return false;
1146 
1147  if(!i6) return true;
1148  n = s.section(' ',6,6);
1149  *i6 = n.toInt(&ok);
1150  if(!ok) return false;
1151 
1152  return true;
1153 }
1154 
1155 // ---------------------------------------------------------------------
1156 bool Component::getPen(const QString& s, QPen& Pen, int i)
1157 {
1158  bool ok;
1159  QString n;
1160 
1161  n = s.section(' ',i,i); // color
1162  QColor co;
1163  co.setNamedColor(n);
1164  Pen.setColor(co);
1165  if(!Pen.color().isValid()) return false;
1166 
1167  i++;
1168  n = s.section(' ',i,i); // thickness
1169  Pen.setWidth(n.toInt(&ok));
1170  if(!ok) return false;
1171 
1172  i++;
1173  n = s.section(' ',i,i); // line style
1174  Pen.setStyle((Qt::PenStyle)n.toInt(&ok));
1175  if(!ok) return false;
1176 
1177  return true;
1178 }
1179 
1180 // ---------------------------------------------------------------------
1181 bool Component::getBrush(const QString& s, QBrush& Brush, int i)
1182 {
1183  bool ok;
1184  QString n;
1185 
1186  n = s.section(' ',i,i); // fill color
1187  QColor co;
1188  co.setNamedColor(n);
1189  Brush.setColor(co);
1190  if(!Brush.color().isValid()) return false;
1191 
1192  i++;
1193  n = s.section(' ',i,i); // fill style
1194  Brush.setStyle((Qt::BrushStyle)n.toInt(&ok));
1195  if(!ok) return false;
1196 
1197  i++;
1198  n = s.section(' ',i,i); // filled
1199  if(n.toInt(&ok) == 0) Brush.setStyle(Qt::NoBrush);
1200  if(!ok) return false;
1201 
1202  return true;
1203 }
1204 
1205 // ---------------------------------------------------------------------
1206 Property * Component::getProperty(const QString& name)
1207 {
1208  for(Property *pp = Props.first(); pp != 0; pp = Props.next())
1209  if(pp->Name == name) {
1210  return pp;
1211  }
1212  return NULL;
1213 }
1214 
1215 // ---------------------------------------------------------------------
1217 {
1218  Type = pc->Type;
1219  x1 = pc->x1;
1220  y1 = pc->y1;
1221  x2 = pc->x2;
1222  y2 = pc->y2;
1223 
1224  Model = pc->Model;
1225  Name = pc->Name;
1226  showName = pc->showName;
1227  Description = pc->Description;
1228 
1229  isActive = pc->isActive;
1230  rotated = pc->rotated;
1231  mirroredX = pc->mirroredX;
1232  tx = pc->tx;
1233  ty = pc->ty;
1234 
1235  Props = pc->Props;
1236  Ports = pc->Ports;
1237  Lines = pc->Lines;
1238  Arcs = pc->Arcs;
1239  Rects = pc->Rects;
1240  Ellips = pc->Ellips;
1241  Texts = pc->Texts;
1242 }
1243 
1244 
1245 // ***********************************************************************
1246 // ******** ********
1247 // ******** Functions of class MultiViewComponent ********
1248 // ******** ********
1249 // ***********************************************************************
1251 {
1252  if(Doc) {
1253  Doc->Components->setAutoDelete(false);
1254  Doc->deleteComp(this);
1255  }
1256 
1257  Ellips.clear();
1258  Texts.clear();
1259  Ports.clear();
1260  Lines.clear();
1261  Rects.clear();
1262  Arcs.clear();
1263  createSymbol();
1264 
1265  bool mmir = mirroredX;
1266  int rrot = rotated;
1267  if (mmir && rrot==2) // mirrorX and rotate 180 = mirrorY
1268  mirrorY();
1269  else {
1270  if(mmir)
1271  mirrorX(); // mirror
1272  if (rrot)
1273  for(int z=0; z<rrot; z++) rotate(); // rotate
1274  }
1275 
1276  rotated = rrot; // restore properties (were changed by rotate/mirror)
1277  mirroredX = mmir;
1278 
1279  if(Doc) {
1280  Doc->insertRawComponent(this);
1281  Doc->Components->setAutoDelete(true);
1282  }
1283 }
1284 
1285 
1286 // ***********************************************************************
1287 // ******** ********
1288 // ******** Functions of class GateComponent ********
1289 // ******** ********
1290 // ***********************************************************************
1292 {
1293  Type = isComponent; // both analog and digital
1294  Name = "Y";
1295 
1296  // the list order must be preserved !!!
1297  Props.append(new Property("in", "2", false,
1298  QObject::tr("number of input ports")));
1299  Props.append(new Property("V", "1 V", false,
1300  QObject::tr("voltage of high level")));
1301  Props.append(new Property("t", "0", false,
1302  QObject::tr("delay time")));
1303  Props.append(new Property("TR", "10", false,
1304  QObject::tr("transfer function scaling factor")));
1305 
1306  // this must be the last property in the list !!!
1307  Props.append(new Property("Symbol", "old", false,
1308  QObject::tr("schematic symbol")+" [old, DIN40900]"));
1309 }
1310 
1311 // -------------------------------------------------------
1313 {
1314  QString s = Model+":"+Name;
1315 
1316  // output all node names
1317  for(Port *pp = Ports.first(); pp != 0; pp = Ports.next())
1318  s += " "+pp->Connection->Name; // node names
1319 
1320  // output all properties
1321  Property *p = Props.at(1);
1322  s += " " + p->Name + "=\"" + p->Value + "\"";
1323  p = Props.next();
1324  s += " " + p->Name + "=\"" + p->Value + "\"";
1325  p = Props.next();
1326  s += " " + p->Name + "=\"" + p->Value + "\"\n";
1327  return s;
1328 }
1329 
1330 // -------------------------------------------------------
1331 QString GateComponent::vhdlCode(int NumPorts)
1332 {
1333  Port *pp = Ports.first();
1334  QString s = " " + pp->Connection->Name + " <= "; // output port
1335 
1336  // xnor NOT defined for std_logic, so here use not and xor
1337  if (Model == "XNOR") {
1338  QString Op = " xor ";
1339 
1340  // first input port
1341  pp = Ports.next();
1342  QString rhs = pp->Connection->Name;
1343 
1344  // output all input ports with node names
1345  for (pp = Ports.next (); pp != 0; pp = Ports.next ())
1346  rhs = "not ((" + rhs + ")" + Op + pp->Connection->Name + ")";
1347  s += rhs;
1348  }
1349  else {
1350  QString Op = ' ' + Model.lower() + ' ';
1351  if(Model.at(0) == 'N') {
1352  s += "not ("; // nor, nand is NOT assoziative !!! but xnor is !!!
1353  Op = Op.remove(1, 1);
1354  }
1355 
1356  pp = Ports.next();
1357  s += pp->Connection->Name; // first input port
1358 
1359  // output all input ports with node names
1360  for(pp = Ports.next(); pp != 0; pp = Ports.next())
1361  s += Op + pp->Connection->Name;
1362  if(Model.at(0) == 'N')
1363  s += ')';
1364  }
1365 
1366  if(NumPorts <= 0) { // no truth table simulation ?
1367  QString td = Props.at(2)->Value; // delay time
1368  if(!VHDL_Delay(td, Name)) return td;
1369  s += td;
1370  }
1371 
1372  s += ";\n";
1373  return s;
1374 }
1375 
1376 // -------------------------------------------------------
1377 QString GateComponent::verilogCode(int NumPorts)
1378 {
1379  bool synthesize = true;
1380  Port *pp = Ports.first();
1381  QString s("");
1382 
1383  if(synthesize) {
1384  QString op = Model.lower();
1385  if(op == "and" || op == "nand")
1386  op = "&";
1387  else if (op == "or" || op == "nor")
1388  op = "|";
1389  else if (op == "xor")
1390  op = "^";
1391  else if (op == "xnor")
1392  op = "^~";
1393 
1394  s = " assign";
1395 
1396  if(NumPorts <= 0) { // no truth table simulation ?
1397  QString td = Props.at(2)->Value; // delay time
1398  if(!Verilog_Delay(td, Name)) return td;
1399  s += td;
1400  }
1401  s += " " + pp->Connection->Name + " = "; // output port
1402  if(Model.at(0) == 'N') s += "~(";
1403 
1404  pp = Ports.next();
1405  s += pp->Connection->Name; // first input port
1406 
1407  // output all input ports with node names
1408  for(pp = Ports.next(); pp != 0; pp = Ports.next())
1409  s += " " + op + " " + pp->Connection->Name;
1410 
1411  if(Model.at(0) == 'N') s += ")";
1412  s += ";\n";
1413  }
1414  else {
1415  s = " " + Model.lower();
1416 
1417  if(NumPorts <= 0) { // no truth table simulation ?
1418  QString td = Props.at(2)->Value; // delay time
1419  if(!Verilog_Delay(td, Name)) return td;
1420  s += td;
1421  }
1422  s += " " + Name + " (" + pp->Connection->Name; // output port
1423 
1424  pp = Ports.next();
1425  s += ", " + pp->Connection->Name; // first input port
1426 
1427  // output all input ports with node names
1428  for(pp = Ports.next(); pp != 0; pp = Ports.next())
1429  s += ", " + pp->Connection->Name;
1430 
1431  s += ");\n";
1432  }
1433  return s;
1434 }
1435 
1436 // -------------------------------------------------------
1438 {
1439  int Num = Props.getFirst()->Value.toInt();
1440  if(Num < 2) Num = 2;
1441  else if(Num > 8) Num = 8;
1442  Props.getFirst()->Value = QString::number(Num);
1443 
1444  int xl, xr, y = 10*Num, z;
1445  x1 = -30; y1 = -y-3;
1446  x2 = 30; y2 = y+3;
1447 
1448  tx = x1+4;
1449  ty = y2+4;
1450 
1451  z = 0;
1452  if(Model.at(0) == 'N') z = 1;
1453 
1454  if(Props.getLast()->Value.at(0) == 'D') { // DIN symbol
1455  xl = -15;
1456  xr = 15;
1457  Lines.append(new Line( 15,-y, 15, y,QPen(Qt::darkBlue,2)));
1458  Lines.append(new Line(-15,-y, 15,-y,QPen(Qt::darkBlue,2)));
1459  Lines.append(new Line(-15, y, 15, y,QPen(Qt::darkBlue,2)));
1460  Lines.append(new Line(-15,-y,-15, y,QPen(Qt::darkBlue,2)));
1461  Lines.append(new Line( 15, 0, 30, 0,QPen(Qt::darkBlue,2)));
1462 
1463  if(Model.at(z) == 'O') {
1464  Lines.append(new Line(-11, 6-y,-6, 9-y,QPen(Qt::darkBlue,0)));
1465  Lines.append(new Line(-11,12-y,-6, 9-y,QPen(Qt::darkBlue,0)));
1466  Lines.append(new Line(-11,14-y,-6,14-y,QPen(Qt::darkBlue,0)));
1467  Lines.append(new Line(-11,16-y,-6,16-y,QPen(Qt::darkBlue,0)));
1468  Texts.append(new Text( -4, 3-y, "1", Qt::darkBlue, 15.0));
1469  }
1470  else if(Model.at(z) == 'A')
1471  Texts.append(new Text( -10, 3-y, "&", Qt::darkBlue, 15.0));
1472  else if(Model.at(0) == 'X') {
1473  if(Model.at(1) == 'N') {
1474  Ellips.append(new Area(xr,-4, 8, 8,
1475  QPen(Qt::darkBlue,0), QBrush(Qt::darkBlue)));
1476  Texts.append(new Text( -11, 3-y, "=1", Qt::darkBlue, 15.0));
1477  }
1478  else
1479  Texts.append(new Text( -11, 3-y, "=1", Qt::darkBlue, 15.0));
1480  }
1481  }
1482  else { // old symbol
1483 
1484  if(Model.at(z) == 'O') xl = 10;
1485  else xl = -10;
1486  xr = 10;
1487  Lines.append(new Line(-10,-y,-10, y,QPen(Qt::darkBlue,2)));
1488  Lines.append(new Line( 10, 0, 30, 0,QPen(Qt::darkBlue,2)));
1489  Arcs.append(new Arc(-30,-y, 40, 30, 0, 16*90,QPen(Qt::darkBlue,2)));
1490  Arcs.append(new Arc(-30,y-30, 40, 30, 0,-16*90,QPen(Qt::darkBlue,2)));
1491  Lines.append(new Line( 10,15-y, 10, y-15,QPen(Qt::darkBlue,2)));
1492 
1493  if(Model.at(0) == 'X') {
1494  Lines.append(new Line(-5, 0, 5, 0,QPen(Qt::darkBlue,1)));
1495  if(Model.at(1) == 'N') {
1496  Lines.append(new Line(-5,-3, 5,-3,QPen(Qt::darkBlue,1)));
1497  Lines.append(new Line(-5, 3, 5, 3,QPen(Qt::darkBlue,1)));
1498  }
1499  else {
1500  Arcs.append(new Arc(-5,-5, 10, 10, 0, 16*360,QPen(Qt::darkBlue,1)));
1501  Lines.append(new Line( 0,-5, 0, 5,QPen(Qt::darkBlue,1)));
1502  }
1503  }
1504  }
1505 
1506  if(Model.at(0) == 'N')
1507  Ellips.append(new Area(xr,-4, 8, 8,
1508  QPen(Qt::darkBlue,0), QBrush(Qt::darkBlue)));
1509 
1510  Ports.append(new Port( 30, 0));
1511  y += 10;
1512  for(z=0; z<Num; z++) {
1513  y -= 20;
1514  Ports.append(new Port(-30, y));
1515  if(xl == 10) if((z == 0) || (z == Num-1)) {
1516  Lines.append(new Line(-30, y, 9, y,QPen(Qt::darkBlue,2)));
1517  continue;
1518  }
1519  Lines.append(new Line(-30, y, xl, y,QPen(Qt::darkBlue,2)));
1520  }
1521 }
1522 
1523 
1524 // ***********************************************************************
1525 // ******** ********
1526 // ******** The following function does not belong to any class. ********
1527 // ******** It creates a component by getting the identification ********
1528 // ******** string used in the schematic file and for copy/paste. ********
1529 // ******** ********
1530 // ***********************************************************************
1531 
1533 {
1534  Component *c = 0;
1535 
1536  Line = Line.stripWhiteSpace();
1537  if(Line.at(0) != '<') {
1538  QMessageBox::critical(0, QObject::tr("Error"),
1539  QObject::tr("Format Error:\nWrong line start!"));
1540  return 0;
1541  }
1542 
1543  QString cstr = Line.section (' ',0,0); // component type
1544  cstr.remove (0,1); // remove leading "<"
1545  if (cstr == "Lib") c = new LibComp ();
1546  else if (cstr == "Eqn") c = new Equation ();
1547  else if (cstr == "SPICE") c = new SpiceFile();
1548  else if (cstr == "Rus") c = new Resistor (false); // backward compatible
1549  else if (cstr.left (6) == "SPfile" && cstr != "SPfile") {
1550  // backward compatible
1551  c = new SParamFile ();
1552  c->Props.getLast()->Value = cstr.mid (6); }
1553  else
1554  c = Module::getComponent (cstr);
1555 
1556  if(!c) {
1558  QMessageBox::critical(0, QObject::tr("Error"),
1559  QObject::tr("Format Error:\nUnknown component!\n"
1560  "%1\n\n"
1561  "Do you make use of loadable components?").arg(cstr));
1562  return 0;
1563  }
1564 
1565  if(!c->load(Line)) {
1566  QMessageBox::critical(0, QObject::tr("Error"),
1567  QObject::tr("Format Error:\nWrong 'component' line format!"));
1568  delete c;
1569  return 0;
1570  }
1571 
1572  cstr = c->Name; // is perhaps changed in "recreate" (e.g. subcircuit)
1573  int x = c->tx, y = c->ty;
1574  c->setSchematic (p);
1575  c->recreate(0);
1576  c->Name = cstr;
1577  c->tx = x; c->ty = y;
1578  return c;
1579 }
int y
Definition: element.h:86
Q3PtrList< Line > Lines
Definition: component.h:67
virtual Component * newOne()
Definition: component.cpp:70
void deleteComp(Component *)
QPainter * Painter
Definition: viewpainter.h:58
QString save()
Definition: component.cpp:704
int Type
Definition: element.h:152
bool getBrush(const QString &, QBrush &, int)
Definition: component.cpp:1181
Definition: element.h:55
void createSymbol()
Definition: component.cpp:1437
Node * Connection
Definition: element.h:79
int w
Definition: element.h:66
int y1
Definition: element.h:153
void copyComponent(Component *)
Definition: component.cpp:1216
bool VHDL_Delay(QString &td, const QString &Name)
Definition: main.cpp:493
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
QString get_Verilog_Code(int)
Definition: component.cpp:660
Q3PtrList< struct Arc > Arcs
Definition: component.h:68
bool under
Definition: element.h:91
bool getSelected(int, int)
Definition: component.cpp:176
int h
Definition: element.h:66
QFont font
Definition: main.h:46
Q3PtrList< Area > Rects
Definition: component.h:69
int isActive
Definition: component.h:77
float Scale
Definition: viewpainter.h:59
void map(int, int, int &, int &)
Definition: viewpainter.cpp:63
tQucsSettings QucsSettings
Definition: main.cpp:52
Component * getComponentFromName(QString &Line, Schematic *p)
Definition: component.cpp:1532
int tx
Definition: component.h:78
static Component * getComponent(QString)
Definition: module.cpp:79
int analyseLine(const QString &, int)
Definition: component.cpp:915
int y2
Definition: element.h:153
Definition: element.h:72
int x1
Definition: element.h:153
int LineSpacing
Definition: viewpainter.h:60
void drawLine(int, int, int, int)
Definition: viewpainter.cpp:85
void convert2Unicode(QString &Text)
Definition: main.cpp:416
int textSize(int &, int &)
Definition: component.cpp:86
void mirrorX()
Definition: component.cpp:490
void mirrorY()
Definition: component.cpp:552
Definition: schematic.h:55
void insertRawComponent(Component *, bool noOptimize=true)
#define COMP_IS_SHORTEN
Definition: component.h:76
virtual QString vhdlCode(int)
Definition: component.cpp:679
bool Verilog_Delay(QString &td, const QString &Name)
Definition: main.cpp:555
bool display
Definition: element.h:99
Definitions and declarations for the main application.
float Size
Definition: element.h:90
int x
Definition: element.h:66
int ty
Definition: component.h:78
QString Value
Definition: element.h:97
int x
Definition: element.h:86
QucsApp * QucsMain
Definition: main.cpp:54
int cx
Definition: element.h:153
void entireBounds(int &, int &, int &, int &, float)
Definition: component.cpp:109
int rotated
Definition: component.h:61
Q3PtrList< Component > * Components
Definition: schematic.h:123
QString vhdlCode(int)
Definition: component.cpp:1331
Q3PtrList< Property > Props
Definition: component.h:72
QPen Pen
Definition: element.h:68
bool isSelected
Definition: element.h:151
virtual QString verilogCode(int)
Definition: component.cpp:654
virtual QString netlist()
Definition: component.cpp:617
virtual void setSchematic(Schematic *p)
Definition: component.h:65
Definition: element.h:63
void drawRoundRect(int, int, int, int)
Definition: element.h:82
void drawArc(int, int, int, int, int, int)
int drawTextMapped(const QString &, int, int, int *Height=0)
bool getPen(const QString &, QPen &, int)
Definition: component.cpp:1156
QBrush Brush
Definition: element.h:69
#define isAnalogComponent
Definition: element.h:112
Definition: element.h:48
void drawRect(int, int, int, int)
void recreate(Schematic *)
Definition: component.cpp:1250
bool mirroredX
Definition: component.h:60
QString netlist()
Definition: component.cpp:1312
bool showName
Definition: component.h:79
void Bounding(int &, int &, int &, int &)
Definition: component.cpp:76
Q3PtrList< Port > Ports
Definition: component.h:70
void rotate()
Definition: component.cpp:390
QString Name
Definition: element.h:97
bool load(const QString &)
Definition: component.cpp:754
void print(ViewPainter *, float)
Definition: component.cpp:376
QTabWidget * DocumentTab
Definition: qucs.h:164
QString Name
Definition: component.h:80
Q3PtrList< Text > Texts
Definition: component.h:71
int getTextSelected(int, int, float)
Definition: component.cpp:143
bool over
Definition: element.h:91
QString Model
Definition: component.h:80
QString Name
Definition: node.h:40
Schematic * containingSchematic
Definition: component.h:96
int cy
Definition: element.h:153
QString Description
Definition: component.h:81
void getCenter(int &, int &)
Definition: component.cpp:136
QColor Color
Definition: element.h:89
float largeFontSize
Definition: main.h:47
float mCos
Definition: element.h:90
#define isComponent
Definition: element.h:110
void setCenter(int, int, bool relative=false)
Definition: component.cpp:129
void paintScheme(Schematic *)
Definition: component.cpp:319
float mSin
Definition: element.h:90
#define M_PI
Definition: diagramdialog.h:25
Q3PtrList< Area > Ellips
Definition: component.h:69
QString Description
Definition: element.h:100
virtual void createSymbol()
Definition: component.h:108
int y
Definition: element.h:66
int x2
Definition: element.h:153
#define COMP_IS_ACTIVE
Definition: component.h:75
Property * getProperty(const QString &)
Definition: component.cpp:1206
QString getNetlist()
Definition: component.cpp:634
QString get_VHDL_Code(int)
Definition: component.cpp:685
virtual void recreate(Schematic *)
Definition: component.h:39
QString s
Definition: element.h:88
void drawEllipse(int, int, int, int)
QString verilogCode(int)
Definition: component.cpp:1377
#define COMP_IS_OPEN
Definition: component.h:74
void paint(ViewPainter *)
Definition: component.cpp:187
bool getIntegers(const QString &, int *i1=0, int *i2=0, int *i3=0, int *i4=0, int *i5=0, int *i6=0)
Definition: component.cpp:1115