Qucs-GUI  0.0.19
/home/travis/build/Qucs/qucs/qucs/qucs/components/libcomp.cpp
Go to the documentation of this file.
00001 /***************************************************************************
00002                                libcomp.cpp
00003                               -------------
00004     begin                : Fri Jun 10 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 
00018 #include "libcomp.h"
00019 #include "qucs.h"
00020 #include "main.h"
00021 #include "schematic.h"
00022 #include "misc.h"
00023 
00024 #include <limits.h>
00025 
00026 #include <QTextStream>
00027 #include <QDir>
00028 #include <QRegExp>
00029 #include <QDebug>
00030 
00031 LibComp::LibComp()
00032 {
00033   Type = isComponent;   // both analog and digital
00034   Description = QObject::tr("Component taken from Qucs library");
00035 
00036   Ports.append(new Port(0,  0));  // dummy port because of being device
00037 
00038   Model = "Lib";
00039   Name  = "X";
00040 
00041   Props.append(new Property("Lib", "", true,
00042     QObject::tr("name of qucs library file")));
00043   Props.append(new Property("Comp", "", true,
00044     QObject::tr("name of component in library")));
00045 }
00046 
00047 // ---------------------------------------------------------------------
00048 Component* LibComp::newOne()
00049 {
00050   LibComp *p = new LibComp();
00051   p->Props.first()->Value = Props.first()->Value;
00052   p->Props.next()->Value = Props.next()->Value;
00053   p->recreate(0);
00054   return p;
00055 }
00056 
00057 // ---------------------------------------------------------------------
00058 // Makes the schematic symbol subcircuit with the correct number
00059 // of ports.
00060 void LibComp::createSymbol()
00061 {
00062   tx = INT_MIN;
00063   ty = INT_MIN;
00064   if(loadSymbol() > 0) {
00065     if(tx == INT_MIN)  tx = x1+4;
00066     if(ty == INT_MIN)  ty = y2+4;
00067   }
00068   else {
00069     // only paint a rectangle
00070     Lines.append(new Line(-15, -15, 15, -15, QPen(Qt::darkBlue,2)));
00071     Lines.append(new Line( 15, -15, 15,  15, QPen(Qt::darkBlue,2)));
00072     Lines.append(new Line(-15,  15, 15,  15, QPen(Qt::darkBlue,2)));
00073     Lines.append(new Line(-15, -15,-15,  15, QPen(Qt::darkBlue,2)));
00074 
00075     x1 = -18; y1 = -18;
00076     x2 =  18; y2 =  18;
00077 
00078     tx = x1+4;
00079     ty = y2+4;
00080   }
00081 }
00082 
00083 // ---------------------------------------------------------------------
00084 // Loads the section with name "Name" from library file into "Section".
00085 int LibComp::loadSection(const QString& Name, QString& Section,
00086        QStringList *Includes)
00087 {
00088   QDir Directory(QucsSettings.LibDir);
00089   QFile file(Directory.absFilePath(Props.first()->Value + ".lib"));
00090   if(!file.open(QIODevice::ReadOnly))
00091     return -1;
00092 
00093   QTextStream ReadWhole(&file);
00094   Section = ReadWhole.read();
00095   file.close();
00096 
00097 
00098   if(Section.left(14) != "<Qucs Library ")  // wrong file type ?
00099     return -2;
00100 
00101   int Start, End = Section.indexOf(' ', 14);
00102   if(End < 15) return -3;
00103   QString Line = Section.mid(14, End-14);
00104   if(!misc::checkVersion(Line)) // wrong version number ?
00105     return -3;
00106 
00107   if(Name == "Symbol") {
00108     Start = Section.indexOf("\n<", 14); // if library has default symbol, take it
00109     if(Start > 0)
00110       if(Section.mid(Start+2, 14) == "DefaultSymbol>") {
00111         Start += 16;
00112         End = Section.indexOf("\n</DefaultSymbol>", Start);
00113         if(End < 0)  return -9;
00114         Section = Section.mid(Start, End-Start);
00115         return 0;
00116       }
00117   }
00118 
00119   // search component
00120   Line = "\n<Component " + Props.next()->Value + ">";
00121   Start = Section.indexOf(Line);
00122   if(Start < 0)  return -4;  // component not found
00123   Start = Section.indexOf('\n', Start);
00124   if(Start < 0)  return -5;  // file corrupt
00125   Start++;
00126   End = Section.indexOf("\n</Component>", Start);
00127   if(End < 0)  return -6;  // file corrupt
00128   Section = Section.mid(Start, End-Start+1);
00129   
00130   // search model includes
00131   if(Includes) {
00132     int StartI, EndI;
00133     StartI = Section.indexOf("<"+Name+"Includes");
00134     if(StartI >= 0) {  // includes found
00135       StartI = Section.indexOf('"', StartI);
00136       if(StartI < 0)  return -10;  // file corrupt
00137       EndI = Section.indexOf('>', StartI);
00138       if(EndI < 0)  return -11;  // file corrupt
00139       StartI++; EndI--;
00140       QString inc = Section.mid(StartI, EndI-StartI);
00141       QStringList f = QStringList::split(QRegExp("\"\\s+\""), inc);
00142       for(QStringList::Iterator it = f.begin(); it != f.end(); ++it ) {
00143   Includes->append(*it);
00144       }
00145     }
00146   }
00147 
00148   // search model
00149   Start = Section.indexOf("<"+Name+">");
00150   if(Start < 0)  return -7;  // symbol not found
00151   Start = Section.indexOf('\n', Start);
00152   if(Start < 0)  return -8;  // file corrupt
00153   while(Section.at(++Start) == ' ') ;
00154   End = Section.indexOf("</"+Name+">", Start);
00155   if(End < 0)  return -9;  // file corrupt
00156 
00157   // snip actual model
00158   Section = Section.mid(Start, End-Start);
00159   return 0;
00160 }
00161 
00162 // ---------------------------------------------------------------------
00163 // Loads the symbol for the subcircuit from the schematic file and
00164 // returns the number of painting elements.
00165 int LibComp::loadSymbol()
00166 {
00167   int z, Result;
00168   QString FileString, Line;
00169   z = loadSection("Symbol", FileString);
00170   if(z < 0) {
00171     if(z != -7)  return z;
00172 
00173     // If library component not defined as subcircuit, then load
00174     // new component and transfer data to this component.
00175     z = loadSection("Model", Line);
00176     if(z < 0)  return z;
00177 
00178     Component *pc = getComponentFromName(Line);
00179     if(pc == 0)  return -20;
00180 
00181     copyComponent(pc);
00182 
00183     pc->Props.setAutoDelete(false);
00184     delete pc;
00185 
00186     return 1;
00187   }
00188 
00189 
00190   z  = 0;
00191   x1 = y1 = INT_MAX;
00192   x2 = y2 = INT_MIN;
00193 
00194   QTextStream stream(&FileString, QIODevice::ReadOnly);
00195   while(!stream.atEnd()) {
00196     Line = stream.readLine();
00197     Line = Line.trimmed();
00198     if(Line.isEmpty())  continue;
00199     if(Line.at(0) != '<') return -11;
00200     if(Line.at(Line.length()-1) != '>') return -12;
00201     Line = Line.mid(1, Line.length()-2); // cut off start and end character
00202     Result = analyseLine(Line, 2);
00203     if(Result < 0) return -13;   // line format error
00204     z += Result;
00205   }
00206 
00207   x1 -= 4;  x2 += 4;   // enlarge component boundings a little
00208   y1 -= 4;  y2 += 4;
00209   return z;      // return number of ports
00210 }
00211 
00212 // -------------------------------------------------------
00213 QString LibComp::getSubcircuitFile()
00214 {
00215   QDir Directory(QucsSettings.LibDir);
00216   QString FileName = Directory.absFilePath(Props.first()->Value);
00217   return misc::properAbsFileName(FileName);
00218 }
00219 
00220 // -------------------------------------------------------
00221 bool LibComp::createSubNetlist(QTextStream *stream, QStringList &FileList,
00222              int type)
00223 {
00224   int r = -1;
00225   QString FileString;
00226   QStringList Includes;
00227   if(type&1) {
00228     r = loadSection("Model", FileString, &Includes);
00229   } else if(type&2) {
00230     r = loadSection("VHDLModel", FileString, &Includes);
00231   } else if(type&4) {
00232     r = loadSection("VerilogModel", FileString, &Includes);
00233   }
00234   if(r < 0)  return false;
00235 
00236   // also include files
00237   int error = 0;
00238   for(QStringList::Iterator it = Includes.begin();
00239       it != Includes.end(); ++it ) {
00240     QString s = getSubcircuitFile()+"/"+*it;
00241     if(FileList.findIndex(s) >= 0) continue;
00242     FileList.append(s);
00243 
00244     // load file and stuff into stream
00245     QFile file(s);
00246     if(!file.open(QIODevice::ReadOnly)) {
00247       error++;
00248     } else {
00249       QByteArray FileContent = file.readAll();
00250       file.close();
00251       //?stream->writeRawBytes(FileContent.data(), FileContent.size());
00252       (*stream) << FileContent.data();
00253       qDebug() << "hi from libcomp";
00254     }
00255   }
00256 
00257   (*stream) << "\n" << FileString << "\n";
00258   return error > 0 ? false : true;
00259 }
00260 
00261 // -------------------------------------------------------
00262 QString LibComp::createType()
00263 {
00264   QString Type = misc::properFileName(Props.first()->Value);
00265   return misc::properName(Type + "_" + Props.next()->Value);
00266 }
00267 
00268 // -------------------------------------------------------
00269 QString LibComp::netlist()
00270 {
00271   QString s = "Sub:"+Name;   // output as subcircuit
00272 
00273   // output all node names
00274   foreach(Port *p1, Ports)
00275     s += " "+p1->Connection->Name;   // node names
00276 
00277   // output property
00278   s += " Type=\""+createType()+"\"";   // type for subcircuit
00279 
00280   // output user defined parameters
00281   for(Property *pp = Props.at(2); pp != 0; pp = Props.next())
00282     s += " "+pp->Name+"=\""+pp->Value+"\"";
00283 
00284   return s + '\n';
00285 }
00286 
00287 // -------------------------------------------------------
00288 QString LibComp::verilogCode(int)
00289 {
00290   QString s = "  Sub_" + createType() + " " + Name + " (";
00291 
00292   // output all node names
00293   QListIterator<Port *> iport(Ports);
00294   Port *pp = iport.next();
00295   if(pp)  s += pp->Connection->Name;
00296   while (iport.hasNext()) {
00297     pp = iport.next();
00298     s += ", "+pp->Connection->Name;   // node names
00299   }
00300 
00301   s += ");\n";
00302   return s;
00303 }
00304 
00305 // -------------------------------------------------------
00306 QString LibComp::vhdlCode(int)
00307 {
00308   QString s = "  " + Name + ": entity Sub_" + createType() + " port map (";
00309 
00310   // output all node names
00311   QListIterator<Port *> iport(Ports);
00312   Port *pp = iport.next();
00313   if(pp)  s += pp->Connection->Name;
00314   while (iport.hasNext()) {
00315     pp = iport.next();
00316     s += ", "+pp->Connection->Name;   // node names
00317   }
00318 
00319   s += ");\n";
00320   return s;
00321 }
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines