Merge pull request #1201 from ThomasZecha/current

Introduce optional netlisting to console
This commit is contained in:
Vadim Kuznetsov 2025-02-04 13:08:12 +03:00 committed by GitHub
commit 75040f363d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 897 additions and 610 deletions

View File

@ -828,7 +828,7 @@ QString Component::getVerilogACode() {
} }
} }
QString Component::getExpression(bool, bool) { QString Component::getExpression(spicecompat::SpiceDialect) {
return QString(); return QString();
} }
@ -840,7 +840,7 @@ QStringList Component::getExtraVariables() {
return QStringList(); return QStringList();
} }
QString Component::getProbeVariable(bool) { QString Component::getProbeVariable(spicecompat::SpiceDialect) {
return QString(); return QString();
} }

View File

@ -44,10 +44,10 @@ public:
QString getNetlist(); QString getNetlist();
QString getSpiceNetlist(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault); QString getSpiceNetlist(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
QString getVerilogACode(); QString getVerilogACode();
virtual QString getExpression(bool isXyce = false, bool isCdl = false); virtual QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
virtual QString getEquations(QString sim, QStringList &dep_vars); virtual QString getEquations(QString sim, QStringList &dep_vars);
virtual QStringList getExtraVariables(); virtual QStringList getExtraVariables();
virtual QString getProbeVariable(bool isXyce = false); virtual QString getProbeVariable(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
virtual QString getSpiceModel(); virtual QString getSpiceModel();
virtual QString getSpiceLibrary() { return QString(); } virtual QString getSpiceLibrary() { return QString(); }
virtual QStringList getSpiceLibraryFiles() { return QStringList(); } virtual QStringList getSpiceLibraryFiles() { return QStringList(); }

View File

@ -119,14 +119,11 @@ QString Equation::getVAExpressions()
/*! /*!
* \brief Equation::getExpression Extract equations that don't contain simulation variables * \brief Equation::getExpression Extract equations that don't contain simulation variables
* (voltages/cureents) in .PARAM section of spice netlist * (voltages/cureents) in .PARAM section of spice netlist
* \param isXyce True if Xyce is used. * \param dialect Which spice-dialect is used.
* \param isCdl True if CDL is used.
* \return .PARAM section of spice netlist as a single string. * \return .PARAM section of spice netlist as a single string.
*/ */
QString Equation::getExpression(bool isXyce, bool isCdl /* = false */) QString Equation::getExpression(spicecompat::SpiceDialect dialect /* = spicecompat::SPICEDefault */)
{ {
Q_UNUSED(isCdl);
if (isActive != COMP_IS_ACTIVE) return QString(); if (isActive != COMP_IS_ACTIVE) return QString();
QStringList ng_vars,ngsims; QStringList ng_vars,ngsims;
@ -145,9 +142,9 @@ QString Equation::getExpression(bool isXyce, bool isCdl /* = false */)
QStringList tokens; QStringList tokens;
QString eqn = Props.at(i)->Value; QString eqn = Props.at(i)->Value;
spicecompat::splitEqn(eqn,tokens); spicecompat::splitEqn(eqn,tokens);
spicecompat::convert_functions(tokens,isXyce); spicecompat::convert_functions(tokens, dialect == spicecompat::SPICEXyce);
eqn = tokens.join(""); eqn = tokens.join("");
if (isXyce) { if (dialect == spicecompat::SPICEXyce) {
eqn.replace("^","**"); eqn.replace("^","**");
if (!(fp_pattern.match(eqn).hasMatch()|| if (!(fp_pattern.match(eqn).hasMatch()||

View File

@ -28,7 +28,7 @@ public:
~Equation(); ~Equation();
Component* newOne(); Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false); static Element* info(QString&, char* &, bool getNewOne=false);
QString getExpression(bool isXyce, bool isCdl = false); QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
QString getEquations(QString sim, QStringList &dep_vars); QString getEquations(QString sim, QStringList &dep_vars);
QString getVAvariables(); QString getVAvariables();
QString getVAExpressions(); QString getVAExpressions();

View File

@ -90,13 +90,13 @@ QString iProbe::spice_netlist(spicecompat::SpiceDialect dialect /* = spicecompat
/*! /*!
* \brief iProbe::getProbeVariable Get current probe variable * \brief iProbe::getProbeVariable Get current probe variable
* \param isXyce True if Xyce simulator * \param dialect Spice dialect used
* \return Current probe variable in Ngspice or Xyce notation * \return Current probe variable in Ngspice or Xyce notation
*/ */
QString iProbe::getProbeVariable(bool isXyce) QString iProbe::getProbeVariable(spicecompat::SpiceDialect dialect)
{ {
QString s; QString s;
if (isXyce) { if (dialect == spicecompat::SPICEXyce) {
s = QStringLiteral("I(V%1)").arg(Name); s = QStringLiteral("I(V%1)").arg(Name);
} else { } else {
s = QStringLiteral("V%1#branch").arg(Name); s = QStringLiteral("V%1#branch").arg(Name);

View File

@ -27,8 +27,8 @@ public:
~iProbe(); ~iProbe();
Component* newOne(); Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false); static Element* info(QString&, char* &, bool getNewOne=false);
QString getExpression(bool, bool) { return "";} QString getExpression(spicecompat::SpiceDialect) { return "";}
QString getProbeVariable(bool isXyce = false); QString getProbeVariable(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
protected: protected:
QString spice_netlist(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault); QString spice_netlist(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);

View File

@ -73,7 +73,7 @@ Element* vProbe::info(QString& Name, char* &BitmapFile, bool getNewOne)
return 0; return 0;
} }
QString vProbe::getProbeVariable(bool) QString vProbe::getProbeVariable(spicecompat::SpiceDialect)
{ {
return Name; return Name;
} }

View File

@ -27,7 +27,7 @@ public:
~vProbe(); ~vProbe();
Component* newOne(); Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false); static Element* info(QString&, char* &, bool getNewOne=false);
QString getProbeVariable(bool isXyce = false); QString getProbeVariable(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
protected: protected:
QString spice_netlist(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault); QString spice_netlist(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
}; };

View File

@ -149,7 +149,7 @@ void CdlNetlistWriter::startNetlist()
{ {
if (pc->isEquation) if (pc->isEquation)
{ {
s = pc->getExpression(false, true); s = pc->getExpression(spicecompat::CDL);
a_netlistStream << s; a_netlistStream << s;
} }
} }

View File

@ -25,7 +25,7 @@
#include "main.h" #include "main.h"
#include "qucs.h" #include "qucs.h"
ExternSimDialog::ExternSimDialog(Schematic *sch, bool netlist_mode) : ExternSimDialog::ExternSimDialog(Schematic* sch, bool netlist2Console, bool netlist_mode) :
QDialog(sch), QDialog(sch),
a_schematic(sch), a_schematic(sch),
a_buttonStopSim(new QPushButton(tr("Stop"),this)), 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_ngspice(new Ngspice(sch,this)),
a_xyce(new Xyce(sch,this)), a_xyce(new Xyce(sch,this)),
a_wasSimulated(true), a_wasSimulated(true),
a_hasError(false) a_hasError(false),
a_netlist2Console(netlist2Console)
{ {
const QString workdir(QucsSettings.S4Qworkdir); const QString workdir(QucsSettings.S4Qworkdir);
@ -296,27 +297,40 @@ void ExternSimDialog::slotStop()
void ExternSimDialog::slotSaveNetlist() void ExternSimDialog::slotSaveNetlist()
{ {
QFileInfo inf(a_schematic->getDocName()); QFileInfo inf(a_schematic->getDocName());
QString filename = QFileDialog::getSaveFileName(this,tr("Save netlist"),inf.path()+QDir::separator()+"netlist.cir", QString filename;
"All files (*)");
if (filename.isEmpty()) return;
switch (QucsSettings.DefaultSimulator) { 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)
{
case spicecompat::simNgspice: case spicecompat::simNgspice:
case spicecompat::simSpiceOpus: { case spicecompat::simSpiceOpus:
a_ngspice->SaveNetlist(filename); a_ngspice->SaveNetlist(filename, a_netlist2Console);
}
break; break;
case spicecompat::simXyce: { case spicecompat::simXyce:
a_xyce->SaveNetlist(filename); a_xyce->SaveNetlist(filename, a_netlist2Console);
}
break; break;
default: default:
break; break;
} }
if (!QFile::exists(filename)) { if (!a_netlist2Console && !QFile::exists(filename))
QMessageBox::critical(0, QObject::tr("Save netlist"), {
QObject::tr("Disk write error!"), QMessageBox::Ok); QMessageBox::critical(
nullptr,
QObject::tr("Save netlist"),
QObject::tr("Disk write error!"), QMessageBox::Ok);
} }
} }

View File

@ -30,7 +30,7 @@ class ExternSimDialog : public QDialog
Q_OBJECT Q_OBJECT
private: private:
Schematic *a_schematic; Schematic* a_schematic;
QPushButton *a_buttonStopSim; QPushButton *a_buttonStopSim;
QPushButton *a_buttonSaveNetlist; QPushButton *a_buttonSaveNetlist;
@ -46,10 +46,13 @@ private:
bool a_wasSimulated; bool a_wasSimulated;
bool a_hasError; bool a_hasError;
bool a_netlist2Console;
public: public:
explicit ExternSimDialog(Schematic *sch, explicit ExternSimDialog(
bool netlist_mode = false); Schematic* sch,
bool netlist2Console,
bool netlist_mode = false);
~ExternSimDialog(); ~ExternSimDialog();
bool wasSimulated() const { return a_wasSimulated; } bool wasSimulated() const { return a_wasSimulated; }

View File

@ -33,6 +33,10 @@
#include "config.h" #include "config.h"
#endif #endif
#include <QScopedPointer>
#include <iostream>
/*! /*!
\file ngspice.cpp \file ngspice.cpp
\brief Implementation of the Ngspice class \brief Implementation of the Ngspice class
@ -43,7 +47,7 @@
* \param schematic Schematic that need to be simulated with Ngspice. * \param schematic Schematic that need to be simulated with Ngspice.
* \param parent Parent object * \param parent Parent object
*/ */
Ngspice::Ngspice(Schematic *schematic, QObject *parent) : Ngspice::Ngspice(Schematic* schematic, QObject *parent) :
AbstractSpiceKernel(schematic, parent), AbstractSpiceKernel(schematic, parent),
a_spinit_name() 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] vars The list of output variables and node names.
* \param[out] outputs The list of spice output raw text files. * \param[out] outputs The list of spice output raw text files.
*/ */
void Ngspice::createNetlist(QTextStream &stream, int , void Ngspice::createNetlist(
QStringList &simulations, QStringList &vars, QStringList &outputs) QTextStream& stream,
QStringList& simulations,
QStringList& vars,
QStringList& outputs)
{ {
Q_UNUSED(simulations); Q_UNUSED(simulations);
@ -464,7 +471,7 @@ void Ngspice::slotSimulate()
QString netfile = "spice4qucs.cir"; QString netfile = "spice4qucs.cir";
QString tmp_path = QDir::toNativeSeparators(a_workdir+QDir::separator()+netfile); QString tmp_path = QDir::toNativeSeparators(a_workdir+QDir::separator()+netfile);
SaveNetlist(tmp_path); SaveNetlist(tmp_path, false);
removeAllSimulatorOutputs(); removeAllSimulatorOutputs();
@ -583,24 +590,43 @@ void Ngspice::slotProcessOutput()
* \brief Ngspice::SaveNetlist Create netlist and save it to file without execution * \brief Ngspice::SaveNetlist Create netlist and save it to file without execution
* of simulator. * of simulator.
* \param[in] filename Absolute path to netlist * \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_sims.clear();
a_vars.clear(); a_vars.clear();
QFile spice_file(filename); QScopedPointer<QString> netlistString;
if (spice_file.open(QFile::WriteOnly)) { QScopedPointer<QTextStream> netlistStream;
QTextStream stream(&spice_file); QScopedPointer<QFile> netlistFile;
createNetlist(stream,num,a_sims,a_vars,a_output_files);
spice_file.close(); if (netlist2Console)
{
netlistString.reset(new QString);
netlistStream.reset(new QTextStream(netlistString.get()));
} }
else else
{ {
QString msg=QStringLiteral("Tried to save netlist \nin %1\n(could not open for writing!)").arg(filename); netlistFile.reset(new QFile(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); if (netlistFile->open(QFile::WriteOnly))
QMessageBox::critical(nullptr,tr("Problem with SaveNetlist"),final_msg,QMessageBox::Ok); {
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;
} }
} }

View File

@ -41,7 +41,7 @@ private:
QString a_spinit_name; QString a_spinit_name;
bool checkNodeNames(QStringList &incompat); bool checkNodeNames(QStringList &incompat);
static QString collectSpiceinit(Schematic *sch); static QString collectSpiceinit(Schematic* sch);
bool findMathFuncInc(QString &mathf_inc); bool findMathFuncInc(QString &mathf_inc);
QString getParentSWPscript(Component *pc_swp, QString sim, bool before, bool &hasDblSWP); QString getParentSWPscript(Component *pc_swp, QString sim, bool before, bool &hasDblSWP);
QString getParentSWPCntVar(Component *pc_swp, QString sim); QString getParentSWPCntVar(Component *pc_swp, QString sim);
@ -49,14 +49,17 @@ private:
void createSpiceinit(const QString &initial_spiceinit); void createSpiceinit(const QString &initial_spiceinit);
public: public:
explicit Ngspice(Schematic *schematic, QObject *parent = 0); explicit Ngspice(Schematic* schematic, QObject *parent = 0);
void SaveNetlist(QString filename); void SaveNetlist(QString filename, bool netlist2Console);
void setSimulatorCmd(QString cmd); void setSimulatorCmd(QString cmd);
void setSimulatorParameters(QString parameters); void setSimulatorParameters(QString parameters);
protected: protected:
void createNetlist(QTextStream &stream, int NumPorts, QStringList &simulations, void createNetlist(
QStringList &vars, QStringList &outputs); QTextStream& stream,
QStringList& simulations,
QStringList& vars,
QStringList& outputs);
public slots: public slots:
void slotSimulate(); void slotSimulate();

View File

@ -25,6 +25,10 @@
#include "config.h" #include "config.h"
#endif #endif
#include <QScopedPointer>
#include <iostream>
/*! /*!
\file xyce.cpp \file xyce.cpp
\brief Implementation of the Xyce class \brief Implementation of the Xyce class
@ -35,7 +39,7 @@
* \param schematic Schematic that need to be simulated with Ngspice. * \param schematic Schematic that need to be simulated with Ngspice.
* \param parent Parent object * \param parent Parent object
*/ */
Xyce::Xyce(Schematic *schematic, QObject *parent) : Xyce::Xyce(Schematic* schematic, QObject *parent) :
AbstractSpiceKernel(schematic, parent), AbstractSpiceKernel(schematic, parent),
a_Noisesim(false), a_Noisesim(false),
a_simulationsQueue(), 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] vars The list of output variables and node names.
* \param[out] outputs The list of spice output raw text files. * \param[out] outputs The list of spice output raw text files.
*/ */
void Xyce::createNetlist(QTextStream &stream, int , QStringList &simulations, void Xyce::createNetlist(
QStringList &vars, QStringList &outputs) QTextStream& stream,
QStringList& simulations,
QStringList& vars,
QStringList& outputs)
{ {
QString s; QString s;
bool hasParSweep = false; bool hasParSweep = false;
@ -110,7 +117,7 @@ void Xyce::createNetlist(QTextStream &stream, int , QStringList &simulations,
} }
for(Component *pc = a_schematic->a_DocComps.first(); pc != 0; pc = a_schematic->a_DocComps.next()) { for(Component *pc = a_schematic->a_DocComps.first(); pc != 0; pc = a_schematic->a_DocComps.next()) {
if (pc->isProbe) { if (pc->isProbe) {
QString var_pr = pc->getProbeVariable(true); QString var_pr = pc->getProbeVariable(spicecompat::SPICEXyce);
if (!vars.contains(var_pr)) { if (!vars.contains(var_pr)) {
vars.append(var_pr); vars.append(var_pr);
} }
@ -312,7 +319,6 @@ void Xyce::slotSimulate()
return; return;
} }
int num=0;
a_netlistQueue.clear(); a_netlistQueue.clear();
a_output_files.clear(); a_output_files.clear();
@ -332,7 +338,7 @@ void Xyce::slotSimulate()
QFile spice_file(tmp_path); QFile spice_file(tmp_path);
if (spice_file.open(QFile::WriteOnly)) { if (spice_file.open(QFile::WriteOnly)) {
QTextStream stream(&spice_file); 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(); spice_file.close();
} }
} }
@ -347,16 +353,36 @@ void Xyce::slotSimulate()
* \brief Xyce::SaveNetlist Save netlist into specified file without * \brief Xyce::SaveNetlist Save netlist into specified file without
* execution of simulator. * execution of simulator.
* \param[in] filename The name of file in which netlist is saved * \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(); determineUsedSimulations();
int num = 0;
QFile spice_file(filename); QScopedPointer<QString> netlistString;
if (spice_file.open(QFile::WriteOnly)) { QScopedPointer<QTextStream> netlistStream;
QTextStream stream(&spice_file); QScopedPointer<QFile> netlistFile;
createNetlist(stream,num,a_simulationsQueue,a_vars,a_output_files);
spice_file.close(); 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;
} }
} }

View File

@ -46,15 +46,19 @@ private:
public: public:
void determineUsedSimulations(QStringList *sim_lst = NULL); 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); void setParallel(bool par);
bool waitEndOfSimulation(); bool waitEndOfSimulation();
protected: protected:
void createNetlist(QTextStream &stream, int NumPorts, QStringList &simulations, void createNetlist(
QStringList &vars, QStringList &outputs); QTextStream& stream,
QStringList& simulations,
QStringList& vars,
QStringList& outputs);
protected slots: protected slots:
void slotFinished(); void slotFinished();
void slotProcessOutput(); void slotProcessOutput();

File diff suppressed because it is too large Load Diff

View File

@ -88,9 +88,9 @@
//#include "extsimkernels/codemodelgen.h" //#include "extsimkernels/codemodelgen.h"
#include "symbolwidget.h" #include "symbolwidget.h"
QucsApp::QucsApp() QucsApp::QucsApp(bool netlist2Console) :
a_netlist2Console(netlist2Console)
{ {
windowTitle = misc::getWindowTitle(); windowTitle = misc::getWindowTitle();
setWindowTitle(windowTitle); setWindowTitle(windowTitle);
@ -575,11 +575,11 @@ void QucsApp::initView()
messageDock = new MessageDock(this); messageDock = new MessageDock(this);
// initial projects directory model // initial projects directory model
m_homeDirModel = new QucsFileSystemModel(this); a_homeDirModel = new QucsFileSystemModel(this);
m_proxyModel = new QucsSortFilterProxyModel(); a_proxyModel = new QucsSortFilterProxyModel();
//m_proxyModel->setDynamicSortFilter(true); //a_proxyModel->setDynamicSortFilter(true);
// show all directories (project and non-project) // show all directories (project and non-project)
m_homeDirModel->setFilter(QDir::NoDot | QDir::AllDirs); a_homeDirModel->setFilter(QDir::NoDot | QDir::AllDirs);
// ............................................ // ............................................
QString path = QucsSettings.qucsWorkspaceDir.absolutePath(); QString path = QucsSettings.qucsWorkspaceDir.absolutePath();
@ -1386,21 +1386,21 @@ void QucsApp::readProjects()
if (path == homepath) { if (path == homepath) {
// in Qucs Home, disallow further up in the dirs tree // in Qucs Home, disallow further up in the dirs tree
m_homeDirModel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs); a_homeDirModel->setFilter(QDir::NoDotAndDotDot | QDir::AllDirs);
} else { } else {
m_homeDirModel->setFilter(QDir::NoDot | QDir::AllDirs); a_homeDirModel->setFilter(QDir::NoDot | QDir::AllDirs);
} }
// set the root path // set the root path
QModelIndex rootModelIndex = m_homeDirModel->setRootPath(path); QModelIndex rootModelIndex = a_homeDirModel->setRootPath(path);
// assign the model to the proxy and the proxy to the view // assign the model to the proxy and the proxy to the view
m_proxyModel->setSourceModel(m_homeDirModel); a_proxyModel->setSourceModel(a_homeDirModel);
m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive); a_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
// sort by first column (file name, only column show in the QListView) // sort by first column (file name, only column show in the QListView)
m_proxyModel->sort(0); a_proxyModel->sort(0);
Projects->setModel(m_proxyModel); Projects->setModel(a_proxyModel);
// fix the listview on the root path of the model // fix the listview on the root path of the model
Projects->setRootIndex(m_proxyModel->mapFromSource(rootModelIndex)); Projects->setRootIndex(a_proxyModel->mapFromSource(rootModelIndex));
} }
// ---------------------------------------------------------- // ----------------------------------------------------------
@ -2410,7 +2410,7 @@ void QucsApp::slotTune(bool checked)
return; return;
} }
Schematic *d = dynamic_cast<Schematic*>(w); Schematic* d(dynamic_cast<Schematic*>(w));
assert(d); assert(d);
bool found = false; bool found = false;
@ -3463,57 +3463,83 @@ void QucsApp::slotSimSettings()
void QucsApp::slotSimulateWithSpice() void QucsApp::slotSimulateWithSpice()
{ {
if (!isTextDocument(DocumentTab->currentWidget())) { if (!isTextDocument(DocumentTab->currentWidget()))
Schematic *sch = (Schematic*)DocumentTab->currentWidget(); {
if (TuningMode) { Schematic* schematic(dynamic_cast<Schematic*>(DocumentTab->currentWidget()));
QFileInfo Info(sch->getDocName()); if (TuningMode)
{
QFileInfo Info(schematic->getDocName());
QString ext = Info.suffix(); QString ext = Info.suffix();
if (ext == "dpl") { if (ext == "dpl")
QucsDoc *Doc = (QucsDoc *)sch; {
sch = (Schematic *) getSchematicWidget(Doc); QucsDoc *doc(dynamic_cast<QucsDoc*>(schematic));
if (sch == nullptr) return; Q_ASSERT(doc != nullptr);
schematic = dynamic_cast<Schematic*>(getSchematicWidget(doc));
if (schematic == nullptr)
{
return;
}
} }
} }
if (sch->getDocName().isEmpty()) { if (schematic->getDocName().isEmpty())
auto biasState = sch->getShowBias(); {
QMessageBox::warning(this,tr("Simulate schematic"), auto biasState = schematic->getShowBias();
QMessageBox::warning(
this,
tr("Simulate schematic"),
tr("Schematic not saved! Simulation of unsaved schematic " tr("Schematic not saved! Simulation of unsaved schematic "
"not possible. Save schematic first!")); "not possible. Save schematic first!"));
slotFileSaveAs(); slotFileSaveAs();
sch->setShowBias(biasState); schematic->setShowBias(biasState);
} }
ExternSimDialog *SimDlg = new ExternSimDialog(sch); ExternSimDialog *SimDlg = new ExternSimDialog(schematic, false);
connect(SimDlg,SIGNAL(simulated(ExternSimDialog*)), connect(SimDlg, SIGNAL(simulated(ExternSimDialog*)), this, SLOT(slotAfterSpiceSimulation(ExternSimDialog*)));
this,SLOT(slotAfterSpiceSimulation(ExternSimDialog*))); connect(SimDlg, SIGNAL(warnings()), this, SLOT(slotShowWarnings()));
connect(SimDlg,SIGNAL(warnings()),this,SLOT(slotShowWarnings())); connect(SimDlg, SIGNAL(success()), this, SLOT(slotResetWarnings()));
connect(SimDlg,SIGNAL(success()),this,SLOT(slotResetWarnings()));
if (TuningMode || sch->getShowBias() == 0) SimDlg->slotStart(); if (TuningMode || schematic->getShowBias() == 0)
else SimDlg->exec(); {
/*disconnect(SimDlg,SIGNAL(simulated()),this,SLOT(slotAfterSpiceSimulation())); SimDlg->slotStart();
disconnect(SimDlg,SIGNAL(warnings()),this,SLOT(slotShowWarnings())); }
disconnect(SimDlg,SIGNAL(success()),this,SLOT(slotResetWarnings()));*/ else
/*if (SimDlg->wasSimulated && sch->getSimOpenDpl()) {
if (sch->getShowBias() < 1) slotChangePage(sch->getDocName(),sch->getDataDisplay()); 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 && schematic->getSimOpenDpl())
if (schematic->getShowBias() < 1) slotChangePage(schematic->getDocName(), schematic->getDataDisplay());
delete SimDlg;*/ delete SimDlg;*/
} else { }
QMessageBox::warning(this,tr("Simulate schematic"), else
tr("Simulation of text document is not possible!")); {
QMessageBox::warning(
this,
tr("Simulate schematic"),
tr("Simulation of text document is not possible!"));
} }
} }
void QucsApp::slotSaveNetlist() void QucsApp::slotSaveNetlist()
{ {
if (QucsSettings.DefaultSimulator == spicecompat::simQucsator) { if (QucsSettings.DefaultSimulator == spicecompat::simQucsator)
QMessageBox::information(this,tr("Save netlist"), {
tr("This action is supported only for SPICE simulators!")); QMessageBox::information(
this,
tr("Save netlist"),
tr("This action is supported only for SPICE simulators!"));
return; return;
} }
if (!isTextDocument(DocumentTab->currentWidget())) {
Schematic *sch = (Schematic*)DocumentTab->currentWidget(); if (!isTextDocument(DocumentTab->currentWidget()))
ExternSimDialog *SimDlg = new ExternSimDialog(sch, true); {
SimDlg->slotSaveNetlist(); Schematic* schematic(dynamic_cast<Schematic*>(DocumentTab->currentWidget()));
delete SimDlg; Q_ASSERT(schematic != nullptr);
ExternSimDialog simDlg(schematic, a_netlist2Console, true);
simDlg.slotSaveNetlist();
} }
} }
@ -3524,53 +3550,55 @@ void QucsApp::slotSaveCdlNetlist()
Schematic* schematic = dynamic_cast<Schematic*>(DocumentTab->currentWidget()); Schematic* schematic = dynamic_cast<Schematic*>(DocumentTab->currentWidget());
Q_ASSERT(schematic != nullptr); Q_ASSERT(schematic != nullptr);
#ifdef NETLIST_CDL_TO_CONSOLE // for fast testing purposes if (a_netlist2Console)
QString netlistString;
{ {
QTextStream netlistStream(&netlistString); QString netlistString;
CdlNetlistWriter cdlWriter(netlistStream, schematic);
if (!cdlWriter.write())
{ {
QMessageBox::critical( QTextStream netlistStream(&netlistString);
this, CdlNetlistWriter cdlWriter(netlistStream, schematic);
tr("Save CDL netlist"), if (!cdlWriter.write())
tr("Save CDL netlist failed!"), {
QMessageBox::Ok); QMessageBox::critical(
this,
tr("Save CDL netlist"),
tr("Save CDL netlist failed!"),
QMessageBox::Ok);
}
printf("\nCDL netlist:\n%s\n", netlistString.toUtf8().constData());
Content->refresh();
} }
printf("\nCDL netlist:\n%s\n", netlistString.toUtf8().constData());
Content->refresh();
} }
#else else
QFileInfo inf(schematic->getDocName());
QString filename = QFileDialog::getSaveFileName(
this,
tr("Save CDL netlist"),
inf.path() + QDir::separator() + "netlist.cdl",
"CDL netlist (*.cdl)");
if (filename.isEmpty())
{ {
return; QFileInfo inf(schematic->getDocName());
} QString filename = QFileDialog::getSaveFileName(
this,
tr("Save CDL netlist"),
inf.path() + QDir::separator() + "netlist.cdl",
"CDL netlist (*.cdl)");
QFile netlistFile(filename); if (filename.isEmpty())
if (netlistFile.open(QIODevice::WriteOnly))
{
QTextStream netlistStream(&netlistFile);
CdlNetlistWriter cdlWriter(netlistStream, schematic);
if (!cdlWriter.write())
{ {
QMessageBox::critical( return;
this,
tr("Save CDL netlist"),
tr("Save CDL netlist failed!"),
QMessageBox::Ok);
} }
netlistFile.close();
Content->refresh();
}
#endif
QFile netlistFile(filename);
if (netlistFile.open(QIODevice::WriteOnly))
{
QTextStream netlistStream(&netlistFile);
CdlNetlistWriter cdlWriter(netlistStream, schematic);
if (!cdlWriter.write())
{
QMessageBox::critical(
this,
tr("Save CDL netlist"),
tr("Save CDL netlist failed!"),
QMessageBox::Ok);
}
netlistFile.close();
Content->refresh();
}
}
} }
} }

View File

@ -88,7 +88,7 @@ protected:
class QucsApp : public QMainWindow { class QucsApp : public QMainWindow {
Q_OBJECT Q_OBJECT
public: public:
QucsApp(); QucsApp(bool netlist2Console);
~QucsApp(); ~QucsApp();
bool closeAllFiles(); bool closeAllFiles();
bool gotoPage(const QString&); // to load a document bool gotoPage(const QString&); // to load a document
@ -251,10 +251,10 @@ private:
// ********** Properties ************************************************ // ********** Properties ************************************************
QStack<QString> HierarchyHistory; // keeps track of "go into subcircuit" QStack<QString> HierarchyHistory; // keeps track of "go into subcircuit"
QString QucsFileFilter; QString QucsFileFilter;
QFileSystemModel *m_homeDirModel; QFileSystemModel *a_homeDirModel;
QucsSortFilterProxyModel *m_proxyModel; QucsSortFilterProxyModel *a_proxyModel;
QFileSystemModel *m_projModel;
int ccCurIdx; // CompChooser current index (used during search) int ccCurIdx; // CompChooser current index (used during search)
bool a_netlist2Console;
// ********** Methods *************************************************** // ********** Methods ***************************************************
void initView(); void initView();

View File

@ -574,12 +574,12 @@ void QucsApp::initActions()
save_netlist = new QAction(tr("Save netlist"), this); save_netlist = new QAction(tr("Save netlist"), this);
save_netlist->setStatusTip(tr("Save netlist")); 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())); connect(save_netlist, SIGNAL(triggered()), SLOT(slotSaveNetlist()));
saveCdlNetlist = new QAction(tr("Save CDL netlist"), this); saveCdlNetlist = new QAction(tr("Save CDL netlist"), this);
saveCdlNetlist->setStatusTip(tr("Save CDL netlist")); 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())); connect(saveCdlNetlist, SIGNAL(triggered()), SLOT(slotSaveCdlNetlist()));
setMarker = new QAction(QIcon((":/bitmaps/svg/marker.svg")), tr("Set Marker on Graph"), this); setMarker = new QAction(QIcon((":/bitmaps/svg/marker.svg")), tr("Set Marker on Graph"), this);

View File

@ -77,9 +77,9 @@ Element* InclScript::info(QString& Name, char* &BitmapFile, bool getNewOne)
return 0; return 0;
} }
QString InclScript::getExpression(bool, bool isCdl /* = false */) QString InclScript::getExpression(spicecompat::SpiceDialect dialect /* = spicecompat::SPICEDefault */)
{ {
if (isActive != COMP_IS_ACTIVE || isCdl) if (isActive != COMP_IS_ACTIVE || dialect == spicecompat::CDL)
return QString(); return QString();
return Props.at(0)->Value+"\n"; return Props.at(0)->Value+"\n";
} }

View File

@ -27,7 +27,7 @@ public:
~InclScript(); ~InclScript();
Component* newOne(); Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false); static Element* info(QString&, char* &, bool getNewOne=false);
QString getExpression(bool isXyce, bool isCdl = false); QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
protected: protected:
QString vhdlCode(int) { return QString(); } QString vhdlCode(int) { return QString(); }

View File

@ -69,8 +69,10 @@ Element* SpiceCSParam::info(QString& Name, char* &BitmapFile, bool getNewOne)
return 0; return 0;
} }
QString SpiceCSParam::getExpression(bool) QString SpiceCSParam::getExpression(spicecompat::SpiceDialect dialect /* = spicecompat::SPICEDefault */)
{ {
Q_UNUSED(dialect);
if (isActive != COMP_IS_ACTIVE) return QString(); if (isActive != COMP_IS_ACTIVE) return QString();
QString s; QString s;

View File

@ -29,7 +29,7 @@ public:
Component* newOne(); Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false); static Element* info(QString&, char* &, bool getNewOne=false);
static void splitEqn(QString &eqn, QStringList &tokens); static void splitEqn(QString &eqn, QStringList &tokens);
QString getExpression(bool isXyce = false); QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
protected: protected:
QString netlist() { return QString(); } QString netlist() { return QString(); }

View File

@ -70,9 +70,9 @@ Element* SpiceFunc::info(QString& Name, char* &BitmapFile, bool getNewOne)
return 0; return 0;
} }
QString SpiceFunc::getExpression(bool, bool isCdl /* = false */) QString SpiceFunc::getExpression(spicecompat::SpiceDialect dialect /* = spicecompat::SPICEDefault */)
{ {
if (isActive != COMP_IS_ACTIVE || isCdl) return QString(); if (isActive != COMP_IS_ACTIVE || dialect == spicecompat::CDL) return QString();
QString s; QString s;
s.clear(); s.clear();

View File

@ -28,7 +28,7 @@ public:
~SpiceFunc(); ~SpiceFunc();
Component* newOne(); Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false); static Element* info(QString&, char* &, bool getNewOne=false);
QString getExpression(bool isXyce, bool isCdl = false); QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
protected: protected:
QString vhdlCode(int) { return QString(); } QString vhdlCode(int) { return QString(); }

View File

@ -70,14 +70,15 @@ Element* SpiceGlobalParam::info(QString& Name, char* &BitmapFile, bool getNewOne
} }
QString SpiceGlobalParam::getExpression(bool, bool isCdl /* = false */) QString SpiceGlobalParam::getExpression(spicecompat::SpiceDialect dialect /* = spicecompat::SPICEDefault */)
{ {
if (isActive != COMP_IS_ACTIVE) return QString(); if (isActive != COMP_IS_ACTIVE) return QString();
QString s; QString s;
s.clear(); s.clear();
for (Property *pp : Props) { for (Property *pp : Props) {
s += QStringLiteral(".%1PARAM %2 = %3\n").arg(isCdl ? "" : "GLOBAL_").arg(pp->Name).arg(pp->Value); s += QStringLiteral(".%1PARAM %2 = %3\n")
.arg(dialect == spicecompat::CDL ? "" : "GLOBAL_").arg(pp->Name).arg(pp->Value);
} }
return s; return s;
} }

View File

@ -29,7 +29,7 @@ public:
Component* newOne(); Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false); static Element* info(QString&, char* &, bool getNewOne=false);
static void splitEqn(QString &eqn, QStringList &tokens); static void splitEqn(QString &eqn, QStringList &tokens);
QString getExpression(bool isXyce, bool isCdl = false); QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
protected: protected:
QString vhdlCode(int) { return QString(); } QString vhdlCode(int) { return QString(); }

View File

@ -69,9 +69,9 @@ Element* SpiceIC::info(QString& Name, char* &BitmapFile, bool getNewOne)
return 0; return 0;
} }
QString SpiceIC::getExpression(bool, bool isCdl /* = false */) QString SpiceIC::getExpression(spicecompat::SpiceDialect dialect /* = spicecompat::SPICEDefault */)
{ {
if (isActive != COMP_IS_ACTIVE || isCdl) return QString(); if (isActive != COMP_IS_ACTIVE || dialect == spicecompat::CDL) return QString();
QString s; QString s;
s.clear(); s.clear();

View File

@ -28,7 +28,7 @@ public:
~SpiceIC(); ~SpiceIC();
Component* newOne(); Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false); static Element* info(QString&, char* &, bool getNewOne=false);
QString getExpression(bool isXyce, bool isCdl = false); QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
protected: protected:
QString vhdlCode(int) { return QString(); } QString vhdlCode(int) { return QString(); }

View File

@ -69,9 +69,9 @@ Element* SpiceNodeset::info(QString& Name, char* &BitmapFile, bool getNewOne)
return 0; return 0;
} }
QString SpiceNodeset::getExpression(bool, bool isCdl /* = false */) QString SpiceNodeset::getExpression(spicecompat::SpiceDialect dialect /* = spicecompat::SPICEDefault */)
{ {
if (isActive != COMP_IS_ACTIVE || isCdl) return QString(); if (isActive != COMP_IS_ACTIVE || dialect == spicecompat::CDL) return QString();
QString s; QString s;
s.clear(); s.clear();

View File

@ -28,7 +28,7 @@ public:
~SpiceNodeset(); ~SpiceNodeset();
Component* newOne(); Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false); static Element* info(QString&, char* &, bool getNewOne=false);
QString getExpression(bool isXyce, bool isCdl = false); QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
protected: protected:
QString vhdlCode(int) { return QString(); } QString vhdlCode(int) { return QString(); }

View File

@ -71,13 +71,13 @@ Element* SpiceOptions::info(QString& Name, char* &BitmapFile, bool getNewOne)
return 0; return 0;
} }
QString SpiceOptions::getExpression(bool isXyce, bool isCdl /* = false */) QString SpiceOptions::getExpression(spicecompat::SpiceDialect dialect /* = spicecompat::SPICEDefault */)
{ {
if (isActive != COMP_IS_ACTIVE || isCdl) return QString(); if (isActive != COMP_IS_ACTIVE || dialect == spicecompat::CDL) return QString();
QString s; QString s;
s.clear(); s.clear();
if (isXyce) { if (dialect == spicecompat::SPICEXyce) {
s += QStringLiteral(".OPTIONS %1 ").arg(Props.at(0)->Value); s += QStringLiteral(".OPTIONS %1 ").arg(Props.at(0)->Value);
for (int i=1;i<Props.count();i++) { for (int i=1;i<Props.count();i++) {
s += QStringLiteral(" %1 = %2 ").arg(Props.at(i)->Name).arg(Props.at(i)->Value); s += QStringLiteral(" %1 = %2 ").arg(Props.at(i)->Name).arg(Props.at(i)->Value);

View File

@ -29,7 +29,7 @@ public:
Component* newOne(); Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false); static Element* info(QString&, char* &, bool getNewOne=false);
static void splitEqn(QString &eqn, QStringList &tokens); static void splitEqn(QString &eqn, QStringList &tokens);
QString getExpression(bool isXyce, bool isCdl = false); QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
protected: protected:
QString vhdlCode(int) { return QString(); } QString vhdlCode(int) { return QString(); }

View File

@ -69,14 +69,14 @@ Element* SpiceParam::info(QString& Name, char* &BitmapFile, bool getNewOne)
return 0; return 0;
} }
QString SpiceParam::getExpression(bool, bool isCdl /* = false */) QString SpiceParam::getExpression(spicecompat::SpiceDialect dialect /* = spicecompat::SPICEDefault */)
{ {
if (isActive != COMP_IS_ACTIVE) return QString(); if (isActive != COMP_IS_ACTIVE) return QString();
QString s; QString s;
s.clear(); s.clear();
for (Property *pp : Props) { for (Property *pp : Props) {
if (isCdl) if (dialect == spicecompat::CDL)
{ {
s += QStringLiteral(".PARAM %1=%2\n").arg(pp->Name).arg(pp->Value); s += QStringLiteral(".PARAM %1=%2\n").arg(pp->Name).arg(pp->Value);
} }

View File

@ -29,7 +29,7 @@ public:
Component* newOne(); Component* newOne();
static Element* info(QString&, char* &, bool getNewOne=false); static Element* info(QString&, char* &, bool getNewOne=false);
static void splitEqn(QString &eqn, QStringList &tokens); static void splitEqn(QString &eqn, QStringList &tokens);
QString getExpression(bool isXyce, bool isCdl = false); QString getExpression(spicecompat::SpiceDialect dialect = spicecompat::SPICEDefault);
protected: protected:
QString vhdlCode(int) { return QString(); } QString vhdlCode(int) { return QString(); }