My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
symbolwidget.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  symbolwidget.cpp
3  ------------------
4  begin : Sat May 28 2005
5  copyright : (C) 2005 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 #include <math.h>
19 #include <limits.h>
20 
21 #include <qpainter.h>
22 #include <qdragobject.h>
23 #include <qtextstream.h>
24 
25 #include "symbolwidget.h"
26 #include "qucslib.h"
27 
28 
29 const char *empty_xpm[] = { // for drag n'drop
30 "1 1 1 1", " c None", " "};
31 
32 
33 SymbolWidget::SymbolWidget(QWidget *parent) : QWidget(parent)
34 {
35  myDragObject = 0;
36  Arcs.setAutoDelete(true);
37  Lines.setAutoDelete(true);
38  Rects.setAutoDelete(true);
39  Ellips.setAutoDelete(true);
40  Texts.setAutoDelete(true);
41 
42  Text_x = Text_y = 0;
43  PaintText = tr("Symbol:");
44  QFontMetrics metrics(QucsSettings.font);
45  TextWidth = metrics.width(PaintText) + 4; // get size of text
46 
47  DragNDropText = tr("! Drag n'Drop me !");
48  DragNDropWidth = metrics.width(DragNDropText); // get size of text
49  TextHeight = metrics.lineSpacing();
50 
51  setPaletteBackgroundColor(Qt::white);
52  setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
53 }
54 
56 {
57 }
58 
59 // ************************************************************
61 {
62  // single component line
63  if(!ModelString.isEmpty())
64  if(ModelString.contains('\n') < 2)
65  return ModelString.remove('\n');
66 
67  // real library component
68  return "<Lib " + Prefix + " 1 0 0 " +
69  QString::number(Text_x) + " " +
70  QString::number(Text_y) + " 0 0 \"" +
71  LibraryName + "\" 0 \"" + ComponentName + "\" 0>";
72 }
73 
74 // ************************************************************
75 void SymbolWidget::mouseMoveEvent(QMouseEvent*)
76 {
77  myDragObject = new QTextDrag("QucsComponent:"+theModel(), this);
78  myDragObject->setPixmap( QPixmap(empty_xpm), QPoint(0, 0) );
79  myDragObject->dragCopy();
80 }
81 
82 // ************************************************************
83 void SymbolWidget::paintEvent(QPaintEvent*)
84 {
85  QPainter Painter(this);
86  Painter.drawText(2, 2, 0, 0, Qt::AlignAuto | Qt::DontClip, PaintText);
87 
88  int dx = (x2-x1)/2 + TextWidth - DragNDropWidth/2;
89  if(dx < 2) dx = 2;
90  Painter.drawText(dx, y2-y1+2, 0, 0, Qt::AlignAuto | Qt::DontClip, DragNDropText);
91 
92  // paint all lines
93  for(Line *pl = Lines.first(); pl != 0; pl = Lines.next()) {
94  Painter.setPen(pl->style);
95  Painter.drawLine(cx+pl->x1, cy+pl->y1, cx+pl->x2, cy+pl->y2);
96  }
97 
98  // paint all arcs
99  for(Arc *pc = Arcs.first(); pc != 0; pc = Arcs.next()) {
100  Painter.setPen(pc->style);
101  Painter.drawArc(cx+pc->x, cy+pc->y, pc->w, pc->h, pc->angle, pc->arclen);
102  }
103 
104  // paint all rectangles
105  Area *pa;
106  for(pa = Rects.first(); pa != 0; pa = Rects.next()) {
107  Painter.setPen(pa->Pen);
108  Painter.setBrush(pa->Brush);
109  Painter.drawRect(cx+pa->x, cy+pa->y, pa->w, pa->h);
110  }
111 
112  // paint all ellipses
113  for(pa = Ellips.first(); pa != 0; pa = Ellips.next()) {
114  Painter.setPen(pa->Pen);
115  Painter.setBrush(pa->Brush);
116  Painter.drawEllipse(cx+pa->x, cy+pa->y, pa->w, pa->h);
117  }
118 
119  Painter.setPen(QPen(QPen::black,1));
120  QFont Font = Painter.font(); // save current font
121  Font.setWeight(QFont::Light);
122  // write all text
123  for(Text *pt = Texts.first(); pt != 0; pt = Texts.next()) {
124  Font.setPointSizeFloat(pt->Size);
125  Painter.setFont(Font);
126  Painter.setPen(pt->Color);
127  Painter.drawText(cx+pt->x, cy+pt->y, 0, 0, Qt::DontClip, pt->s);
128  }
129 }
130 
131 // ************************************************************
132 // Creates a symbol from the model name of a component.
133 int SymbolWidget::createSymbol(const QString& Lib_, const QString& Comp_)
134 {
135  Arcs.clear();
136  Lines.clear();
137  Rects.clear();
138  Ellips.clear();
139  Texts.clear();
140  LibraryName = Lib_;
141  ComponentName = Comp_;
142 
143  int PortNo = 0;
144  QString Comp = ModelString.section(' ', 0,0);
145  Comp.remove(0, 1); // remove '<'
146 
147  QString FirstProp = ModelString.section('"', 1,1);
148 
149  if(Comp == "_BJT") {
150  Lines.append(new Line(-10,-15,-10, 15,QPen(QPen::darkBlue,3)));
151  Lines.append(new Line(-30, 0,-10, 0,QPen(QPen::darkBlue,2)));
152  Lines.append(new Line(-10, -5, 0,-15,QPen(QPen::darkBlue,2)));
153  Lines.append(new Line( 0,-15, 0,-30,QPen(QPen::darkBlue,2)));
154  Lines.append(new Line(-10, 5, 0, 15,QPen(QPen::darkBlue,2)));
155  Lines.append(new Line( 0, 15, 0, 30,QPen(QPen::darkBlue,2)));
156 
157  if(FirstProp == "npn") {
158  Lines.append(new Line( -6, 15, 0, 15,QPen(QPen::darkBlue,2)));
159  Lines.append(new Line( 0, 9, 0, 15,QPen(QPen::darkBlue,2)));
160  }
161  else {
162  Lines.append(new Line( -5, 10, -5, 16,QPen(QPen::darkBlue,2)));
163  Lines.append(new Line( -5, 10, 1, 10,QPen(QPen::darkBlue,2)));
164  }
165 
166  Arcs.append(new struct Arc(-34, -4, 8, 8, 0, 16*360,
167  QPen(QPen::red,1)));
168  Arcs.append(new struct Arc(-4, -34, 8, 8, 0, 16*360,
169  QPen(QPen::red,1)));
170  Arcs.append(new struct Arc(-4, 26, 8, 8, 0, 16*360,
171  QPen(QPen::red,1)));
172 
173  PortNo = 3;
174  x1 = -34; y1 = -34;
175  x2 = 4; y2 = 34;
176  }
177  else if(Comp == "JFET") {
178  Lines.append(new Line(-10,-15,-10, 15,QPen(QPen::darkBlue,3)));
179  Lines.append(new Line(-30, 0,-10, 0,QPen(QPen::darkBlue,2)));
180  Lines.append(new Line(-10,-10, 0,-10,QPen(QPen::darkBlue,2)));
181  Lines.append(new Line( 0,-10, 0,-30,QPen(QPen::darkBlue,2)));
182  Lines.append(new Line(-10, 10, 0, 10,QPen(QPen::darkBlue,2)));
183  Lines.append(new Line( 0, 10, 0, 30,QPen(QPen::darkBlue,2)));
184 
185  Lines.append(new Line( -4, 24, 4, 20,QPen(QPen::darkBlue,2)));
186 
187  if(FirstProp == "nfet") {
188  Lines.append(new Line(-16, -5,-11, 0,QPen(QPen::darkBlue,2)));
189  Lines.append(new Line(-16, 5,-11, 0,QPen(QPen::darkBlue,2)));
190  }
191  else {
192  Lines.append(new Line(-18, 0,-13, -5,QPen(QPen::darkBlue,2)));
193  Lines.append(new Line(-18, 0,-13, 5,QPen(QPen::darkBlue,2)));
194  }
195 
196  Arcs.append(new struct Arc(-34, -4, 8, 8, 0, 16*360,
197  QPen(QPen::red,1)));
198  Arcs.append(new struct Arc(-4, -34, 8, 8, 0, 16*360,
199  QPen(QPen::red,1)));
200  Arcs.append(new struct Arc(-4, 26, 8, 8, 0, 16*360,
201  QPen(QPen::red,1)));
202 
203  PortNo = 3;
204  x1 = -30; y1 = -30;
205  x2 = 4; y2 = 30;
206  }
207  else if(Comp == "_MOSFET") {
208  Lines.append(new Line(-14,-13,-14, 13,QPen(QPen::darkBlue,3)));
209  Lines.append(new Line(-30, 0,-14, 0,QPen(QPen::darkBlue,2)));
210 
211  Lines.append(new Line(-10,-11, 0,-11,QPen(QPen::darkBlue,2)));
212  Lines.append(new Line( 0,-11, 0,-30,QPen(QPen::darkBlue,2)));
213  Lines.append(new Line(-10, 11, 0, 11,QPen(QPen::darkBlue,2)));
214  Lines.append(new Line( 0, 0, 0, 30,QPen(QPen::darkBlue,2)));
215  Lines.append(new Line(-10, 0, 0, 0,QPen(QPen::darkBlue,2)));
216 
217  Lines.append(new Line(-10,-16,-10, -7,QPen(QPen::darkBlue,3)));
218  Lines.append(new Line(-10, 7,-10, 16,QPen(QPen::darkBlue,3)));
219 
220  if(FirstProp == "nfet") {
221  Lines.append(new Line( -9, 0, -4, -5,QPen(QPen::darkBlue,2)));
222  Lines.append(new Line( -9, 0, -4, 5,QPen(QPen::darkBlue,2)));
223  }
224  else {
225  Lines.append(new Line( -1, 0, -6, -5,QPen(QPen::darkBlue,2)));
226  Lines.append(new Line( -1, 0, -6, 5,QPen(QPen::darkBlue,2)));
227  }
228 
229  // depletion or enhancement MOSFET ?
230  if((ModelString.section('"', 3,3).stripWhiteSpace().at(0) == '-') ==
231  (FirstProp == "nfet"))
232  Lines.append(new Line(-10, -8,-10, 8,QPen(QPen::darkBlue,3)));
233  else
234  Lines.append(new Line(-10, -4,-10, 4,QPen(QPen::darkBlue,3)));
235 
236  Arcs.append(new struct Arc(-34, -4, 8, 8, 0, 16*360,
237  QPen(QPen::red,1)));
238  Arcs.append(new struct Arc(-4, -34, 8, 8, 0, 16*360,
239  QPen(QPen::red,1)));
240  Arcs.append(new struct Arc(-4, 26, 8, 8, 0, 16*360,
241  QPen(QPen::red,1)));
242 
243  PortNo = 3;
244  x1 = -34; y1 = -34;
245  x2 = 4; y2 = 34;
246  }
247  else if(Comp == "Diode") {
248  Lines.append(new Line(-30, 0, 30, 0,QPen(QPen::darkBlue,2)));
249  Lines.append(new Line( -6, -9, -6, 9,QPen(QPen::darkBlue,2)));
250  Lines.append(new Line( 6, -9, 6, 9,QPen(QPen::darkBlue,2)));
251  Lines.append(new Line( -6, 0, 6, -9,QPen(QPen::darkBlue,2)));
252  Lines.append(new Line( -6, 0, 6, 9,QPen(QPen::darkBlue,2)));
253 
254  Arcs.append(new struct Arc(-34, -4, 8, 8, 0, 16*360,
255  QPen(QPen::red,1)));
256  Arcs.append(new struct Arc(26, -4, 8, 8, 0, 16*360,
257  QPen(QPen::red,1)));
258 
259  PortNo = 2;
260  x1 = -34; y1 = -9;
261  x2 = 34; y2 = 9;
262  }
263  else if(Comp == "hicumL2V2p1" || Comp == "hic2_full" ||
264  Comp == "hic0_full" || Comp == "hicumL0V1p2" ||
265  Comp == "hicumL2V2p23" || Comp == "hicumL2V2p24" ||
266  Comp == "hicumL0V1p2g" || Comp == "hicumL0V1p3") {
267  // normal bipolar
268  Lines.append(new Line(-10,-15,-10, 15,QPen(QPen::darkBlue,3)));
269  Lines.append(new Line(-30, 0,-10, 0,QPen(QPen::darkBlue,2)));
270  Lines.append(new Line(-10, -5, 0,-15,QPen(QPen::darkBlue,2)));
271  Lines.append(new Line( 0,-15, 0,-30,QPen(QPen::darkBlue,2)));
272  Lines.append(new Line(-10, 5, 0, 15,QPen(QPen::darkBlue,2)));
273  Lines.append(new Line( 0, 15, 0, 30,QPen(QPen::darkBlue,2)));
274 
275  // substrate node
276  Lines.append(new Line( 9, 0, 30, 0,QPen(QPen::darkBlue,2)));
277  Lines.append(new Line( 9, -7, 9, 7,QPen(QPen::darkBlue,3)));
278 
279  // thermal node
280  Lines.append(new Line(-30, 20,-20, 20,QPen(QPen::darkBlue,2)));
281  Lines.append(new Line(-20, 17,-20, 23,QPen(QPen::darkBlue,2)));
282 
283  // arrow
284  if(FirstProp == "npn" || Comp == "hic2_full" || Comp == "hicumL2V2p23" ||
285  Comp == "hicumL2V2p1") {
286  Lines.append(new Line( -6, 15, 0, 15,QPen(QPen::darkBlue,2)));
287  Lines.append(new Line( 0, 9, 0, 15,QPen(QPen::darkBlue,2)));
288  } else {
289  Lines.append(new Line( -5, 10, -5, 16,QPen(QPen::darkBlue,2)));
290  Lines.append(new Line( -5, 10, 1, 10,QPen(QPen::darkBlue,2)));
291  }
292 
293  // H
294  Lines.append(new Line(-30,-30,-30,-24,QPen(QPen::darkBlue,1)));
295  Lines.append(new Line(-30,-27,-26,-27,QPen(QPen::darkBlue,1)));
296  Lines.append(new Line(-26,-30,-26,-24,QPen(QPen::darkBlue,1)));
297  // I
298  Lines.append(new Line(-24,-30,-24,-24,QPen(QPen::darkBlue,1)));
299  // C
300  Lines.append(new Line(-22,-30,-22,-24,QPen(QPen::darkBlue,1)));
301  Lines.append(new Line(-22,-30,-19,-30,QPen(QPen::darkBlue,1)));
302  Lines.append(new Line(-22,-24,-19,-24,QPen(QPen::darkBlue,1)));
303  // U
304  Lines.append(new Line(-17,-30,-17,-24,QPen(QPen::darkBlue,1)));
305  Lines.append(new Line(-14,-30,-14,-24,QPen(QPen::darkBlue,1)));
306  Lines.append(new Line(-17,-24,-14,-24,QPen(QPen::darkBlue,1)));
307  // M
308  Lines.append(new Line(-12,-30,-12,-24,QPen(QPen::darkBlue,1)));
309  Lines.append(new Line( -8,-30, -8,-24,QPen(QPen::darkBlue,1)));
310  Lines.append(new Line(-12,-30,-10,-28,QPen(QPen::darkBlue,1)));
311  Lines.append(new Line( -8,-30,-10,-28,QPen(QPen::darkBlue,1)));
312 
313  // terminal definitions
314  Arcs.append(new struct Arc( -4, -34, 8, 8, 0, 16*360,
315  QPen(QPen::red,1))); // collector
316  Arcs.append(new struct Arc(-34, -4, 8, 8, 0, 16*360,
317  QPen(QPen::red,1))); // base
318  Arcs.append(new struct Arc( -4, 26, 8, 8, 0, 16*360,
319  QPen(QPen::red,1))); // emitter
320  Arcs.append(new struct Arc( 26, -4, 8, 8, 0, 16*360,
321  QPen(QPen::red,1))); // substrate
322  Arcs.append(new struct Arc(-34, 16, 8, 8, 0, 16*360,
323  QPen(QPen::red,1))); // thermal node
324 
325  // relative boundings
326  x1 = -34; y1 = -34;
327  x2 = 34; y2 = 34;
328  }
329  else if(Comp == "SUBST") {
330  Lines.append(new Line(-30,-16, 30,-16,QPen(QPen::darkBlue,2)));
331  Lines.append(new Line(-30,-12, 30,-12,QPen(QPen::darkBlue,2)));
332  Lines.append(new Line(-30, 16, 30, 16,QPen(QPen::darkBlue,2)));
333  Lines.append(new Line(-30, 12, 30, 12,QPen(QPen::darkBlue,2)));
334  Lines.append(new Line(-30,-16,-30, 16,QPen(QPen::darkBlue,2)));
335  Lines.append(new Line( 30,-16, 30, 16,QPen(QPen::darkBlue,2)));
336 
337  Lines.append(new Line(-30,-16, 16,-40,QPen(QPen::darkBlue,2)));
338  Lines.append(new Line( 30,-16, 80,-40,QPen(QPen::darkBlue,2)));
339  Lines.append(new Line( 30,-12, 80,-36,QPen(QPen::darkBlue,2)));
340  Lines.append(new Line( 30, 12, 80,-16,QPen(QPen::darkBlue,2)));
341  Lines.append(new Line( 30, 16, 80,-12,QPen(QPen::darkBlue,2)));
342  Lines.append(new Line( 16,-40, 80,-40,QPen(QPen::darkBlue,2)));
343  Lines.append(new Line( 80,-40, 80,-12,QPen(QPen::darkBlue,2)));
344 
345  Lines.append(new Line(-30, 0,-18,-12,QPen(QPen::darkBlue,1)));
346  Lines.append(new Line(-22, 12, 2,-12,QPen(QPen::darkBlue,1)));
347  Lines.append(new Line( -2, 12, 22,-12,QPen(QPen::darkBlue,1)));
348  Lines.append(new Line( 18, 12, 30, 0,QPen(QPen::darkBlue,1)));
349 
350  Lines.append(new Line( 30, 1, 37, 8,QPen(QPen::darkBlue,1)));
351  Lines.append(new Line( 37,-15, 52, 0,QPen(QPen::darkBlue,1)));
352  Lines.append(new Line( 52,-22, 66, -8,QPen(QPen::darkBlue,1)));
353  Lines.append(new Line( 66,-30, 80,-16,QPen(QPen::darkBlue,1)));
354 
355  PortNo = 0;
356  x1 = -34; y1 =-44;
357  x2 = 84; y2 = 20;
358  }
359 
360  x1 -= 4; // enlarge component boundings a little
361  x2 += 4;
362  y1 -= 4;
363  y2 += 4;
364  cx = -x1 + TextWidth;
365  cy = -y1;
366 
367  int dx = x2-x1 + TextWidth;
368  if((x2-x1) < DragNDropWidth)
369  dx = (x2-x1 + DragNDropWidth)/2 + TextWidth;
370  if(dx < DragNDropWidth)
371  dx = DragNDropWidth;
372  setMinimumSize(dx, y2-y1 + TextHeight+4);
373  if(width() > dx) dx = width();
374  resize(dx, y2-y1 + TextHeight+4);
375  update();
376  return PortNo;
377 }
378 
379 // ************************************************************
380 // Loads the symbol for the component from the symbol field and
381 // returns the number of painting elements.
382 int SymbolWidget::setSymbol(const QString& SymbolString,
383  const QString& Lib_, const QString& Comp_)
384 {
385  Arcs.clear();
386  Lines.clear();
387  Rects.clear();
388  Ellips.clear();
389  Texts.clear();
390  LibraryName = Lib_;
391  ComponentName = Comp_;
392 
393  QString Line;
394  QTextIStream stream(&SymbolString);
395 
396  x1 = y1 = INT_MAX;
397  x2 = y2 = INT_MIN;
398 
399  int z=0, Result;
400  while(!stream.atEnd()) {
401  Line = stream.readLine();
402  Line = Line.stripWhiteSpace();
403  if(Line.isEmpty()) continue;
404 
405  if(Line.at(0) != '<') return -1;
406  if(Line.at(Line.length()-1) != '>') return -1;
407  Line = Line.mid(1, Line.length()-2); // cut off start and end character
408  Result = analyseLine(Line);
409  if(Result < 0) return -6; // line format error
410  z += Result;
411  }
412 
413  x1 -= 4; // enlarge component boundings a little
414  x2 += 4;
415  y1 -= 4;
416  y2 += 4;
417  cx = -x1 + TextWidth;
418  cy = -y1;
419 
420  int dx = x2-x1 + TextWidth;
421  if((x2-x1) < DragNDropWidth)
422  dx = (x2-x1 + DragNDropWidth)/2 + TextWidth;
423  if(dx < DragNDropWidth)
424  dx = DragNDropWidth;
425  setMinimumSize(dx, y2-y1 + TextHeight+4);
426  if(width() > dx) dx = width();
427  resize(dx, y2-y1 + TextHeight+4);
428  update();
429  return z; // return number of ports
430 }
431 
432 // ---------------------------------------------------------------------
433 int SymbolWidget::analyseLine(const QString& Row)
434 {
435  QPen Pen;
436  QBrush Brush;
437  QColor Color;
438  QString s;
439  int i1, i2, i3, i4, i5, i6;
440 
441  s = Row.section(' ',0,0); // component type
442  if(s == ".PortSym") { // here: ports are open nodes
443  if(!getIntegers(Row, &i1, &i2, &i3)) return -1;
444  Arcs.append(new struct Arc(i1-4, i2-4, 8, 8, 0, 16*360,
445  QPen(QPen::red,1)));
446 
447  if((i1-4) < x1) x1 = i1-4; // keep track of component boundings
448  if((i1+4) > x2) x2 = i1+4;
449  if((i2-4) < y1) y1 = i2-4;
450  if((i2+4) > y2) y2 = i2+4;
451  return 0; // do not count Ports
452  }
453  else if(s == "Line") {
454  if(!getIntegers(Row, &i1, &i2, &i3, &i4)) return -1;
455  if(!getPen(Row, Pen, 5)) return -1;
456  i3 += i1;
457  i4 += i2;
458  Lines.append(new Line(i1, i2, i3, i4, Pen));
459 
460  if(i1 < x1) x1 = i1; // keep track of component boundings
461  if(i1 > x2) x2 = i1;
462  if(i2 < y1) y1 = i2;
463  if(i2 > y2) y2 = i2;
464  if(i3 < x1) x1 = i3;
465  if(i3 > x2) x2 = i3;
466  if(i4 < y1) y1 = i4;
467  if(i4 > y2) y2 = i4;
468  return 1;
469  }
470  else if(s == "EArc") {
471  if(!getIntegers(Row, &i1, &i2, &i3, &i4, &i5, &i6)) return -1;
472  if(!getPen(Row, Pen, 7)) return -1;
473  Arcs.append(new struct Arc(i1, i2, i3, i4, i5, i6, Pen));
474 
475  if(i1 < x1) x1 = i1; // keep track of component boundings
476  if(i1+i3 > x2) x2 = i1+i3;
477  if(i2 < y1) y1 = i2;
478  if(i2+i4 > y2) y2 = i2+i4;
479  return 1;
480  }
481  else if(s == ".ID") {
482  if(!getIntegers(Row, &i1, &i2)) return -1;
483  Text_x = i1;
484  Text_y = i2;
485  Prefix = Row.section(' ',3,3);
486  if(Prefix.isEmpty()) Prefix = "X";
487  return 0; // do not count IDs
488  }
489  else if(s == "Arrow") {
490  if(!getIntegers(Row, &i1, &i2, &i3, &i4, &i5, &i6)) return -1;
491  if(!getPen(Row, Pen, 7)) return -1;
492 
493  double beta = atan2(double(i6), double(i5));
494  double phi = atan2(double(i4), double(i3));
495  double Length = sqrt(double(i6*i6 + i5*i5));
496 
497  i3 += i1;
498  i4 += i2;
499  if(i1 < x1) x1 = i1; // keep track of component boundings
500  if(i1 > x2) x2 = i1;
501  if(i3 < x1) x1 = i3;
502  if(i3 > x2) x2 = i3;
503  if(i2 < y1) y1 = i2;
504  if(i2 > y2) y2 = i2;
505  if(i4 < y1) y1 = i4;
506  if(i4 > y2) y2 = i4;
507 
508  Lines.append(new Line(i1, i2, i3, i4, Pen)); // base line
509 
510  double w = beta+phi;
511  i5 = i3-int(Length*cos(w));
512  i6 = i4-int(Length*sin(w));
513  Lines.append(new Line(i3, i4, i5, i6, Pen)); // arrow head
514  if(i5 < x1) x1 = i5; // keep track of component boundings
515  if(i5 > x2) x2 = i5;
516  if(i6 < y1) y1 = i6;
517  if(i6 > y2) y2 = i6;
518 
519  w = phi-beta;
520  i5 = i3-int(Length*cos(w));
521  i6 = i4-int(Length*sin(w));
522  Lines.append(new Line(i3, i4, i5, i6, Pen));
523  if(i5 < x1) x1 = i5; // keep track of component boundings
524  if(i5 > x2) x2 = i5;
525  if(i6 < y1) y1 = i6;
526  if(i6 > y2) y2 = i6;
527 
528  return 1;
529  }
530  else if(s == "Ellipse") {
531  if(!getIntegers(Row, &i1, &i2, &i3, &i4)) return -1;
532  if(!getPen(Row, Pen, 5)) return -1;
533  if(!getBrush(Row, Brush, 8)) return -1;
534  Ellips.append(new Area(i1, i2, i3, i4, Pen, Brush));
535 
536  if(i1 < x1) x1 = i1; // keep track of component boundings
537  if(i1 > x2) x2 = i1;
538  if(i2 < y1) y1 = i2;
539  if(i2 > y2) y2 = i2;
540  if(i1+i3 < x1) x1 = i1+i3;
541  if(i1+i3 > x2) x2 = i1+i3;
542  if(i2+i4 < y1) y1 = i2+i4;
543  if(i2+i4 > y2) y2 = i2+i4;
544  return 1;
545  }
546  else if(s == "Rectangle") {
547  if(!getIntegers(Row, &i1, &i2, &i3, &i4)) return -1;
548  if(!getPen(Row, Pen, 5)) return -1;
549  if(!getBrush(Row, Brush, 8)) return -1;
550  Rects.append(new Area(i1, i2, i3, i4, Pen, Brush));
551 
552  if(i1 < x1) x1 = i1; // keep track of component boundings
553  if(i1 > x2) x2 = i1;
554  if(i2 < y1) y1 = i2;
555  if(i2 > y2) y2 = i2;
556  if(i1+i3 < x1) x1 = i1+i3;
557  if(i1+i3 > x2) x2 = i1+i3;
558  if(i2+i4 < y1) y1 = i2+i4;
559  if(i2+i4 > y2) y2 = i2+i4;
560  return 1;
561  }
562  else if(s == "Text") { // must be last in order to reuse "s" *********
563  if(!getIntegers(Row, &i1, &i2, &i3)) return -1;
564  Color.setNamedColor(Row.section(' ',4,4));
565  if(!Color.isValid()) return -1;
566 
567  s = Row.mid(Row.find('"')+1); // Text (can contain " !!!)
568  s = s.left(s.length()-1);
569  if(s.isEmpty()) return -1;
570  s.replace("\\n", "\n");
571  s.replace("\\\\", "\\");
572 
573  Texts.append(new Text(i1, i2, s, Color, float(i3)));
574 
575  QFont Font(QucsSettings.font);
576  Font.setPointSizeFloat(float(i3));
577  QFontMetrics metrics(Font);
578  QSize r = metrics.size(0, s); // get size of text
579  i3 = i1 + r.width();
580  i4 = i2 + r.height();
581 
582  if(i1 < x1) x1 = i1; // keep track of component boundings
583  if(i3 > x2) x2 = i3;
584  if(i2 < y1) y1 = i2;
585  if(i4 > y2) y2 = i4;
586  }
587 
588  return 0;
589 }
590 
591 // ---------------------------------------------------------------------
592 bool SymbolWidget::getIntegers(const QString& s, int *i1, int *i2, int *i3,
593  int *i4, int *i5, int *i6)
594 {
595  bool ok;
596  QString n;
597 
598  if(!i1) return true;
599  n = s.section(' ',1,1);
600  *i1 = n.toInt(&ok);
601  if(!ok) return false;
602 
603  if(!i2) return true;
604  n = s.section(' ',2,2);
605  *i2 = n.toInt(&ok);
606  if(!ok) return false;
607 
608  if(!i3) return true;
609  n = s.section(' ',3,3);
610  *i3 = n.toInt(&ok);
611  if(!ok) return false;
612 
613  if(!i4) return true;
614  n = s.section(' ',4,4);
615  *i4 = n.toInt(&ok);
616  if(!ok) return false;
617 
618  if(!i5) return true;
619  n = s.section(' ',5,5);
620  *i5 = n.toInt(&ok);
621  if(!ok) return false;
622 
623  if(!i6) return true;
624  n = s.section(' ',6,6);
625  *i6 = n.toInt(&ok);
626  if(!ok) return false;
627 
628  return true;
629 }
630 
631 // ---------------------------------------------------------------------
632 bool SymbolWidget::getPen(const QString& s, QPen& Pen, int i)
633 {
634  bool ok;
635  QString n;
636 
637  n = s.section(' ',i,i); // color
638  QColor co;
639  co.setNamedColor(n);
640  Pen.setColor(co);
641  if(!Pen.color().isValid()) return false;
642 
643  i++;
644  n = s.section(' ',i,i); // thickness
645  Pen.setWidth(n.toInt(&ok));
646  if(!ok) return false;
647 
648  i++;
649  n = s.section(' ',i,i); // line style
650  Pen.setStyle((Qt::PenStyle)n.toInt(&ok));
651  if(!ok) return false;
652 
653  return true;
654 }
655 
656 // ---------------------------------------------------------------------
657 bool SymbolWidget::getBrush(const QString& s, QBrush& Brush, int i)
658 {
659  bool ok;
660  QString n;
661 
662  n = s.section(' ',i,i); // fill color
663  QColor co;
664  co.setNamedColor(n);
665  Brush.setColor(co);
666  if(!Brush.color().isValid()) return false;
667 
668  i++;
669  n = s.section(' ',i,i); // fill style
670  Brush.setStyle((Qt::BrushStyle)n.toInt(&ok));
671  if(!ok) return false;
672 
673  i++;
674  n = s.section(' ',i,i); // filled
675  if(n.toInt(&ok) == 0) Brush.setStyle(QBrush::NoBrush);
676  if(!ok) return false;
677 
678  return true;
679 }