diff --git a/qucs/extsimkernels/externsimdialog.cpp b/qucs/extsimkernels/externsimdialog.cpp index 17c78553..3a3d195c 100644 --- a/qucs/extsimkernels/externsimdialog.cpp +++ b/qucs/extsimkernels/externsimdialog.cpp @@ -25,7 +25,7 @@ #include "main.h" #include "qucs.h" -ExternSimDialog::ExternSimDialog(Schematic *sch, bool netlist_mode) : +ExternSimDialog::ExternSimDialog(Schematic* sch, bool netlist2Console, bool netlist_mode) : QDialog(sch), a_schematic(sch), a_buttonStopSim(new QPushButton(tr("Stop"),this)), @@ -37,7 +37,8 @@ ExternSimDialog::ExternSimDialog(Schematic *sch, bool netlist_mode) : a_ngspice(new Ngspice(sch,this)), a_xyce(new Xyce(sch,this)), a_wasSimulated(true), - a_hasError(false) + a_hasError(false), + a_netlist2Console(netlist2Console) { const QString workdir(QucsSettings.S4Qworkdir); @@ -296,27 +297,40 @@ void ExternSimDialog::slotStop() void ExternSimDialog::slotSaveNetlist() { QFileInfo inf(a_schematic->getDocName()); - QString filename = QFileDialog::getSaveFileName(this,tr("Save netlist"),inf.path()+QDir::separator()+"netlist.cir", - "All files (*)"); - if (filename.isEmpty()) return; + QString filename; + + if (!a_netlist2Console) + { + filename = QFileDialog::getSaveFileName( + this, + tr("Save netlist"), + inf.path() + QDir::separator() + "netlist.cir", + "All files (*)"); + if (filename.isEmpty()) + { + return; + } + } - switch (QucsSettings.DefaultSimulator) { + switch (QucsSettings.DefaultSimulator) + { case spicecompat::simNgspice: - case spicecompat::simSpiceOpus: { - a_ngspice->SaveNetlist(filename); - } + case spicecompat::simSpiceOpus: + a_ngspice->SaveNetlist(filename, a_netlist2Console); break; - case spicecompat::simXyce: { - a_xyce->SaveNetlist(filename); - } + case spicecompat::simXyce: + a_xyce->SaveNetlist(filename, a_netlist2Console); break; default: break; } - if (!QFile::exists(filename)) { - QMessageBox::critical(0, QObject::tr("Save netlist"), - QObject::tr("Disk write error!"), QMessageBox::Ok); + if (!a_netlist2Console && !QFile::exists(filename)) + { + QMessageBox::critical( + nullptr, + QObject::tr("Save netlist"), + QObject::tr("Disk write error!"), QMessageBox::Ok); } } diff --git a/qucs/extsimkernels/externsimdialog.h b/qucs/extsimkernels/externsimdialog.h index 5541b4fe..acbbccd3 100644 --- a/qucs/extsimkernels/externsimdialog.h +++ b/qucs/extsimkernels/externsimdialog.h @@ -30,7 +30,7 @@ class ExternSimDialog : public QDialog Q_OBJECT private: - Schematic *a_schematic; + Schematic* a_schematic; QPushButton *a_buttonStopSim; QPushButton *a_buttonSaveNetlist; @@ -46,10 +46,13 @@ class ExternSimDialog : public QDialog bool a_wasSimulated; bool a_hasError; + bool a_netlist2Console; public: - explicit ExternSimDialog(Schematic *sch, - bool netlist_mode = false); + explicit ExternSimDialog( + Schematic* sch, + bool netlist2Console, + bool netlist_mode = false); ~ExternSimDialog(); bool wasSimulated() const { return a_wasSimulated; } diff --git a/qucs/extsimkernels/ngspice.cpp b/qucs/extsimkernels/ngspice.cpp index 6169e4bf..e704c6c7 100644 --- a/qucs/extsimkernels/ngspice.cpp +++ b/qucs/extsimkernels/ngspice.cpp @@ -33,6 +33,10 @@ #include "config.h" #endif +#include + +#include + /*! \file ngspice.cpp \brief Implementation of the Ngspice class @@ -43,7 +47,7 @@ * \param schematic Schematic that need to be simulated with Ngspice. * \param parent Parent object */ -Ngspice::Ngspice(Schematic *schematic, QObject *parent) : +Ngspice::Ngspice(Schematic* schematic, QObject *parent) : AbstractSpiceKernel(schematic, parent), a_spinit_name() { @@ -67,8 +71,11 @@ Ngspice::Ngspice(Schematic *schematic, QObject *parent) : * \param[out] vars The list of output variables and node names. * \param[out] outputs The list of spice output raw text files. */ -void Ngspice::createNetlist(QTextStream &stream, int , - QStringList &simulations, QStringList &vars, QStringList &outputs) +void Ngspice::createNetlist( + QTextStream& stream, + QStringList& simulations, + QStringList& vars, + QStringList& outputs) { Q_UNUSED(simulations); @@ -464,7 +471,7 @@ void Ngspice::slotSimulate() QString netfile = "spice4qucs.cir"; QString tmp_path = QDir::toNativeSeparators(a_workdir+QDir::separator()+netfile); - SaveNetlist(tmp_path); + SaveNetlist(tmp_path, false); removeAllSimulatorOutputs(); @@ -583,24 +590,43 @@ void Ngspice::slotProcessOutput() * \brief Ngspice::SaveNetlist Create netlist and save it to file without execution * of simulator. * \param[in] filename Absolute path to netlist + * \param[in] netlist2Console Whether netlist to console instead to file */ -void Ngspice::SaveNetlist(QString filename) +void Ngspice::SaveNetlist(QString filename, bool netlist2Console) { - int num=0; a_sims.clear(); a_vars.clear(); - QFile spice_file(filename); - if (spice_file.open(QFile::WriteOnly)) { - QTextStream stream(&spice_file); - createNetlist(stream,num,a_sims,a_vars,a_output_files); - spice_file.close(); + QScopedPointer netlistString; + QScopedPointer netlistStream; + QScopedPointer netlistFile; + + if (netlist2Console) + { + netlistString.reset(new QString); + netlistStream.reset(new QTextStream(netlistString.get())); } else { - QString msg=QStringLiteral("Tried to save netlist \nin %1\n(could not open for writing!)").arg(filename); - QString final_msg=QStringLiteral("%1\n This could be an error in the QSettings settings file\n(usually in ~/.config/qucs/qucs_s.conf)\nThe value for S4Q_workdir (default:/spice4qucs) needs to be writeable!\nFor a Simulation Simulation will raise error! (most likely S4Q_workdir does not exists)").arg(msg); - QMessageBox::critical(nullptr,tr("Problem with SaveNetlist"),final_msg,QMessageBox::Ok); + netlistFile.reset(new QFile(filename)); + if (netlistFile->open(QFile::WriteOnly)) + { + netlistStream.reset(new QTextStream(netlistFile.get())); + } + else + { + QString msg = QStringLiteral("Tried to save netlist \nin %1\n(could not open for writing!)").arg(filename); + QString final_msg = QStringLiteral("%1\n This could be an error in the QSettings settings file\n(usually in ~/.config/qucs/qucs_s.conf)\nThe value for S4Q_workdir (default:/spice4qucs) needs to be writeable!\nFor a Simulation Simulation will raise error! (most likely S4Q_workdir does not exists)").arg(msg); + QMessageBox::critical(nullptr,tr("Problem with SaveNetlist"), final_msg, QMessageBox::Ok); + return; + } + } + + createNetlist(*netlistStream, a_sims, a_vars, a_output_files); + + if (netlist2Console) + { + std::cout << netlistString->toUtf8().constData() << std::endl; } } diff --git a/qucs/extsimkernels/ngspice.h b/qucs/extsimkernels/ngspice.h index a63f5b2e..a2a4bedc 100644 --- a/qucs/extsimkernels/ngspice.h +++ b/qucs/extsimkernels/ngspice.h @@ -41,7 +41,7 @@ class Ngspice : public AbstractSpiceKernel QString a_spinit_name; bool checkNodeNames(QStringList &incompat); - static QString collectSpiceinit(Schematic *sch); + static QString collectSpiceinit(Schematic* sch); bool findMathFuncInc(QString &mathf_inc); QString getParentSWPscript(Component *pc_swp, QString sim, bool before, bool &hasDblSWP); QString getParentSWPCntVar(Component *pc_swp, QString sim); @@ -49,14 +49,17 @@ class Ngspice : public AbstractSpiceKernel void createSpiceinit(const QString &initial_spiceinit); public: - explicit Ngspice(Schematic *schematic, QObject *parent = 0); - void SaveNetlist(QString filename); + explicit Ngspice(Schematic* schematic, QObject *parent = 0); + void SaveNetlist(QString filename, bool netlist2Console); void setSimulatorCmd(QString cmd); void setSimulatorParameters(QString parameters); protected: - void createNetlist(QTextStream &stream, int NumPorts, QStringList &simulations, - QStringList &vars, QStringList &outputs); + void createNetlist( + QTextStream& stream, + QStringList& simulations, + QStringList& vars, + QStringList& outputs); public slots: void slotSimulate(); diff --git a/qucs/extsimkernels/xyce.cpp b/qucs/extsimkernels/xyce.cpp index 743e63d4..36a41680 100644 --- a/qucs/extsimkernels/xyce.cpp +++ b/qucs/extsimkernels/xyce.cpp @@ -25,6 +25,10 @@ #include "config.h" #endif +#include + +#include + /*! \file xyce.cpp \brief Implementation of the Xyce class @@ -35,7 +39,7 @@ * \param schematic Schematic that need to be simulated with Ngspice. * \param parent Parent object */ -Xyce::Xyce(Schematic *schematic, QObject *parent) : +Xyce::Xyce(Schematic* schematic, QObject *parent) : AbstractSpiceKernel(schematic, parent), a_Noisesim(false), a_simulationsQueue(), @@ -79,8 +83,11 @@ void Xyce::determineUsedSimulations(QStringList *sim_lst) * \param[out] vars The list of output variables and node names. * \param[out] outputs The list of spice output raw text files. */ -void Xyce::createNetlist(QTextStream &stream, int , QStringList &simulations, - QStringList &vars, QStringList &outputs) +void Xyce::createNetlist( + QTextStream& stream, + QStringList& simulations, + QStringList& vars, + QStringList& outputs) { QString s; bool hasParSweep = false; @@ -312,7 +319,6 @@ void Xyce::slotSimulate() return; } - int num=0; a_netlistQueue.clear(); a_output_files.clear(); @@ -332,7 +338,7 @@ void Xyce::slotSimulate() QFile spice_file(tmp_path); if (spice_file.open(QFile::WriteOnly)) { QTextStream stream(&spice_file); - createNetlist(stream,num,sim_lst,a_vars,a_output_files); + createNetlist(stream,sim_lst,a_vars,a_output_files); spice_file.close(); } } @@ -347,16 +353,36 @@ void Xyce::slotSimulate() * \brief Xyce::SaveNetlist Save netlist into specified file without * execution of simulator. * \param[in] filename The name of file in which netlist is saved + * \param[in] netlist2Console Whether netlist to console instead to file */ -void Xyce::SaveNetlist(QString filename) +void Xyce::SaveNetlist(QString filename, bool netlist2Console) { determineUsedSimulations(); - int num = 0; - QFile spice_file(filename); - if (spice_file.open(QFile::WriteOnly)) { - QTextStream stream(&spice_file); - createNetlist(stream,num,a_simulationsQueue,a_vars,a_output_files); - spice_file.close(); + + QScopedPointer netlistString; + QScopedPointer netlistStream; + QScopedPointer netlistFile; + + if (netlist2Console) + { + netlistString.reset(new QString); + netlistStream.reset(new QTextStream(netlistString.get())); + } + else + { + netlistFile.reset(new QFile(filename)); + + if (netlistFile->open(QFile::WriteOnly)) + { + netlistStream.reset(new QTextStream(netlistFile.get())); + } + } + + createNetlist(*netlistStream, a_simulationsQueue, a_vars, a_output_files); + + if (netlist2Console) + { + std::cout << netlistString->toUtf8().constData() << std::endl; } } diff --git a/qucs/extsimkernels/xyce.h b/qucs/extsimkernels/xyce.h index 1917fb7f..e0e8afba 100644 --- a/qucs/extsimkernels/xyce.h +++ b/qucs/extsimkernels/xyce.h @@ -46,15 +46,19 @@ class Xyce : public AbstractSpiceKernel public: void determineUsedSimulations(QStringList *sim_lst = NULL); - explicit Xyce(Schematic *schematic, QObject *parent = 0); + explicit Xyce(Schematic* schematic, QObject *parent = 0); - void SaveNetlist(QString filename); + void SaveNetlist(QString filename, bool netlist2Console); void setParallel(bool par); bool waitEndOfSimulation(); protected: - void createNetlist(QTextStream &stream, int NumPorts, QStringList &simulations, - QStringList &vars, QStringList &outputs); + void createNetlist( + QTextStream& stream, + QStringList& simulations, + QStringList& vars, + QStringList& outputs); + protected slots: void slotFinished(); void slotProcessOutput(); diff --git a/qucs/main.cpp b/qucs/main.cpp index a11d4530..bdb30143 100644 --- a/qucs/main.cpp +++ b/qucs/main.cpp @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include "qucs.h" #include "main.h" @@ -52,6 +54,7 @@ #include "extsimkernels/ngspice.h" #include "extsimkernels/xyce.h" +#include "extsimkernels/CdlNetlistWriter.h" #if defined(_WIN32) ||defined(__MINGW32__) #include //for OutputDebugString @@ -270,202 +273,315 @@ void qucsMessageOutput(QtMsgType type, const QMessageLogContext &context, const fflush(stderr); } -Schematic *openSchematic(QString schematic) +Schematic* openSchematic(const QString& schematicFileName) { - qDebug() << "*** try to load schematic :" << schematic; + qDebug() << "*** try to load schematic :" << schematicFileName; - QFile file(schematic); // save simulator messages - if(file.open(QIODevice::ReadOnly)) { - file.close(); - } - else { - fprintf(stderr, "Error: Could not load schematic %s\n", schematic.toLatin1().data()); - return NULL; - } + QFile file(schematicFileName); // save simulator messages + if (file.open(QIODevice::ReadOnly)) + { + file.close(); + } + else + { + fprintf(stderr, "Error: Could not load schematic %s\n", schematicFileName.toLatin1().data()); + return nullptr; + } - // populate Modules list - //Module::registerModules (); + // populate Modules list + //Module::registerModules (); - // new schematic from file - Schematic *sch = new Schematic(0, schematic); + // new schematic from file + Schematic *schematic = new Schematic(nullptr, schematicFileName); - // load schematic file if possible - if(!sch->loadDocument()) { - fprintf(stderr, "Error: Could not load schematic %s\n", schematic.toLatin1().data()); - delete sch; - return NULL; - } - return sch; + // load schematic file if possible + if (!schematic->loadDocument()) + { + fprintf(stderr, "Error: Could not load schematic %s\n", schematicFileName.toLatin1().data()); + delete schematic; + return nullptr; + } + + return schematic; } -int doNetlist(QString schematic, QString netlist) +int doNetlist(QString schematicFileName, QString netlistFileName, bool netlist2Console) { - QucsSettings.DefaultSimulator = spicecompat::simQucsator; - Module::registerModules(); - Schematic *sch = openSchematic(schematic); - if (sch == NULL) { - return 1; - } + QucsSettings.DefaultSimulator = spicecompat::simQucsator; + Module::registerModules(); - qDebug() << "*** try to write netlist :" << netlist; + QScopedPointer schematic(openSchematic(schematicFileName)); + if (!schematic) + { + return 1; + } - QStringList Collect; + if (!netlist2Console) + { + qDebug() << "*** try to write netlist :" << netlistFileName; + } - QPlainTextEdit *ErrText = new QPlainTextEdit(); //dummy - QFile NetlistFile; - QTextStream Stream; + QScopedPointer netlistFile; + QScopedPointer netlistStream; + QScopedPointer netlistString; - Collect.clear(); // clear list for NodeSets, SPICE components etc. + if (!netlist2Console) + { + netlistFile.reset(new QFile(netlistFileName)); + if (!netlistFile->open(QIODevice::WriteOnly)) + { + fprintf(stderr, "Error: Could not load netlist %s\n", netlistFileName.toLatin1().data()); + return -1; + } - NetlistFile.setFileName(netlist); - if(!NetlistFile.open(QIODevice::WriteOnly)) { - fprintf(stderr, "Error: Could not load netlist %s\n", netlist.toLatin1().data()); - return -1; - } + netlistStream.reset(new QTextStream(netlistFile.get())); + } + else + { + netlistString.reset(new QString); + netlistStream.reset(new QTextStream(netlistString.get())); + } - Stream.setDevice(&NetlistFile); - int SimPorts = sch->prepareNetlist(Stream, Collect, ErrText); + QPlainTextEdit errText; // dummy + QStringList Collect; // clear list for NodeSets, SPICE components etc. + int SimPorts = schematic->prepareNetlist(*netlistStream, Collect, &errText); - if(SimPorts < -5) { - NetlistFile.close(); - QByteArray ba = netlist.toLatin1(); - fprintf(stderr, "Error: Could not prepare netlist %s\n", ba.data()); - /// \todo better handling for error/warnings - qCritical() << ErrText->toPlainText(); - return 1; - } + if (SimPorts < -5) + { + QByteArray ba = netlistFileName.toLatin1(); + fprintf(stderr, "Error: Could not prepare netlist %s\n", ba.data()); + /// \todo better handling for error/warnings + qCritical() << errText.toPlainText(); + return 1; + } - // output NodeSets, SPICE simulations etc. - for(QStringList::Iterator it = Collect.begin(); - it != Collect.end(); ++it) { - // don't put library includes into netlist... - if ((*it).right(4) != ".lst" && - (*it).right(5) != ".vhdl" && - (*it).right(4) != ".vhd" && - (*it).right(2) != ".v") { - Stream << *it << '\n'; + // output NodeSets, SPICE simulations etc. + for (QStringList::Iterator it = Collect.begin(); it != Collect.end(); ++it) + { + // don't put library includes into netlist... + if ((*it).right(4) != ".lst" && + (*it).right(5) != ".vhdl" && + (*it).right(4) != ".vhd" && + (*it).right(2) != ".v") + { + *netlistStream << *it << '\n'; + } } - } - Stream << '\n'; + *netlistStream << '\n'; - QString SimTime = sch->createNetlist(Stream, SimPorts); - delete(sch); + schematic->createNetlist(*netlistStream, SimPorts); - NetlistFile.close(); + if (netlist2Console) + { + std::cout << std::endl << netlistString->toLatin1().constData() << std::endl; + } - return 0; + return 0; } -int runNgspice(QString schematic, QString dataset) +int runNgspice(QString schematicFileName, QString dataset) { QucsSettings.DefaultSimulator = spicecompat::simNgspice; Module::registerModules(); - Schematic *sch = openSchematic(schematic); - if (sch == NULL) { - return 1; + + QScopedPointer schematic(openSchematic(schematicFileName)); + if (!schematic) + { + return 1; } - Ngspice *ngspice = new Ngspice(sch); + QScopedPointer ngspice(new Ngspice(schematic.get())); ngspice->slotSimulate(); bool ok = ngspice->waitEndOfSimulation(); - if (!ok) { + if (!ok) + { fprintf(stderr, "Ngspice timed out or start error!\n"); - delete ngspice; return -1; - } else { + } + else + { ngspice->convertToQucsData(dataset); } - delete ngspice; return 0; } -int runXyce(QString schematic, QString dataset) +int runXyce(QString schematicFileName, QString dataset) { QucsSettings.DefaultSimulator = spicecompat::simXyce; Module::registerModules(); - Schematic *sch = openSchematic(schematic); - if (sch == NULL) { - return 1; + + QScopedPointer schematic(openSchematic(schematicFileName)); + if (!schematic) + { + return 1; } - Xyce *xyce = new Xyce(sch); + QScopedPointer xyce(new Xyce(schematic.get())); xyce->slotSimulate(); bool ok = xyce->waitEndOfSimulation(); - if (!ok) { + if (!ok) + { fprintf(stderr, "Xyce timed out or start error!\n"); - delete xyce; return -1; - } else { + } + else + { xyce->convertToQucsData(dataset); } - delete xyce; return 0; } -int doNgspiceNetlist(QString schematic, QString netlist) +int doNgspiceNetlist(QString schematicFileName, QString netlistFileName, bool netlist2Console) +{ + QucsSettings.DefaultSimulator = spicecompat::simNgspice; + Module::registerModules(); + + QScopedPointer schematic(openSchematic(schematicFileName)); + if (!schematic) + { + return 1; + } + + QScopedPointer ngspice(new Ngspice(schematic.get())); + ngspice->SaveNetlist(netlistFileName, netlist2Console); + + if (!netlist2Console && !QFile::exists(netlistFileName)) + { + return -1; + } + + return 0; +} + +int doCdlNetlist(QString schematicFileName, QString netlistFileName, bool netlist2Console) { QucsSettings.DefaultSimulator = spicecompat::simNgspice; Module::registerModules(); - Schematic *sch = openSchematic(schematic); - if (sch == NULL) { - return 1; + + QScopedPointer schematic(openSchematic(schematicFileName)); + if (!schematic) + { + return -1; } - Ngspice *ngspice = new Ngspice(sch); - ngspice->SaveNetlist(netlist); - delete ngspice; - if (!QFile::exists(netlist)) return -1; - else return 0; + QScopedPointer netlistStream; + QScopedPointer netlistString; + QScopedPointer cdlFile; + + if (netlist2Console) + { + netlistString.reset(new QString()); + netlistStream.reset(new QTextStream(netlistString.get())); + } + else + { + cdlFile.reset(new QFile(netlistFileName)); + + if (cdlFile->open(QFile::WriteOnly)) + { + netlistStream.reset(new QTextStream(cdlFile.get())); + } + else + { + QString msg = QStringLiteral( + "Tried to save netlist \nto %1\n(could not open for writing!)") + .arg(netlistFileName); + QString finalMsg = QStringLiteral( + "%1\n This could be an error in the QSettings settings file\n" + "(usually in ~/.config/qucs/qucs_s.conf)\n" + "The value for S4Q_workdir (default:/spice4qucs) needs to be writeable!") + .arg(msg); + QMessageBox::critical(nullptr, QStringLiteral("Problem with SaveNetlist"), finalMsg, QMessageBox::Ok); + + return -1; + } + } + + CdlNetlistWriter cdlWriter(*netlistStream, schematic.get()); + if (!cdlWriter.write()) + { + QMessageBox::critical( + nullptr, + QStringLiteral("Save CDL netlist"), + QStringLiteral("Save CDL netlist failed!"), + QMessageBox::Ok); + return -1; + } + + if (netlist2Console) + { + std::cout << std::endl << netlistString->toUtf8().constData() << std::endl; + } + else + { + if (!QFile::exists(netlistFileName)) + { + return -1; + } + } + + return 0; } -int doXyceNetlist(QString schematic, QString netlist) +int doXyceNetlist(QString schematicFileName, QString netlistFileName, bool netlist2Console) { QucsSettings.DefaultSimulator = spicecompat::simXyce; Module::registerModules(); - Schematic *sch = openSchematic(schematic); - if (sch == NULL) { - return 1; + QScopedPointer schematic(openSchematic(schematicFileName)); + + if (!schematic) + { + return 1; } - Xyce *xyce = new Xyce(sch); - xyce->SaveNetlist(netlist); - delete xyce; - if (!QFile::exists(netlist)) return -1; - else return 0; + QScopedPointer xyce(new Xyce(schematic.get())); + xyce->SaveNetlist(netlistFileName, netlist2Console); + + if (!netlist2Console && !QFile::exists(netlistFileName)) + { + return -1; + } + + return 0; } -int doPrint(QString schematic, QString printFile, +int doPrint(QString schematicFileName, QString printFile, QString page, int dpi, QString color, QString orientation) { - QucsSettings.DefaultSimulator = spicecompat::simQucsator; - Schematic *sch = openSchematic(schematic); - if (sch == NULL) { - return 1; - } + QucsSettings.DefaultSimulator = spicecompat::simQucsator; - sch->a_Nodes = &(sch->a_DocNodes); - sch->a_Wires = &(sch->a_DocWires); - sch->a_Diagrams = &(sch->a_DocDiags); - sch->a_Paintings = &(sch->a_DocPaints); - sch->a_Components = &(sch->a_DocComps); - sch->reloadGraphs(); - - qDebug() << "*** try to print file :" << printFile; - - // determine filetype - if (printFile.endsWith(".pdf")) { - //initial printer - PrinterWriter *Printer = new PrinterWriter(); - Printer->setFitToPage(true); - Printer->noGuiPrint(sch, printFile, page, dpi, color, orientation); - } else { - ImageWriter *Printer = new ImageWriter(""); - Printer->noGuiPrint(sch, printFile, color); - } - return 0; + QScopedPointer schematic(openSchematic(schematicFileName)); + if (!schematic) + { + return 1; + } + + schematic->a_Nodes = &(schematic->a_DocNodes); + schematic->a_Wires = &(schematic->a_DocWires); + schematic->a_Diagrams = &(schematic->a_DocDiags); + schematic->a_Paintings = &(schematic->a_DocPaints); + schematic->a_Components = &(schematic->a_DocComps); + schematic->reloadGraphs(); + + qDebug() << "*** try to print file :" << printFile; + + // determine filetype + if (printFile.endsWith(".pdf")) { + //initial printer + PrinterWriter *Printer = new PrinterWriter(); + Printer->setFitToPage(true); + Printer->noGuiPrint(schematic.get(), printFile, page, dpi, color, orientation); + } + else + { + ImageWriter *Printer = new ImageWriter(""); + Printer->noGuiPrint(schematic.get(), printFile, color); + } + + return 0; } /*! @@ -939,6 +1055,7 @@ int main(int argc, char *argv[]) {"i", QCoreApplication::translate("main", "use file as input schematic"), "FILENAME"}, {"o", QCoreApplication::translate("main", "use file as output netlist"), "FILENAME"}, {"ngspice", QCoreApplication::translate("main", "create Ngspice netlist")}, + {"cdl", QCoreApplication::translate("main", "create CDL netlist")}, {"xyce", QCoreApplication::translate("main", "Xyce netlist")}, {"run", QCoreApplication::translate("main", "execute Ngspice/Xyce immediately")}, {"icons", QCoreApplication::translate("main", "create component icons under ./bitmaps_generated")}, @@ -971,7 +1088,7 @@ int main(int argc, char *argv[]) " qucs -n -i FILENAME -o FILENAME\n" " qucs -p -i FILENAME -o FILENAME.[pdf|png|svg|eps]\n")); - QRegularExpression optIndent(QString::fromUtf8("--page|--dpi|--color|--orin|--ngspice|--xyce|--run")); + QRegularExpression optIndent(QString::fromUtf8("--page|--dpi|--color|--orin|--ngspice|--xyce|--run|--cdl")); int idx; int from = 0; while ((idx = helpText.indexOf(optIndent, from)) != -1) @@ -993,6 +1110,7 @@ int main(int argc, char *argv[]) const QString inputfile(parser.value("i")); const QString outputfile(parser.value("o")); const bool ngspice_flag(parser.isSet("ngspice")); + const bool cdl_flag(parser.isSet("cdl")); const bool xyce_flag(parser.isSet("xyce")); const bool run_flag(parser.isSet("run")); const bool netlist2Console(parser.isSet("netlist2Console")); @@ -1008,6 +1126,7 @@ int main(int argc, char *argv[]) std::cout << "inputfile: " << inputfile.toUtf8().constData() << std::endl; std::cout << "outputfile: " << outputfile.toUtf8().constData() << std::endl; std::cout << "ngspice_flag: " << ngspice_flag << std::endl; + std::cout << "cdl_flag: " << cdl_flag << std::endl; std::cout << "xyce_flag: " << xyce_flag << std::endl; std::cout << "run_flag: " << run_flag << std::endl; std::cout << "netlist2Console: " << netlist2Console << std::endl; @@ -1042,9 +1161,14 @@ int main(int argc, char *argv[]) fprintf(stderr, "Error: --print and --netlist cannot be used together\n"); return -1; } - else if (((ngspice_flag || xyce_flag) && print_flag) || (run_flag && print_flag)) + else if (cdl_flag and run_flag) { - fprintf(stderr, "Error: --print and Ngspice/Xyce cannot be used together\n"); + fprintf(stderr, "Error: --cdl and --run cannot be used together\n"); + return -1; + } + else if (((ngspice_flag || xyce_flag || cdl_flag) && print_flag) || (run_flag && print_flag)) + { + fprintf(stderr, "Error: --print and Ngspice/CDL/Xyce cannot be used together\n"); return -1; } else if (netlist_flag or print_flag) @@ -1054,7 +1178,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "Error: Expected input file.\n"); return -1; } - if (outputfile.isEmpty()) + if (!netlist2Console && outputfile.isEmpty()) { fprintf(stderr, "Error: Expected output file.\n"); return -1; @@ -1066,15 +1190,19 @@ int main(int argc, char *argv[]) { if (ngspice_flag) { - return doNgspiceNetlist(inputfile, outputfile); + return doNgspiceNetlist(inputfile, outputfile, netlist2Console); + } + else if (cdl_flag) + { + return doCdlNetlist(inputfile, outputfile, netlist2Console); } else if (xyce_flag) { - return doXyceNetlist(inputfile, outputfile); + return doXyceNetlist(inputfile, outputfile, netlist2Console); } else { - return doNetlist(inputfile, outputfile); + return doNetlist(inputfile, outputfile, netlist2Console); } } else @@ -1095,7 +1223,7 @@ int main(int argc, char *argv[]) } else if (print_flag) { - return doPrint(inputfile, outputfile, page, dpi, color, orientation); + return doPrint(inputfile, outputfile, page, dpi, color, orientation); } } diff --git a/qucs/qucs.cpp b/qucs/qucs.cpp index 476b2cf1..4b1577e5 100644 --- a/qucs/qucs.cpp +++ b/qucs/qucs.cpp @@ -2410,7 +2410,7 @@ void QucsApp::slotTune(bool checked) return; } - Schematic *d = dynamic_cast(w); + Schematic* d(dynamic_cast(w)); assert(d); bool found = false; @@ -3463,57 +3463,83 @@ void QucsApp::slotSimSettings() void QucsApp::slotSimulateWithSpice() { - if (!isTextDocument(DocumentTab->currentWidget())) { - Schematic *sch = (Schematic*)DocumentTab->currentWidget(); - if (TuningMode) { - QFileInfo Info(sch->getDocName()); + if (!isTextDocument(DocumentTab->currentWidget())) + { + Schematic* schematic(dynamic_cast(DocumentTab->currentWidget())); + if (TuningMode) + { + QFileInfo Info(schematic->getDocName()); QString ext = Info.suffix(); - if (ext == "dpl") { - QucsDoc *Doc = (QucsDoc *)sch; - sch = (Schematic *) getSchematicWidget(Doc); - if (sch == nullptr) return; + if (ext == "dpl") + { + QucsDoc *doc(dynamic_cast(schematic)); + Q_ASSERT(doc != nullptr); + schematic = dynamic_cast(getSchematicWidget(doc)); + if (schematic == nullptr) + { + return; + } } } - if (sch->getDocName().isEmpty()) { - auto biasState = sch->getShowBias(); - QMessageBox::warning(this,tr("Simulate schematic"), + if (schematic->getDocName().isEmpty()) + { + auto biasState = schematic->getShowBias(); + QMessageBox::warning( + this, + tr("Simulate schematic"), tr("Schematic not saved! Simulation of unsaved schematic " - "not possible. Save schematic first!")); + "not possible. Save schematic first!")); slotFileSaveAs(); - sch->setShowBias(biasState); + schematic->setShowBias(biasState); + } + ExternSimDialog *SimDlg = new ExternSimDialog(schematic, false); + connect(SimDlg, SIGNAL(simulated(ExternSimDialog*)), this, SLOT(slotAfterSpiceSimulation(ExternSimDialog*))); + connect(SimDlg, SIGNAL(warnings()), this, SLOT(slotShowWarnings())); + connect(SimDlg, SIGNAL(success()), this, SLOT(slotResetWarnings())); + + if (TuningMode || schematic->getShowBias() == 0) + { + SimDlg->slotStart(); + } + else + { + SimDlg->exec(); } - ExternSimDialog *SimDlg = new ExternSimDialog(sch); - connect(SimDlg,SIGNAL(simulated(ExternSimDialog*)), - this,SLOT(slotAfterSpiceSimulation(ExternSimDialog*))); - connect(SimDlg,SIGNAL(warnings()),this,SLOT(slotShowWarnings())); - connect(SimDlg,SIGNAL(success()),this,SLOT(slotResetWarnings())); - if (TuningMode || sch->getShowBias() == 0) SimDlg->slotStart(); - else SimDlg->exec(); - /*disconnect(SimDlg,SIGNAL(simulated()),this,SLOT(slotAfterSpiceSimulation())); - disconnect(SimDlg,SIGNAL(warnings()),this,SLOT(slotShowWarnings())); - disconnect(SimDlg,SIGNAL(success()),this,SLOT(slotResetWarnings()));*/ - /*if (SimDlg->wasSimulated && sch->getSimOpenDpl()) - if (sch->getShowBias() < 1) slotChangePage(sch->getDocName(),sch->getDataDisplay()); + /*disconnect(SimDlg, SIGNAL(simulated()), this, SLOT(slotAfterSpiceSimulation())); + disconnect(SimDlg, SIGNAL(warnings()), this, SLOT(slotShowWarnings())); + disconnect(SimDlg, SIGNAL(success()), this, SLOT(slotResetWarnings()));*/ + /*if (SimDlg->wasSimulated && schematic->getSimOpenDpl()) + if (schematic->getShowBias() < 1) slotChangePage(schematic->getDocName(), schematic->getDataDisplay()); delete SimDlg;*/ - } else { - QMessageBox::warning(this,tr("Simulate schematic"), - tr("Simulation of text document is not possible!")); + } + else + { + QMessageBox::warning( + this, + tr("Simulate schematic"), + tr("Simulation of text document is not possible!")); } } void QucsApp::slotSaveNetlist() { - if (QucsSettings.DefaultSimulator == spicecompat::simQucsator) { - QMessageBox::information(this,tr("Save netlist"), - tr("This action is supported only for SPICE simulators!")); + if (QucsSettings.DefaultSimulator == spicecompat::simQucsator) + { + QMessageBox::information( + this, + tr("Save netlist"), + tr("This action is supported only for SPICE simulators!")); return; } - if (!isTextDocument(DocumentTab->currentWidget())) { - Schematic *sch = (Schematic*)DocumentTab->currentWidget(); - ExternSimDialog *SimDlg = new ExternSimDialog(sch, true); - SimDlg->slotSaveNetlist(); - delete SimDlg; + + if (!isTextDocument(DocumentTab->currentWidget())) + { + Schematic* schematic(dynamic_cast(DocumentTab->currentWidget())); + Q_ASSERT(schematic != nullptr); + + ExternSimDialog simDlg(schematic, a_netlist2Console, true); + simDlg.slotSaveNetlist(); } } diff --git a/qucs/qucs_init.cpp b/qucs/qucs_init.cpp index d90e638c..161894dd 100644 --- a/qucs/qucs_init.cpp +++ b/qucs/qucs_init.cpp @@ -574,12 +574,12 @@ void QucsApp::initActions() save_netlist = new QAction(tr("Save netlist"), this); save_netlist->setStatusTip(tr("Save netlist")); - save_netlist->setWhatsThis(tr("Save netlist to file")); + save_netlist->setWhatsThis(tr(QString::fromUtf8("Save netlist to %1").arg(a_netlist2Console ? "console" : "file").toLatin1().constData())); connect(save_netlist, SIGNAL(triggered()), SLOT(slotSaveNetlist())); saveCdlNetlist = new QAction(tr("Save CDL netlist"), this); saveCdlNetlist->setStatusTip(tr("Save CDL netlist")); - saveCdlNetlist->setWhatsThis(tr("Save CDL netlist to file")); + saveCdlNetlist->setWhatsThis(tr(QString::fromUtf8("Save CDL netlist to %1").arg(a_netlist2Console ? "console" : "file").toLatin1().constData())); connect(saveCdlNetlist, SIGNAL(triggered()), SLOT(slotSaveCdlNetlist())); setMarker = new QAction(QIcon((":/bitmaps/svg/marker.svg")), tr("Set Marker on Graph"), this);