Qucs-GUI
0.0.19
|
00001 /*************************************************************************** 00002 sweepdialog.cpp 00003 ----------------- 00004 begin : Sat Aug 13 2005 00005 copyright : (C) 2005 by Michael Margraf 00006 email : michael.margraf@alumni.tu-berlin.de 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * * 00011 * This program is free software; you can redistribute it and/or modify * 00012 * it under the terms of the GNU General Public License as published by * 00013 * the Free Software Foundation; either version 2 of the License, or * 00014 * (at your option) any later version. * 00015 * * 00016 ***************************************************************************/ 00017 #include "sweepdialog.h" 00018 #include "schematic.h" 00019 #include "qucs.h" 00020 00021 #include <QGridLayout> 00022 #include "main.h" 00023 #include "../diagrams/graph.h" 00024 #include "misc.h" 00025 00026 #include <QLabel> 00027 #include <QLineEdit> 00028 #include <QValidator> 00029 #include <QPushButton> 00030 #include <QDebug> 00031 00032 // SpinBoxes are used to show the calculated bias points at the given set of sweep points 00033 mySpinBox::mySpinBox(int Min, int Max, int Step, double *Val, QWidget *Parent) 00034 : QSpinBox(Parent) 00035 { 00036 setMinimum(Min); 00037 setMaximum(Max); 00038 setSingleStep(Step); 00039 Values = Val; 00040 ValueSize = Max; 00041 //editor()-> 00042 // setReadOnly(true); 00043 } 00044 00045 00046 #include <iostream> 00047 using namespace std; 00048 QString mySpinBox::textFromValue(int Val) const 00049 { 00050 if (Values == NULL) return ""; 00051 00052 qDebug() << "Values + Val" << *(Values+Val) << endl; 00053 return QString::number(*(Values+Val)); 00054 } 00055 00056 QValidator::State mySpinBox::validate ( QString & text, int & pos ) const 00057 { 00058 if(pos>ValueSize)return QValidator::Invalid; 00059 if(QString::number(*(Values+pos))==text) 00060 return QValidator::Acceptable; 00061 else return QValidator::Invalid; 00062 } 00063 00064 00065 SweepDialog::SweepDialog(Schematic *Doc_) 00066 : QDialog(Doc_) 00067 { 00068 qDebug() << "SweepDialog::SweepDialog()"; 00069 00070 Doc = Doc_; 00071 00072 pGraph = setBiasPoints(); 00073 // if simulation has no sweeps, terminate dialog before showing it 00074 if(!pGraph->numAxes()) { 00075 reject(); 00076 return; 00077 } 00078 if(pGraph->numAxes() <= 1) 00079 if(pGraph->axis(0)->count <= 1) { 00080 reject(); 00081 return; 00082 } 00083 00084 00085 setWindowTitle(tr("Bias Points")); 00086 00087 int i = 0; 00088 // ........................................................... 00089 QGridLayout *all = new QGridLayout(this);//, pGraph->cPointsX.count()+2,2,3,3); 00090 all->setMargin(5); 00091 all->setSpacing(5); 00092 all->setColStretch(1,5); 00093 00094 DataX const *pD; 00095 mySpinBox *Box; 00096 00097 for(unsigned ii=0; (pD=pGraph->axis(ii)); ++ii) { 00098 all->addWidget(new QLabel(pD->Var, this), i,0); 00099 //cout<<"count: "<<pD->count-1<<", points: "<<*pD->Points<<endl; 00100 //works only for linear: 00101 /*double Min = pD->Points[0]; 00102 double Max = pD->Points[pD->count-1]; 00103 double Step = (Max-Min)/(pD->count); 00104 cout<<"Min: "<<Min<<", Max: "<<Max<<", Step: "<<Step<<endl; 00105 Box = new mySpinBox(Min, Max, Step, pD->Points, this);*/ 00106 Box = new mySpinBox(0, pD->count-1, 1, pD->Points, this); 00107 Box->setValue(0); 00108 all->addWidget(Box, i++,1); 00109 connect(Box, SIGNAL(valueChanged(int)), SLOT(slotNewValue(int))); 00110 BoxList.append(Box); 00111 } 00112 00113 // ........................................................... 00114 all->setRowStretch(i,5); 00115 QPushButton *ButtClose = new QPushButton(tr("Close"), this); 00116 all->addMultiCellWidget(ButtClose, i+1,i+1, 0,1); 00117 connect(ButtClose, SIGNAL(clicked()), SLOT(accept())); 00118 show(); 00119 } 00120 00121 SweepDialog::~SweepDialog() 00122 { 00123 delete pGraph; 00124 00125 while(!ValueList.isEmpty()) { 00126 delete ValueList.takeFirst(); 00127 } 00128 } 00129 00130 // --------------------------------------------------------------- 00131 void SweepDialog::slotNewValue(int) 00132 { 00133 DataX const*pD = pGraph->axis(0); 00134 00135 int Factor = 1, Index = 0; 00136 QList<mySpinBox *>::const_iterator it; 00137 for(it = BoxList.constBegin(); it != BoxList.constEnd(); it++) { 00138 Index += (*it)->value() * Factor; 00139 Factor *= pD->count; 00140 } 00141 Index *= 2; // because of complex values 00142 00143 QList<Node *>::iterator node_it; 00144 QList<double *>::const_iterator value_it = ValueList.begin(); 00145 for(node_it = NodeList.begin(); node_it != NodeList.end(); node_it++) { 00146 qDebug() << "SweepDialog::slotNewValue:(*node_it)->Name:" << (*node_it)->Name; 00147 (*node_it)->Name = misc::num2str(*((*value_it)+Index)); 00148 (*node_it)->Name += ((*node_it)->x1 & 0x10)? "A" : "V"; 00149 value_it++; 00150 } 00151 00152 Doc->viewport()->update(); 00153 } 00154 00155 // --------------------------------------------------- 00156 Graph* SweepDialog::setBiasPoints() 00157 { 00158 // When this function is entered, a simulation was performed. 00159 // Thus, the node names are still in "node->Name". 00160 00161 qDebug() << "SweepDialog::setBiasPoints()"; 00162 00163 bool hasNoComp; 00164 Graph *pg = new Graph(NULL, ""); // HACK! 00165 QFileInfo Info(Doc->DocName); 00166 QString DataSet = Info.dirPath() + QDir::separator() + Doc->DataSet; 00167 00168 Node *pn; 00169 Element *pe; 00170 00171 // Note 1: 00172 // Invalidate it so that "Graph::loadDatFile()" does not check for the previously loaded time. 00173 // This is a current hack as "Graph::loadDatFile()" does not support multi-node data loading 00174 // from the simulation results without refreshing (changing) or invalidating the timestamp. 00175 00176 NodeList.clear(); 00177 ValueList.clear(); 00178 00179 // create DC voltage for all nodes 00180 for(pn = Doc->Nodes->first(); pn != 0; pn = Doc->Nodes->next()) { 00181 if(pn->Name.isEmpty()) continue; 00182 00183 pn->x1 = 0; 00184 if(pn->Connections.count() < 2) { 00185 pn->Name = ""; // no text at open nodes 00186 continue; 00187 } 00188 else { 00189 hasNoComp = true; 00190 for(pe = pn->Connections.first(); pe!=0; pe = pn->Connections.next()) 00191 if(pe->Type == isWire) { 00192 if( ((Wire*)pe)->isHorizontal() ) pn->x1 |= 2; 00193 } 00194 else { 00195 if( ((Component*)pe)->Model == "GND" ) { 00196 hasNoComp = true; // no text at ground symbol 00197 break; 00198 } 00199 00200 if(pn->cx < pe->cx) pn->x1 |= 1; // to the right is no room 00201 hasNoComp = false; 00202 } 00203 if(hasNoComp) { // text only were a component is connected 00204 pn->Name = ""; 00205 continue; 00206 } 00207 } 00208 00209 pg->Var = pn->Name + ".V"; 00210 pg->lastLoaded = QDateTime(); // Note 1 at the start of this function 00211 if(pg->loadDatFile(DataSet) == 2) { 00212 pn->Name = misc::num2str(*(pg->cPointsY)) + "V"; 00213 NodeList.append(pn); // remember node ... 00214 ValueList.append(pg->cPointsY); // ... and all of its values 00215 pg->cPointsY = 0; // do not delete it next time ! 00216 } 00217 else 00218 pn->Name = "0V"; 00219 00220 00221 for(pe = pn->Connections.first(); pe!=0; pe = pn->Connections.next()) 00222 if(pe->Type == isWire) { 00223 if( ((Wire*)pe)->Port1 != pn ) // no text at next node 00224 ((Wire*)pe)->Port1->Name = ""; 00225 else ((Wire*)pe)->Port2->Name = ""; 00226 } 00227 } 00228 00229 00230 // create DC current through each probe 00231 Component *pc; 00232 for(pc = Doc->Components->first(); pc != 0; pc = Doc->Components->next()) 00233 if(pc->Model == "IProbe") { 00234 pn = pc->Ports.first()->Connection; 00235 if(!pn->Name.isEmpty()) // preserve node voltage ? 00236 pn = pc->Ports.at(1)->Connection; 00237 00238 pn->x1 = 0x10; // mark current 00239 pg->Var = pc->Name + ".I"; 00240 pg->lastLoaded = QDateTime(); // Note 1 at the start of this function 00241 if(pg->loadDatFile(DataSet) == 2) { 00242 pn->Name = misc::num2str(*(pg->cPointsY)) + "A"; 00243 NodeList.append(pn); // remember node ... 00244 ValueList.append(pg->cPointsY); // ... and all of its values 00245 pg->cPointsY = 0; // do not delete it next time ! 00246 } 00247 else 00248 pn->Name = "0A"; 00249 00250 for(pe = pn->Connections.first(); pe!=0; pe = pn->Connections.next()) 00251 if(pe->Type == isWire) { 00252 if( ((Wire*)pe)->isHorizontal() ) pn->x1 |= 2; 00253 } 00254 else { 00255 if(pn->cx < pe->cx) pn->x1 |= 1; // to the right is no room 00256 } 00257 } 00258 00259 00260 Doc->showBias = 1; 00261 00262 return pg; 00263 }