My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
sweepdialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  sweepdialog.cpp
3  -----------------
4  begin : Sat Aug 13 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 "sweepdialog.h"
19 #include "schematic.h"
20 #include "qucs.h"
21 #include "main.h"
22 #include "../diagrams/graph.h"
23 
24 #include <qlabel.h>
25 #include <qlayout.h>
26 #include <qlineedit.h>
27 #include <qvalidator.h>
28 #include <qpushbutton.h>
29 
30 
31 mySpinBox::mySpinBox(int Min, int Max, int Step, double *Val, QWidget *Parent)
32  : QSpinBox(Min, Max, Step, Parent)
33 {
34  Values = Val;
35  editor()->setReadOnly(true);
36 }
37 
38 QString mySpinBox::mapValueToText(int Val)
39 {
40  return QString::number(*(Values+Val));
41 }
42 
43 
44 
45 
47  : QDialog(Doc_, 0, TRUE, Qt::WDestructiveClose)
48 {
49  Doc = Doc_;
50 
51  pGraph = setBiasPoints();
52  // if simulation has no sweeps, terminate dialog before showing it
53  if(pGraph->cPointsX.count() == 0) {
54  reject();
55  return;
56  }
57  if(pGraph->cPointsX.count() <= 1)
58  if(pGraph->cPointsX.getFirst()->count <= 1) {
59  reject();
60  return;
61  }
62 
63 
64  setCaption(tr("Bias Points"));
65 
66  int i = 0;
67  // ...........................................................
68  QGridLayout *all = new QGridLayout(this, pGraph->cPointsX.count()+2,2,3,3);
69  all->setMargin(5);
70  all->setSpacing(5);
71  all->setColStretch(1,5);
72 
73  DataX *pD;
74  mySpinBox *Box;
75  for(pD = pGraph->cPointsX.first(); pD!=0; pD = pGraph->cPointsX.next()) {
76  all->addWidget(new QLabel(pD->Var, this), i,0);
77 
78  Box = new mySpinBox(0, pD->count-1, 1, pD->Points, this);
79  Box->setValue(0); // call "mapValueToText()"
80  all->addWidget(Box, i++,1);
81  connect(Box, SIGNAL(valueChanged(int)), SLOT(slotNewValue(int)));
82  BoxList.append(Box);
83  }
84 
85  // ...........................................................
86  all->setRowStretch(i,5);
87  QPushButton *ButtClose = new QPushButton(tr("Close"), this);
88  all->addMultiCellWidget(ButtClose, i+1,i+1, 0,1);
89  connect(ButtClose, SIGNAL(clicked()), SLOT(accept()));
90 }
91 
93 {
94  delete pGraph;
95 
96  for(double *p = ValueList.first(); p!=0; p = ValueList.next())
97  delete p;
98 }
99 
100 // ---------------------------------------------------------------
101 void SweepDialog::slotNewValue(int)
102 {
103  DataX *pD = pGraph->cPointsX.first();
104 
105  int Factor = 1, Index = 0;
106  for(mySpinBox *pb = BoxList.first(); pb!=0; pb = BoxList.next()) {
107  Index += pb->value() * Factor;
108  Factor *= pD->count;
109  }
110  Index *= 2; // because of complex values
111 
112  double *p = ValueList.first();
113  for(Node *pn = NodeList.first(); pn!=0; pn = NodeList.next()) {
114  pn->Name = num2str(*(p+Index));
115  if(pn->x1 & 0x10)
116  pn->Name += "A";
117  else
118  pn->Name += "V";
119  p = ValueList.next();
120  }
121 
122  Doc->viewport()->update();
123 }
124 
125 // ---------------------------------------------------
126 Graph* SweepDialog::setBiasPoints()
127 {
128  // When this function is entered, a simulation was performed.
129  // Thus, the node names are still in "node->Name".
130 
131  bool hasNoComp;
132  Graph *pg = new Graph("");
133  Diagram *Diag = new Diagram();
134  QFileInfo Info(Doc->DocName);
135  QString DataSet = Info.dirPath() + QDir::separator() + Doc->DataSet;
136 
137  Node *pn;
138  Element *pe;
139  // create DC voltage for all nodes
140  for(pn = Doc->Nodes->first(); pn != 0; pn = Doc->Nodes->next()) {
141  if(pn->Name.isEmpty()) continue;
142 
143  pn->x1 = 0;
144  if(pn->Connections.count() < 2) {
145  pn->Name = ""; // no text at open nodes
146  continue;
147  }
148  else {
149  hasNoComp = true;
150  for(pe = pn->Connections.first(); pe!=0; pe = pn->Connections.next())
151  if(pe->Type == isWire) {
152  if( ((Wire*)pe)->isHorizontal() ) pn->x1 |= 2;
153  }
154  else {
155  if( ((Component*)pe)->Model == "GND" ) {
156  hasNoComp = true; // no text at ground symbol
157  break;
158  }
159 
160  if(pn->cx < pe->cx) pn->x1 |= 1; // to the right is no room
161  hasNoComp = false;
162  }
163  if(hasNoComp) { // text only were a component is connected
164  pn->Name = "";
165  continue;
166  }
167  }
168 
169  pg->Var = pn->Name + ".V";
170  if(Diag->loadVarData(DataSet, pg)) {
171  pn->Name = num2str(*(pg->cPointsY)) + "V";
172  NodeList.append(pn); // remember node ...
173  ValueList.append(pg->cPointsY); // ... and all of its values
174  pg->cPointsY = 0; // do not delete it next time !
175  }
176  else
177  pn->Name = "0V";
178 
179 
180  for(pe = pn->Connections.first(); pe!=0; pe = pn->Connections.next())
181  if(pe->Type == isWire) {
182  if( ((Wire*)pe)->Port1 != pn ) // no text at next node
183  ((Wire*)pe)->Port1->Name = "";
184  else ((Wire*)pe)->Port2->Name = "";
185  }
186  }
187 
188 
189  // create DC current through each probe
190  Component *pc;
191  for(pc = Doc->Components->first(); pc != 0; pc = Doc->Components->next())
192  if(pc->Model == "IProbe") {
193  pn = pc->Ports.first()->Connection;
194  if(!pn->Name.isEmpty()) // preserve node voltage ?
195  pn = pc->Ports.next()->Connection;
196 
197  pn->x1 = 0x10; // mark current
198  pg->Var = pc->Name + ".I";
199  if(Diag->loadVarData(DataSet, pg)) {
200  pn->Name = num2str(*(pg->cPointsY)) + "A";
201  NodeList.append(pn); // remember node ...
202  ValueList.append(pg->cPointsY); // ... and all of its values
203  pg->cPointsY = 0; // do not delete it next time !
204  }
205  else
206  pn->Name = "0A";
207 
208  for(pe = pn->Connections.first(); pe!=0; pe = pn->Connections.next())
209  if(pe->Type == isWire) {
210  if( ((Wire*)pe)->isHorizontal() ) pn->x1 |= 2;
211  }
212  else {
213  if(pn->cx < pe->cx) pn->x1 |= 1; // to the right is no room
214  }
215  }
216 
217 
218  Doc->showBias = 1;
219  delete Diag;
220  return pg;
221 }