Skip to content

Commit

Permalink
Merge pull request #700 from wawuwo/feature-export-symbol
Browse files Browse the repository at this point in the history
Add symbol editor
  • Loading branch information
ra3xdh committed May 3, 2024
2 parents d59b5e7 + 483bd60 commit ae63391
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 37 deletions.
54 changes: 52 additions & 2 deletions qucs/paintings/portsymbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "portsymbol.h"
#include "schematic.h"

#include <QInputDialog>
#include <QPainter>

PortSymbol::PortSymbol(int cx_, int cy_, const QString& numberStr_,
Expand Down Expand Up @@ -53,7 +54,7 @@ void PortSymbol::paint(ViewPainter *p)
p->Painter->setPen(QPen(Qt::red,1)); // like open node
p->drawEllipse(cx-4, cy-4, 8, 8);

QSize r = p->Painter->fontMetrics().size(0, nameStr);
QSize r = p->Painter->fontMetrics().size(0, nameStr.isEmpty() ? numberStr : nameStr);
int Unit = int(8.0 * p->Scale);
x1 = -r.width() - Unit;
y1 = -((r.height() + Unit) >> 1);
Expand Down Expand Up @@ -88,7 +89,7 @@ void PortSymbol::paint(ViewPainter *p)
}

p->Painter->setPen(Qt::black);
p->Painter->drawText(tx, ty, 0, 0, Qt::TextDontClip, nameStr);
p->Painter->drawText(tx, ty, 0, 0, Qt::TextDontClip, nameStr.isEmpty() ? numberStr : nameStr);


p->Painter->setWorldTransform(wm);
Expand Down Expand Up @@ -225,3 +226,52 @@ void PortSymbol::mirrorY()
if(Angel == 0) Angel = 180;
else if(Angel == 180) Angel = 0;
}

bool PortSymbol::MousePressing(Schematic *) {
QString text = QInputDialog::getText(nullptr, QObject::tr("Port name"),
QObject::tr("Input port name:"));
if (!text.isNull() && !text.isEmpty()) {
numberStr = text;
return true;
}

return false;
}

void PortSymbol::MouseMoving(Schematic* doc, int, int, int gx, int gy, Schematic *, int, int, bool) {
cx = gx;
cy = gy;
paintScheme(doc);
}

Painting* PortSymbol::newOne() {
return new PortSymbol();
}

// This function is called from double click handler, see mouseactions.cpp
// Returned bool signal whether the object has changed as a result of
// the invocation.
bool PortSymbol::Dialog(QWidget* /*parent*/) {
// nameStr is not empty only in case when it got its value from a
// corresponding port in schematic. Forbid manual editing, change
// port name on schematic to change it in the symbol
if (!nameStr.isEmpty()) {
return false;
}

// When nameStr is empty, we're dealing with just a symbol without
// a corresponding schematic. In that case allow to user to input
// port name
QString text = QInputDialog::getText(nullptr, QObject::tr("Port name"),
QObject::tr("Input port name:"),
QLineEdit::Normal,
numberStr);
if (text.isNull() || text.isEmpty()) {
return false;
}

// nameStr is auto derived from corresponding port in schematic.
// When there is no such port, fallback value is used.
numberStr = text;
return true;
}
4 changes: 4 additions & 0 deletions qucs/paintings/portsymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class PortSymbol : public Painting {
void paintScheme(Schematic*);
void getCenter(int&, int&);
void setCenter(int, int, bool relative=false);
void MouseMoving(Schematic*, int, int, int, int, Schematic*, int, int, bool) override;
bool MousePressing(Schematic*) override;
Painting* newOne() override;
bool Dialog(QWidget *parent) override;

bool load(const QString&);
QString save();
Expand Down
49 changes: 30 additions & 19 deletions qucs/qucs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ QucsApp::QucsApp()

QucsFileFilter =
tr("Schematic") + " (*.sch);;" +
tr("Symbol only") + " (*.sym);;" +
tr("Data Display") + " (*.dpl);;" +
tr("Qucs Documents") + " (*.sch *.dpl);;" +
tr("VHDL Sources") + " (*.vhdl *.vhd);;" +
Expand Down Expand Up @@ -1610,7 +1611,12 @@ bool QucsApp::gotoPage(const QString& Name)
return false;
}
slotChangeView();
if (is_sch) {
if (Info.suffix() == "sym") {
// We dealing with a file containing *only* a symbol definition.
// Because of that we want to switch straight to symbol editing mode
// and skip any actions performed with a usual schematic.
slotSymbolEdit();
} else if (is_sch) {
Schematic *sch = (Schematic *)d;
if (sch->checkDplAndDatNames()) sch->setChanged(true,true);
}
Expand Down Expand Up @@ -1660,7 +1666,13 @@ bool QucsApp::saveFile(QucsDoc *Doc)
int Result = Doc->save();
if(Result < 0) return false;

updatePortNumber(Doc, Result);
// It's assumed that *.sym files contain *only* a symbol
// definition. We don't want these files to be subject
// of any activities or "optimizations" which may change
// the symbol.
if (!Doc->DocName.endsWith(".sym")) {
updatePortNumber(Doc, Result);
}
slotUpdateTreeview();
return true;
}
Expand Down Expand Up @@ -1707,7 +1719,7 @@ bool QucsApp::saveAs()
}

// list of known file extensions
QString ext = "vhdl;vhd;v;va;sch;dpl;m;oct;net;qnet;ckt;cir;sp;txt";
QString ext = "vhdl;vhd;v;va;sch;dpl;m;oct;net;qnet;ckt;cir;sp;txt;sym";
QStringList extlist = ext.split (';');

if(isTextDocument (w))
Expand Down Expand Up @@ -1765,7 +1777,14 @@ bool QucsApp::saveAs()
n = Doc->save(); // SAVE
if(n < 0) return false;

updatePortNumber(Doc, n);
// It's assumed that *.sym files contain *only* a symbol
// definition. We don't want these files to be subject
// of any activities or "optimizations" which may change
// the symbol.
if (!Doc->DocName.endsWith(".sym")) {
updatePortNumber(Doc, n);
}

slotUpdateTreeview();
updateRecentFilesList(s);
return true;
Expand Down Expand Up @@ -2949,7 +2968,6 @@ void QucsApp::switchEditMode(bool SchematicMode)
changeProps->setEnabled(SchematicMode);
insEquation->setEnabled(SchematicMode);
insGround->setEnabled(SchematicMode);
insPort->setEnabled(SchematicMode);
insWire->setEnabled(SchematicMode);
insLabel->setEnabled(SchematicMode);
setMarker->setEnabled(SchematicMode);
Expand Down Expand Up @@ -3021,22 +3039,15 @@ void QucsApp::slotSymbolEdit()
SDoc->viewport()->update();
view->drawn = false;
}
// in a normal schematic, data display or symbol file
// in a normal schematic, symbol file
else {
Schematic *SDoc = (Schematic*)w;
// in a symbol file
if(SDoc->DocName.right(4) == ".sym") {
slotChangePage(SDoc->DocName, SDoc->DataDisplay);
}
// in a normal schematic
else {
slotHideEdit(); // disable text edit of component property
SDoc->switchPaintMode(); // twist the view coordinates
changeSchematicSymbolMode(SDoc);
SDoc->becomeCurrent(true);
SDoc->viewport()->update();
view->drawn = false;
}
slotHideEdit(); // disable text edit of component property
SDoc->switchPaintMode(); // twist the view coordinates
changeSchematicSymbolMode(SDoc);
SDoc->becomeCurrent(true);
SDoc->viewport()->update();
view->drawn = false;
}
}

Expand Down
9 changes: 7 additions & 2 deletions qucs/qucs_actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include <QListWidget>
#include <QDesktopServices>

#include "portsymbol.h"
#include "projectView.h"
#include "main.h"
#include "qucs.h"
Expand Down Expand Up @@ -513,9 +514,13 @@ void QucsApp::slotInsertPort(bool on)
if(view->selElem)
delete view->selElem; // delete previously selected component

view->selElem = new SubCirPort();

Schematic *Doc = (Schematic*)DocumentTab->currentWidget();
if (Doc->symbolMode) {
view->selElem = new PortSymbol();
} else {
view->selElem = new SubCirPort();
}

if(view->drawn) Doc->viewport()->update();
view->drawn = false;
MouseMoveAction = &MouseActions::MMoveElement;
Expand Down
32 changes: 19 additions & 13 deletions qucs/schematic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,15 +189,9 @@ void Schematic::becomeCurrent(bool update)

// update appropriate menu entry
if (symbolMode) {
if (DocName.right(4) == ".sym") {
App->symEdit->setText(tr("Edit Text"));
App->symEdit->setStatusTip(tr("Edits the Text"));
App->symEdit->setWhatsThis(tr("Edit Text\n\nEdits the text file"));
} else {
App->symEdit->setText(tr("Edit Schematic"));
App->symEdit->setStatusTip(tr("Edits the schematic"));
App->symEdit->setWhatsThis(tr("Edit Schematic\n\nEdits the schematic"));
}
App->symEdit->setText(tr("Edit Schematic"));
App->symEdit->setStatusTip(tr("Edits the schematic"));
App->symEdit->setWhatsThis(tr("Edit Schematic\n\nEdits the schematic"));
} else {
App->symEdit->setText(tr("Edit Circuit Symbol"));
App->symEdit->setStatusTip(tr("Edits the symbol for this schematic"));
Expand All @@ -212,8 +206,12 @@ void Schematic::becomeCurrent(bool update)
Paintings = &SymbolPaints;
Components = &SymbolComps;

// if no symbol yet exists -> create one
if (createSubcircuitSymbol()) {
// "Schematic" is used to edit usual schematic files (containing
// a schematic and a subcircuit symbol) and *.sym files (which
// contain *only* a symbol definition). If we're dealing with
// symbol file, then there is no need to create a subcircuit
// symbol, a symbol is already there.
if (!DocName.endsWith(".sym") && createSubcircuitSymbol()) {
updateAllBoundingRect();
setChanged(true, true);
}
Expand Down Expand Up @@ -1675,7 +1673,16 @@ bool Schematic::load()
// Saves this Qucs document. Returns the number of subcircuit ports.
int Schematic::save()
{
int result = adjustPortNumbers(); // same port number for schematic and symbol
int result = 0;
// When saving *only* a symbol, there is no corresponding schematic:
// and thus ports in symbol don't have corresponding ports in schematic.
// There is just nothing to adjust.
//
// In other cases we want to delete any dangling ports from symbol
// and invoke "adjustPortNumbers" for it.
if (!DocName.endsWith("sym")) {
result = adjustPortNumbers(); // same port number for schematic and symbol
}
if (saveDocument() < 0)
return -1;

Expand Down Expand Up @@ -1947,7 +1954,6 @@ bool Schematic::undo()
}

rebuildSymbol(undoSymbol.at(--undoSymbolIdx));
adjustPortNumbers(); // set port names

emit signalUndoState(undoSymbolIdx != 0);
emit signalRedoState(undoSymbolIdx != undoSymbol.size() - 1);
Expand Down
16 changes: 15 additions & 1 deletion qucs/schematic_element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <stdlib.h>
#include <limits.h>

#include "portsymbol.h"
#include "schematic.h"
#include <qt3_compat/qt_compat.h>
#include <QDebug>
Expand Down Expand Up @@ -2076,14 +2077,27 @@ bool Schematic::deleteElements()
Painting *pp = Paintings->first();
while(pp != 0) // test all paintings
{
if(pp->isSelected)
if(pp->isSelected) {
// Allow removing of manually inserted port symbols when in symbol
// editing mode. If port symbol is inserted manually i.e. doesn't
// have a corresponding port in schematic, its nameStr is empty.
// If it's not empty, then invocation of Schematic::adjustPortNumbers
// must have found a pairing port in schematic.
if (pp->Name.trimmed() == ".PortSym" && ((PortSymbol*)pp)->nameStr.isEmpty()) {
sel = true;
Paintings->remove();
pp = Paintings->current();
continue;
}

if(pp->Name.at(0) != '.') // do not delete "PortSym", "ID_text"
{
sel = true;
Paintings->remove();
pp = Paintings->current();
continue;
}
}
pp = Paintings->next();
}

Expand Down
12 changes: 12 additions & 0 deletions qucs/schematic_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,6 +567,18 @@ int Schematic::saveDocument()

stream << "<Qucs Schematic " << PACKAGE_VERSION << ">\n";

// Special case of saving a file when we want to save *only*
// the symbol defintion (i.e. to create a "symbol file")
if (DocName.endsWith(".sym")) {
stream << "<Symbol>\n";
for(auto* pp : SymbolPaints) {
stream << " <" << pp->save() << ">\n";
}
stream << "</Symbol>\n";
file.close();
return 0;
}

stream << "<Properties>\n";
if(symbolMode) {
stream << " <View=" << tmpViewX1<<","<<tmpViewY1<<","
Expand Down

0 comments on commit ae63391

Please sign in to comment.