Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add symbol editor #700

Merged
merged 6 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -104,6 +104,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 @@ -1597,7 +1598,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 @@ -1647,7 +1653,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 @@ -1694,7 +1706,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 @@ -1752,7 +1764,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 @@ -2942,7 +2961,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 @@ -3014,22 +3032,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
Loading