Qucs-GUI  0.0.18
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
subcircuit.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  subcircuit.cpp
3  ----------------
4  begin : Sat Aug 23 2003
5  copyright : (C) 2003 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 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include <QtGui>
22 #include "subcircuit.h"
23 #include "qucs.h"
24 //Added by qt3to4:
25 #include <QTextStream>
26 #include "schematic.h"
27 #include "main.h"
28 
29 #include <QDir>
30 #include <QFileInfo>
31 #include <QRegExp>
32 
33 #include <math.h>
34 #include <limits.h>
35 
36 
37 
39 {
40  Type = isComponent; // both analog and digital
41  Description = QObject::tr("subcircuit");
42 
43  Props.append(new Property("File", "", false,
44  QObject::tr("name of qucs schematic file")));
45 
46  Model = "Sub";
47  Name = "SUB";
48 
49  // Do NOT call createSymbol() here. But create port to let it rotate.
50  Ports.append(new Port(0, 0, false));
51 }
52 
53 // ---------------------------------------------------------------------
55 {
56  Subcircuit *p = new Subcircuit();
57  p->Props.getFirst()->Value = Props.getFirst()->Value;
58  p->recreate(0);
59  return p;
60 }
61 
62 // -------------------------------------------------------
63 Element* Subcircuit::info(QString& Name, char* &BitmapFile, bool getNewOne)
64 {
65  Name = QObject::tr("Subcircuit");
66  BitmapFile = (char *) "subcircuit";
67 
68  if(getNewOne) {
69  Subcircuit *p = new Subcircuit();
70  p->recreate(0); // createSymbol() is NOT called in constructor !!!
71  return p;
72  }
73  return 0;
74 }
75 
76 // ---------------------------------------------------------------------
77 // Makes the schematic symbol subcircuit with the correct number
78 // of ports.
80 {
81  int No;
82  QString FileName(Props.getFirst()->Value);
83  FileName = getSubcircuitFile();
84 
85  tx = INT_MIN;
86  ty = INT_MIN;
87  if(loadSymbol(FileName) > 0) { // try to load subcircuit symbol
88  if(tx == INT_MIN) tx = x1+4;
89  if(ty == INT_MIN) ty = y2+4;
90  // remove unused ports
91  for(Port *pp = Ports.first(); pp != 0; ) {
92  if(!pp->avail) { Ports.remove(); pp = Ports.current (); }
93  else pp = Ports.next();
94  }
95  }
96  else {
97  No = QucsApp::testFile(FileName);
98  if(No < 0) No = 0;
99 
100  Ports.clear();
101  remakeSymbol(No); // no symbol was found -> create standard symbol
102  }
103 }
104 
105 // ---------------------------------------------------------------------
107 {
108  int h = 30*((No-1)/2) + 15;
109  Lines.append(new Line(-15, -h, 15, -h,QPen(Qt::darkBlue,2)));
110  Lines.append(new Line( 15, -h, 15, h,QPen(Qt::darkBlue,2)));
111  Lines.append(new Line(-15, h, 15, h,QPen(Qt::darkBlue,2)));
112  Lines.append(new Line(-15, -h,-15, h,QPen(Qt::darkBlue,2)));
113  Texts.append(new Text(-10, -6,"sub"));
114 
115  int i=0, y = 15-h;
116  while(i<No) {
117  i++;
118  Lines.append(new Line(-30, y,-15, y,QPen(Qt::darkBlue,2)));
119  Ports.append(new Port(-30, y));
120  Texts.append(new Text(-25,y-14,QString::number(i)));
121 
122  if(i == No) break;
123  i++;
124  Lines.append(new Line( 15, y, 30, y,QPen(Qt::darkBlue,2)));
125  Ports.append(new Port( 30, y));
126  Texts.append(new Text( 19,y-14,QString::number(i)));
127  y += 60;
128  }
129 
130  x1 = -30; y1 = -h-2;
131  x2 = 30; y2 = h+2;
132  tx = x1+4;
133  ty = y2+4;
134 }
135 
136 // ---------------------------------------------------------------------
137 // Loads the symbol for the subcircuit from the schematic file and
138 // returns the number of painting elements.
139 int Subcircuit::loadSymbol(const QString& DocName)
140 {
141  QFile file(DocName);
142  if(!file.open(QIODevice::ReadOnly))
143  return -1;
144 
145  QString Line;
146  // *****************************************************************
147  // To strongly speed up the file read operation the whole file is
148  // read into the memory in one piece.
149  QTextStream ReadWhole(&file);
150  QString FileString = ReadWhole.read();
151  file.close();
152  QTextStream stream(&FileString, QIODevice::ReadOnly);
153 
154 
155  // read header **************************
156  do {
157  if(stream.atEnd()) return -2;
158  Line = stream.readLine();
159  Line = Line.stripWhiteSpace();
160  } while(Line.isEmpty());
161 
162  if(Line.left(16) != "<Qucs Schematic ") // wrong file type ?
163  return -3;
164 
165  Line = Line.mid(16, Line.length()-17);
166  if(!checkVersion(Line)) // wrong version number ?
167  return -4;
168 
169  // read content *************************
170  while(!stream.atEnd()) {
171  Line = stream.readLine();
172  if(Line == "<Symbol>") break;
173  }
174 
175  x1 = y1 = INT_MAX;
176  x2 = y2 = INT_MIN;
177 
178  int z=0, Result;
179  while(!stream.atEnd()) {
180  Line = stream.readLine();
181  if(Line == "</Symbol>") {
182  x1 -= 4; // enlarge component boundings a little
183  x2 += 4;
184  y1 -= 4;
185  y2 += 4;
186  return z; // return number of ports
187  }
188 
189  Line = Line.stripWhiteSpace();
190  if(Line.at(0) != '<') return -5;
191  if(Line.at(Line.length()-1) != '>') return -6;
192  Line = Line.mid(1, Line.length()-2); // cut off start and end character
193  Result = analyseLine(Line, 1);
194  if(Result < 0) return -7; // line format error
195  z += Result;
196  }
197 
198  return -8; // field not closed
199 }
200 
201 // -------------------------------------------------------
203 {
204  QString s = Model+":"+Name;
205 
206  // output all node names
207  for(Port *p1 = Ports.first(); p1 != 0; p1 = Ports.next())
208  s += " "+p1->Connection->Name; // node names
209 
210  // type for subcircuit
211  QString f = properFileName(Props.first()->Value);
212  s += " Type=\""+properName(f)+"\"";
213 
214  // output all user defined properties
215  for(Property *pp = Props.next(); pp != 0; pp = Props.next())
216  s += " "+pp->Name+"=\""+pp->Value+"\"";
217  return s + '\n';
218 }
219 
220 // -------------------------------------------------------
222 {
223  QString f = properFileName(Props.first()->Value);
224  QString s = " " + Name + ": entity Sub_" + properName(f);
225 
226  // output all user defined properties
227  Property *pr = Props.next();
228  if (pr) {
229  s += " generic map (";
230  s += pr->Value;
231  for(pr = Props.next(); pr != 0; pr = Props.next())
232  s += ", " + pr->Value;
233  s += ")";
234  }
235 
236  // output all node names
237  s += " port map (";
238  Port *pp = Ports.first();
239  if(pp) s += pp->Connection->Name;
240  for(pp = Ports.next(); pp != 0; pp = Ports.next())
241  s += ", "+pp->Connection->Name; // node names
242 
243  s += ");\n";
244  return s;
245 }
246 
247 // -------------------------------------------------------
249 {
250  QString f = properFileName(Props.first()->Value);
251  QString s = " Sub_" + properName(f);
252 
253  // output all user defined properties
254  Property *pr = Props.next();
255  if (pr) {
256  s += " #(";
257  s += Verilog_Param(pr->Value);
258  for(pr = Props.next(); pr != 0; pr = Props.next())
259  s += ", " + Verilog_Param(pr->Value);
260  s += ")";
261  }
262 
263  // output all node names
264  s += " " + Name + " (";
265  Port *pp = Ports.first();
266  if(pp) s += pp->Connection->Name;
267  for(pp = Ports.next(); pp != 0; pp = Ports.next())
268  s += ", "+pp->Connection->Name; // node names
269 
270  s += ");\n";
271  return s;
272 }
273 
274 // -------------------------------------------------------
276 {
277  // construct full filename
278  QString FileName = Props.getFirst()->Value;
279 
280  if (FileName.isEmpty())
281  {
282  return properAbsFileName(FileName);
283  }
284 
285  QFileInfo FileInfo(FileName);
286 
287  if (FileInfo.exists())
288  {
289  // the file must be an absolute path to a schematic file
290  return FileInfo.absoluteFilePath();
291  }
292  else
293  {
294  // get the complete base name (everything except the last '.'
295  // and whatever follows
296  QString baseName = FileInfo.completeBaseName();
297 
298  // if only a file name is supplied, first check if it is in the
299  // same directory as the schematic file it is a part of
300  if (FileInfo.fileName () == FileName)
301  {
302  // the file has no path information, just the file name
304  {
305  // check if a file of the same name is in the same directory
306  // as the schematic file, if we have a pointer to it, in
307  // which case we use this one
308  QFileInfo schematicFileInfo = containingSchematic->getFileInfo ();
309  QFileInfo localFIleInfo (schematicFileInfo.canonicalPath () + "/" + baseName + ".sch");
310  if (localFIleInfo.exists ())
311  {
312  // return the subcircuit saved in the same directory
313  // as the schematic file
314  return localFIleInfo.absoluteFilePath();
315  }
316  }
317  }
318 
319  // look up the hash table for the schematic file as
320  // it does not seem to be an absolute path, this will also
321  // search the home directory which is always hashed
322  QMutex mutex;
323  mutex.lock();
324  QString hashsearchresult = QucsMain->schNameHash.value(baseName);
325  mutex.unlock();
326 
327  if (hashsearchresult.isEmpty())
328  {
329  // the schematic was not found in the hash table, return
330  // what would always have been returned in this case
331  return properAbsFileName(FileName);
332  }
333  else
334  {
335  // we found an entry in the hash table, check it actually still exists
336  FileInfo.setFile(hashsearchresult);
337 
338  if (FileInfo.exists())
339  {
340  // it does exist so return the absolute file path
341  return FileInfo.absoluteFilePath();
342  }
343  else
344  {
345  // the schematic file does not actually exist, return
346  // what would always have been returned in this case
347  return properAbsFileName(FileName);
348  }
349  }
350 
351  }
352 
353 }
Q3PtrList< Line > Lines
Definition: component.h:67
int Type
Definition: element.h:152
QString netlist()
Definition: subcircuit.cpp:202
Component * newOne()
Definition: subcircuit.cpp:54
Node * Connection
Definition: element.h:79
QString properFileName(const QString &Name)
Definition: main.cpp:468
int y1
Definition: element.h:153
QString Verilog_Param(const QString Value)
Definition: main.cpp:540
int tx
Definition: component.h:78
int analyseLine(const QString &, int)
Definition: component.cpp:915
int y2
Definition: element.h:153
Definition: element.h:72
int x1
Definition: element.h:153
bool checkVersion(QString &Line)
Definition: main.cpp:602
QFileInfo getFileInfo(void)
Definition: schematic.h:147
QString getSubcircuitFile()
Definition: subcircuit.cpp:275
void createSymbol()
Definition: subcircuit.cpp:79
Definitions and declarations for the main application.
void remakeSymbol(int No)
Definition: subcircuit.cpp:106
int ty
Definition: component.h:78
QString Value
Definition: element.h:97
QucsApp * QucsMain
Definition: main.cpp:54
QString properAbsFileName(const QString &Name)
Definition: main.cpp:452
Q3PtrList< Property > Props
Definition: component.h:72
Definition: element.h:82
Definition: element.h:48
Superclass of all schematic drawing elements.
Definition: element.h:142
QString verilogCode(int)
Definition: subcircuit.cpp:248
void recreate(Schematic *)
Definition: component.cpp:1250
Q3PtrList< Port > Ports
Definition: component.h:70
static Element * info(QString &, char *&, bool getNewOne=false)
Definition: subcircuit.cpp:63
QString Name
Definition: component.h:80
Q3PtrList< Text > Texts
Definition: component.h:71
QString Model
Definition: component.h:80
QString Name
Definition: node.h:40
Schematic * containingSchematic
Definition: component.h:96
QString Description
Definition: component.h:81
#define isComponent
Definition: element.h:110
int loadSymbol(const QString &)
Definition: subcircuit.cpp:139
QString properName(const QString &Name)
Definition: main.cpp:476
int x2
Definition: element.h:153
QString vhdlCode(int)
Definition: subcircuit.cpp:221
QHash< QString, QString > schNameHash
Definition: qucs.h:76
static int testFile(const QString &)
Definition: qucs.cpp:1156