diff --git a/src/edt/edt/edtPropertiesPages.cc b/src/edt/edt/edtPropertiesPages.cc index 1fc0fe92e..db756da64 100644 --- a/src/edt/edt/edtPropertiesPages.cc +++ b/src/edt/edt/edtPropertiesPages.cc @@ -86,12 +86,59 @@ ShapePropertiesPage::select_entries (const std::vector &entries) m_index = entries.front (); } +lay::LayoutViewBase * +ShapePropertiesPage::view () const +{ + return mp_service->view (); +} + +const db::Shape & +ShapePropertiesPage::shape (size_t entry) const +{ + return m_selection_ptrs [entry]->shape (); +} + +double +ShapePropertiesPage::dbu (size_t entry) const +{ + unsigned int cv_index = m_selection_ptrs [entry]->cv_index (); + return view ()->cellview (cv_index)->layout ().dbu (); +} + std::string ShapePropertiesPage::description (size_t entry) const { - return m_selection_ptrs [entry]->shape ().to_string (); // @@@ + unsigned int cv_index = m_selection_ptrs [entry]->cv_index (); + unsigned int layer = m_selection_ptrs [entry]->layer (); + + if (view ()->cellview (cv_index).is_valid ()) { + const db::LayerProperties &lp = view ()->cellview (cv_index)->layout ().get_properties (layer); + if (view ()->cellviews () > 1) { + return lp.to_string () + "@" + tl::to_string (cv_index + 1); + } else { + return lp.to_string (); + } + } + + return std::string (); } +QIcon +ShapePropertiesPage::icon (size_t entry, int w, int h) const +{ + int cv_index = m_selection_ptrs [entry]->cv_index (); + int layer = m_selection_ptrs [entry]->layer (); + + auto *view = mp_service->view (); + for (auto lp = view->begin_layers (view->current_layer_list ()); ! lp.at_end (); ++lp) { + const lay::LayerPropertiesNode *ln = lp.operator-> (); + if (ln->cellview_index () == cv_index && ln->layer_index () == layer) { + return QIcon (QPixmap::fromImage (view->icon_for_layer (lp, w, h).to_image ())); + } + } + + return QIcon (); +} std::string ShapePropertiesPage::description () const { @@ -394,7 +441,32 @@ PolygonPropertiesPage::PolygonPropertiesPage (edt::Service *service, db::Manager } } -void +static size_t count_polygon_points (const db::Shape &sh) +{ + size_t n = 0; + for (auto pt = sh.begin_hull (); pt != sh.end_hull (); ++pt) { + ++n; + } + return n; +} + +std::string +PolygonPropertiesPage::description (size_t entry) const +{ + const db::Shape &sh = shape (entry); + + size_t npts = count_polygon_points (sh); + if (sh.holes () == 0 && npts > 4) { + return ShapePropertiesPage::description () + " " + tl::sprintf (tl::to_string (tr ("Polygon(%d points)")), npts); + } else if (sh.holes () > 0) { + return ShapePropertiesPage::description () + " " + tl::sprintf (tl::to_string (tr ("Polygon(%d points, %d holes)")), npts, sh.holes ()); + } else { + db::CplxTrans dbu_trans (dbu (entry)); + return ShapePropertiesPage::description () + " " + tl::sprintf (tl::to_string (tr ("Polygon(%s)")), (dbu_trans * sh.polygon ()).to_string ()); + } +} + +void PolygonPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname) { layer_lbl->setText (tl::to_qstring (lname)); @@ -562,6 +634,14 @@ BoxPropertiesPage::BoxPropertiesPage (edt::Service *service, db::Manager *manage connect (prop_pb, SIGNAL (clicked ()), this, SLOT (show_props ())); } +std::string +BoxPropertiesPage::description (size_t entry) const +{ + const db::Shape &sh = shape (entry); + db::CplxTrans dbu_trans (dbu (entry)); + return ShapePropertiesPage::description () + " " + tl::sprintf (tl::to_string (tr ("Box(%s)")), (dbu_trans * sh.box ()).to_string ()); +} + void BoxPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname) { @@ -793,7 +873,15 @@ TextPropertiesPage::TextPropertiesPage (edt::Service *service, db::Manager *mana } } -void +std::string +TextPropertiesPage::description (size_t entry) const +{ + const db::Shape &sh = shape (entry); + db::CplxTrans dbu_trans (dbu (entry)); + return ShapePropertiesPage::description () + " " + tl::sprintf (tl::to_string (tr ("Text(%s)")), (dbu_trans * sh.text ()).to_string ()); +} + +void TextPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname) { layer_lbl->setText (tl::to_qstring (lname)); @@ -917,6 +1005,32 @@ PathPropertiesPage::PathPropertiesPage (edt::Service *service, db::Manager *mana round_cb->setEnabled (false); } +static size_t count_path_points (const db::Shape &sh) +{ + size_t n = 0; + for (auto pt = sh.begin_point (); pt != sh.end_point (); ++pt) { + ++n; + } + return n; +} + +static std::string path_description (const db::Shape &sh, double dbu) +{ + size_t npts = count_path_points (sh); + if (npts > 4) { + return tl::sprintf (tl::to_string (tr ("Path(%d points, w=%s)")), npts, tl::micron_to_string (sh.path_width () * dbu)); + } else { + db::CplxTrans dbu_trans (dbu); + return tl::sprintf (tl::to_string (tr ("Path(%s)")), (dbu_trans * sh.path ()).to_string ()); + } +} + +std::string +PathPropertiesPage::description (size_t entry) const +{ + return ShapePropertiesPage::description () + " " + path_description (shape (entry), dbu (entry)); +} + void PathPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname) { @@ -1015,6 +1129,12 @@ EditablePathPropertiesPage::text_changed () m_in_text_changed = false; } +std::string +EditablePathPropertiesPage::description (size_t entry) const +{ + return ShapePropertiesPage::description () + " " + path_description (shape (entry), dbu (entry)); +} + void EditablePathPropertiesPage::do_update (const db::Shape &shape, double dbu, const std::string &lname) { diff --git a/src/edt/edt/edtPropertiesPages.h b/src/edt/edt/edtPropertiesPages.h index dd767f7ad..36f1785f1 100644 --- a/src/edt/edt/edtPropertiesPages.h +++ b/src/edt/edt/edtPropertiesPages.h @@ -52,6 +52,7 @@ public: virtual size_t count () const; virtual void select_entries (const std::vector &entries); virtual std::string description (size_t entry) const; + virtual QIcon icon (size_t entry, int w, int h) const; virtual std::string description () const; virtual void leave (); @@ -82,6 +83,9 @@ protected: bool abs_trans () const; db::ICplxTrans trans () const; void setup (); + lay::LayoutViewBase *view () const; + const db::Shape &shape (size_t entry) const; + double dbu (size_t entry) const; public slots: void show_inst (); @@ -100,6 +104,7 @@ Q_OBJECT public: PolygonPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent); + virtual std::string description (size_t entry) const; virtual void do_update (const db::Shape &shape, double dbu, const std::string &lname); virtual ChangeApplicator *create_applicator (db::Shapes &shapes, const db::Shape &shape, double dbu); @@ -123,6 +128,7 @@ Q_OBJECT public: BoxPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent); + virtual std::string description (size_t entry) const; virtual void do_update (const db::Shape &shape, double dbu, const std::string &lname); virtual ChangeApplicator *create_applicator (db::Shapes &shapes, const db::Shape &shape, double dbu); @@ -152,6 +158,7 @@ Q_OBJECT public: TextPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent); + virtual std::string description (size_t entry) const; virtual void do_update (const db::Shape &shape, double dbu, const std::string &lname); virtual ChangeApplicator *create_applicator (db::Shapes &shapes, const db::Shape &shape, double dbu); @@ -169,6 +176,7 @@ Q_OBJECT public: PathPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent); + virtual std::string description (size_t entry) const; virtual void do_update (const db::Shape &shape, double dbu, const std::string &lname); virtual ChangeApplicator *create_applicator (db::Shapes &shapes, const db::Shape &shape, double dbu); @@ -189,6 +197,7 @@ Q_OBJECT public: EditablePathPropertiesPage (edt::Service *service, db::Manager *manager, QWidget *parent); + virtual std::string description (size_t entry) const; virtual void do_update (const db::Shape &shape, double dbu, const std::string &lname); virtual ChangeApplicator *create_applicator (db::Shapes &shapes, const db::Shape &shape, double dbu); diff --git a/src/laybasic/laybasic/layLayoutCanvas.cc b/src/laybasic/laybasic/layLayoutCanvas.cc index 4ae778d95..06eb5664f 100644 --- a/src/laybasic/laybasic/layLayoutCanvas.cc +++ b/src/laybasic/laybasic/layLayoutCanvas.cc @@ -198,20 +198,6 @@ LayoutCanvas::~LayoutCanvas () clear_fg_bitmaps (); } -#if defined(HAVE_QT) && QT_VERSION >= 0x050000 -double -LayoutCanvas::dpr () const -{ - return widget () ? widget ()->devicePixelRatio () : 1.0; -} -#else -double -LayoutCanvas::dpr () const -{ - return 1.0; -} -#endif - double LayoutCanvas::resolution () const { @@ -297,6 +283,16 @@ LayoutCanvas::set_highres_mode (bool hrm) } } +double +LayoutCanvas::dpr () const +{ +#if defined(HAVE_QT) && QT_VERSION >= 0x50000 + return widget () ? widget ()->devicePixelRatio () : 1.0; +#else + return 1.0; +#endif +} + void LayoutCanvas::set_colors (tl::Color background, tl::Color foreground, tl::Color active) { diff --git a/src/laybasic/laybasic/layLayoutCanvas.h b/src/laybasic/laybasic/layLayoutCanvas.h index d73f614b2..001cf0f33 100644 --- a/src/laybasic/laybasic/layLayoutCanvas.h +++ b/src/laybasic/laybasic/layLayoutCanvas.h @@ -277,6 +277,11 @@ public: return m_hrm; } + /** + * @brief Gets the default device pixel ratio for this canvas + */ + double dpr () const; + /** * @brief Sets the depth of the image cache */ @@ -439,7 +444,6 @@ private: void do_redraw_all (bool force_redraw = true); void prepare_drawing (); - double dpr () const; virtual double resolution () const; const std::vector &scaled_view_ops (unsigned int lw); diff --git a/src/laybasic/laybasic/layLayoutViewBase.cc b/src/laybasic/laybasic/layLayoutViewBase.cc index b6051a571..b2e3a805d 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.cc +++ b/src/laybasic/laybasic/layLayoutViewBase.cc @@ -1548,6 +1548,10 @@ single_bitmap_to_image (const lay::ViewOp &view_op, lay::Bitmap &bitmap, tl::PixelBuffer LayoutViewBase::icon_for_layer (const LayerPropertiesConstIterator &iter, unsigned int w, unsigned int h, double dpr, unsigned int di_off, bool no_state) { + if (dpr < 0.0) { + dpr = canvas ()->dpr (); + } + int oversampling = canvas () ? canvas ()->oversampling () : 1; double gamma = 2.0; diff --git a/src/laybasic/laybasic/layLayoutViewBase.h b/src/laybasic/laybasic/layLayoutViewBase.h index 9f7b188d5..a45056f80 100644 --- a/src/laybasic/laybasic/layLayoutViewBase.h +++ b/src/laybasic/laybasic/layLayoutViewBase.h @@ -587,11 +587,11 @@ public: * @param iter indicates the layer * @param w The width in logical pixels of the generated pixmap (will be multiplied by dpr) * @param h The height in logical pixels of the generated pixmap (will be multiplied by dpr) - * @param dpr The device pixel ratio (number of image pixes per logical pixel) + * @param dpr The device pixel ratio (number of image pixes per logical pixel) - negative values mean auto-detect * @param di_off The dither pattern offset (used for animation) * @param no_state If true, the state will not be indicated */ - tl::PixelBuffer icon_for_layer (const lay::LayerPropertiesConstIterator &iter, unsigned int w, unsigned int h, double dpr, unsigned int di_off, bool no_state); + tl::PixelBuffer icon_for_layer (const lay::LayerPropertiesConstIterator &iter, unsigned int w, unsigned int h, double dpr = -1.0, unsigned int di_off = 0, bool no_state = false); /** * @brief Sets the layers that are selected in the layer browser diff --git a/src/laybasic/laybasic/layProperties.h b/src/laybasic/laybasic/layProperties.h index c346ce0da..cea5288dc 100644 --- a/src/laybasic/laybasic/layProperties.h +++ b/src/laybasic/laybasic/layProperties.h @@ -29,6 +29,7 @@ #include "layEditable.h" #include +#include namespace db { @@ -97,11 +98,27 @@ public: */ virtual std::string description (size_t entry) const = 0; + /** + * @brief Gets the icon for the nth entry + */ + virtual QIcon icon (size_t /*entry*/, int /*w*/, int /*h*/) const + { + return QIcon (); + } + /** * @brief Gets a description text for the whole group */ virtual std::string description () const = 0; + /** + * @brief Gets the icon associated with the whole group + */ + virtual QIcon icon (int /*w*/, int /*h*/) const + { + return QIcon (); + } + /** * @brief Update the display * diff --git a/src/layui/layui/layPropertiesDialog.cc b/src/layui/layui/layPropertiesDialog.cc index fbc9dde4d..22749fdbf 100644 --- a/src/layui/layui/layPropertiesDialog.cc +++ b/src/layui/layui/layPropertiesDialog.cc @@ -44,8 +44,8 @@ class PropertiesTreeModel : public QAbstractItemModel { public: - PropertiesTreeModel (PropertiesDialog *dialog) - : QAbstractItemModel (dialog), mp_dialog (dialog) + PropertiesTreeModel (PropertiesDialog *dialog, int icon_width, int icon_height) + : QAbstractItemModel (dialog), mp_dialog (dialog), m_icon_width (icon_width), m_icon_height (icon_height) { } int columnCount (const QModelIndex &) const @@ -61,6 +61,16 @@ public: } else { return tl::to_qstring (mp_dialog->properties_pages () [index.row ()]->description ()); } + } else if (role == Qt::DecorationRole) { + QIcon icon; + if (index.internalId () < mp_dialog->properties_pages ().size ()) { + icon = mp_dialog->properties_pages () [index.internalId ()]->icon (index.row (), m_icon_width, m_icon_height); + } else { + icon = mp_dialog->properties_pages () [index.internalId ()]->icon (m_icon_width, m_icon_height); + } + if (! icon.isNull ()) { + return QVariant (icon); + } } return QVariant (); } @@ -68,7 +78,7 @@ public: Qt::ItemFlags flags (const QModelIndex &index) const { Qt::ItemFlags f = QAbstractItemModel::flags (index); - if (index.internalId () >= mp_dialog->properties_pages ().size ()) { + if (index.internalId () >= mp_dialog->properties_pages ().size () && ! mp_dialog->properties_pages () [index.row ()]->can_apply_to_all ()) { f &= ~Qt::ItemIsSelectable; } return f; @@ -120,11 +130,25 @@ public: QModelIndex index_for (int page_index, int object_index) { - return createIndex (object_index, 0, qint64 (page_index)); + if (page_index < 0) { + return QModelIndex (); + } else { + return createIndex (object_index, 0, qint64 (page_index)); + } + } + + QModelIndex index_for (int page_index) + { + if (page_index < 0) { + return QModelIndex (); + } else { + return createIndex (page_index, 0, qint64 (mp_dialog->properties_pages ().size ())); + } } private: PropertiesDialog *mp_dialog; + int m_icon_width, m_icon_height; }; // ---------------------------------------------------------------------------------------------------------- @@ -175,14 +199,6 @@ PropertiesDialog::PropertiesDialog (QWidget * /*parent*/, db::Manager *manager, mp_ui->content_frame->setLayout (mp_stack); - // disable the apply button for first .. - mp_ui->apply_to_all_cbx->setEnabled (false); - mp_ui->relative_cbx->setEnabled (false); - mp_ui->ok_button->setEnabled (false); - - // as a proposal, the start button can be enabled in most cases - mp_ui->prev_button->setEnabled (true); - // count the total number of objects m_objects = mp_editables->selection_size (); m_current_object = 0; @@ -195,41 +211,26 @@ PropertiesDialog::PropertiesDialog (QWidget * /*parent*/, db::Manager *manager, update_title (); // if at end disable the "Next" button and return (this may only happen at the first call) - if (m_index < 0) { + mp_tree_model = new PropertiesTreeModel (this, mp_ui->tree->iconSize ().width (), mp_ui->tree->iconSize ().height ()); + mp_ui->tree->setModel (mp_tree_model); + mp_ui->tree->expandAll (); - mp_ui->prev_button->setEnabled (false); - mp_ui->next_button->setEnabled (false); - mp_stack->setCurrentWidget (mp_none); - mp_ui->apply_to_all_cbx->setEnabled (false); - mp_ui->apply_to_all_cbx->setChecked (false); - mp_ui->relative_cbx->setEnabled (false); - mp_ui->relative_cbx->setChecked (false); - mp_ui->ok_button->setEnabled (false); - mp_ui->tree->setEnabled (false); + m_signals_enabled = false; + mp_ui->tree->setCurrentIndex (mp_tree_model->index_for (m_index, m_object_index)); + m_signals_enabled = true; - } else { - - mp_tree_model = new PropertiesTreeModel (this); - mp_ui->tree->setModel (mp_tree_model); - mp_ui->tree->expandAll (); - - m_signals_enabled = false; - mp_ui->tree->setCurrentIndex (mp_tree_model->index_for (m_index, m_object_index)); - m_signals_enabled = true; - - update_controls (); + update_controls (); // @@@ save this status! - mp_ui->apply_to_all_cbx->setChecked (false); - mp_ui->relative_cbx->setChecked (true); + mp_ui->apply_to_all_cbx->setChecked (false); + mp_ui->relative_cbx->setChecked (true); - connect (mp_ui->ok_button, SIGNAL (clicked ()), this, SLOT (ok_pressed ())); - connect (mp_ui->cancel_button, SIGNAL (clicked ()), this, SLOT (cancel_pressed ())); - connect (mp_ui->prev_button, SIGNAL (clicked ()), this, SLOT (prev_pressed ())); - connect (mp_ui->next_button, SIGNAL (clicked ()), this, SLOT (next_pressed ())); - connect (mp_ui->tree->selectionModel (), SIGNAL (currentChanged (const QModelIndex &, const QModelIndex &)), this, SLOT (current_index_changed (const QModelIndex &, const QModelIndex &))); - - } + connect (mp_ui->ok_button, SIGNAL (clicked ()), this, SLOT (ok_pressed ())); + connect (mp_ui->cancel_button, SIGNAL (clicked ()), this, SLOT (cancel_pressed ())); + connect (mp_ui->prev_button, SIGNAL (clicked ()), this, SLOT (prev_pressed ())); + connect (mp_ui->next_button, SIGNAL (clicked ()), this, SLOT (next_pressed ())); + connect (mp_ui->apply_to_all_cbx, SIGNAL (clicked ()), this, SLOT (apply_to_all_pressed ())); + connect (mp_ui->tree->selectionModel (), SIGNAL (currentChanged (const QModelIndex &, const QModelIndex &)), this, SLOT (current_index_changed (const QModelIndex &, const QModelIndex &))); } PropertiesDialog::~PropertiesDialog () @@ -251,51 +252,91 @@ PropertiesDialog::disconnect () mp_properties_pages.clear (); } +void +PropertiesDialog::apply_to_all_pressed () +{ + m_signals_enabled = false; + if (mp_ui->apply_to_all_cbx->isChecked ()) { + mp_ui->tree->setCurrentIndex (mp_tree_model->index_for (m_index)); + } else { + mp_ui->tree->setCurrentIndex (mp_tree_model->index_for (m_index, m_object_index)); + } + m_signals_enabled = true; +} + void PropertiesDialog::current_index_changed (const QModelIndex &index, const QModelIndex & /*previous*/) { - if (m_signals_enabled && index.isValid ()) { + if (! m_signals_enabled) { + return; + } - if (mp_tree_model->parent (index).isValid ()) { + if (! index.isValid ()) { + return; + } - m_index = mp_tree_model->page_index (index); - m_object_index = mp_tree_model->object_index (index); + if (mp_tree_model->parent (index).isValid ()) { - } else { + m_index = mp_tree_model->page_index (index); + mp_ui->apply_to_all_cbx->setChecked (false); - m_index = index.row (); - m_object_index = 0; + m_object_index = mp_tree_model->object_index (index); - } + } else { - m_current_object = 0; - for (int i = 0; i < m_index; ++i) { - m_current_object += mp_properties_pages [i]->count (); - } - m_current_object += m_object_index; + m_index = index.row (); + mp_ui->apply_to_all_cbx->setChecked (mp_properties_pages [m_index]->can_apply_to_all ()); - update_title (); - update_controls (); + m_object_index = 0; } + + m_current_object = 0; + for (int i = 0; i < m_index; ++i) { + m_current_object += mp_properties_pages [i]->count (); + } + m_current_object += m_object_index; + + update_title (); + update_controls (); } void PropertiesDialog::update_controls () { if (m_prev_index >= 0 && m_index != m_prev_index) { - mp_properties_pages [m_prev_index]->leave (); + if (m_prev_index >= 0 && m_prev_index < int (mp_properties_pages.size ())) { + mp_properties_pages [m_prev_index]->leave (); + } } m_prev_index = m_index; - mp_stack->setCurrentWidget (mp_properties_pages [m_index]); - mp_ui->prev_button->setEnabled (any_prev ()); - mp_ui->next_button->setEnabled (any_next ()); - mp_ui->apply_to_all_cbx->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ()); - mp_ui->relative_cbx->setEnabled (mp_ui->apply_to_all_cbx->isEnabled () && mp_ui->apply_to_all_cbx->isChecked ()); - mp_ui->ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ()); - mp_properties_pages [m_index]->select_entry (m_object_index); - mp_properties_pages [m_index]->update (); + if (m_index < 0) { + + mp_stack->setCurrentWidget (mp_none); + + mp_ui->prev_button->setEnabled (false); + mp_ui->next_button->setEnabled (false); + mp_ui->apply_to_all_cbx->setEnabled (false); + mp_ui->relative_cbx->setEnabled (false); + mp_ui->ok_button->setEnabled (false); + mp_ui->tree->setEnabled (false); + + } else { + + mp_stack->setCurrentWidget (mp_properties_pages [m_index]); + + mp_ui->prev_button->setEnabled (any_prev ()); + mp_ui->next_button->setEnabled (any_next ()); + mp_ui->apply_to_all_cbx->setEnabled (! mp_properties_pages [m_index]->readonly () && mp_properties_pages [m_index]->can_apply_to_all ()); + mp_ui->relative_cbx->setEnabled (mp_ui->apply_to_all_cbx->isEnabled () && mp_ui->apply_to_all_cbx->isChecked ()); + mp_ui->ok_button->setEnabled (! mp_properties_pages [m_index]->readonly ()); + mp_ui->tree->setEnabled (true); + + mp_properties_pages [m_index]->select_entry (m_object_index); + mp_properties_pages [m_index]->update (); + + } } void diff --git a/src/layui/layui/layPropertiesDialog.h b/src/layui/layui/layPropertiesDialog.h index 354d0cf3b..6caf8ebcd 100644 --- a/src/layui/layui/layPropertiesDialog.h +++ b/src/layui/layui/layPropertiesDialog.h @@ -108,6 +108,7 @@ public slots: void prev_pressed (); void cancel_pressed (); void ok_pressed (); + void apply_to_all_pressed (); void current_index_changed (const QModelIndex &index, const QModelIndex &previous); protected: