Skip to content

Commit

Permalink
Merge pull request #842 from wawuwo/fix-property-editbox-position-and…
Browse files Browse the repository at this point in the history
…-size

Fix property editbox position and size
  • Loading branch information
ra3xdh authored Jul 14, 2024
2 parents 586dcc4 + 9d72037 commit 8b842cb
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 84 deletions.
15 changes: 11 additions & 4 deletions qucs/components/component.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,14 @@ void Component::getCenter(int &x, int &y) {
// Given coordinates of a point (usually coming from a mouse click), finds
// out whether this point is within boundaries of one of component's text
// properties (i.e whether a text property is clicked) and returns the
// index of that property. Returns -1 when point is not within bounds of
// any of text properties — i.e. click has missed.
// index of that property.
//
// Returns:
// -1 when point is not within bounds of any of component's texts, i.e.
// click has missed
// 0 when click is within bounds of component name
// n + 1 when click is within bounds of one of component's properties, `n`
// is the index of that property
//
// To find out whether given coordinates are within one of text properties,
// we iterate over all properties, computing their bounding rectangles and
Expand Down Expand Up @@ -203,8 +209,8 @@ int Component::getTextSelected(int point_x, int point_y) {
}

bounding_rect_top = text_br.bottom();
text_index += 1;
}
text_index += 1;

for (auto* prop : Props) {
if (!prop->display) {
Expand Down Expand Up @@ -252,7 +258,8 @@ void Component::paint(QPainter *p) {

for (auto *prop : Props) {
if (!prop->display) continue;
p->drawText(text_br.left(), text_br.bottom(), 0, 0, Qt::TextDontClip, prop->Name + "=" + prop->Value, &text_br);
prop->paint(text_br.left(), text_br.bottom(), p);
text_br = prop->boundingRect();
}

if (isActive == COMP_IS_OPEN)
Expand Down
5 changes: 5 additions & 0 deletions qucs/element.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ double Text::angle() const {
return -degrees;
}

// x and y are relative to component's x and y
void Property::paint(int x, int y, QPainter* p)
{
p->drawText(x, y, 0, 0, Qt::TextDontClip, Name + "=" + Value, &br);
}

Element::Element()
{
Expand Down
4 changes: 4 additions & 0 deletions qucs/element.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,10 @@ struct Property {
QString Name, Value;
bool display; // show on schematic or not ?
QString Description;
QRect boundingRect() const { return br; };
void paint(int x, int y, QPainter* p);
private:
QRect br;
};


Expand Down
136 changes: 60 additions & 76 deletions qucs/qucs_actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1219,110 +1219,94 @@ void QucsApp::slotCursorUp(bool up)
// In "view->MAx3" is the number of the current property.
void QucsApp::slotApplyCompText()
{
QString s;
QFont f = QucsSettings.font;
Schematic *Doc = (Schematic*)DocumentTab->currentWidget();
f.setPointSizeF( Doc->Scale * float(f.pointSize()) );
editText->setFont(f);

Property *pp = 0;
Component *pc = (Component*)view->focusElement;
if(!pc) return; // should never happen
view->MAx1 = pc->cx + pc->tx;
view->MAy1 = pc->cy + pc->ty;

int z, n=0; // "n" is number of property on screen
pp = pc->Props.first();
for(z=view->MAx3; z>0; z--) { // calculate "n"
if(!pp) { // should never happen
slotHideEdit();
return;
}
if(pp->display) n++; // is visible ?
pp = pc->Props.next();
}

pp = 0;
if(view->MAx3 > 0) pp = pc->Props.at(view->MAx3-1); // current property
else s = pc->Name;

if(!editText->isHidden()) { // is called the first time ?
// no -> apply value to current property
if(view->MAx3 == 0) { // component name ?
Component *pc2;
if(!editText->text().isEmpty())
if(pc->Name != editText->text()) {
for(pc2 = Doc->Components->first(); pc2!=0; pc2 = Doc->Components->next())
if(pc2->Name == editText->text())
break; // found component with the same name ?
if(!pc2) {
pc->Name = editText->text();
Doc->setChanged(true, true); // only one undo state
Component *const component = dynamic_cast<Component*>(view->focusElement);
if(!component) return; // should never happen
view->MAx1 = component->cx + component->tx;
view->MAy1 = component->cy + component->ty;

// Here is a bit of *magic* and implicit coupling: the value of view->MAx3
// comes from Component::getTextSelected, and it's equal 0 when component
// name is clicked, N + 1 when Nth component property is clicked.
const int component_text_index = view->MAx3;
const bool is_name = component_text_index == 0;

Property *const component_property = !is_name
? component->Props.at(component_text_index - 1)
: nullptr;

if (editText->isVisible()) { // is called the first time ?
if (is_name) {
const auto new_name{editText->text()};

if (!new_name.isEmpty() && component->Name != new_name) {
// TODO: rewrite with std::none_of after replacing Q3PtrList
// with modern container
bool is_unique = true;
for (auto* other : *Doc->Components) {
if (other->Name == new_name) {
is_unique = false;
break;
}
}
}
else if(pp) { // property was applied
if(pp->Value != editText->text()) {
pp->Value = editText->text();
Doc->recreateComponent(pc); // because of "Num" and schematic symbol
Doc->setChanged(true, true); // only one undo state
}
}

n++; // next row on screen
(view->MAx3)++; // next property
pp = pc->Props.at(view->MAx3-1); // search for next property

Doc->viewport()->update();
view->drawn = false;
if (is_unique) {
component->Name = new_name;
Doc->setChanged(true, true); // only one undo state
}
}

if(!pp) { // was already last property ?
slotHideEdit();
return;
}


while(!pp->display) { // search for next visible property
(view->MAx3)++; // next property
pp = pc->Props.next();
if(!pp) { // was already last property ?
slotHideEdit();
return;
else if (component_property) { // property was applied
if (component_property->Value != editText->text()) {
component_property->Value = editText->text();
Doc->recreateComponent(component); // because of "Num" and schematic symbol
Doc->setChanged(true, true); // only one undo state
}
}
}

// avoid seeing the property text behind the line edit
if(pp) // Is it first property or component name ?
s = pp->Value;
editText->setMinimumWidth(editText->fontMetrics().boundingRect(s).width()+4);

const QString s = is_name
? component->Name
: component_property->Value;

Doc->contentsToViewport(int(Doc->Scale * float(view->MAx1 - Doc->ViewX1)),
int(Doc->Scale * float(view->MAy1 - Doc->ViewY1)),
view->MAx2, view->MAy2);
editText->setReadOnly(false);
if(pp) { // is it a property ?
s = pp->Value;
view->MAx2 += editText->fontMetrics().boundingRect(pp->Name+"=").width();
if(pp->Description.indexOf('[') >= 0) // is selection list ?
QPoint editTextTopLeft;
if (component_property) { // is it a property ?
editTextTopLeft = Doc->modelToViewport(QPoint{component->cx, component->cy} + component_property->boundingRect().topLeft());
editTextTopLeft.rx() += editText->fontMetrics().boundingRect(component_property->Name + "=" + '\u0020').width();

if(component_property->Description.indexOf('[') >= 0) // is selection list ?
editText->setReadOnly(true);
Expr_CompProp.setPattern("[^\"]*");
if(!pc->showName) n--;
}
else // it is the component name
else { // it is the component name
Expr_CompProp.setPattern("[\\w_]+");
editTextTopLeft = Doc->modelToViewport(QPoint{component->cx + component->tx, component->cy + component->ty});
}

{
auto size = editText->fontMetrics().boundingRect(s ).size();
size.rwidth() += editText->fontMetrics().averageCharWidth();
editText->setFixedSize(size);
}

view->MAx2 = editTextTopLeft.x();
view->MAy2 = editTextTopLeft.y();

Val_CompProp.setRegularExpression(Expr_CompProp);
editText->setValidator(&Val_CompProp);

z = editText->fontMetrics().lineSpacing();
view->MAy2 += n*z;
editText->setText(s);
editText->setStyleSheet("color: black; background-color: " + QucsSettings.BGColor.name());
editText->setFocus();
editText->selectAll();
editText->setParent(Doc->viewport());
editText->move(QPoint(view->MAx2, view->MAy2));
editText->move(view->MAx2, view->MAy2);
editText->show();
//editText->reparent(Doc->viewport(), 0, QPoint(view->MAx2, view->MAy2), true);
}
Expand Down
4 changes: 2 additions & 2 deletions qucs/schematic.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,13 @@ class Schematic : public Q3ScrollView, public QucsDoc {
@brief Given cordinates of a model point returns coordinates of this point
relative to viewport. It's a reverse of @ref Schematic::viewportToModel
*/
QPoint modelToViewport(QPoint modelCoordinates);
QPoint modelToViewport(const QPoint& modelCoordinates);

/**
Given a coordinates of viewport point returns coordinates of the model plane point
displayed at given location of the viewport.
*/
QPoint viewportToModel(QPoint viewportCoordinates);
QPoint viewportToModel(const QPoint& viewportCoordinates);

/**
Given coordinates of a point on the view plane (schematic's canvas), this method
Expand Down
4 changes: 2 additions & 2 deletions qucs/schematic_render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ QRect Schematic::viewportRect() {
return QRect{0, 0, viewport()->width(), viewport()->height()};
}

QPoint Schematic::modelToViewport(QPoint modelCoordinates)
QPoint Schematic::modelToViewport(const QPoint& modelCoordinates)
{
return modelToContents(modelCoordinates) - QPoint{ contentsX(), contentsY() };
}

QPoint Schematic::viewportToModel(QPoint viewportCoordinates)
QPoint Schematic::viewportToModel(const QPoint& viewportCoordinates)
{
return contentsToModel(QPoint{ contentsX(), contentsY() } + viewportCoordinates);
}
Expand Down

0 comments on commit 8b842cb

Please sign in to comment.