Qucs-GUI
0.0.19
|
00001 /* 00002 * librarydialog.cpp - implementation of dialog to create library 00003 * 00004 * Copyright (C) 2006, Michael Margraf, michael.margraf@alumni.tu-berlin.de 00005 * Copyright (C) 2014, Yodalee, lc85301@gmail.com 00006 * 00007 * This file is part of Qucs 00008 * 00009 * Qucs is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2, or (at your option) 00012 * any later version. 00013 * 00014 * This software is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License 00020 * along with Qucs. If not, see <http://www.gnu.org/licenses/>. 00021 * 00022 */ 00023 00024 #ifdef HAVE_CONFIG_H 00025 # include <config.h> 00026 #endif 00027 #include <QLabel> 00028 #include <QLineEdit> 00029 #include <QPlainTextEdit> 00030 #include <QTextStream> 00031 00032 #include <QDataStream> 00033 #include <QCheckBox> 00034 #include <QTreeWidgetItem> 00035 #include <QValidator> 00036 #include <QMessageBox> 00037 #include <QPushButton> 00038 #include <QScrollArea> 00039 #include <QButtonGroup> 00040 #include <QVBoxLayout> 00041 #include <QHBoxLayout> 00042 #include <QStackedWidget> 00043 #include <QGroupBox> 00044 #include <QDebug> 00045 #include <QStringList> 00046 00047 #include "librarydialog.h" 00048 #include "main.h" 00049 #include "schematic.h" 00050 00051 extern SubMap FileList; 00052 00053 LibraryDialog::LibraryDialog(QWidget *parent) 00054 : QDialog(parent) 00055 { 00056 setWindowTitle(tr("Create Library")); 00057 00058 Expr.setPattern("[\\w_]+"); 00059 Validator = new QRegExpValidator(Expr, this); 00060 00061 curDescr = 0; // description counter, prev, next 00062 00063 // ........................................................... 00064 all = new QVBoxLayout(this); 00065 all->setMargin(5); 00066 all->setSpacing(6); 00067 00068 stackedWidgets = new QStackedWidget(this); 00069 all->addWidget(stackedWidgets); 00070 00071 00072 // stacked 0 - select subcirbuit, name, and descriptions 00073 // ........................................................... 00074 QWidget *selectSubckt = new QWidget(); 00075 stackedWidgets->addWidget(selectSubckt); 00076 00077 QVBoxLayout *selectSubcktLayout = new QVBoxLayout(); 00078 selectSubckt->setLayout(selectSubcktLayout); 00079 00080 00081 QHBoxLayout *h1 = new QHBoxLayout(); 00082 selectSubcktLayout->addLayout(h1); 00083 theLabel = new QLabel(tr("Library Name:")); 00084 h1->addWidget(theLabel); 00085 NameEdit = new QLineEdit(); 00086 h1->addWidget(NameEdit); 00087 NameEdit->setValidator(Validator); 00088 00089 // ........................................................... 00090 Group = new QGroupBox(tr("Choose subcircuits:")); 00091 selectSubcktLayout->addWidget(Group); 00092 00093 QScrollArea *scrollArea = new QScrollArea(Group); 00094 scrollArea->setWidgetResizable(true); 00095 00096 QWidget *scrollWidget = new QWidget(); 00097 00098 checkBoxLayout = new QVBoxLayout(); 00099 scrollWidget->setLayout(checkBoxLayout); 00100 scrollArea->setWidget(scrollWidget); 00101 00102 QVBoxLayout *areaLayout = new QVBoxLayout(); 00103 areaLayout->addWidget(scrollArea); 00104 Group->setLayout(areaLayout); 00105 00106 // ........................................................... 00107 QHBoxLayout *hCheck = new QHBoxLayout(); 00108 selectSubcktLayout->addLayout(hCheck); 00109 checkDescr = new QCheckBox(tr("Add subcircuit description")); 00110 checkDescr->setChecked(true); 00111 hCheck->addWidget(checkDescr); 00112 hCheck->addStretch(); 00113 connect(checkDescr, SIGNAL(stateChanged(int)), this, SLOT(slotCheckDescrChanged(int))); 00114 00115 // ........................................................... 00116 QGridLayout *gridButts = new QGridLayout(); 00117 selectSubcktLayout->addLayout(gridButts); 00118 ButtSelectAll = new QPushButton(tr("Select All")); 00119 gridButts->addWidget(ButtSelectAll, 0, 0); 00120 connect(ButtSelectAll, SIGNAL(clicked()), SLOT(slotSelectAll())); 00121 ButtSelectNone = new QPushButton(tr("Deselect All")); 00122 gridButts->addWidget(ButtSelectNone, 0, 1); 00123 connect(ButtSelectNone, SIGNAL(clicked()), SLOT(slotSelectNone())); 00124 // ........................................................... 00125 ButtCancel = new QPushButton(tr("Cancel")); 00126 gridButts->addWidget(ButtCancel, 1, 0); 00127 connect(ButtCancel, SIGNAL(clicked()), SLOT(reject())); 00128 ButtCreateNext = new QPushButton(tr("Next >>")); 00129 gridButts->addWidget(ButtCreateNext, 1, 1); 00130 connect(ButtCreateNext, SIGNAL(clicked()), SLOT(slotCreateNext())); 00131 ButtCreateNext->setDefault(true); 00132 00133 00134 // stacked 1 - enter description, loop over checked subckts 00135 // ........................................................... 00136 QWidget *subcktDescr = new QWidget(); 00137 stackedWidgets->addWidget(subcktDescr); 00138 00139 QVBoxLayout *subcktDescrLayout = new QVBoxLayout(); 00140 subcktDescr->setLayout(subcktDescrLayout); 00141 00142 QHBoxLayout *hbox = new QHBoxLayout(); 00143 subcktDescrLayout->addLayout(hbox); 00144 QLabel *libName = new QLabel(tr("Enter description for:")); 00145 hbox->addWidget(libName); 00146 checkedCktName = new QLabel(); 00147 checkedCktName->setText("dummy"); 00148 hbox->addWidget(checkedCktName); 00149 00150 QGroupBox *descrBox = new QGroupBox(tr("Description:")); 00151 subcktDescrLayout->addWidget(descrBox); 00152 textDescr = new QTextEdit(); 00153 textDescr->setTextFormat(Qt::PlainText); 00154 textDescr->setWordWrapMode(QTextOption::NoWrap); 00155 connect(textDescr, SIGNAL(textChanged()), SLOT(slotUpdateDescription())); 00156 QVBoxLayout *vGroup = new QVBoxLayout; 00157 vGroup->addWidget(textDescr); 00158 descrBox->setLayout(vGroup); 00159 00160 // ........................................................... 00161 gridButts = new QGridLayout(); 00162 subcktDescrLayout->addLayout(gridButts); 00163 prevButt = new QPushButton(tr("Previous")); 00164 gridButts->addWidget(prevButt, 0, 0); 00165 prevButt->setDisabled(true); 00166 connect(prevButt, SIGNAL(clicked()), SLOT(slotPrevDescr())); 00167 nextButt = new QPushButton(tr("Next >>")); 00168 nextButt->setDefault(true); 00169 gridButts->addWidget(nextButt, 0, 1); 00170 connect(nextButt, SIGNAL(clicked()), SLOT(slotNextDescr())); 00171 // ........................................................... 00172 ButtCancel = new QPushButton(tr("Cancel")); 00173 gridButts->addWidget(ButtCancel, 1, 0); 00174 connect(ButtCancel, SIGNAL(clicked()), SLOT(reject())); 00175 createButt = new QPushButton(tr("Create")); 00176 connect(createButt, SIGNAL(clicked()), SLOT(slotSave())); 00177 gridButts->addWidget(createButt, 1, 1); 00178 createButt->setDisabled(true); 00179 00180 00181 // stacked 2 - show error / sucess message 00182 // ........................................................... 00183 QWidget *msg = new QWidget(); 00184 stackedWidgets->addWidget(msg); 00185 00186 QVBoxLayout *msgLayout = new QVBoxLayout(); 00187 msg->setLayout(msgLayout); 00188 00189 QHBoxLayout *hbox1 = new QHBoxLayout(); 00190 msgLayout->addLayout(hbox1); 00191 QLabel *finalLabel = new QLabel(tr("Library Name:")); 00192 hbox1->addWidget(finalLabel); 00193 libSaveName = new QLabel(); 00194 hbox1->addWidget(libSaveName); 00195 00196 QGroupBox *msgBox = new QGroupBox(tr("Message:")); 00197 msgLayout->addWidget(msgBox); 00198 ErrText = new QPlainTextEdit(); 00199 ErrText->setWordWrapMode(QTextOption::NoWrap); 00200 ErrText->setReadOnly(true); 00201 QVBoxLayout *vbox1 = new QVBoxLayout(); 00202 vbox1->addWidget(ErrText); 00203 msgBox->setLayout(vbox1); 00204 00205 QHBoxLayout *hbox2 = new QHBoxLayout(); 00206 hbox2->addStretch(); 00207 QPushButton *close = new QPushButton(tr("Close")); 00208 hbox2->addWidget(close); 00209 connect(close, SIGNAL(clicked()), SLOT(reject())); 00210 msgLayout->addLayout(hbox2); 00211 } 00212 00213 00214 LibraryDialog::~LibraryDialog() 00215 { 00216 delete all; 00217 delete Validator; 00218 } 00219 00220 void 00221 LibraryDialog::fillSchematicList(QStringList SchematicList) 00222 { 00223 // ........................................................... 00224 // insert all subcircuits of into checklist 00225 if (SchematicList.size() == 0) { 00226 ButtCreateNext->setEnabled(false); 00227 QLabel *noProj = new QLabel(tr("No projects!")); 00228 checkBoxLayout->addWidget(noProj); 00229 } else { 00230 foreach(const QString &filename, SchematicList) { 00231 QCheckBox *subCheck = new QCheckBox(filename); 00232 checkBoxLayout->addWidget(subCheck); 00233 BoxList.append(subCheck); 00234 } 00235 } 00236 } 00237 00238 // --------------------------------------------------------------- 00239 void LibraryDialog::slotCreateNext() 00240 { 00241 if(NameEdit->text().isEmpty()) { 00242 QMessageBox::critical(this, tr("Error"), tr("Please insert a library name!")); 00243 return; 00244 } 00245 00246 int count=0; 00247 QCheckBox *p; 00248 QListIterator<QCheckBox *> i(BoxList); 00249 while(i.hasNext()){ 00250 p = i.next(); 00251 if(p->isChecked()) { 00252 SelectedNames.append(p->text()); 00253 Descriptions.append(""); 00254 count++; 00255 } 00256 } 00257 00258 if(count < 1) { 00259 QMessageBox::critical(this, tr("Error"), tr("Please choose at least one subcircuit!")); 00260 return; 00261 } 00262 00263 LibDir = QDir(QucsSettings.QucsHomeDir); 00264 if(!LibDir.cd("user_lib")) { // user library directory exists ? 00265 if(!LibDir.mkdir("user_lib")) { // no, then create it 00266 QMessageBox::warning(this, tr("Warning"), 00267 tr("Cannot create user library directory !")); 00268 return; 00269 } 00270 LibDir.cd("user_lib"); 00271 } 00272 00273 LibFile.setFileName(QucsSettings.LibDir + NameEdit->text() + ".lib"); 00274 if(LibFile.exists()) { 00275 QMessageBox::critical(this, tr("Error"), tr("A system library with this name already exists!")); 00276 return; 00277 } 00278 00279 LibFile.setFileName(LibDir.absFilePath(NameEdit->text()) + ".lib"); 00280 if(LibFile.exists()) { 00281 QMessageBox::critical(this, tr("Error"), tr("A library with this name already exists!")); 00282 return; 00283 } 00284 00285 if (checkDescr->checkState() == Qt::Checked){ 00286 // user enter descriptions 00287 stackedWidgets->setCurrentIndex(1); // subcircuit description view 00288 00289 checkedCktName->setText(SelectedNames[0]); 00290 textDescr->setText(Descriptions[0]); 00291 00292 if (SelectedNames.count() == 1){ 00293 prevButt->setDisabled(true); 00294 nextButt->setDisabled(true); 00295 createButt->setEnabled(true); 00296 } 00297 } 00298 else { 00299 // save whitout description 00300 emit slotSave(); 00301 } 00302 } 00303 00304 // --------------------------------------------------------------- 00305 void LibraryDialog::intoStream(QTextStream &Stream, QString &tmp, 00306 const char *sec) 00307 { 00308 int i = tmp.indexOf("TOP LEVEL MARK"); 00309 if(i >= 0) { 00310 i = tmp.indexOf('\n',i) + 1; 00311 tmp = tmp.mid(i); 00312 } 00313 Stream << " <" << sec << ">"; 00314 Stream << tmp; 00315 Stream << " </" << sec << ">\n"; 00316 } 00317 00318 // --------------------------------------------------------------- 00319 int LibraryDialog::intoFile(QString &ifn, QString &ofn, QStringList &IFiles) 00320 { 00321 int error = 0; 00322 QFile ifile(ifn); 00323 if(!ifile.open(QIODevice::ReadOnly)) { 00324 ErrText->insertPlainText(QObject::tr("ERROR: Cannot open file \"%1\".\n"). 00325 arg(ifn)); 00326 error++; 00327 } 00328 else { 00329 QByteArray FileContent = ifile.readAll(); 00330 ifile.close(); 00331 if(ifile.name().right(4) == ".lst") 00332 LibDir.remove(ifile.name()); 00333 QDir LibDirSub(LibDir); 00334 if(!LibDirSub.cd(NameEdit->text())) { 00335 if(!LibDirSub.mkdir(NameEdit->text())) { 00336 ErrText->insertPlainText( 00337 QObject::tr("ERROR: Cannot create user library subdirectory !\n")); 00338 error++; 00339 } 00340 LibDirSub.cd(NameEdit->text()); 00341 } 00342 QFileInfo Info(ofn); 00343 ofn = Info.fileName(); 00344 IFiles.append(ofn); 00345 QFile ofile; 00346 ofile.setFileName(LibDirSub.absFilePath(ofn)); 00347 if(!ofile.open(QIODevice::WriteOnly)) { 00348 ErrText->insertPlainText( 00349 QObject::tr("ERROR: Cannot create file \"%1\".\n").arg(ofn)); 00350 error++; 00351 } 00352 else { 00353 QDataStream ds(&ofile); 00354 ds.writeRawBytes(FileContent.data(), FileContent.size()); 00355 ofile.close(); 00356 } 00357 } 00358 return error; 00359 } 00360 00361 // --------------------------------------------------------------- 00362 void LibraryDialog::slotCheckDescrChanged(int state) 00363 { 00364 if (state == Qt::Unchecked){ 00365 ButtCreateNext->setText(tr("Create")); 00366 } 00367 else { 00368 ButtCreateNext->setText(tr("Next...")); 00369 } 00370 } 00371 00372 // --------------------------------------------------------------- 00373 void LibraryDialog::slotPrevDescr() 00374 { 00375 if ( curDescr > 0 ) { 00376 nextButt->setDisabled(false); 00377 checkedCktName->setText(SelectedNames[curDescr]); 00378 curDescr--; 00379 checkedCktName->setText(SelectedNames[curDescr]); 00380 textDescr->setText(Descriptions[curDescr]); 00381 } 00382 00383 if (curDescr == 0){ 00384 prevButt->setDisabled(true); 00385 nextButt->setEnabled(true); 00386 } 00387 } 00388 00389 // --------------------------------------------------------------- 00390 void LibraryDialog::slotNextDescr() 00391 { 00392 if ( curDescr < SelectedNames.count()) { 00393 prevButt->setDisabled(false); 00394 checkedCktName->setText(SelectedNames[curDescr]); 00395 curDescr++; 00396 checkedCktName->setText(SelectedNames[curDescr]); 00397 textDescr->setText(Descriptions[curDescr]); 00398 } 00399 00400 if (curDescr == SelectedNames.count()-1){ 00401 nextButt->setDisabled(true); 00402 createButt->setEnabled(true); 00403 } 00404 } 00405 00406 void LibraryDialog::slotUpdateDescription() 00407 { 00408 // store on every change 00409 Descriptions[curDescr] = textDescr->text(); 00410 } 00411 00412 // --------------------------------------------------------------- 00413 void LibraryDialog::slotSave() 00414 { 00415 stackedWidgets->setCurrentIndex(2); //message window 00416 libSaveName->setText(NameEdit->text() + ".lib"); 00417 00418 ErrText->insertPlainText(tr("Saving library...")); 00419 00420 if(!LibFile.open(QIODevice::WriteOnly)) { 00421 ErrText->appendPlainText(tr("Error: Cannot create library!")); 00422 return; 00423 } 00424 QTextStream Stream; 00425 Stream.setDevice(&LibFile); 00426 Stream << "<Qucs Library " PACKAGE_VERSION " \"" 00427 << NameEdit->text() << "\">\n\n"; 00428 00429 bool Success = true, ret; 00430 00431 QString tmp; 00432 QTextStream ts(&tmp, QIODevice::WriteOnly); 00433 00434 for (int i=0; i < SelectedNames.count(); i++) { 00435 ErrText->insertPlainText("\n=================\n"); 00436 00437 QString description = ""; 00438 if(checkDescr->checkState() == Qt::Checked) 00439 description = Descriptions[i]; 00440 00441 Stream << "<Component " + SelectedNames[i].section('.',0,0) + ">\n" 00442 << " <Description>\n" 00443 << description 00444 << "\n </Description>\n"; 00445 00446 Schematic *Doc = new Schematic(0, QucsSettings.QucsWorkDir.filePath(SelectedNames[i])); 00447 ErrText->insertPlainText(tr("Loading subcircuit \"%1\".\n").arg(SelectedNames[i])); 00448 if(!Doc->loadDocument()) { // load document if possible 00449 delete Doc; 00450 ErrText->appendPlainText(tr("Error: Cannot load subcircuit \"%1\"."). 00451 arg(SelectedNames[i])); 00452 break; 00453 } 00454 Doc->DocName = NameEdit->text() + "_" + SelectedNames[i]; 00455 Success = false; 00456 00457 // save analog model 00458 tmp.truncate(0); 00459 Doc->isAnalog = true; 00460 00461 ErrText->insertPlainText("\n"); 00462 ErrText->insertPlainText(tr("Creating Qucs netlist.\n")); 00463 ret = Doc->createLibNetlist(&ts, ErrText, -1); 00464 if(ret) { 00465 intoStream(Stream, tmp, "Model"); 00466 int error = 0; 00467 QStringList IFiles; 00468 SubMap::Iterator it = FileList.begin(); 00469 while(it != FileList.end()) { 00470 QString f = it.data().File; 00471 QString ifn, ofn; 00472 if(it.data().Type == "SCH") { 00473 ifn = f + ".lst"; 00474 ofn = ifn; 00475 } 00476 else if(it.data().Type == "CIR") { 00477 ifn = f + ".lst"; 00478 ofn = ifn; 00479 } 00480 if (!ifn.isEmpty()) error += intoFile(ifn, ofn, IFiles); 00481 it++; 00482 } 00483 FileList.clear(); 00484 if(!IFiles.isEmpty()) { 00485 Stream << " <ModelIncludes \"" << IFiles.join("\" \"") << "\">\n"; 00486 } 00487 Success = error > 0 ? false : true; 00488 } 00489 else { 00490 ErrText->insertPlainText("\n"); 00491 ErrText->insertPlainText(tr("Error: Cannot create netlist for \"%1\".\n").arg(SelectedNames[i])); 00492 } 00493 00494 // save verilog model 00495 tmp.truncate(0); 00496 Doc->isVerilog = true; 00497 Doc->isAnalog = false; 00498 00499 ErrText->insertPlainText("\n"); 00500 ErrText->insertPlainText(tr("Creating Verilog netlist.\n")); 00501 ret = Doc->createLibNetlist(&ts, ErrText, 0); 00502 if(ret) { 00503 intoStream(Stream, tmp, "VerilogModel"); 00504 int error = 0; 00505 QStringList IFiles; 00506 SubMap::Iterator it = FileList.begin(); 00507 while(it != FileList.end()) { 00508 QString f = it.data().File; 00509 QString ifn, ofn; 00510 if(it.data().Type == "SCH") { 00511 ifn = f + ".lst"; 00512 ofn = f + ".v"; 00513 } 00514 else if(it.data().Type == "VER") { 00515 ifn = f; 00516 ofn = ifn; 00517 } 00518 if (!ifn.isEmpty()) error += intoFile(ifn, ofn, IFiles); 00519 it++; 00520 } 00521 FileList.clear(); 00522 if(!IFiles.isEmpty()) { 00523 Stream << " <VerilogModelIncludes \"" 00524 << IFiles.join("\" \"") << "\">\n"; 00525 } 00526 Success = error > 0 ? false : true; 00527 } 00528 else { 00529 ErrText->insertPlainText("\n"); 00530 } 00531 00532 // save vhdl model 00533 tmp.truncate(0); 00534 Doc->isVerilog = false; 00535 Doc->isAnalog = false; 00536 00537 ErrText->insertPlainText(tr("Creating VHDL netlist.\n")); 00538 ret = Doc->createLibNetlist(&ts, ErrText, 0); 00539 if(ret) { 00540 intoStream(Stream, tmp, "VHDLModel"); 00541 int error = 0; 00542 QStringList IFiles; 00543 SubMap::Iterator it = FileList.begin(); 00544 while(it != FileList.end()) { 00545 QString f = it.data().File; 00546 QString ifn, ofn; 00547 if(it.data().Type == "SCH") { 00548 ifn = f + ".lst"; 00549 ofn = f + ".vhdl"; 00550 } 00551 else if(it.data().Type == "VHD") { 00552 ifn = f; 00553 ofn = ifn; 00554 } 00555 if (!ifn.isEmpty()) error += intoFile(ifn, ofn, IFiles); 00556 it++; 00557 } 00558 FileList.clear(); 00559 if(!IFiles.isEmpty()) { 00560 Stream << " <VHDLModelIncludes \"" 00561 << IFiles.join("\" \"") << "\">\n"; 00562 } 00563 Success = error > 0 ? false : true; 00564 } 00565 else { 00566 ErrText->insertPlainText("\n"); 00567 } 00568 00569 Stream << " <Symbol>\n"; 00570 Doc->createSubcircuitSymbol(); 00571 Painting *pp; 00572 for(pp = Doc->SymbolPaints.first(); pp != 0; pp = Doc->SymbolPaints.next()) 00573 Stream << " <" << pp->save() << ">\n"; 00574 00575 Stream << " </Symbol>\n" 00576 << "</Component>\n\n"; 00577 00578 delete Doc; 00579 00580 if(!Success) break; 00581 00582 } // for 00583 00584 LibFile.close(); 00585 if(!Success) { 00586 LibFile.remove(); 00587 ErrText->appendPlainText(tr("Error creating library.")); 00588 return; 00589 } 00590 00591 ErrText->appendPlainText(tr("Successfully created library.")); 00592 } 00593 00594 // --------------------------------------------------------------- 00595 void LibraryDialog::slotSelectAll() 00596 { 00597 QCheckBox *p; 00598 QListIterator<QCheckBox *> i(BoxList); 00599 while(i.hasNext()){ 00600 p = i.next(); 00601 p->setChecked(true); 00602 } 00603 } 00604 00605 // --------------------------------------------------------------- 00606 void LibraryDialog::slotSelectNone() 00607 { 00608 QCheckBox *p; 00609 QListIterator<QCheckBox *> i(BoxList); 00610 while(i.hasNext()){ 00611 p = i.next(); 00612 p->setChecked(false); 00613 } 00614 }