My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
qucstrans.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qucstrans.cpp - description
3  -------------------
4  begin : Sun Feb 27 2005
5  copyright : (C) 2005, 2006 by Stefan Jahn
6  email : stefan@lkcc.org
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 
22 #include <qlayout.h>
23 #include <qhbox.h>
24 #include <qvbox.h>
25 #include <qpushbutton.h>
26 #include <qfile.h>
27 #include <qtextstream.h>
28 #include <qmessagebox.h>
29 #include <qtoolbutton.h>
30 #include <qimage.h>
31 #include <qfiledialog.h>
32 #include <qmenubar.h>
33 #include <qaction.h>
34 #include <qpopupmenu.h>
35 #include <qhgroupbox.h>
36 #include <qvgroupbox.h>
37 #include <qcombobox.h>
38 #include <qlabel.h>
39 #include <qlineedit.h>
40 #include <qimage.h>
41 #include <qiconset.h>
42 #include <qscrollview.h>
43 #include <qtooltip.h>
44 #include <qradiobutton.h>
45 #include <qstatusbar.h>
46 #include <qdir.h>
47 #include <qbuttongroup.h>
48 #include <qwidgetstack.h>
49 #include <qregexp.h>
50 #include <qvalidator.h>
51 #include <qclipboard.h>
52 #include <qapplication.h>
53 
54 #include "qucstrans.h"
55 #include "helpdialog.h"
56 #include "optionsdialog.h"
57 #include "transline.h"
58 #include "units.h"
59 #include "microstrip.h"
60 #include "coplanar.h"
61 #include "coax.h"
62 #include "rectwaveguide.h"
63 #include "c_microstrip.h"
64 
66 
67 // Defines maximum number of entries in each property category.
68 static const int TransMaxBox[MAX_TRANS_BOXES] = { 9, 1, 4, 3 };
69 
70 // Helper #defines for the below transmission line types.
71 #define TRANS_RADIOS { -1, -1, -1, -1 }
72 #define TRANS_QOBJS NULL, NULL, NULL, NULL, NULL
73 #define TRANS_END { NULL, 0, NULL, { NULL }, 0, TRANS_QOBJS }
74 #define TRANS_RESULT { NULL, NULL, NULL }
75 #define TRANS_RESULTS { TRANS_RESULT }
76 
77 // Defines the available transmission line types.
79  { ModeMicrostrip, "Microstrip", "microstrip.png", NULL,
80  { { {
81  { "Er", 2.94, NULL, TRANS_NONES, 0, TRANS_QOBJS },
82  { "Mur", 1, NULL, TRANS_NONES, 0, TRANS_QOBJS },
83  { "H", 10, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
84  { "H_t", 1e20, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
85  { "T", 0.1, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
86  { "Cond", 4.1e7, NULL, TRANS_NONES, 0, TRANS_QOBJS },
87  { "Tand", 0, NULL, TRANS_NONES, 0, TRANS_QOBJS },
88  { "Rough", 0, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
89  TRANS_END
90  } },
91  { {
92  { "Freq", 1, NULL, TRANS_FREQS, 0, TRANS_QOBJS },
93  TRANS_END
94  } },
95  { {
96  { "W", 10, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
97  { "L", 100, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
98  TRANS_END
99  } },
100  { {
101  { "Z0", 50, NULL, TRANS_OHMS, 0, TRANS_QOBJS },
102  { "Ang_l", 90, NULL, TRANS_ANGLES, 0, TRANS_QOBJS },
103  TRANS_END
104  } } },
106  },
107  { ModeCoplanar, "Coplanar", "cpw.png", NULL,
108  { { {
109  { "Er", 2.94, NULL, TRANS_NONES, 0, TRANS_QOBJS },
110  { "H", 10, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
111  { "T", 0.1, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
112  { "Cond", 4.1e7, NULL, TRANS_NONES, 0, TRANS_QOBJS },
113  { "Tand", 0, NULL, TRANS_NONES, 0, TRANS_QOBJS },
114  TRANS_END
115  } },
116  { {
117  { "Freq", 1, NULL, TRANS_FREQS, 0, TRANS_QOBJS },
118  TRANS_END
119  } },
120  { {
121  { "W", 10, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
122  { "S", 5, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
123  { "L", 100, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
124  TRANS_END
125  } },
126  { {
127  { "Z0", 50, NULL, TRANS_OHMS, 0, TRANS_QOBJS },
128  { "Ang_l", 90, NULL, TRANS_ANGLES, 0, TRANS_QOBJS },
129  TRANS_END
130  } } },
131  4, TRANS_RESULTS, { 1, 0, -1, -1 }
132  },
133  { ModeGroundedCoplanar, "GroundedCoplanar", "cpw_back.png", NULL,
134  { { {
135  { "Er", 2.94, NULL, TRANS_NONES, 0, TRANS_QOBJS },
136  { "H", 10, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
137  { "T", 0.1, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
138  { "Cond", 4.1e7, NULL, TRANS_NONES, 0, TRANS_QOBJS },
139  { "Tand", 0, NULL, TRANS_NONES, 0, TRANS_QOBJS },
140  TRANS_END
141  } },
142  { {
143  { "Freq", 1, NULL, TRANS_FREQS, 0, TRANS_QOBJS },
144  TRANS_END
145  } },
146  { {
147  { "W", 10, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
148  { "S", 5, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
149  { "L", 100, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
150  TRANS_END
151  } },
152  { {
153  { "Z0", 50, NULL, TRANS_OHMS, 0, TRANS_QOBJS },
154  { "Ang_l", 90, NULL, TRANS_ANGLES, 0, TRANS_QOBJS },
155  TRANS_END
156  } } },
157  4, TRANS_RESULTS, { 1, 0, -1, -1 }
158  },
159  { ModeRectangular, "Rectangular", "rectwaveguide.png", NULL,
160  { { {
161  { "Er", 1, NULL, TRANS_NONES, 0, TRANS_QOBJS },
162  { "Mur", 1, NULL, TRANS_NONES, 0, TRANS_QOBJS },
163  { "Cond", 4.1e7, NULL, TRANS_NONES, 0, TRANS_QOBJS },
164  { "Tand", 0, NULL, TRANS_NONES, 0, TRANS_QOBJS },
165  { "TanM", 0, NULL, TRANS_NONES, 0, TRANS_QOBJS },
166  TRANS_END
167  } },
168  { {
169  { "Freq", 10, NULL, TRANS_FREQS, 0, TRANS_QOBJS },
170  TRANS_END
171  } },
172  { {
173  { "a", 1000, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
174  { "b", 500, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
175  { "L", 4000, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
176  TRANS_END
177  } },
178  { {
179  { "Z0", 50, NULL, TRANS_OHMS, 0, TRANS_QOBJS },
180  { "Ang_l", 90, NULL, TRANS_ANGLES, 0, TRANS_QOBJS },
181  TRANS_END
182  } } },
183  3, TRANS_RESULTS, { 0, 1, -1, -1 }
184  },
185  { ModeCoaxial, "Coaxial", "coax.png", NULL,
186  { { {
187  { "Er", 2.1, NULL, TRANS_NONES, 0, TRANS_QOBJS },
188  { "Mur", 1, NULL, TRANS_NONES, 0, TRANS_QOBJS },
189  { "Tand", 0.002, NULL, TRANS_NONES, 0, TRANS_QOBJS },
190  { "Sigma", 4.1e7, NULL, TRANS_NONES, 0, TRANS_QOBJS },
191  TRANS_END
192  } },
193  { {
194  { "Freq", 10, NULL, TRANS_FREQS, 0, TRANS_QOBJS },
195  TRANS_END
196  } },
197  { {
198  { "din", 40, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
199  { "dout", 134, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
200  { "L", 1000, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
201  TRANS_END
202  } },
203  { {
204  { "Z0", 50, NULL, TRANS_OHMS, 0, TRANS_QOBJS },
205  { "Ang_l", 90, NULL, TRANS_ANGLES, 0, TRANS_QOBJS },
206  TRANS_END
207  } } },
208  2, TRANS_RESULTS, { 0, 1, -1, -1 }
209  },
210  { ModeCoupledMicrostrip, "CoupledMicrostrip", "c_microstrip.png", NULL,
211  { { {
212  { "Er", 4.3, NULL, TRANS_NONES, 0, TRANS_QOBJS },
213  { "Mur", 1, NULL, TRANS_NONES, 0, TRANS_QOBJS },
214  { "H", 8.27, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
215  { "H_t", 1e20, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
216  { "T", 0.68, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
217  { "Cond", 4.1e7, NULL, TRANS_NONES, 0, TRANS_QOBJS },
218  { "Tand", 0, NULL, TRANS_NONES, 0, TRANS_QOBJS },
219  { "Rough", 0, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
220  TRANS_END
221  } },
222  { {
223  { "Freq", 10, NULL, TRANS_FREQS, 0, TRANS_QOBJS },
224  TRANS_END
225  } },
226  { {
227  { "W", 8.66, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
228  { "S", 5.31, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
229  { "L", 1000, NULL, TRANS_LENGTHS, 0, TRANS_QOBJS },
230  TRANS_END
231  } },
232  { {
233  { "Z0e", 50, NULL, TRANS_OHMS, 0, TRANS_QOBJS },
234  { "Z0o", 50, NULL, TRANS_OHMS, 0, TRANS_QOBJS },
235  { "Ang_l", 90, NULL, TRANS_ANGLES, 0, TRANS_QOBJS },
236  TRANS_END
237  } } },
239  },
240  { ModeNone, NULL, NULL, NULL, { { { TRANS_END } } }, 0,
242 };
243 
244 struct TransUnit TransUnits[] = {
245  { "Frequency", TRANS_FREQS },
246  { "Length", TRANS_LENGTHS },
247  { "Resistance", TRANS_OHMS },
248  { "Angle", TRANS_ANGLES },
249 };
250 
251 /* Constructor setups the GUI. */
253  // set application icon
254  setIcon (QPixmap(QucsSettings.BitmapDir + "big.qucs.xpm"));
255  setCaption("Qucs Transcalc " PACKAGE_VERSION);
256 
257  QMenuBar * menuBar = new QMenuBar (this);
258 
259  // create file menu
260  QPopupMenu * fileMenu = new QPopupMenu ();
261  QAction * fileLoad =
262  new QAction (tr("Load"), tr("&Load"), CTRL+Key_L, this);
263  fileLoad->addTo (fileMenu);
264  connect(fileLoad, SIGNAL(activated()), SLOT(slotFileLoad()));
265  QAction * fileSave =
266  new QAction (tr("Save"), tr("&Save"), CTRL+Key_S, this);
267  fileSave->addTo (fileMenu);
268  connect(fileSave, SIGNAL(activated()), SLOT(slotFileSave()));
269  fileMenu->insertSeparator ();
270  QAction * fileOption =
271  new QAction (tr("Options"), tr("&Options"), CTRL+Key_O, this);
272  fileOption->addTo (fileMenu);
273  connect(fileOption, SIGNAL(activated()), SLOT(slotOptions()));
274  fileMenu->insertSeparator ();
275  QAction * fileQuit =
276  new QAction (tr("Quit"), tr("&Quit"), CTRL+Key_Q, this);
277  fileQuit->addTo (fileMenu);
278  connect(fileQuit, SIGNAL(activated()), SLOT(slotQuit()));
279 
280  // create execute menu
281  QPopupMenu * execMenu = new QPopupMenu ();
282  QAction * execCopy =
283  new QAction (tr("Copy to Clipboard"),
284  tr("&Copy to Clipboard"), Key_F2, this);
285  execCopy->addTo (execMenu);
286  connect(execCopy, SIGNAL(activated()), SLOT(slotCopyToClipBoard()));
287  QAction * execAnalyze =
288  new QAction (tr("Analyze"), tr("&Analyze"), Key_F3, this);
289  execAnalyze->addTo (execMenu);
290  connect(execAnalyze, SIGNAL(activated()), SLOT(slotAnalyze()));
291  QAction * execSynthesize =
292  new QAction (tr("Synthesize"), tr("&Synthesize"), Key_F4, this);
293  execSynthesize->addTo (execMenu);
294  connect(execSynthesize, SIGNAL(activated()), SLOT(slotSynthesize()));
295 
296  // create help menu
297  QPopupMenu * helpMenu = new QPopupMenu ();
298  QAction * helpHelp =
299  new QAction (tr("Help"), tr("&Help"), Key_F1, this);
300  helpHelp->addTo (helpMenu);
301  connect(helpHelp, SIGNAL(activated()), SLOT(slotHelpIntro()));
302  QAction * helpAbout =
303  new QAction (tr("About"), tr("About"), 0, helpMenu);
304  helpAbout->addTo (helpMenu);
305  connect(helpAbout, SIGNAL(activated()), SLOT(slotAbout()));
306 
307  // setup menu bar
308  menuBar->insertItem (tr("&File"), fileMenu);
309  menuBar->insertItem (tr("&Execute"), execMenu);
310  menuBar->insertSeparator ();
311  menuBar->insertItem (tr("&Help"), helpMenu);
312 
313  // main box
314  QVBoxLayout * v = new QVBoxLayout (this);
315  v->setSpacing (0);
316  v->setMargin (0);
317 
318  // reserve space for menubar
319  QWidget * Space = new QWidget (this);
320  Space->setFixedSize(5, menuBar->height() + 2);
321  v->addWidget (Space);
322 
323  // main layout
324  QHBox * h = new QHBox (this);
325  h->setSpacing (5);
326  v->addWidget (h);
327 
328  // left margin
329  QWidget * sl = new QWidget (h);
330  sl->setFixedWidth (2);
331 
332  // transmission line type choice
333  QVGroupBox * lineGroup = new QVGroupBox (tr("Transmission Line Type"), h);
334  tranType = new QComboBox (lineGroup);
335  tranType->insertItem (tr("Microstrip Line"));
336  tranType->insertItem (tr("Coplanar Waveguide"));
337  tranType->insertItem (tr("Grounded Coplanar"));
338  tranType->insertItem (tr("Rectangular Waveguide"));
339  tranType->insertItem (tr("Coaxial Line"));
340  tranType->insertItem (tr("Coupled Microstrip"));
341  connect(tranType, SIGNAL(activated(int)), SLOT(slotSelectType(int)));
342  // setup transmission line picture
343  pix = new QLabel (lineGroup);
344  pix->setPixmap (QPixmap (QImage (QucsSettings.BitmapDir +
345  "microstrip.png")));
346 
347  QVBox * vm = new QVBox (h);
348  vm->setSpacing (3);
349  QVBox * vr = new QVBox (h);
350  vr->setSpacing (3);
351 
352  // right margin
353  QWidget * sr = new QWidget (h);
354  sr->setFixedWidth (2);
355 
356  // init additional translations
357  setupTranslations ();
358 
359  // set current mode
360  mode = ModeMicrostrip;
361 
362  // substrate parameter box
363  QHGroupBox * substrate = new QHGroupBox (tr("Substrate Parameters"), vm);
364  createPropItems (substrate, TRANS_SUBSTRATE);
365 
366  // component parameter box
367  QHGroupBox * component = new QHGroupBox (tr("Component Parameters"), vm);
368  createPropItems (component, TRANS_COMPONENT);
369 
370  // physical parameter box
371  QHGroupBox * physical = new QHGroupBox (tr("Physical Parameters"), vr);
372  createPropItems (physical, TRANS_PHYSICAL);
373 
374  // analyze/synthesize buttons
375  QHBox * h2 = new QHBox (vr);
376  QPushButton * analyze = new QPushButton (tr("Analyze"), h2);
377  QToolTip::add (analyze, tr("Derive Electrical Parameters"));
378  connect(analyze, SIGNAL(clicked()), SLOT(slotAnalyze()));
379  QPushButton * synthesize = new QPushButton (tr("Synthesize"), h2);
380  QToolTip::add (synthesize, tr("Compute Physical Parameters"));
381  connect(synthesize, SIGNAL(clicked()), SLOT(slotSynthesize()));
382 
383  // electrical parameter box
384  QHGroupBox * electrical = new QHGroupBox (tr("Electrical Parameters"), vr);
385  createPropItems (electrical, TRANS_ELECTRICAL);
386 
387  calculated = new QHGroupBox (tr("Calculated Results"), vr);
388 
389  // status line
390  statBar = new QStatusBar (this);
391  QLabel * statText = new QLabel ("Ready.", statBar);
392  statBar->message (tr("Ready."));
393  statBar->setFixedHeight (statText->height ());
394  v->addWidget (statBar);
395  delete statText;
396 
397  // setup calculated result bix
398  createResultItems (calculated);
399  updateSelection ();
400 
401  // intantiate transmission lines
402  TransLineTypes[0].line = new microstrip ();
403  TransLineTypes[0].line->setApplication (this);
404  TransLineTypes[1].line = new coplanar ();
405  TransLineTypes[1].line->setApplication (this);
406  TransLineTypes[2].line = new groundedCoplanar ();
407  TransLineTypes[2].line->setApplication (this);
408  TransLineTypes[3].line = new rectwaveguide ();
409  TransLineTypes[3].line->setApplication (this);
410  TransLineTypes[4].line = new coax ();
411  TransLineTypes[4].line->setApplication (this);
412  TransLineTypes[5].line = new c_microstrip ();
413  TransLineTypes[5].line->setApplication (this);
414 }
415 
416 /* Destructor destroys the application. */
418 {
419  for (int i = 0; i < MAX_TRANS_TYPES; i++) {
420  if (TransLineTypes[i].line)
421  delete TransLineTypes[i].line;
422  }
423 }
424 
425 /* The function puts translatable text into the transmission line
426  structures. */
427 void QucsTranscalc::setupTranslations () {
428  // calculated results
429  int i = 0;
430  TransLineTypes[i].result[0].name = new QString(tr("ErEff"));
431  TransLineTypes[i].result[1].name = new QString(tr("Conductor Losses"));
432  TransLineTypes[i].result[2].name = new QString(tr("Dielectric Losses"));
433  TransLineTypes[i].result[3].name = new QString(tr("Skin Depth"));
434 
435  i++;
436  TransLineTypes[i].result[0].name = new QString(tr("ErEff"));
437  TransLineTypes[i].result[1].name = new QString(tr("Conductor Losses"));
438  TransLineTypes[i].result[2].name = new QString(tr("Dielectric Losses"));
439  TransLineTypes[i].result[3].name = new QString(tr("Skin Depth"));
440 
441  i++;
442  TransLineTypes[i].result[0].name = new QString(tr("ErEff"));
443  TransLineTypes[i].result[1].name = new QString(tr("Conductor Losses"));
444  TransLineTypes[i].result[2].name = new QString(tr("Dielectric Losses"));
445  TransLineTypes[i].result[3].name = new QString(tr("Skin Depth"));
446 
447  i++;
448  TransLineTypes[i].result[0].name = new QString(tr("ErEff"));
449  TransLineTypes[i].result[1].name = new QString(tr("Conductor Losses"));
450  TransLineTypes[i].result[2].name = new QString(tr("Dielectric Losses"));
451  TransLineTypes[i].result[3].name = new QString(tr("TE-Modes"));
452  TransLineTypes[i].result[4].name = new QString(tr("TM-Modes"));
453 
454  i++;
455  TransLineTypes[i].result[0].name = new QString(tr("Conductor Losses"));
456  TransLineTypes[i].result[1].name = new QString(tr("Dielectric Losses"));
457  TransLineTypes[i].result[2].name = new QString(tr("TE-Modes"));
458  TransLineTypes[i].result[3].name = new QString(tr("TM-Modes"));
459 
460  i++;
461  TransLineTypes[i].result[0].name = new QString(tr("ErEff Even"));
462  TransLineTypes[i].result[1].name = new QString(tr("ErEff Odd"));
463  TransLineTypes[i].result[2].name = new QString(tr("Conductor Losses Even"));
464  TransLineTypes[i].result[3].name = new QString(tr("Conductor Losses Odd"));
465  TransLineTypes[i].result[4].name = new QString(tr("Dielectric Losses Even"));
466  TransLineTypes[i].result[5].name = new QString(tr("Dielectric Losses Odd"));
467  TransLineTypes[i].result[6].name = new QString(tr("Skin Depth"));
468 
469  // extra tool tips
470  struct TransType * t = TransLineTypes;
471  t->array[0].item[0].tip = new QString(tr("Relative Permittivity"));
472  t->array[0].item[1].tip = new QString(tr("Relative Permeability"));
473  t->array[0].item[2].tip = new QString(tr("Height of Substrate"));
474  t->array[0].item[3].tip = new QString(tr("Height of Box Top"));
475  t->array[0].item[4].tip = new QString(tr("Strip Thickness"));
476  t->array[0].item[5].tip = new QString(tr("Strip Conductivity"));
477  t->array[0].item[6].tip = new QString(tr("Dielectric Loss Tangent"));
478  t->array[0].item[7].tip = new QString(tr("Conductor Roughness"));
479  t->array[1].item[0].tip = new QString(tr("Frequency"));
480  t->array[2].item[0].tip = new QString(tr("Line Width"));
481  t->array[2].item[1].tip = new QString(tr("Line Length"));
482  t->array[3].item[0].tip = new QString(tr("Characteristic Impedance"));
483  t->array[3].item[1].tip = new QString(tr("Electrical Length"));
484 
485  t++;
486  t->array[0].item[0].tip = new QString(tr("Relative Permittivity"));
487  t->array[0].item[1].tip = new QString(tr("Height of Substrate"));
488  t->array[0].item[2].tip = new QString(tr("Strip Thickness"));
489  t->array[0].item[3].tip = new QString(tr("Strip Conductivity"));
490  t->array[0].item[4].tip = new QString(tr("Dielectric Loss Tangent"));
491  t->array[1].item[0].tip = new QString(tr("Frequency"));
492  t->array[2].item[0].tip = new QString(tr("Line Width"));
493  t->array[2].item[1].tip = new QString(tr("Gap Width"));
494  t->array[2].item[2].tip = new QString(tr("Line Length"));
495  t->array[3].item[0].tip = new QString(tr("Characteristic Impedance"));
496  t->array[3].item[1].tip = new QString(tr("Electrical Length"));
497 
498  t++;
499  t->array[0].item[0].tip = new QString(tr("Relative Permittivity"));
500  t->array[0].item[1].tip = new QString(tr("Height of Substrate"));
501  t->array[0].item[2].tip = new QString(tr("Strip Thickness"));
502  t->array[0].item[3].tip = new QString(tr("Strip Conductivity"));
503  t->array[0].item[4].tip = new QString(tr("Dielectric Loss Tangent"));
504  t->array[1].item[0].tip = new QString(tr("Frequency"));
505  t->array[2].item[0].tip = new QString(tr("Line Width"));
506  t->array[2].item[1].tip = new QString(tr("Gap Width"));
507  t->array[2].item[2].tip = new QString(tr("Line Length"));
508  t->array[3].item[0].tip = new QString(tr("Characteristic Impedance"));
509  t->array[3].item[1].tip = new QString(tr("Electrical Length"));
510 
511  t++;
512  t->array[0].item[0].tip = new QString(tr("Relative Permittivity"));
513  t->array[0].item[1].tip = new QString(tr("Relative Permeability"));
514  t->array[0].item[2].tip = new QString(tr("Conductivity of Metal"));
515  t->array[0].item[3].tip = new QString(tr("Dielectric Loss Tangent"));
516  t->array[0].item[4].tip = new QString(tr("Magnetic Loss Tangent"));
517  t->array[1].item[0].tip = new QString(tr("Frequency"));
518  t->array[2].item[0].tip = new QString(tr("Width of Waveguide"));
519  t->array[2].item[1].tip = new QString(tr("Height of Waveguide"));
520  t->array[2].item[2].tip = new QString(tr("Waveguide Length"));
521  t->array[3].item[0].tip = new QString(tr("Characteristic Impedance"));
522  t->array[3].item[1].tip = new QString(tr("Electrical Length"));
523 
524  t++;
525  t->array[0].item[0].tip = new QString(tr("Relative Permittivity"));
526  t->array[0].item[1].tip = new QString(tr("Relative Permeability"));
527  t->array[0].item[2].tip = new QString(tr("Dielectric Loss Tangent"));
528  t->array[0].item[3].tip = new QString(tr("Conductivity of Metal"));
529  t->array[1].item[0].tip = new QString(tr("Frequency"));
530  t->array[2].item[0].tip = new QString(tr("Inner Diameter"));
531  t->array[2].item[1].tip = new QString(tr("Outer Diameter"));
532  t->array[2].item[2].tip = new QString(tr("Length"));
533  t->array[3].item[0].tip = new QString(tr("Characteristic Impedance"));
534  t->array[3].item[1].tip = new QString(tr("Electrical Length"));
535 
536  t++;
537  t->array[0].item[0].tip = new QString(tr("Relative Permittivity"));
538  t->array[0].item[1].tip = new QString(tr("Relative Permeability"));
539  t->array[0].item[2].tip = new QString(tr("Height of Substrate"));
540  t->array[0].item[3].tip = new QString(tr("Height of Box Top"));
541  t->array[0].item[4].tip = new QString(tr("Strip Thickness"));
542  t->array[0].item[5].tip = new QString(tr("Strip Conductivity"));
543  t->array[0].item[6].tip = new QString(tr("Dielectric Loss Tangent"));
544  t->array[0].item[7].tip = new QString(tr("Conductor Roughness"));
545  t->array[1].item[0].tip = new QString(tr("Frequency"));
546  t->array[2].item[0].tip = new QString(tr("Line Width"));
547  t->array[2].item[1].tip = new QString(tr("Gap Width"));
548  t->array[2].item[2].tip = new QString(tr("Length"));
549  t->array[3].item[0].tip = new QString(tr("Even-Mode Impedance"));
550  t->array[3].item[1].tip = new QString(tr("Odd-Mode Impedance"));
551  t->array[3].item[2].tip = new QString(tr("Electrical Length"));
552 }
553 
554 /* Creates a property item 'val' in a parameter category specified by
555  its 'box'. */
556 void QucsTranscalc::createPropItem (QVBox ** parentRows, TransValue * val,
557  int box, QButtonGroup * group) {
558  QRadioButton * r = NULL;
559  QLabel * l;
560  QLineEdit * e;
561  QComboBox * c;
562  QDoubleValidator * v = new QDoubleValidator (this);
563 
564  // name label
565  l = new QLabel (val->name, parentRows[0]);
566  l->setAlignment (Qt::AlignRight);
567  if (val->tip) QToolTip::add (l, *(val->tip));
568  val->label = l;
569 
570  // editable value text
571  e = new QLineEdit (parentRows[1]);
572  e->setText (QString::number (val->value));
573  e->setAlignment (Qt::AlignRight);
574  e->setValidator (v);
575  connect(e, SIGNAL(textChanged(const QString&)), SLOT(slotValueChanged()));
576  if (!val->name) e->setDisabled (true);
577  val->lineedit = e;
578 
579  // unit choice
580  c = new QComboBox (parentRows[2]);
581  if (!val->units[0]) {
582  c->insertItem ("NA");
583  c->setDisabled(true);
584  }
585  else {
586  int nounit = 0;
587  for (int i = 0; val->units[i]; i++) {
588  c->insertItem (val->units[i]);
589  if (!strcmp (val->units[i], "NA")) nounit++;
590  }
591  c->setDisabled (nounit != 0);
592  c->setCurrentItem (0);
593  }
594  connect(c, SIGNAL(activated(int)), SLOT(slotValueChanged()));
595  val->combobox = c;
596 
597  // special synthesize-computation choice
598  if (box == TRANS_PHYSICAL) {
599  QWidgetStack * s = new QWidgetStack(parentRows[3]);
600  s->setFixedSize (val->lineedit->height()-10, val->lineedit->height()-10);
601  r = new QRadioButton (s);
602  QWidget * spacer = new QWidget (s);
603  s->addWidget (r, 1);
604  s->addWidget (spacer, 2);
605  r->setDisabled (true);
606  val->radio = r;
607  val->stack = s;
608  group->insert(r);
609  }
610 }
611 
612 /* The function changes the content of a GUI's property entry
613  depending on the given transmission line property. */
614 void QucsTranscalc::updatePropItem (TransValue * val) {
615  // update label text
616  val->label->setText (val->name);
617  QToolTip::remove (val->label);
618  if (val->tip) QToolTip::add (val->label, *(val->tip));
619 
620  // update editable value text
621  val->lineedit->setText (QString::number (val->value));
622  val->lineedit->setDisabled (!val->name);
623 
624  // update unit choice
625  val->combobox->clear();
626  if (!val->units[0]) {
627  val->combobox->insertItem ("NA");
628  val->combobox->setDisabled (true);
629  }
630  else {
631  int nounit = 0;
632  for (int i = 0; val->units[i]; i++) {
633  val->combobox->insertItem (val->units[i]);
634  if (!strcmp (val->units[i], "NA")) nounit++;
635  }
636  val->combobox->setCurrentItem(val->unit);
637  val->combobox->setDisabled (nounit);
638  }
639 }
640 
641 /* Switches to the current type of transmission line layout. */
642 void QucsTranscalc::setMode (int _mode) {
643  // change necessary?
644  if (mode == _mode) return;
645  storeValues ();
646  mode = _mode;
647  setUpdatesEnabled(false);
648  updateMode ();
649 
650  // update selection and results
651  updateSelection ();
652  updateResultItems ();
653 
654  slotAnalyze();
655  setUpdatesEnabled(true);
656  repaint();
657 }
658 
659 /* Updates the property items of the current mode. */
660 void QucsTranscalc::updateMode (void) {
661  // go through each type of parameter category
662  for (int box = 0; box < MAX_TRANS_BOXES; box++) {
663  int last = 0, idx = getTypeIndex();
664  struct TransValue * val = TransLineTypes[idx].array[box].item;
665  // update each property item
666  for (int i = 0; i < TransMaxBox[box]; i++) {
667  // fix uninitialized memory
668  if (val->name == NULL) last++;
669  if (last) {
670  val->name = NULL;
671  val->value = 0;
672  val->tip = NULL;
673  val->units[0] = NULL;
674  }
675  updatePropItem (val);
676  val++;
677  }
678  }
679 }
680 
681 /* Updates the current choice of physical property selection. */
682 void QucsTranscalc::updateSelection () {
683  int idx = getTypeIndex ();
684  struct TransValue * val = TransLineTypes[idx].array[TRANS_PHYSICAL].item;
685  for (int i = 0; i < TransMaxBox[TRANS_PHYSICAL]; i++) {
686  if (TransLineTypes[idx].radio[i] != -1) {
687  val->stack->raiseWidget (1);
688  if (TransLineTypes[idx].radio[i] == 1) {
689  val->radio->setDown (true);
690  val->radio->setChecked (true);
691  QToolTip::add (val->radio, tr("Selected for Calculation"));
692  }
693  else {
694  val->radio->setDown (false);
695  val->radio->setChecked (false);
696  QToolTip::add (val->radio, tr("Check item for Calculation"));
697  }
698  val->radio->setDisabled (false);
699  }
700  else {
701  QToolTip::remove (val->radio);
702  val->stack->raiseWidget (2);
703  val->radio->setDown (false);
704  val->radio->setChecked (false);
705  val->radio->setDisabled (true);
706  }
707  val++;
708  }
709 }
710 
711 /* The function creates the property items for the given category of
712  transmission line parameters. */
713 void QucsTranscalc::createPropItems (QHGroupBox * parent, int box) {
714  struct TransValue * val, * dup;
715  int last = 0, idx = getTypeIndex ();
716  val = TransLineTypes[idx].array[box].item;
717 
718  QVBox *rows[4];
719  QButtonGroup * group = new QButtonGroup();
720  connect(group, SIGNAL(pressed(int)), SLOT(slotRadioChecked(int)));
721  rows[0] = new QVBox (parent);
722  rows[1] = new QVBox (parent);
723  rows[2] = new QVBox (parent);
724  rows[3] = new QVBox (parent);
725 
726  parent->layout()->setSpacing (2);
727  rows[0]->setSpacing (2);
728  rows[1]->setSpacing (2);
729  rows[2]->setSpacing (2);
730  rows[3]->setSpacing (2);
731 
732  // go through each parameter category
733  for (int i = 0; i < TransMaxBox[box]; i++) {
734  // fix uninitialized memory
735  if (val->name == NULL) last++;
736  if (last) {
737  val->name = NULL;
738  val->value = 0;
739  val->tip = NULL;
740  val->units[0] = NULL;
741  }
742  createPropItem (rows, val, box, group);
743  // publish the newly created widgets to the other transmission lines
744  for (int _mode = 0; _mode < MAX_TRANS_TYPES; _mode++) {
745  if (idx != _mode) {
746  dup = & TransLineTypes[_mode].array[box].item[i];
747  dup->label = val->label;
748  dup->lineedit = val->lineedit;
749  dup->combobox = val->combobox;
750  dup->radio = val->radio;
751  dup->stack = val->stack;
752  }
753  }
754  val++;
755  }
756 }
757 
758 /* Creates a single result item. */
759 void QucsTranscalc::createResultItem (QVBox ** parentRows, TransResult * res) {
760  QLabel * n =
761  new QLabel (res->name ? *(res->name) + ":" : QString(), parentRows[0]);
762  n->setAlignment (Qt::AlignRight);
763  res->label = n;
764  QLabel * v = new QLabel (parentRows[1]);
765  v->setAlignment (Qt::AlignLeft);
766  res->value = v;
767  if (!res->name) {
768  v->hide ();
769  n->hide ();
770  }
771 }
772 
773 /* Updates the given result item. */
774 void QucsTranscalc::updateResultItem (TransResult * res) {
775  if (res->name) {
776  res->label->setText (*(res->name) + ":");
777  res->label->show ();
778  res->value->show ();
779  } else {
780  res->label->hide ();
781  res->value->hide ();
782  }
783 }
784 
785 /* Creates all the result items. */
786 void QucsTranscalc::createResultItems (QHGroupBox * parent) {
787  struct TransResult * res, * dup;
788  int idx = getTypeIndex ();
789  res = & TransLineTypes[idx].result[0];
790 
791  QVBox *rows[2];
792  rows[0] = new QVBox (parent);
793  rows[1] = new QVBox (parent);
794 
795  parent->layout()->setSpacing (2);
796  rows[0]->setSpacing (2);
797  rows[1]->setSpacing (2);
798 
799  for (int i = 0; i < MAX_TRANS_RESULTS; i++) {
800  createResultItem (rows, res);
801  for (int _mode = 0; _mode < MAX_TRANS_TYPES; _mode++) {
802  if (idx != _mode) {
803  dup = & TransLineTypes[_mode].result[i];
804  dup->label = res->label;
805  dup->value = res->value;
806  }
807  }
808  res++;
809  }
810 }
811 
812 /* Puts the given result into its widget. */
813 void QucsTranscalc::setResult (int line, const char * text) {
814  struct TransResult * res;
815  res = & TransLineTypes[getTypeIndex ()].result[line];
816  res->value->setText (text);
817 }
818 
819 /* Updates the current result items. */
820 void QucsTranscalc::updateResultItems() {
821  int idx = getTypeIndex ();
822  struct TransResult * res = TransLineTypes[idx].result;
823  for (int i = 0; i < MAX_TRANS_RESULTS; i++) {
824  updateResultItem (res);
825  res++;
826  }
827 }
828 
829 /* Returns the appropriate array index for the given mode. */
830 int QucsTranscalc::getTypeIndex () {
831  struct TransType * type = TransLineTypes;
832  for (int i = 0; type->type != ModeNone; i++) {
833  if (type->type == mode) return i;
834  type++;
835  }
836  return 0;
837 }
838 
839 /* Returns the property value specified by its name. */
840 struct TransValue * QucsTranscalc::findProperty (QString prop) {
841  struct TransValue * val = NULL;
842  for (int box = 0; box < MAX_TRANS_BOXES; box++) {
843  val = TransLineTypes[getTypeIndex ()].array[box].item;
844  for (int i = 0; val->name; i++) {
845  if (prop == val->name) return val;
846  val++;
847  }
848  }
849  return NULL;
850 }
851 
852 /* Sets the given property to the given value. */
853 void QucsTranscalc::setProperty (QString prop, double value) {
854  struct TransValue * val = findProperty (prop);
855  if (val) {
856  val->lineedit->setText (QString::number (value));
857  val->value = value;
858  }
859 }
860 
861 /* Returns the given property value. */
862 double QucsTranscalc::getProperty (QString prop) {
863  struct TransValue * val = findProperty (prop);
864  if (val) {
865  QString str = val->lineedit->text ();
866  val->value = str.toDouble ();
867  return val->value;
868  }
869  return 0;
870 }
871 
872 /* Sets the given property unit. */
873 void QucsTranscalc::setUnit (QString prop, const char * unit) {
874  struct TransValue * val = findProperty (prop);
875  if (val) {
876  if (!unit) {
877  val->combobox->setCurrentItem (0);
878  val->unit = 0;
879  }
880  else for (int i = 0; val->units[i]; i++) {
881  if (!strcmp (unit, val->units[i])) {
882  val->combobox->setCurrentItem (i);
883  val->unit = i;
884  break;
885  }
886  }
887  }
888 }
889 
890 /* Returns the given property unit. */
891 char * QucsTranscalc::getUnit (QString prop) {
892  struct TransValue * val = findProperty (prop);
893  if (val) {
894  QString str = val->combobox->currentText ();
895  for (int i = 0; val->units[i]; i++) {
896  if (str == val->units[i]) {
897  val->unit = i;
898  return (char *) val->units[i];
899  }
900  }
901  }
902  return NULL;
903 }
904 
905 /* Returns the given property selection. */
906 bool QucsTranscalc::isSelected (QString prop) {
907  struct TransValue * val = findProperty (prop);
908  if (val) {
909  if (val->radio)
910  if (val->radio->isChecked ()) {
911  return true;
912  }
913  }
914  return false;
915 }
916 
917 void QucsTranscalc::slotAbout()
918 {
919  QMessageBox::about(this, tr("About..."),
920  "QucsTranscalc Version " PACKAGE_VERSION "\n"+
921  tr("Transmission Line Calculator for Qucs\n")+
922  tr("Copyright (C) 2001 by Gopal Narayanan\n")+
923  tr("Copyright (C) 2002 by Claudio Girardi\n")+
924  tr("Copyright (C) 2005 by Stefan Jahn\n")+
925  tr("Copyright (C) 2008 by Michael Margraf\n")+
926  "\nThis is free software; see the source for copying conditions."
927  "\nThere is NO warranty; not even for MERCHANTABILITY or "
928  "\nFITNESS FOR A PARTICULAR PURPOSE.");
929 }
930 
931 void QucsTranscalc::slotQuit()
932 {
933  int tmp;
934  tmp = x(); // call size and position function in order to ...
935  tmp = y(); // ... set them correctly before closing the ...
936  tmp = width(); // dialog !!! Otherwise the frame of the window ...
937  tmp = height(); // will not be recognized (a X11 problem).
938 
939  storeValues ();
940  accept();
941 }
942 
943 void QucsTranscalc::closeEvent(QCloseEvent *Event)
944 {
945  int tmp;
946  tmp = x(); // call size and position function in order to ...
947  tmp = y(); // ... set them correctly before closing the ...
948  tmp = width(); // dialog !!! Otherwise the frame of the window ...
949  tmp = height(); // will not be recognized (a X11 problem).
950 
951  storeValues ();
952  Event->accept();
953 }
954 
955 void QucsTranscalc::slotSelectType (int Type)
956 {
957  pix->setPixmap (QPixmap (QImage (
958  QucsSettings.BitmapDir + QString(TransLineTypes[Type].bitmap))));
959  setMode (Type);
960  statBar->message(tr("Ready."));
961 }
962 
963 void QucsTranscalc::slotAnalyze()
964 {
965  if (TransLineTypes[getTypeIndex()].line)
966  TransLineTypes[getTypeIndex()].line->analyze();
967  statBar->message(tr("Values are consistent."));
968 }
969 
970 void QucsTranscalc::slotSynthesize()
971 {
972  if (TransLineTypes[getTypeIndex()].line)
973  TransLineTypes[getTypeIndex()].line->synthesize();
974  statBar->message(tr("Values are consistent."));
975 }
976 
977 void QucsTranscalc::slotValueChanged()
978 {
979  statBar->message(tr("Values are inconsistent."));
980 }
981 
982 // Load transmission line values from the given file.
983 bool QucsTranscalc::loadFile(QString fname, int * _mode) {
984  QFile file(QDir::convertSeparators (fname));
985  if(!file.open(IO_ReadOnly)) return false; // file doesn't exist
986 
987  QTextStream stream(&file);
988  QString Line, Name, Unit;
989  double Value;
990 
991  int oldmode = mode;
992  while(!stream.atEnd()) {
993  Line = stream.readLine();
994  for (int i = 0; i < MAX_TRANS_TYPES; i++) {
995  if (Line == "<" + QString(TransLineTypes[i].description) + ">") {
996  if (_mode) {
997  *_mode = TransLineTypes[i].type;
998  setMode (*_mode);
999  updatePixmap (mode);
1000  } else {
1001  mode = TransLineTypes[i].type;
1002  }
1003  while(!stream.atEnd()) {
1004  Line = stream.readLine();
1005  if (Line == "</" + QString(TransLineTypes[i].description) + ">")
1006  break;
1007  Line = Line.simplifyWhiteSpace();
1008  Name = Line.section(' ',0,0);
1009  Value = Line.section(' ',1,1).toDouble();
1010  Unit = Line.section(' ',2,2);
1011  setProperty (Name, Value);
1012  setUnit (Name, Unit);
1013  }
1014  break;
1015  }
1016  }
1017  }
1018  if (!_mode) mode = oldmode;
1019  updateMode ();
1020  file.close();
1021  return true;
1022 }
1023 
1024 // Saves current transmission line values into the given file.
1025 bool QucsTranscalc::saveFile(QString fname) {
1026  QFile file (QDir::convertSeparators (fname));
1027  if(!file.open (IO_WriteOnly)) return false; // file not writable
1028  QTextStream stream (&file);
1029 
1030  // some lines of documentation
1031  stream << "# QucsTranscalc " << PACKAGE_VERSION << " " << fname << "\n";
1032  stream << "# Generated on " << QDate::currentDate().toString()
1033  << " at " << QTime::currentTime().toString() << ".\n";
1034  stream << "# It is not suggested to edit the file, use QucsTranscalc "
1035  << "instead.\n\n";
1036 
1037  storeValues ();
1038  saveMode (stream);
1039  file.close ();
1040  return true;
1041 }
1042 
1043 /* Writes the transmission line values for the current modes into the
1044  given stream. */
1045 void QucsTranscalc::saveMode(QTextStream& stream) {
1046  struct TransType * t = &TransLineTypes[getTypeIndex ()];
1047  struct TransValue * val = NULL;
1048  stream << "<" << t->description << ">\n";
1049  for (int box = 0; box < MAX_TRANS_BOXES; box++) {
1050  val = t->array[box].item;
1051  while (val->name) {
1052  stream << " " << val->name << " " << val->value << " "
1053  << val->units[val->unit] << "\n";
1054  val++;
1055  }
1056  }
1057  stream << "</" << t->description << ">\n";
1058 }
1059 
1060 // Writes the transmission line values for all modes into the given stream.
1061 void QucsTranscalc::saveModes(QTextStream& stream) {
1062  int oldmode = mode;
1063  for (int i = 0; i < MAX_TRANS_TYPES; i++) {
1064  mode = TransLineTypes[i].type;
1065  saveMode (stream);
1066  }
1067  mode = oldmode;
1068 }
1069 
1070 // Saves the GUI values into internal data structures.
1071 void QucsTranscalc::storeValues (void) {
1072  struct TransType * t = &TransLineTypes[getTypeIndex ()];
1073  struct TransValue * val;
1074  for (int box = 0; box < MAX_TRANS_BOXES; box++) {
1075  val = t->array[box].item;
1076  int i = 0;
1077  while (val->name) {
1078  getProperty (val->name);
1079  getUnit (val->name);
1080  if (box == TRANS_PHYSICAL) {
1081  if (val->radio->isEnabled()) {
1082  if (val->radio->isChecked())
1083  t->radio[i] = 1;
1084  else
1085  t->radio[i] = 0;
1086  }
1087  else t->radio[i] = -1;
1088  }
1089  i++;
1090  val++;
1091  }
1092  }
1093 }
1094 
1095 void QucsTranscalc::slotFileLoad()
1096 {
1097  statBar->message(tr("Loading file..."));
1098  int _mode = 0;
1099  QString s = QFileDialog::getOpenFileName(QucsWorkDir.path(),
1100  tr("Transcalc File")+" (*.trc)", this, "", tr("Enter a Filename"));
1101  if (!s.isEmpty()) {
1102  QucsWorkDir.setPath(QDir::cleanDirPath(s));
1103  if (!loadFile (s, &_mode)) {
1104  QMessageBox::critical (this, tr("Error"),
1105  tr("Cannot load file:")+" '"+s+"'!");
1106  }
1107  }
1108  else statBar->message(tr("Loading aborted."), 2000);
1109 
1110  statBar->message(tr("Ready."));
1111 }
1112 
1113 void QucsTranscalc::slotFileSave()
1114 {
1115  statBar->message(tr("Saving file..."));
1116 
1117  QString s = QFileDialog::getSaveFileName(QucsWorkDir.path(),
1118  tr("Transcalc File")+" (*.trc)", this, "", tr("Enter a Filename"));
1119  if (!s.isEmpty()) {
1120  QucsWorkDir.setPath(QDir::cleanDirPath(s));
1121  if (!saveFile (s)) {
1122  QMessageBox::critical (this, tr("Error"),
1123  tr("Cannot save file:")+" '"+s+"'!");
1124  }
1125  }
1126  else statBar->message(tr("Saving aborted."), 2000);
1127 
1128  statBar->message(tr("Ready."));
1129 }
1130 
1131 // Returns the current textual mode.
1132 QString QucsTranscalc::getMode (void) {
1133  return TransLineTypes[getTypeIndex ()].description;
1134 }
1135 
1136 // Sets the mode according to the given textual mode.
1137 void QucsTranscalc::setMode (QString _mode) {
1138  for (int i = 0; i < MAX_TRANS_TYPES; i++) {
1139  if (TransLineTypes[i].description == _mode) {
1140  setMode (TransLineTypes[i].type);
1141  updatePixmap (mode);
1142  break;
1143  }
1144  }
1145 }
1146 
1147 // Updates the combobox and pixmap for the current mode.
1148 void QucsTranscalc::updatePixmap (int _mode) {
1149  pix->setPixmap (QPixmap (QImage (
1150  QucsSettings.BitmapDir + QString(TransLineTypes[_mode].bitmap))));
1151  tranType->setCurrentItem(_mode);
1152 }
1153 
1154 void QucsTranscalc::slotHelpIntro()
1155 {
1156  HelpDialog *d = new HelpDialog(this);
1157  d->show();
1158 }
1159 
1160 void QucsTranscalc::slotOptions()
1161 {
1162  OptionsDialog *d = new OptionsDialog(this);
1163  d->show();
1164 }
1165 
1166 // Translates a given textual unit into a array index.
1167 int QucsTranscalc::translateUnit(const char * unit, int type) {
1168  for (int i = 0; TransUnits[type].units[i]; i++) {
1169  if (unit && !strcmp (unit, TransUnits[type].units[i]))
1170  return i;
1171  }
1172  return 0;
1173 }
1174 
1175 void QucsTranscalc::slotRadioChecked(int id)
1176 {
1177  int idx = getTypeIndex ();
1178  for (int i = 0; i < TransMaxBox[TRANS_PHYSICAL]; i++) {
1179  if (TransLineTypes[idx].radio[i] != -1) {
1180  TransLineTypes[idx].radio[i] = 0;
1181  if (i == id) {
1182  TransLineTypes[idx].radio[i] = 1;
1183  }
1184  }
1185  }
1186  updateSelection ();
1187 }
1188 
1189 void QucsTranscalc::slotCopyToClipBoard()
1190 {
1191  int created = 0;
1192  QString s = "<Qucs Schematic " PACKAGE_VERSION ">\n";
1193 
1194  // create microstrip schematic
1195  if (mode == ModeMicrostrip) {
1196  transline * l = TransLineTypes[ModeMicrostrip].line;
1197  s += "<Components>\n";
1198  s += " <Pac P1 1 90 150 -74 -26 1 1 \"1\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1199  s +=" <Pac P2 1 270 150 18 -26 0 1 \"2\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1200  s += " <GND * 1 90 180 0 0 0 0>\n";
1201  s += " <GND * 1 270 180 0 0 0 0>\n";
1202  s += QString(" <SUBST SubstTC1 1 390 140 -30 24 0 0 \"%1\" 1 \"%2 mm\" 1 \"%3 um\" 1 \"%4\" 1 \"%5\" 1 \"%6\" 1>\n").
1203  arg(l->getProperty("Er")).
1204  arg(l->getProperty("H", UNIT_LENGTH, LENGTH_MM)).
1205  arg(l->getProperty("T", UNIT_LENGTH, LENGTH_UM)).
1206  arg(l->getProperty("Tand")).
1207  arg(1 / l->getProperty("Cond")).
1208  arg(l->getProperty("Rough", UNIT_LENGTH, LENGTH_M));
1209  s += " <.SP SPTC1 1 90 240 0 51 0 0 ";
1210  double freq = l->getProperty("Freq", UNIT_FREQ, FREQ_GHZ);
1211  if (freq > 0)
1212  s += QString("\"log\" 1 \"%1 GHz\" 1 \"%2 GHz\" 1 ").
1213  arg(freq / 10).arg(freq * 10);
1214  else
1215  s += "\"lin\" 1 \"0 GHz\" 1 \"10 GHz\" 1 ";
1216  s += "\"51\" 1 \"no\" 0 \"1\" 0 \"2\" 0>\n";
1217  s += QString(" <MLIN MSTC1 1 180 100 -26 15 0 0 \"SubstTC1\" 1 \"%1 mm\" 1 \"%2 mm\" 1 \"Hammerstad\" 0 \"Kirschning\" 0 \"26.85\" 0>\n").
1218  arg(l->getProperty("W", UNIT_LENGTH, LENGTH_MM)).
1219  arg(l->getProperty("L", UNIT_LENGTH, LENGTH_MM));
1220  s += " <Eqn EqnTC1 1 240 260 -23 12 0 0 \"A=twoport(S,'S','A')\" 1 \"ZL=real(sqrt(A[1,2]/A[2,1]))\" 1 \"yes\" 0>\n";
1221  s += "</Components>\n";
1222  s += "<Wires>\n";
1223  s += " <90 100 150 100 \"\" 0 0 0 \"\">\n";
1224  s += " <90 100 90 120 \"\" 0 0 0 \"\">\n";
1225  s += " <210 100 270 100 \"\" 0 0 0 \"\">\n";
1226  s += " <270 100 270 120 \"\" 0 0 0 \"\">\n";
1227  s += "</Wires>\n";
1228  created++;
1229  }
1230 
1231  // create coupled microstrip schematic
1232  else if (mode == ModeCoupledMicrostrip) {
1233  transline * l = TransLineTypes[ModeCoupledMicrostrip].line;
1234  s += "<Components>\n";
1235  s += " <Pac P1 1 100 130 -74 -26 1 1 \"1\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1236  s += " <Pac P2 1 320 130 18 -26 0 1 \"2\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1237  s += " <Pac P3 1 280 220 18 -26 0 1 \"3\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1238  s += " <Pac P4 1 140 200 -74 -26 1 1 \"4\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1239  s += " <GND * 1 100 160 0 0 0 0>\n";
1240  s += " <GND * 1 140 230 0 0 0 0>\n";
1241  s += " <GND * 1 320 160 0 0 0 0>\n";
1242  s += " <GND * 1 280 250 0 0 0 0>\n";
1243  s += QString(" <SUBST SubstTC1 1 410 220 -30 24 0 0 \"%1\" 1 \"%2 mm\" 1 \"%3 um\" 1 \"%4\" 1 \"%5\" 1 \"%6\" 1>\n").
1244  arg(l->getProperty("Er")).
1245  arg(l->getProperty("H", UNIT_LENGTH, LENGTH_MM)).
1246  arg(l->getProperty("T", UNIT_LENGTH, LENGTH_UM)).
1247  arg(l->getProperty("Tand")).
1248  arg(1 / l->getProperty("Cond")).
1249  arg(l->getProperty("Rough", UNIT_LENGTH, LENGTH_M));
1250  s += " <.SP SPTC1 1 100 290 0 51 0 0 ";
1251  double freq = l->getProperty("Freq", UNIT_FREQ, FREQ_GHZ);
1252  if (freq > 0)
1253  s += QString("\"log\" 1 \"%1 GHz\" 1 \"%2 GHz\" 1 ").
1254  arg(freq / 10).arg(freq * 10);
1255  else
1256  s += "\"lin\" 1 \"0 GHz\" 1 \"10 GHz\" 1 ";
1257  s += "\"51\" 1 \"no\" 0 \"1\" 0 \"2\" 0>\n";
1258  s += QString(" <MCOUPLED MSTC1 1 190 110 -26 37 0 0 \"SubstTC1\" 1 \"%1 mm\" 1 \"%2 mm\" 1 \"%3 mm\" 1 \"Kirschning\" 0 \"Kirschning\" 0 \"26.85\" 0>\n").
1259  arg(l->getProperty("W", UNIT_LENGTH, LENGTH_MM)).
1260  arg(l->getProperty("L", UNIT_LENGTH, LENGTH_MM)).
1261  arg(l->getProperty("S", UNIT_LENGTH, LENGTH_MM));
1262  s += "</Components>\n";
1263  s += "<Wires>\n";
1264  s += " <100 80 160 80 \"\" 0 0 0 \"\">\n";
1265  s += " <100 80 100 100 \"\" 0 0 0 \"\">\n";
1266  s += " <140 140 140 170 \"\" 0 0 0 \"\">\n";
1267  s += " <140 140 160 140 \"\" 0 0 0 \"\">\n";
1268  s += " <320 80 320 100 \"\" 0 0 0 \"\">\n";
1269  s += " <220 80 320 80 \"\" 0 0 0 \"\">\n";
1270  s += " <280 140 280 190 \"\" 0 0 0 \"\">\n";
1271  s += " <220 140 280 140 \"\" 0 0 0 \"\">\n";
1272  s += "</Wires>\n";
1273  created++;
1274  }
1275 
1276  // create coaxial line schematic
1277  else if (mode == ModeCoaxial) {
1278  transline * l = TransLineTypes[ModeCoaxial].line;
1279  s += "<Components>\n";
1280  s += " <Pac P1 1 90 150 -74 -26 1 1 \"1\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1281  s +=" <Pac P2 1 270 150 18 -26 0 1 \"2\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1282  s += " <GND * 1 90 180 0 0 0 0>\n";
1283  s += " <GND * 1 270 180 0 0 0 0>\n";
1284  s += " <.SP SPTC1 1 90 240 0 51 0 0 ";
1285  double freq = l->getProperty("Freq", UNIT_FREQ, FREQ_GHZ);
1286  if (freq > 0)
1287  s += QString("\"log\" 1 \"%1 GHz\" 1 \"%2 GHz\" 1 ").
1288  arg(freq / 10).arg(freq * 10);
1289  else
1290  s += "\"lin\" 1 \"0 GHz\" 1 \"10 GHz\" 1 ";
1291  s += "\"51\" 1 \"no\" 0 \"1\" 0 \"2\" 0>\n";
1292  s += QString(" <COAX CXTC1 1 180 100 -26 15 0 0 \"%1\" 1 \"%2\" 0 \"%3\" 0 \"%4 mm\" 1 \"%5 mm\" 1 \"%6 mm\" 1 \"%7\" 0 \"26.85\" 0>\n").
1293  arg(l->getProperty("Er")).
1294  arg(1 / l->getProperty("Sigma")).
1295  arg(l->getProperty("Mur")).
1296  arg(l->getProperty("dout", UNIT_LENGTH, LENGTH_MM)).
1297  arg(l->getProperty("din", UNIT_LENGTH, LENGTH_MM)).
1298  arg(l->getProperty("L", UNIT_LENGTH, LENGTH_MM)).
1299  arg(l->getProperty("Tand"));
1300  s += "</Components>\n";
1301  s += "<Wires>\n";
1302  s += " <90 100 150 100 \"\" 0 0 0 \"\">\n";
1303  s += " <90 100 90 120 \"\" 0 0 0 \"\">\n";
1304  s += " <210 100 270 100 \"\" 0 0 0 \"\">\n";
1305  s += " <270 100 270 120 \"\" 0 0 0 \"\">\n";
1306  s += "</Wires>\n";
1307  created++;
1308  }
1309 
1310  // create coplanar schematic
1311  else if (mode == ModeCoplanar) {
1312  transline * l = TransLineTypes[ModeCoplanar].line;
1313  s += "<Components>\n";
1314  s += " <Pac P1 1 90 150 -74 -26 1 1 \"1\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1315  s +=" <Pac P2 1 270 150 18 -26 0 1 \"2\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1316  s += " <GND * 1 90 180 0 0 0 0>\n";
1317  s += " <GND * 1 270 180 0 0 0 0>\n";
1318  s += QString(" <SUBST SubstTC1 1 390 140 -30 24 0 0 \"%1\" 1 \"%2 mm\" 1 \"%3 um\" 1 \"%4\" 1 \"%5\" 1 \"0\" 1>\n").
1319  arg(l->getProperty("Er")).
1320  arg(l->getProperty("H", UNIT_LENGTH, LENGTH_MM)).
1321  arg(l->getProperty("T", UNIT_LENGTH, LENGTH_UM)).
1322  arg(l->getProperty("Tand")).
1323  arg(1 / l->getProperty("Cond"));
1324  s += " <.SP SPTC1 1 90 240 0 51 0 0 ";
1325  double freq = l->getProperty("Freq", UNIT_FREQ, FREQ_GHZ);
1326  if (freq > 0)
1327  s += QString("\"log\" 1 \"%1 GHz\" 1 \"%2 GHz\" 1 ").
1328  arg(freq / 10).arg(freq * 10);
1329  else
1330  s += "\"lin\" 1 \"0 GHz\" 1 \"10 GHz\" 1 ";
1331  s += "\"51\" 1 \"no\" 0 \"1\" 0 \"2\" 0>\n";
1332  s += QString(" <CLIN CLTC1 1 180 100 -26 25 0 0 \"SubstTC1\" 1 \"%1 mm\" 1 \"%2 mm\" 1 \"%3 mm\" 1 \"Air\" 1 \"yes\" 0>\n").
1333  arg(l->getProperty("W", UNIT_LENGTH, LENGTH_MM)).
1334  arg(l->getProperty("S", UNIT_LENGTH, LENGTH_MM)).
1335  arg(l->getProperty("L", UNIT_LENGTH, LENGTH_MM));
1336  s += " <Eqn EqnTC1 1 240 260 -23 12 0 0 \"A=twoport(S,'S','A')\" 1 \"ZL=real(sqrt(A[1,2]/A[2,1]))\" 1 \"yes\" 0>\n";
1337  s += "</Components>\n";
1338  s += "<Wires>\n";
1339  s += " <90 100 150 100 \"\" 0 0 0 \"\">\n";
1340  s += " <90 100 90 120 \"\" 0 0 0 \"\">\n";
1341  s += " <210 100 270 100 \"\" 0 0 0 \"\">\n";
1342  s += " <270 100 270 120 \"\" 0 0 0 \"\">\n";
1343  s += "</Wires>\n";
1344  created++;
1345  }
1346 
1347  // create coplanar schematic
1348  else if (mode == ModeGroundedCoplanar) {
1349  transline * l = TransLineTypes[ModeGroundedCoplanar].line;
1350  s += "<Components>\n";
1351  s += " <Pac P1 1 90 150 -74 -26 1 1 \"1\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1352  s +=" <Pac P2 1 270 150 18 -26 0 1 \"2\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1353  s += " <GND * 1 90 180 0 0 0 0>\n";
1354  s += " <GND * 1 270 180 0 0 0 0>\n";
1355  s += QString(" <SUBST SubstTC1 1 390 140 -30 24 0 0 \"%1\" 1 \"%2 mm\" 1 \"%3 um\" 1 \"%4\" 1 \"%5\" 1 \"0\" 1>\n").
1356  arg(l->getProperty("Er")).
1357  arg(l->getProperty("H", UNIT_LENGTH, LENGTH_MM)).
1358  arg(l->getProperty("T", UNIT_LENGTH, LENGTH_UM)).
1359  arg(l->getProperty("Tand")).
1360  arg(1 / l->getProperty("Cond"));
1361  s += " <.SP SPTC1 1 90 240 0 51 0 0 ";
1362  double freq = l->getProperty("Freq", UNIT_FREQ, FREQ_GHZ);
1363  if (freq > 0)
1364  s += QString("\"log\" 1 \"%1 GHz\" 1 \"%2 GHz\" 1 ").
1365  arg(freq / 10).arg(freq * 10);
1366  else
1367  s += "\"lin\" 1 \"0 GHz\" 1 \"10 GHz\" 1 ";
1368  s += "\"51\" 1 \"no\" 0 \"1\" 0 \"2\" 0>\n";
1369  s += QString(" <CLIN CLTC1 1 180 100 -26 25 0 0 \"SubstTC1\" 1 \"%1 mm\" 1 \"%2 mm\" 1 \"%3 mm\" 1 \"Metal\" 1 \"yes\" 0>\n").
1370  arg(l->getProperty("W", UNIT_LENGTH, LENGTH_MM)).
1371  arg(l->getProperty("S", UNIT_LENGTH, LENGTH_MM)).
1372  arg(l->getProperty("L", UNIT_LENGTH, LENGTH_MM));
1373  s += " <Eqn EqnTC1 1 240 260 -23 12 0 0 \"A=twoport(S,'S','A')\" 1 \"ZL=real(sqrt(A[1,2]/A[2,1]))\" 1 \"yes\" 0>\n";
1374  s += "</Components>\n";
1375  s += "<Wires>\n";
1376  s += " <90 100 150 100 \"\" 0 0 0 \"\">\n";
1377  s += " <90 100 90 120 \"\" 0 0 0 \"\">\n";
1378  s += " <210 100 270 100 \"\" 0 0 0 \"\">\n";
1379  s += " <270 100 270 120 \"\" 0 0 0 \"\">\n";
1380  s += "</Wires>\n";
1381  created++;
1382  }
1383 
1384  // rectangular waveguide schematic
1385  else if (mode == ModeRectangular) {
1386  transline * l = TransLineTypes[ModeRectangular].line;
1387  s += "<Components>\n";
1388  s += " <Pac P1 1 90 150 -74 -26 1 1 \"1\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1389  s +=" <Pac P2 1 270 150 18 -26 0 1 \"2\" 1 \"50 Ohm\" 1 \"0 dBm\" 0 \"1 GHz\" 0 \"26.85\" 0>\n";
1390  s += " <GND * 1 90 180 0 0 0 0>\n";
1391  s += " <GND * 1 270 180 0 0 0 0>\n";
1392  s += " <.SP SPTC1 1 90 240 0 51 0 0 ";
1393  double freq = l->getProperty("Freq", UNIT_FREQ, FREQ_GHZ);
1394  if (freq > 0)
1395  s += QString("\"log\" 1 \"%1 GHz\" 1 \"%2 GHz\" 1 ").
1396  arg(freq / 10).arg(freq * 10);
1397  else
1398  s += "\"lin\" 1 \"0 GHz\" 1 \"10 GHz\" 1 ";
1399  s += "\"51\" 1 \"no\" 0 \"1\" 0 \"2\" 0>\n";
1400  s += QString(" <RECTLINE RLTC1 1 180 100 -26 25 0 0 \"%1 mm\" 1 \"%2 mm\" 1 \"%3 mm\" 1 \"%4\" 0 \"%5\" 0 \"%6\" 0 \"%7\" 0 \"26.85\" 0>\n").
1401  arg(l->getProperty("a", UNIT_LENGTH, LENGTH_MM)).
1402  arg(l->getProperty("b", UNIT_LENGTH, LENGTH_MM)).
1403  arg(l->getProperty("L", UNIT_LENGTH, LENGTH_MM)).
1404  arg(l->getProperty("Er")).
1405  arg(l->getProperty("Mur")).
1406  arg(l->getProperty("Tand")).
1407  arg(1 / l->getProperty("Cond"));
1408  s += " <Eqn EqnTC1 1 240 260 -23 12 0 0 \"A=twoport(S,'S','A')\" 1 \"ZL=real(sqrt(A[1,2]/A[2,1]))\" 1 \"yes\" 0>\n";
1409  s += "</Components>\n";
1410  s += "<Wires>\n";
1411  s += " <90 100 150 100 \"\" 0 0 0 \"\">\n";
1412  s += " <90 100 90 120 \"\" 0 0 0 \"\">\n";
1413  s += " <210 100 270 100 \"\" 0 0 0 \"\">\n";
1414  s += " <270 100 270 120 \"\" 0 0 0 \"\">\n";
1415  s += "</Wires>\n";
1416  created++;
1417  }
1418 
1419  // put resulting transmission line schematic into clipboard
1420  QClipboard *cb = QApplication::clipboard();
1421  cb->setText(s);
1422 
1423  // put a message into status line
1424  if (created)
1425  statBar->message(tr("Schematic copied into clipboard."), 2000);
1426  else
1427  statBar->message(tr("Transmission line type not available."), 2000);
1428 }