Qucs-GUI  0.0.19
/home/travis/build/Qucs/qucs/qucs/qucs/dialogs/sweepdialog.cpp
Go to the documentation of this file.
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 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines