My Project  0.0.16
QUCS Mapping
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
librarydialog.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  librarydialog.cpp
3  -------------------
4  begin : Sun Jun 04 2006
5  copyright : (C) 2006 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 
22 #include <qhbox.h>
23 #include <qvbox.h>
24 #include <qlabel.h>
25 #include <qlayout.h>
26 #include <qlineedit.h>
27 #include <qtextedit.h>
28 #include <qtextstream.h>
29 #include <qdatastream.h>
30 #include <qcheckbox.h>
31 #include <qlistview.h>
32 #include <qvalidator.h>
33 #include <qmessagebox.h>
34 #include <qpushbutton.h>
35 #include <qscrollview.h>
36 #include <qvbuttongroup.h>
37 
38 #include "librarydialog.h"
39 #include "qucs.h"
40 #include "main.h"
41 #include "schematic.h"
42 
43 extern SubMap FileList;
44 
45 LibraryDialog::LibraryDialog(QucsApp *App_, QListViewItem *SchematicList)
46  : QDialog(App_, 0, TRUE, Qt::WDestructiveClose)
47 {
48  App = App_;
49  setCaption(tr("Create Library"));
50 
51  Expr.setPattern("[\\w_]+");
52  Validator = new QRegExpValidator(Expr, this);
53 
54  // ...........................................................
55  all = new QVBoxLayout(this);
56  all->setMargin(5);
57  all->setSpacing(6);
58 
59  QHBox *h1 = new QHBox(this);
60  all->addWidget(h1);
61  theLabel = new QLabel(tr("Library Name:"), h1);
62  NameEdit = new QLineEdit(h1);
63  NameEdit->setValidator(Validator);
64 
65  Group = new QVButtonGroup(tr("Choose subcircuits:"), this);
66  all->addWidget(Group);
67 
68  // ...........................................................
69  QHBox *h3 = new QHBox(Group);
70  ButtSelectAll = new QPushButton(tr("Select All"), h3);
71  connect(ButtSelectAll, SIGNAL(clicked()), SLOT(slotSelectAll()));
72  ButtSelectNone = new QPushButton(tr("Deselect All"), h3);
73  connect(ButtSelectNone, SIGNAL(clicked()), SLOT(slotSelectNone()));
74 
75  // ...........................................................
76  QScrollView *Dia_Scroll = new QScrollView(Group);
77  Dia_Scroll->setMargin(5);
78  QVBox *Dia_Box = new QVBox(Dia_Scroll->viewport());
79  Dia_Scroll->addChild(Dia_Box);
80 
81  ErrText = new QTextEdit(this);
82  ErrText->setHidden(true);
83  ErrText->setTextFormat(Qt::PlainText);
84  ErrText->setWordWrap(QTextEdit::NoWrap);
85  all->addWidget(ErrText);
86 
87  // ...........................................................
88  QHBox *h2 = new QHBox(this);
89  all->addWidget(h2);
90  ButtCancel = new QPushButton(tr("Cancel"), h2);
91  connect(ButtCancel, SIGNAL(clicked()), SLOT(reject()));
92  ButtCreate = new QPushButton(tr("Next >>"), h2);
93  connect(ButtCreate, SIGNAL(clicked()), SLOT(slotCreate()));
94  ButtCreate->setDefault(true);
95 
96  // ...........................................................
97  // insert all subcircuits of current project
98  QListViewItem *p = SchematicList->firstChild();
99  while(p) {
100  if(p->parent() == 0)
101  break;
102  if(!p->text(1).isEmpty())
103  BoxList.append(new QCheckBox(p->text(0), Dia_Box));
104  p = p->nextSibling();
105  }
106 
107  QColor theColor;
108  if(BoxList.isEmpty()) {
109  ButtCreate->setEnabled(false);
110  theColor =
111  (new QLabel(tr("No subcircuits!"), Dia_Box))->paletteBackgroundColor();
112  }
113  else
114  theColor = BoxList.current()->paletteBackgroundColor();
115  Dia_Scroll->viewport()->setPaletteBackgroundColor(theColor);
116 }
117 
119 {
120  delete all;
121  delete Validator;
122 }
123 
124 // ---------------------------------------------------------------
125 void LibraryDialog::slotCreate()
126 {
127  if(NameEdit->text().isEmpty()) {
128  QMessageBox::critical(this, tr("Error"), tr("Please insert a library name!"));
129  return;
130  }
131 
132  int count=0;
133  QCheckBox *p;
134  for(p = BoxList.first(); p != 0; p = BoxList.next())
135  if(p->isChecked())
136  count++;
137 
138  if(count < 1) {
139  QMessageBox::critical(this, tr("Error"), tr("Please choose at least one subcircuit!"));
140  return;
141  }
142 
143 
144  LibDir = QDir(QucsHomeDir);
145  if(!LibDir.cd("user_lib")) { // user library directory exists ?
146  if(!LibDir.mkdir("user_lib")) { // no, then create it
147  QMessageBox::warning(this, tr("Warning"),
148  tr("Cannot create user library directory !"));
149  return;
150  }
151  LibDir.cd("user_lib");
152  }
153 
154 
155  LibFile.setName(QucsSettings.LibDir + NameEdit->text() + ".lib");
156  if(LibFile.exists()) {
157  QMessageBox::critical(this, tr("Error"), tr("A system library with this name already exists!"));
158  return;
159  }
160 
161  LibFile.setName(LibDir.absFilePath(NameEdit->text()) + ".lib");
162  if(LibFile.exists()) {
163  QMessageBox::critical(this, tr("Error"), tr("A library with this name already exists!"));
164  return;
165  }
166 
167  Group->setHidden(true);
168  ErrText->setHidden(false);
169  NameEdit->setHidden(true);
170  disconnect(ButtCreate, SIGNAL(clicked()), 0, 0);
171  connect(ButtCreate, SIGNAL(clicked()), SLOT(slotNext()));
172 
173  for(p = BoxList.first(); p != 0; p = BoxList.next())
174  if(p->isChecked())
175  break;
176  theLabel->setText(tr("Enter description for \"%1\":").arg(p->text()));
177 
178  for(p = BoxList.next(); p != 0; p = BoxList.next())
179  if(p->isChecked())
180  break;
181  if(p == 0)
182  ButtCreate->setText(tr("Create"));
183 }
184 
185 // ---------------------------------------------------------------
186 void LibraryDialog::intoStream(QTextStream &Stream, QString &tmp,
187  const char *sec)
188 {
189  int i = tmp.find("TOP LEVEL MARK");
190  if(i >= 0) {
191  i = tmp.find('\n',i) + 1;
192  tmp = tmp.mid(i);
193  }
194  Stream << " <" << sec << ">";
195  Stream << tmp;
196  Stream << " </" << sec << ">\n";
197 }
198 
199 // ---------------------------------------------------------------
200 int LibraryDialog::intoFile(QString &ifn, QString &ofn, QStringList &IFiles)
201 {
202  int error = 0;
203  QFile ifile(ifn);
204  if(!ifile.open(IO_ReadOnly)) {
205  ErrText->insert(QObject::tr("ERROR: Cannot open file \"%1\".\n").
206  arg(ifn));
207  error++;
208  }
209  else {
210  QByteArray FileContent = ifile.readAll();
211  ifile.close();
212  if(ifile.name().right(4) == ".lst")
213  LibDir.remove(ifile.name());
214  QDir LibDirSub(LibDir);
215  if(!LibDirSub.cd(NameEdit->text())) {
216  if(!LibDirSub.mkdir(NameEdit->text())) {
217  ErrText->insert(
218  QObject::tr("ERROR: Cannot create user library subdirectory !\n"));
219  error++;
220  }
221  LibDirSub.cd(NameEdit->text());
222  }
223  QFileInfo Info(ofn);
224  ofn = Info.fileName();
225  IFiles.append(ofn);
226  QFile ofile;
227  ofile.setName(LibDirSub.absFilePath(ofn));
228  if(!ofile.open(IO_WriteOnly)) {
229  ErrText->insert(
230  QObject::tr("ERROR: Cannot create file \"%1\".\n").arg(ofn));
231  error++;
232  }
233  else {
234  QDataStream ds(&ofile);
235  ds.writeRawBytes(FileContent.data(), FileContent.size());
236  ofile.close();
237  }
238  }
239  return error;
240 }
241 
242 // ---------------------------------------------------------------
243 void LibraryDialog::slotNext()
244 {
245  Descriptions.append(ErrText->text());
246  ErrText->clear();
247 
248  QCheckBox *p = BoxList.current();
249  if(p) {
250  theLabel->setText(tr("Enter description for \"%1\":").arg(p->text()));
251  for(p = BoxList.next(); p != 0; p = BoxList.next())
252  if(p->isChecked())
253  break;
254  if(p == 0)
255  ButtCreate->setText(tr("Create"));
256  return;
257  }
258 
259  theLabel->setShown(false);
260  ErrText->setReadOnly(true);
261  ButtCancel->setEnabled(false);
262  ButtCreate->setText(tr("Close"));
263  disconnect(ButtCreate, SIGNAL(clicked()), 0, 0);
264  connect(ButtCreate, SIGNAL(clicked()), SLOT(accept()));
265 
266  if(!LibFile.open(IO_WriteOnly)) {
267  ErrText->append(tr("Error: Cannot create library!"));
268  return;
269  }
270  QTextStream Stream;
271  Stream.setDevice(&LibFile);
272  Stream << "<Qucs Library " PACKAGE_VERSION " \""
273  << NameEdit->text() << "\">\n\n";
274 
275 
276  bool Success = true, ret;
277  QStringList::Iterator it = Descriptions.begin();
278  QString tmp;
279  QTextStream ts(&tmp, IO_WriteOnly);
280  for(p = BoxList.first(); p != 0; p = BoxList.next())
281  if(p->isChecked()) {
282  Stream << "<Component " + p->text().section('.',0,0) + ">\n"
283  << " <Description>\n"
284  << *(it++)
285  << "\n </Description>\n";
286 
287  Schematic *Doc = new Schematic(0, QucsWorkDir.filePath(p->text()));
288  if(!Doc->loadDocument()) { // load document if possible
289  delete Doc;
290  ErrText->append(tr("Error: Cannot load subcircuit \"%1\".").
291  arg(p->text()));
292  break;
293  }
294  Doc->DocName = NameEdit->text() + "_" + p->text();
295  Success = false;
296 
297  // save analog model
298  tmp.truncate(0);
299  Doc->isAnalog = true;
300  ret = Doc->createLibNetlist(&ts, ErrText, -1);
301  if(ret) {
302  intoStream(Stream, tmp, "Model");
303  int error = 0;
304  QStringList IFiles;
305  SubMap::Iterator it = FileList.begin();
306  while(it != FileList.end()) {
307  QString f = it.data().File;
308  QString ifn, ofn;
309  if(it.data().Type == "SCH") {
310  ifn = f + ".lst";
311  ofn = ifn;
312  } else if(it.data().Type == "CIR") {
313  ifn = f + ".lst";
314  ofn = ifn;
315  }
316  if (!ifn.isEmpty()) error += intoFile(ifn, ofn, IFiles);
317  it++;
318  }
319  FileList.clear();
320  if(!IFiles.isEmpty()) {
321  Stream << " <ModelIncludes \"" << IFiles.join("\" \"") << "\">\n";
322  }
323  Success = error > 0 ? false : true;
324  } else {
325  ErrText->insert("\n");
326  }
327 
328  // save verilog model
329  tmp.truncate(0);
330  Doc->isVerilog = true;
331  Doc->isAnalog = false;
332  ret = Doc->createLibNetlist(&ts, ErrText, 0);
333  if(ret) {
334  intoStream(Stream, tmp, "VerilogModel");
335  int error = 0;
336  QStringList IFiles;
337  SubMap::Iterator it = FileList.begin();
338  while(it != FileList.end()) {
339  QString f = it.data().File;
340  QString ifn, ofn;
341  if(it.data().Type == "SCH") {
342  ifn = f + ".lst";
343  ofn = f + ".v";
344  } else if(it.data().Type == "VER") {
345  ifn = f;
346  ofn = ifn;
347  }
348  if (!ifn.isEmpty()) error += intoFile(ifn, ofn, IFiles);
349  it++;
350  }
351  FileList.clear();
352  if(!IFiles.isEmpty()) {
353  Stream << " <VerilogModelIncludes \""
354  << IFiles.join("\" \"") << "\">\n";
355  }
356  Success = error > 0 ? false : true;
357  } else {
358  ErrText->insert("\n");
359  }
360 
361  // save vhdl model
362  tmp.truncate(0);
363  Doc->isVerilog = false;
364  Doc->isAnalog = false;
365  ret = Doc->createLibNetlist(&ts, ErrText, 0);
366  if(ret) {
367  intoStream(Stream, tmp, "VHDLModel");
368  int error = 0;
369  QStringList IFiles;
370  SubMap::Iterator it = FileList.begin();
371  while(it != FileList.end()) {
372  QString f = it.data().File;
373  QString ifn, ofn;
374  if(it.data().Type == "SCH") {
375  ifn = f + ".lst";
376  ofn = f + ".vhdl";
377  } else if(it.data().Type == "VHD") {
378  ifn = f;
379  ofn = ifn;
380  }
381  if (!ifn.isEmpty()) error += intoFile(ifn, ofn, IFiles);
382  it++;
383  }
384  FileList.clear();
385  if(!IFiles.isEmpty()) {
386  Stream << " <VHDLModelIncludes \""
387  << IFiles.join("\" \"") << "\">\n";
388  }
389  Success = error > 0 ? false : true;
390  } else {
391  ErrText->insert("\n");
392  }
393 
394  Stream << " <Symbol>\n";
395  Doc->createSubcircuitSymbol();
396  Painting *pp;
397  for(pp = Doc->SymbolPaints.first(); pp != 0; pp = Doc->SymbolPaints.next())
398  Stream << " <" << pp->save() << ">\n";
399 
400  Stream << " </Symbol>\n"
401  << "</Component>\n\n";
402 
403  delete Doc;
404  if(!Success) break;
405  }
406 
407  LibFile.close();
408  if(!Success) {
409  LibFile.remove();
410  return;
411  }
412 
413  ErrText->append(tr("Successfully created library."));
414 }
415 
416 // ---------------------------------------------------------------
417 void LibraryDialog::slotSelectAll()
418 {
419  QCheckBox *p;
420  for(p = BoxList.first(); p != 0; p = BoxList.next()) p->setChecked(true);
421 }
422 
423 // ---------------------------------------------------------------
424 void LibraryDialog::slotSelectNone()
425 {
426  QCheckBox *p;
427  for(p = BoxList.first(); p != 0; p = BoxList.next()) p->setChecked(false);
428 }