WIP: life updated on most shape properties, some bug fixes.

This commit is contained in:
Matthias Koefferlein 2020-08-26 00:38:41 +02:00
parent 6e860361c0
commit 3003eb96e7
11 changed files with 482 additions and 281 deletions

View File

@ -65,20 +65,42 @@ InstPropertiesPage::InstPropertiesPage (edt::Service *service, db::Manager *mana
connect (lib_cbx, SIGNAL (currentIndexChanged (int)), this, SLOT (library_changed (int)));
connect (cell_name_le, SIGNAL (textChanged (const QString &)), this, SLOT (cell_name_changed (const QString &)));
connect (lib_cbx, SIGNAL (activated (int)), this, SIGNAL (edited ()));
connect (cell_name_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (array_grp, SIGNAL (clicked ()), this, SIGNAL (edited ()));
connect (rows_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (columns_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (row_x_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (row_y_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (column_x_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (column_y_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (pos_x_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (pos_y_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (angle_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (mag_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (mirror_cbx, SIGNAL (clicked ()), this, SIGNAL (edited ()));
if (! readonly ()) {
connect (lib_cbx, SIGNAL (activated (int)), this, SIGNAL (edited ()));
connect (cell_name_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (array_grp, SIGNAL (clicked ()), this, SIGNAL (edited ()));
connect (rows_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (columns_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (row_x_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (row_y_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (column_x_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (column_y_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (pos_x_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (pos_y_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (angle_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (mag_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (mirror_cbx, SIGNAL (clicked ()), this, SIGNAL (edited ()));
} else {
browse_pb->setEnabled (false);
cell_name_le->setReadOnly (true);
rows_le->setReadOnly (true);
columns_le->setReadOnly (true);
row_x_le->setReadOnly (true);
row_y_le->setReadOnly (true);
column_x_le->setReadOnly (true);
column_y_le->setReadOnly (true);
pos_x_le->setReadOnly (true);
pos_y_le->setReadOnly (true);
angle_le->setReadOnly (true);
mag_le->setReadOnly (true);
lib_cbx->setEnabled (false);
array_grp->setEnabled (false);
mirror_cbx->setEnabled (false);
}
QHBoxLayout *layout = new QHBoxLayout (pcell_tab);
layout->setMargin (0);
@ -580,7 +602,7 @@ InstPropertiesPage::recompute_selection_ptrs (const std::vector<lay::ObjectInstP
}
void
InstPropertiesPage::do_apply (bool current_only)
InstPropertiesPage::do_apply (bool current_only, bool relative)
{
lay::LayerState layer_state = mp_service->view ()->layer_snapshot ();
unsigned int cv_index = m_selection_ptrs [m_index]->cv_index ();
@ -609,32 +631,7 @@ InstPropertiesPage::do_apply (bool current_only)
bool relative_mode = false;
if (! current_only && applicator->supports_relative_mode ()) {
static bool s_relative_mode = true;
QMessageBox mb (QMessageBox::Question,
tr ("Apply Changes To All"),
tr ("For this operation absolute or relative mode is available which affects the way parameters of the selected objects are changed:\n\n"
"In absolute mode, they will be set to the given value. In relative mode, they will be adjusted by the same amount.\n"),
QMessageBox::NoButton, this);
mb.addButton (tr ("Cancel"), QMessageBox::RejectRole);
QPushButton *absolute = mb.addButton (tr ("Absolute"), QMessageBox::NoRole);
QPushButton *relative = mb.addButton (tr ("Relative"), QMessageBox::YesRole);
mb.setDefaultButton (s_relative_mode ? relative : absolute);
mb.exec ();
if (mb.clickedButton () == absolute) {
s_relative_mode = relative_mode = false;
} else if (mb.clickedButton () == relative) {
s_relative_mode = relative_mode = true;
} else {
// Cancel pressed
return;
}
relative_mode = relative;
}
// Note: using the apply-all scheme for applying a single change may look like overhead.
@ -692,9 +689,6 @@ InstPropertiesPage::do_apply (bool current_only)
size_t index = p - m_selection_ptrs.begin ();
// save previous selection so we can restore it
m_saved_selection.push_back (std::make_pair (index, new_sel[index]));
// change selection to new instance
new_sel[index].back ().inst_ptr = new_inst;
@ -729,7 +723,7 @@ InstPropertiesPage::do_apply (bool current_only)
void
InstPropertiesPage::apply ()
{
do_apply (true);
do_apply (true, false);
}
bool
@ -739,9 +733,9 @@ InstPropertiesPage::can_apply_to_all () const
}
void
InstPropertiesPage::apply_to_all ()
InstPropertiesPage::apply_to_all (bool relative)
{
do_apply (false);
do_apply (false, relative);
}
void

View File

@ -65,13 +65,12 @@ protected:
bool m_enable_cb_callback;
db::properties_id_type m_prop_id;
edt::PCellParametersPage *mp_pcell_parameters;
std::list<std::pair<size_t, lay::ObjectInstPath> > m_saved_selection;
virtual bool readonly ();
virtual void apply ();
virtual void apply_to_all ();
virtual void apply_to_all (bool relative);
virtual bool can_apply_to_all () const;
void do_apply (bool current_only);
void do_apply (bool current_only, bool relative);
virtual ChangeApplicator *create_applicator (db::Cell &cell, const db::Instance &inst, double dbu);
protected slots:

View File

@ -787,7 +787,7 @@ coords_to_string (const db::DPoint &dp, double dbu, bool du, const char *sep)
}
void
indicate_error (QLineEdit *le, const tl::Exception *ex)
indicate_error (QWidget *le, const tl::Exception *ex)
{
// by the way, update the foreground color of the cell edit box as well (red, if not valid)
QPalette pl = le->palette ();

View File

@ -483,7 +483,7 @@ db::Coord coord_from_string (const char *txt, double dbu, bool du, const db::VCp
/**
* @brief Configures a QLineEdit to indicate a format error
*/
void indicate_error (QLineEdit *le, const tl::Exception *ex);
void indicate_error (QWidget *le, const tl::Exception *ex);
}

View File

@ -24,6 +24,7 @@
#include "edtPropertiesPages.h"
#include "edtPropertiesPageUtils.h"
#include "edtDialogs.h"
#include "edtPropertiesPageUtils.h"
#include "layDialogs.h"
#include "layObjectInstPath.h"
#include "layLayoutView.h"
@ -174,7 +175,7 @@ ShapePropertiesPage::recompute_selection_ptrs (const std::vector<lay::ObjectInst
}
void
ShapePropertiesPage::do_apply (bool current_only)
ShapePropertiesPage::do_apply (bool current_only, bool relative)
{
std::auto_ptr<ChangeApplicator> applicator;
@ -203,32 +204,7 @@ ShapePropertiesPage::do_apply (bool current_only)
// Ask whether to use relative or absolute mode
bool relative_mode = false;
if (! current_only && applicator->supports_relative_mode ()) {
static bool s_relative_mode = true;
QMessageBox mb (QMessageBox::Question,
tr ("Apply Changes To All"),
tr ("For this operation absolute or relative mode is available which affects the way parameters of the selected objects are changed:\n\n"
"In absolute mode, they will be set to the given value. In relative mode, they will be adjusted by the same amount.\n"),
QMessageBox::NoButton, this);
mb.addButton (tr ("Cancel"), QMessageBox::RejectRole);
QPushButton *absolute = mb.addButton (tr ("Absolute"), QMessageBox::NoRole);
QPushButton *relative = mb.addButton (tr ("Relative"), QMessageBox::YesRole);
mb.setDefaultButton (s_relative_mode ? relative : absolute);
mb.exec ();
if (mb.clickedButton () == absolute) {
s_relative_mode = relative_mode = false;
} else if (mb.clickedButton () == relative) {
s_relative_mode = relative_mode = true;
} else {
// Cancel pressed
return;
}
relative_mode = relative;
}
// Note: using the apply-all scheme for applying a single change may look like overhead.
@ -333,7 +309,7 @@ ShapePropertiesPage::do_apply (bool current_only)
void
ShapePropertiesPage::apply ()
{
do_apply (true);
do_apply (true, false);
}
bool
@ -343,9 +319,9 @@ ShapePropertiesPage::can_apply_to_all () const
}
void
ShapePropertiesPage::apply_to_all ()
ShapePropertiesPage::apply_to_all (bool relative)
{
do_apply (false);
do_apply (false, relative);
}
void
@ -391,7 +367,9 @@ void
ShapePropertiesPage::show_props ()
{
lay::UserPropertiesForm props_form (this);
props_form.show (mp_service->view (), m_selection_ptrs [m_index]->cv_index (), m_prop_id);
if (props_form.show (mp_service->view (), m_selection_ptrs [m_index]->cv_index (), m_prop_id)) {
emit edited ();
}
}
bool
@ -404,13 +382,19 @@ ShapePropertiesPage::readonly ()
// PolygonPropertiesPage implementation
PolygonPropertiesPage::PolygonPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent)
: ShapePropertiesPage (service, manager, parent)
: ShapePropertiesPage (service, manager, parent), m_in_text_changed (false)
{
setupUi (this);
setup ();
connect (inst_pb, SIGNAL (clicked ()), this, SLOT (show_inst ()));
connect (prop_pb, SIGNAL (clicked ()), this, SLOT (show_props ()));
if (! readonly ()) {
connect (pointListEdit, SIGNAL (textChanged ()), this, SLOT (text_changed ()));
} else {
pointListEdit->setReadOnly (true);
}
}
void
@ -448,61 +432,87 @@ PolygonPropertiesPage::do_update (const db::Shape &shape, double dbu, const std:
}
pointListEdit->setText (tl::to_qstring (ptlist));
if (! m_in_text_changed) {
pointListEdit->blockSignals (true);
pointListEdit->setText (tl::to_qstring (ptlist));
pointListEdit->blockSignals (false);
}
pointCountLabel->setText (tl::to_qstring (tl::sprintf (tl::to_string (QObject::tr ("(%lu points)")), poly.vertices ())));
}
void
PolygonPropertiesPage::text_changed ()
{
m_in_text_changed = true;
try {
emit edited ();
} catch (tl::Exception &) {
// ignore exceptions
}
m_in_text_changed = false;
}
ChangeApplicator *
PolygonPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape &shape, double dbu)
{
std::string text (tl::to_string (pointListEdit->toPlainText ()));
tl::Extractor ex (text.c_str ());
db::VCplxTrans t = db::CplxTrans (trans ()).inverted ();
bool du = dbu_units ();
db::Polygon poly;
if (*ex.skip () == '(') {
try {
db::DPolygon dp;
ex.read (dp);
std::string text (tl::to_string (pointListEdit->toPlainText ()));
tl::Extractor ex (text.c_str ());
poly = db::Polygon (dp.transformed (db::DCplxTrans (t) * db::DCplxTrans (du ? 1.0 : 1.0 / dbu)));
db::VCplxTrans t = db::CplxTrans (trans ()).inverted ();
bool du = dbu_units ();
} else {
if (*ex.skip () == '(') {
unsigned int h = 0;
while (! ex.at_end ()) {
db::DPolygon dp;
ex.read (dp);
std::vector <db::Point> points;
poly = db::Polygon (dp.transformed (db::DCplxTrans (t) * db::DCplxTrans (du ? 1.0 : 1.0 / dbu)));
while (! ex.at_end () && ! ex.test ("/")) {
} else {
double dx = 0.0, dy = 0.0;
ex.read (dx);
ex.test (",");
ex.read (dy);
ex.test (";");
unsigned int h = 0;
while (! ex.at_end ()) {
points.push_back (point_from_dpoint (db::DPoint (dx, dy), dbu, du, t));
std::vector <db::Point> points;
while (! ex.at_end () && ! ex.test ("/")) {
double dx = 0.0, dy = 0.0;
ex.read (dx);
ex.test (",");
ex.read (dy);
ex.test (";");
points.push_back (point_from_dpoint (db::DPoint (dx, dy), dbu, du, t));
}
if (points.size () < 3) {
throw tl::Exception (tl::to_string (QObject::tr ("Polygon must have at least three points")));
}
if (h == 0) {
poly.assign_hull (points.begin (), points.end (), false /*not compressed*/);
} else {
poly.insert_hole (points.begin (), points.end (), false /*not compressed*/);
}
++h;
}
if (points.size () < 3) {
throw tl::Exception (tl::to_string (QObject::tr ("Polygon must have at least three points")));
}
if (h == 0) {
poly.assign_hull (points.begin (), points.end (), false /*not compressed*/);
} else {
poly.insert_hole (points.begin (), points.end (), false /*not compressed*/);
}
++h;
}
indicate_error (pointListEdit, 0);
} catch (tl::Exception &ex) {
indicate_error (pointListEdit, &ex);
throw;
}
db::Polygon org_poly;
@ -525,15 +535,32 @@ BoxPropertiesPage::BoxPropertiesPage (edt::Service *service, db::Manager *manage
setup ();
mode_tab->setCurrentIndex (s_coordinateMode ? 0 : 1);
connect (mode_tab, SIGNAL (currentChanged (int)), this, SLOT (changed ()));
connect (x1_le_1, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (y1_le_1, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (x2_le_1, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (y2_le_1, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (w_le_2, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (h_le_2, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (cx_le_2, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (cy_le_2, SIGNAL (editingFinished ()), this, SLOT (changed ()));
if (! readonly ()) {
connect (mode_tab, SIGNAL (currentChanged (int)), this, SLOT (changed ()));
connect (x1_le_1, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (y1_le_1, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (x2_le_1, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (y2_le_1, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (w_le_2, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (h_le_2, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (cx_le_2, SIGNAL (editingFinished ()), this, SLOT (changed ()));
connect (cy_le_2, SIGNAL (editingFinished ()), this, SLOT (changed ()));
} else {
x1_le_1->setReadOnly (true);
y1_le_1->setReadOnly (true);
x2_le_1->setReadOnly (true);
y2_le_1->setReadOnly (true);
w_le_2->setReadOnly (true);
h_le_2->setReadOnly (true);
cx_le_2->setReadOnly (true);
cy_le_2->setReadOnly (true);
}
connect (inst_pb, SIGNAL (clicked ()), this, SLOT (show_inst ()));
connect (prop_pb, SIGNAL (clicked ()), this, SLOT (show_props ()));
}
@ -576,11 +603,44 @@ BoxPropertiesPage::get_box (int mode) const
{
if (mode == 0) {
bool has_error = false;
double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0;
tl::from_string (tl::to_string (x1_le_1->text ()), x1);
tl::from_string (tl::to_string (y1_le_1->text ()), y1);
tl::from_string (tl::to_string (x2_le_1->text ()), x2);
tl::from_string (tl::to_string (y2_le_1->text ()), y2);
try {
tl::from_string (tl::to_string (x1_le_1->text ()), x1);
indicate_error (x1_le_1, 0);
} catch (tl::Exception &ex) {
indicate_error (x1_le_1, &ex);
has_error = true;
}
try {
tl::from_string (tl::to_string (y1_le_1->text ()), y1);
indicate_error (y1_le_1, 0);
} catch (tl::Exception &ex) {
indicate_error (y1_le_1, &ex);
has_error = true;
}
try {
tl::from_string (tl::to_string (x2_le_1->text ()), x2);
indicate_error (x2_le_1, 0);
} catch (tl::Exception &ex) {
indicate_error (x2_le_1, &ex);
has_error = true;
}
try {
tl::from_string (tl::to_string (y2_le_1->text ()), y2);
indicate_error (y2_le_1, 0);
} catch (tl::Exception &ex) {
indicate_error (y2_le_1, &ex);
has_error = true;
}
if (has_error) {
throw tl::Exception (tl::to_string (tr ("Invalid values - see highlighted entry boxes")));
}
if (m_lr_swapped) {
std::swap (x1, x2);
@ -603,11 +663,44 @@ BoxPropertiesPage::get_box (int mode) const
} else {
bool has_error = false;
double cx = 0.0, cy = 0.0, w = 0.0, h = 0.0;
tl::from_string (tl::to_string (cx_le_2->text ()), cx);
tl::from_string (tl::to_string (cy_le_2->text ()), cy);
tl::from_string (tl::to_string (w_le_2->text ()), w);
tl::from_string (tl::to_string (h_le_2->text ()), h);
try {
tl::from_string (tl::to_string (cx_le_2->text ()), cx);
indicate_error (cx_le_2, 0);
} catch (tl::Exception &ex) {
indicate_error (cx_le_2, &ex);
has_error = true;
}
try {
tl::from_string (tl::to_string (cy_le_2->text ()), cy);
indicate_error (cy_le_2, 0);
} catch (tl::Exception &ex) {
indicate_error (cy_le_2, &ex);
has_error = true;
}
try {
tl::from_string (tl::to_string (w_le_2->text ()), w);
indicate_error (w_le_2, 0);
} catch (tl::Exception &ex) {
indicate_error (w_le_2, &ex);
has_error = true;
}
try {
tl::from_string (tl::to_string (h_le_2->text ()), h);
indicate_error (h_le_2, 0);
} catch (tl::Exception &ex) {
indicate_error (h_le_2, &ex);
has_error = true;
}
if (has_error) {
throw tl::Exception (tl::to_string (tr ("Invalid values - see highlighted entry boxes")));
}
db::VCplxTrans t = db::VCplxTrans (trans ().inverted ());
bool du = dbu_units ();
@ -664,6 +757,8 @@ BoxPropertiesPage::changed ()
set_box (get_box (m_tab_index));
} catch (...) {
}
emit edited ();
}
// -------------------------------------------------------------------------
@ -677,6 +772,28 @@ TextPropertiesPage::TextPropertiesPage (edt::Service *service, db::Manager *mana
connect (inst_pb, SIGNAL (clicked ()), this, SLOT (show_inst ()));
connect (prop_pb, SIGNAL (clicked ()), this, SLOT (show_props ()));
if (! readonly ()) {
connect (text_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (x_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (y_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (size_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (orient_cbx, SIGNAL (activated (int)), this, SIGNAL (edited ()));
connect (halign_cbx, SIGNAL (activated (int)), this, SIGNAL (edited ()));
connect (valign_cbx, SIGNAL (activated (int)), this, SIGNAL (edited ()));
} else {
text_le->setReadOnly (true);
x_le->setReadOnly (true);
y_le->setReadOnly (true);
size_le->setReadOnly (true);
orient_cbx->setEnabled (false);
halign_cbx->setEnabled (false);
valign_cbx->setEnabled (false);
}
}
void
@ -707,12 +824,28 @@ TextPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::st
ChangeApplicator *
TextPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape &shape, double dbu)
{
bool has_error = false;
db::VCplxTrans t = db::CplxTrans (trans ()).inverted ();
bool du = dbu_units ();
double x = 0.0, y = 0.0;
tl::from_string (tl::to_string (x_le->text ()), x);
tl::from_string (tl::to_string (y_le->text ()), y);
try {
tl::from_string (tl::to_string (x_le->text ()), x);
indicate_error (x_le, 0);
} catch (tl::Exception &ex) {
indicate_error (x_le, &ex);
has_error = true;
}
try {
tl::from_string (tl::to_string (y_le->text ()), y);
indicate_error (y_le, 0);
} catch (tl::Exception &ex) {
indicate_error (y_le, &ex);
has_error = true;
}
db::Vector tp = db::Vector (point_from_dpoint (db::DPoint (x, y), dbu, du, t));
db::Trans tt (orient_cbx->currentIndex (), tp);
@ -739,7 +872,13 @@ TextPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape
db::Coord size = 0;
if (! size_le->text ().isEmpty ()) {
size = coord_from_string (tl::to_string (size_le->text ()).c_str (), dbu, du, t);
try {
size = coord_from_string (tl::to_string (size_le->text ()).c_str (), dbu, du, t);
indicate_error (size_le, 0);
} catch (tl::Exception &ex) {
indicate_error (size_le, &ex);
has_error = true;
}
}
if (size != org_text.size ()) {
appl->add (new TextSizeChangeApplicator (size));
@ -749,6 +888,10 @@ TextPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape
appl->add (new TextStringChangeApplicator (str));
}
if (has_error) {
throw tl::Exception (tl::to_string (tr ("Invalid values - see highlighted entry boxes")));
}
return appl.release ();
}
@ -756,16 +899,22 @@ TextPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape
// PathPropertiesPage implementation
PathPropertiesPage::PathPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent)
: ShapePropertiesPage (service, manager, parent)
: ShapePropertiesPage (service, manager, parent), m_in_text_changed (false)
{
setupUi (this);
setup ();
connect (inst_pb, SIGNAL (clicked ()), this, SLOT (show_inst ()));
connect (prop_pb, SIGNAL (clicked ()), this, SLOT (show_props ()));
ptlist_le->setReadOnly (true);
width_le->setReadOnly (true);
start_ext_le->setReadOnly (true);
end_ext_le->setReadOnly (true);
round_cb->setEnabled (false);
}
void
void
PathPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname)
{
layer_lbl->setText (tl::to_qstring (lname));
@ -788,7 +937,12 @@ PathPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::st
}
ptlist += coords_to_string (t * *pt, dbu, du);
}
ptlist_le->setText (tl::to_qstring (ptlist));
if (! m_in_text_changed) {
ptlist_le->blockSignals (true);
ptlist_le->setText (tl::to_qstring (ptlist));
ptlist_le->blockSignals (false);
}
width_le->setText (tl::to_qstring (coord_to_string (t.ctrans (path.width ()), dbu, du)));
start_ext_le->setText (tl::to_qstring (coord_to_string (t.ctrans (path.extensions ().first), dbu, du)));
@ -797,68 +951,16 @@ PathPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::st
}
ChangeApplicator *
PathPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape &shape, double dbu)
PathPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape & /*shape*/, double /*dbu*/)
{
db::VCplxTrans t = db::CplxTrans (trans ()).inverted ();
bool du = dbu_units ();
std::string text (tl::to_string (ptlist_le->toPlainText ()));
tl::Extractor ex (text.c_str ());
std::vector <db::Point> points;
while (! ex.at_end ()) {
double dx = 0.0, dy = 0.0;
ex.read (dx);
ex.read (dy);
points.push_back (point_from_dpoint (db::DPoint (dx, dy), dbu, du, t));
}
if (points.size () < 1) {
throw tl::Exception (tl::to_string (QObject::tr ("The path must have at least one point")));
}
db::Coord w = coord_from_string (tl::to_string (width_le->text ()).c_str (), dbu, du, t);
db::Coord se = coord_from_string (tl::to_string (start_ext_le->text ()).c_str (), dbu, du, t);
db::Coord ee = coord_from_string (tl::to_string (end_ext_le->text ()).c_str (), dbu, du, t);
bool round = round_cb->isChecked ();
std::auto_ptr<CombinedChangeApplicator> appl;
db::Path org_path;
shape.path (org_path);
std::vector <db::Point> org_points;
for (db::Path::iterator p = org_path.begin (); p != org_path.end (); ++p) {
org_points.push_back (*p);
}
if (org_points != points) {
appl->add (new PathPointsChangeApplicator (points, org_points));
}
if (w != org_path.width ()) {
appl->add (new PathWidthChangeApplicator (w, org_path.width ()));
}
if (se != org_path.extensions ().first) {
appl->add (new PathStartExtensionChangeApplicator (se));
}
if (ee != org_path.extensions ().second) {
appl->add (new PathEndExtensionChangeApplicator (ee));
}
if (round != org_path.round ()) {
appl->add (new PathRoundEndChangeApplicator (round));
}
return appl.release ();
return 0;
}
// -------------------------------------------------------------------------
// EditablePathPropertiesPage implementation
EditablePathPropertiesPage::EditablePathPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent)
: ShapePropertiesPage (service, manager, parent)
: ShapePropertiesPage (service, manager, parent), m_in_text_changed (false)
{
setupUi (this);
setup ();
@ -866,6 +968,12 @@ EditablePathPropertiesPage::EditablePathPropertiesPage (edt::Service *service, d
connect (inst_pb, SIGNAL (clicked ()), this, SLOT (show_inst ()));
connect (prop_pb, SIGNAL (clicked ()), this, SLOT (show_props ()));
connect (type_cb, SIGNAL (currentIndexChanged (int)), this, SLOT (type_selected (int)));
connect (ptlist_le, SIGNAL (textChanged ()), this, SLOT (text_changed ()));
connect (width_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (start_ext_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (end_ext_le, SIGNAL (editingFinished ()), this, SIGNAL (edited ()));
connect (type_cb, SIGNAL (activated (int)), this, SIGNAL (edited ()));
}
static int
@ -886,7 +994,19 @@ path_type_choice (const db::Path &path)
}
}
void
void
EditablePathPropertiesPage::text_changed ()
{
m_in_text_changed = true;
try {
emit edited ();
} catch (tl::Exception &) {
// ignore exceptions
}
m_in_text_changed = false;
}
void
EditablePathPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname)
{
layer_lbl->setText (tl::to_qstring (lname));
@ -909,7 +1029,12 @@ EditablePathPropertiesPage::do_update (const db::Shape &shape, double dbu, const
}
ptlist += coords_to_string (t * *pt, dbu, du);
}
ptlist_le->setText (tl::to_qstring (ptlist));
if (! m_in_text_changed) {
ptlist_le->blockSignals (true);
ptlist_le->setText (tl::to_qstring (ptlist));
ptlist_le->blockSignals (false);
}
db::Coord w = path.width ();
db::Coord se = path.extensions ().first;
@ -921,6 +1046,10 @@ EditablePathPropertiesPage::do_update (const db::Shape &shape, double dbu, const
end_ext_le->setText (tl::to_qstring (coord_to_string (t.ctrans (ee), dbu, du)));
int type_choice = path_type_choice (path);
if (type_cb->currentIndex () == 2) {
// keep "variable" mode, otherwise if's difficult to switch to it
type_choice = 2;
}
type_cb->setCurrentIndex (type_choice);
type_selected (type_choice);
}
@ -928,6 +1057,8 @@ EditablePathPropertiesPage::do_update (const db::Shape &shape, double dbu, const
ChangeApplicator *
EditablePathPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db::Shape &shape, double dbu)
{
bool has_error = false;
db::VCplxTrans t = db::CplxTrans (trans ()).inverted ();
bool du = dbu_units ();
@ -936,22 +1067,38 @@ EditablePathPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db
std::vector <db::Point> points;
while (! ex.at_end ()) {
try {
double dx = 0.0, dy = 0.0;
ex.read (dx);
ex.read (dy);
while (! ex.at_end ()) {
points.push_back (point_from_dpoint (db::DPoint (dx, dy), dbu, du, t));
double dx = 0.0, dy = 0.0;
ex.read (dx);
ex.read (dy);
points.push_back (point_from_dpoint (db::DPoint (dx, dy), dbu, du, t));
}
if (points.size () < 1) {
throw tl::Exception (tl::to_string (QObject::tr ("The path must have at least one point")));
}
indicate_error (ptlist_le, 0);
} catch (tl::Exception &ex) {
indicate_error (ptlist_le, &ex);
has_error = true;
}
if (points.size () < 1) {
throw tl::Exception (tl::to_string (QObject::tr ("The path must have at least one point")));
db::Coord w = 0;
try {
w = coord_from_string (tl::to_string (width_le->text ()).c_str (), dbu, du, t);
indicate_error (width_le, 0);
} catch (tl::Exception &ex) {
indicate_error (width_le, &ex);
has_error = true;
}
db::Coord w = coord_from_string (tl::to_string (width_le->text ()).c_str (), dbu, du, t);
db::Coord se = 0, ee = 0;
switch (type_cb->currentIndex ()) {
case 0: // flush
@ -961,8 +1108,20 @@ EditablePathPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db
se = ee = std::numeric_limits <db::Coord>::min (); // force to half width
break;
case 2: // variable
se = coord_from_string (tl::to_string (start_ext_le->text ()).c_str (), dbu, du, t);
ee = coord_from_string (tl::to_string (end_ext_le->text ()).c_str (), dbu, du, t);
try {
se = coord_from_string (tl::to_string (start_ext_le->text ()).c_str (), dbu, du, t);
indicate_error (start_ext_le, 0);
} catch (tl::Exception &ex) {
indicate_error (start_ext_le, &ex);
has_error = true;
}
try {
ee = coord_from_string (tl::to_string (end_ext_le->text ()).c_str (), dbu, du, t);
indicate_error (end_ext_le, 0);
} catch (tl::Exception &ex) {
indicate_error (end_ext_le, &ex);
has_error = true;
}
break;
}
@ -989,6 +1148,10 @@ EditablePathPropertiesPage::create_applicator (db::Shapes & /*shapes*/, const db
appl->add (new PathRoundEndChangeApplicator (type_cb->currentIndex () == 3));
}
if (has_error) {
throw tl::Exception (tl::to_string (tr ("Invalid values - see highlighted entry boxes")));
}
return appl.release ();
}

View File

@ -56,13 +56,15 @@ public:
virtual void operator++ ();
virtual void leave ();
protected:
virtual bool readonly ();
private:
virtual void update ();
virtual void apply ();
virtual void apply_to_all ();
virtual void apply_to_all (bool relative);
virtual bool can_apply_to_all () const;
virtual void do_apply (bool current_only);
virtual bool readonly ();
virtual void do_apply (bool current_only, bool relative);
void recompute_selection_ptrs (const std::vector<lay::ObjectInstPath> &new_sel);
protected:
@ -104,6 +106,12 @@ public:
protected:
virtual QCheckBox *dbu_checkbox () const { return dbu_cb; }
virtual QCheckBox *abs_checkbox () const { return abs_cb; }
public slots:
void text_changed ();
private:
bool m_in_text_changed;
};
class BoxPropertiesPage
@ -167,6 +175,9 @@ public:
protected:
virtual QCheckBox *dbu_checkbox () const { return dbu_cb; }
virtual QCheckBox *abs_checkbox () const { return abs_cb; }
private:
bool m_in_text_changed;
};
class EditablePathPropertiesPage
@ -187,6 +198,10 @@ protected:
public slots:
void type_selected (int);
void text_changed ();
private:
bool m_in_text_changed;
};
}

View File

@ -17,7 +17,16 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>9</number>
</property>
<property name="topMargin">
<number>9</number>
</property>
<property name="rightMargin">
<number>9</number>
</property>
<property name="bottomMargin">
<number>9</number>
</property>
<item>
@ -54,7 +63,16 @@
<property name="spacing">
<number>6</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -69,7 +87,7 @@
<string>Previous</string>
</property>
<property name="icon">
<iconset resource="layResources.qrc">
<iconset resource="../../lay/lay/layResources.qrc">
<normaloff>:/left.png</normaloff>:/left.png</iconset>
</property>
<property name="default">
@ -89,7 +107,7 @@
<string>Next</string>
</property>
<property name="icon">
<iconset resource="layResources.qrc">
<iconset resource="../../lay/lay/layResources.qrc">
<normaloff>:/right.png</normaloff>:/right.png</iconset>
</property>
<property name="default">
@ -97,6 +115,39 @@
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="apply_to_all_cbx">
<property name="text">
<string>Change all</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="relative_cbx">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Relative</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
@ -120,20 +171,6 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="apply_button">
<property name="text">
<string>Apply</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="apply_to_all_button">
<property name="text">
<string>Apply To All</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="cancel_button">
<property name="text">
@ -148,7 +185,24 @@
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
<include location="layResources.qrc"/>
<include location="../../lay/lay/layResources.qrc"/>
</resources>
<connections/>
<connections>
<connection>
<sender>apply_to_all_cbx</sender>
<signal>toggled(bool)</signal>
<receiver>relative_cbx</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>260</x>
<y>372</y>
</hint>
<hint type="destinationlabel">
<x>320</x>
<y>372</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -557,7 +557,7 @@ LayoutView::init (db::Manager *mgr, QWidget * /*parent*/)
}
if (is_editable () && (m_options & LV_NoEditorOptionsPanel) == 0 && (m_options & LV_Naked) == 0) {
if ((m_options & LV_NoEditorOptionsPanel) == 0 && (m_options & LV_Naked) == 0) {
mp_editor_options_frame = new QFrame (0);
mp_editor_options_frame->setObjectName (QString::fromUtf8 ("editor_options_frame"));

View File

@ -198,7 +198,7 @@ public:
* If nothing was changed, the objects may be left untouched.
* The dialog will start a transaction on the manager object.
*/
virtual void apply_to_all ()
virtual void apply_to_all (bool /*relative*/)
{
// default implementation is empty.
}

View File

@ -64,8 +64,8 @@ PropertiesDialog::PropertiesDialog (QWidget * /*parent*/, db::Manager *manager,
content_frame->setLayout (mp_stack);
// disable the apply button for first ..
apply_button->setEnabled (false);
apply_to_all_button->setEnabled (false);
apply_to_all_cbx->setEnabled (false);
relative_cbx->setEnabled (false);
ok_button->setEnabled (false);
// as a proposal, the start button can be enabled in most cases
@ -87,22 +87,28 @@ PropertiesDialog::PropertiesDialog (QWidget * /*parent*/, db::Manager *manager,
// if at end disable the "Next" button and return (this may only happen at the first call)
if (m_index >= int (mp_properties_pages.size ())) {
next_button->setEnabled (false);
mp_stack->setCurrentWidget (dummy);
apply_button->setEnabled (false);
apply_to_all_button->setEnabled (false);
apply_to_all_cbx->setEnabled (false);
apply_to_all_cbx->setChecked (false);
relative_cbx->setEnabled (false);
relative_cbx->setChecked (false);
ok_button->setEnabled (false);
} else {
next_button->setEnabled (any_next ());
mp_properties_pages [m_index]->update ();
mp_stack->setCurrentWidget (mp_properties_pages [m_index]);
apply_button->setEnabled (! mp_properties_pages [m_index]->readonly ());
apply_to_all_button->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ());
apply_to_all_cbx->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ());
apply_to_all_cbx->setChecked (false);
relative_cbx->setEnabled (apply_to_all_cbx->isEnabled () && apply_to_all_cbx->isChecked ());
relative_cbx->setChecked (true);
ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ());
}
connect (apply_button, SIGNAL (clicked ()), this, SLOT (apply_pressed ()));
connect (apply_to_all_button, SIGNAL (clicked ()), this, SLOT (apply_to_all_pressed ()));
connect (ok_button, SIGNAL (clicked ()), this, SLOT (ok_pressed ()));
connect (cancel_button, SIGNAL (clicked ()), this, SLOT (cancel_pressed ()));
connect (prev_button, SIGNAL (clicked ()), this, SLOT (prev_pressed ()));
@ -159,8 +165,8 @@ BEGIN_PROTECTED
prev_button->setEnabled (true);
next_button->setEnabled (any_next ());
apply_button->setEnabled (! mp_properties_pages [m_index]->readonly ());
apply_to_all_button->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ());
apply_to_all_cbx->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ());
relative_cbx->setEnabled (apply_to_all_cbx->isEnabled () && apply_to_all_cbx->isChecked ());
ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ());
mp_properties_pages [m_index]->update ();
@ -203,8 +209,8 @@ BEGIN_PROTECTED
next_button->setEnabled (true);
prev_button->setEnabled (any_prev ());
apply_button->setEnabled (! mp_properties_pages [m_index]->readonly ());
apply_to_all_button->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ());
apply_to_all_cbx->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ());
relative_cbx->setEnabled (apply_to_all_cbx->isEnabled () && apply_to_all_cbx->isChecked ());
ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ());
mp_properties_pages [m_index]->update ();
@ -254,23 +260,6 @@ PropertiesDialog::any_prev () const
return (index >= 0);
}
void
PropertiesDialog::apply_to_all_pressed ()
{
BEGIN_PROTECTED
{
db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes to all")), m_transaction_id);
mp_properties_pages [m_index]->apply_to_all ();
mp_properties_pages [m_index]->update ();
m_transaction_id = t.id ();
}
END_PROTECTED
}
void
PropertiesDialog::apply ()
{
@ -280,7 +269,11 @@ BEGIN_PROTECTED
try {
mp_properties_pages [m_index]->apply ();
if (apply_to_all_cbx->isChecked () && mp_properties_pages [m_index]->can_apply_to_all ()) {
mp_properties_pages [m_index]->apply_to_all (relative_cbx->isChecked ());
} else {
mp_properties_pages [m_index]->apply ();
}
mp_properties_pages [m_index]->update ();
} catch (tl::Exception &) {
@ -292,21 +285,6 @@ BEGIN_PROTECTED
END_PROTECTED
}
void
PropertiesDialog::apply_pressed ()
{
BEGIN_PROTECTED
db::Transaction t (mp_manager, tl::to_string (QObject::tr ("Apply changes")), m_transaction_id);
mp_properties_pages [m_index]->apply ();
mp_properties_pages [m_index]->update ();
m_transaction_id = t.id ();
END_PROTECTED
}
void
PropertiesDialog::cancel_pressed ()
{

View File

@ -92,8 +92,6 @@ public slots:
void apply ();
void next_pressed ();
void prev_pressed ();
void apply_pressed ();
void apply_to_all_pressed ();
void cancel_pressed ();
void ok_pressed ();