diff --git a/src/edt/edt/edtService.cc b/src/edt/edt/edtService.cc index 66b4e2ad5..a39fdcd02 100644 --- a/src/edt/edt/edtService.cc +++ b/src/edt/edt/edtService.cc @@ -462,7 +462,7 @@ Service::copy_selected () for (EditableSelectionIterator r = begin_selection (); ! r.at_end () && ! need_to_ask_for_copy_mode; ++r) { if (r->is_cell_inst ()) { const db::Cell &cell = view ()->cellview (r->cv_index ())->layout ().cell (r->back ().inst_ptr.cell_index ()); - if (! cell.is_proxy ()) { + if (! cell.is_proxy () && ! cell.is_leaf ()) { need_to_ask_for_copy_mode = true; } } diff --git a/src/laybasic/laybasic/layLayoutViewConfig.cc b/src/laybasic/laybasic/layLayoutViewConfig.cc index 6956ea9e4..d1372d966 100644 --- a/src/laybasic/laybasic/layLayoutViewConfig.cc +++ b/src/laybasic/laybasic/layLayoutViewConfig.cc @@ -122,6 +122,7 @@ public: options.push_back (std::pair (cfg_line_style_palette, lay::LineStylePalette ().to_string ())); options.push_back (std::pair (cfg_no_stipple, "false")); options.push_back (std::pair (cfg_markers_visible, "true")); + options.push_back (std::pair (cfg_copy_cell_mode, "-1")); } }; diff --git a/src/laybasic/laybasic/laybasicConfig.h b/src/laybasic/laybasic/laybasicConfig.h index 6fc547669..9fb24ee86 100644 --- a/src/laybasic/laybasic/laybasicConfig.h +++ b/src/laybasic/laybasic/laybasicConfig.h @@ -132,6 +132,7 @@ static const std::string cfg_default_font_size ("default-font-size"); static const std::string cfg_hide_empty_layers ("hide-empty-layers"); static const std::string cfg_test_shapes_in_view ("test-shapes-in-view"); +static const std::string cfg_copy_cell_mode ("copy-cell-mode"); static const std::string cfg_flat_cell_list ("flat-cell-list"); static const std::string cfg_split_cell_list ("split-cell-list"); static const std::string cfg_cell_list_sorting ("cell-list-sorting"); diff --git a/src/layui/layui/CopyCellModeDialog.ui b/src/layui/layui/CopyCellModeDialog.ui index 3f8497c35..6dfe18c4c 100644 --- a/src/layui/layui/CopyCellModeDialog.ui +++ b/src/layui/layui/CopyCellModeDialog.ui @@ -1,46 +1,41 @@ - + + CopyCellModeDialog - - + + 0 0 - 400 - 178 + 546 + 198 - + Copy Cell Options - - - 9 - - - 6 - + - - + + Copy Cell Mode - - - 9 - - + + 6 + + 9 + - - + + Shallow copy (don't copy subcells) - - + + Deep copy (include subcells) @@ -48,12 +43,19 @@ + + + + Don't ask again (you can always reset this in Setup: Application/Cells page) + + + - + Qt::Vertical - + 382 31 @@ -62,12 +64,12 @@ - - + + Qt::Horizontal - - QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok @@ -86,11 +88,11 @@ CopyCellModeDialog accept() - + 248 254 - + 157 274 @@ -102,11 +104,11 @@ CopyCellModeDialog reject() - + 316 260 - + 286 274 diff --git a/src/layui/layui/LayoutViewConfigPage8.ui b/src/layui/layui/LayoutViewConfigPage8.ui new file mode 100644 index 000000000..9c15bae72 --- /dev/null +++ b/src/layui/layui/LayoutViewConfigPage8.ui @@ -0,0 +1,69 @@ + + + LayoutViewConfigPage8 + + + + 0 + 0 + 414 + 46 + + + + Form + + + + + + Cell copy mode + + + + + + + + 1 + 0 + + + + QComboBox::AdjustToContents + + + + Shallow mode (cell only) + + + + + Deep mode (cell and subcells) + + + + + Ask + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + diff --git a/src/layui/layui/layDialogs.cc b/src/layui/layui/layDialogs.cc index 748c20520..b1c60d1c4 100644 --- a/src/layui/layui/layDialogs.cc +++ b/src/layui/layui/layDialogs.cc @@ -579,7 +579,7 @@ CopyCellModeDialog::~CopyCellModeDialog () } bool -CopyCellModeDialog::exec_dialog (int ©_mode) +CopyCellModeDialog::exec_dialog (int ©_mode, bool &dont_ask) { QRadioButton *buttons [] = { mp_ui->shallow_rb, mp_ui->deep_rb }; @@ -592,6 +592,7 @@ CopyCellModeDialog::exec_dialog (int ©_mode) if (buttons [i]->isChecked ()) { copy_mode = i; } + dont_ask = mp_ui->dont_ask_cbx->isChecked (); } return true; } else { diff --git a/src/layui/layui/layDialogs.h b/src/layui/layui/layDialogs.h index 5aefa8a7c..cea190b36 100644 --- a/src/layui/layui/layDialogs.h +++ b/src/layui/layui/layDialogs.h @@ -233,7 +233,7 @@ public: * * The mode is either 0 (for shallow), 1 (for deep) */ - bool exec_dialog (int ©_mode); + bool exec_dialog (int ©_mode, bool &dont_ask_again); private: Ui::CopyCellModeDialog *mp_ui; diff --git a/src/layui/layui/layHierarchyControlPanel.cc b/src/layui/layui/layHierarchyControlPanel.cc index 417148bee..ba90fa997 100644 --- a/src/layui/layui/layHierarchyControlPanel.cc +++ b/src/layui/layui/layHierarchyControlPanel.cc @@ -218,6 +218,7 @@ HierarchyControlPanel::HierarchyControlPanel (lay::LayoutViewBase *view, QWidget m_flat (false), m_split_mode (false), m_sorting (CellTreeModel::ByName), + m_cell_copy_mode (-1), m_do_update_content_dm (this, &HierarchyControlPanel::do_update_content), m_do_full_update_content_dm (this, &HierarchyControlPanel::do_full_update_content) { @@ -398,6 +399,12 @@ HierarchyControlPanel::clear_all () mp_cell_lists.clear (); } +void +HierarchyControlPanel::set_cell_copy_mode (int m) +{ + m_cell_copy_mode = m; +} + void HierarchyControlPanel::set_flat (bool f) { @@ -1002,6 +1009,47 @@ HierarchyControlPanel::has_focus () const return m_active_index >= 0 && m_active_index < int (mp_cell_lists.size ()) && mp_cell_lists [m_active_index]->hasFocus (); } +bool +HierarchyControlPanel::ask_for_cell_copy_mode (const db::Layout &layout, const std::vector &paths, int &cell_copy_mode) +{ + bool needs_to_ask = false; + cell_copy_mode = 0; + + if (m_cell_copy_mode < 0) { // ask + + // check if there is a cell that we have to ask for + for (std::vector::const_iterator p = paths.begin (); p != paths.end (); ++p) { + if (! p->empty ()) { + const db::Cell &cell = layout.cell (p->back ()); + if (! cell.is_proxy () && ! cell.is_leaf ()) { + needs_to_ask = true; + } + } + } + + } else { + cell_copy_mode = m_cell_copy_mode; + } + + if (needs_to_ask) { + + bool dont_ask_again = false; + + lay::CopyCellModeDialog mode_dialog (this); + if (! mode_dialog.exec_dialog (cell_copy_mode, dont_ask_again)) { + return false; + } + + if (dont_ask_again) { + view ()->dispatcher ()->config_set (cfg_copy_cell_mode, tl::to_string (cell_copy_mode)); + view ()->dispatcher ()->config_end (); + } + + } + + return true; +} + void HierarchyControlPanel::cut () { @@ -1017,34 +1065,25 @@ HierarchyControlPanel::cut () } // first copy - bool needs_to_ask = false; db::Layout &layout = m_cellviews [m_active_index]->layout (); if (! layout.is_editable ()) { return; } - // collect the called cells of the cells to copy, so we don't copy a cell twice - db::Clipboard::instance ().clear (); - // don't copy the cells which would be copied anyway + int cut_mode = 1; // 0: shallow, 1: deep + if (! ask_for_cell_copy_mode (layout, paths, cut_mode)) { + return; + } + + // collect the called cells of the cells to copy, so we don't copy a cell twice std::set called_cells; for (std::vector::const_iterator p = paths.begin (); p != paths.end (); ++p) { if (! p->empty ()) { const db::Cell &cell = layout.cell (p->back ()); cell.collect_called_cells (called_cells); - if (cell.cell_instances () > 0) { - needs_to_ask = true; - } - } - } - - int cut_mode = 1; // 0: shallow, 1: deep - if (needs_to_ask) { - lay::CopyCellModeDialog mode_dialog (this); - if (! mode_dialog.exec_dialog (cut_mode)) { - return; } } @@ -1115,34 +1154,25 @@ HierarchyControlPanel::copy () return; } - bool needs_to_ask = false; - db::Layout &layout = m_cellviews [m_active_index]->layout (); - // collect the called cells of the cells to copy, so we don't copy a cell twice - db::Clipboard::instance ().clear (); - // don't copy the cells which would be copied anyway + int copy_mode = 1; // 0: shallow, 1: deep + if (! ask_for_cell_copy_mode (layout, paths, copy_mode)) { + return; + } + + // collect the called cells of the cells to copy, so we don't copy a cell twice std::set called_cells; for (std::vector::const_iterator p = paths.begin (); p != paths.end (); ++p) { if (! p->empty ()) { const db::Cell &cell = layout.cell (p->back ()); cell.collect_called_cells (called_cells); - if (cell.cell_instances () > 0) { - needs_to_ask = true; - } - } - } - - int copy_mode = 1; // 0: shallow, 1: deep - if (needs_to_ask) { - lay::CopyCellModeDialog mode_dialog (this); - if (! mode_dialog.exec_dialog (copy_mode)) { - return; } } + // actually copy for (std::vector::const_iterator p = paths.begin (); p != paths.end (); ++p) { if (! p->empty () && called_cells.find (p->back ()) == called_cells.end ()) { db::ClipboardValue *cd = new db::ClipboardValue (); diff --git a/src/layui/layui/layHierarchyControlPanel.h b/src/layui/layui/layHierarchyControlPanel.h index 6801728d8..2053628d1 100644 --- a/src/layui/layui/layHierarchyControlPanel.h +++ b/src/layui/layui/layHierarchyControlPanel.h @@ -219,6 +219,12 @@ public: */ void paste (); + /** + * @brief Selects cell copy mode + * 0: shallow, 1: deep, -1: ask + */ + void set_cell_copy_mode (int m); + /** * @brief Return true, if the panel has a selection */ @@ -308,6 +314,7 @@ private: QSplitter *mp_splitter; tl::Color m_background_color; tl::Color m_text_color; + int m_cell_copy_mode; tl::DeferredMethod m_do_update_content_dm; tl::DeferredMethod m_do_full_update_content_dm; std::unique_ptr mp_tree_style; @@ -336,6 +343,9 @@ private: // clears all widgets of the cell lists void clear_all (); + + // ask for cell copy mode + bool ask_for_cell_copy_mode (const db::Layout &layout, const std::vector &paths, int &cell_copy_mode); }; } // namespace lay diff --git a/src/layui/layui/layLayoutViewConfigPages.cc b/src/layui/layui/layLayoutViewConfigPages.cc index c7f57f806..81d7cbf1e 100644 --- a/src/layui/layui/layLayoutViewConfigPages.cc +++ b/src/layui/layui/layLayoutViewConfigPages.cc @@ -42,6 +42,7 @@ #include "ui_LayoutViewConfigPage6.h" #include "ui_LayoutViewConfigPage6a.h" #include "ui_LayoutViewConfigPage7.h" +#include "ui_LayoutViewConfigPage8.h" #include "laySelectStippleForm.h" #include "laySelectLineStyleForm.h" @@ -1529,6 +1530,37 @@ LayoutViewConfigPage7::commit (lay::Dispatcher *root) root->config_set (cfg_initial_hier_depth, mp_ui->def_depth->value ()); } +// ------------------------------------------------------------ +// LayoutConfigPage8 implementation + +LayoutViewConfigPage8::LayoutViewConfigPage8 (QWidget *parent) + : lay::ConfigPage (parent) +{ + mp_ui = new Ui::LayoutViewConfigPage8 (); + mp_ui->setupUi (this); +} + +LayoutViewConfigPage8::~LayoutViewConfigPage8 () +{ + delete mp_ui; + mp_ui = 0; +} + +void +LayoutViewConfigPage8::setup (lay::Dispatcher *root) +{ + int cpm = -1; + root->config_get (cfg_copy_cell_mode, cpm); + mp_ui->hier_copy_mode_cbx->setCurrentIndex ((cpm < 0 || cpm > 1) ? 2 : cpm); +} + +void +LayoutViewConfigPage8::commit (lay::Dispatcher *root) +{ + int cpm = mp_ui->hier_copy_mode_cbx->currentIndex (); + root->config_set (cfg_copy_cell_mode, (cpm < 0 || cpm > 1) ? -1 : cpm); +} + // ------------------------------------------------------------ // The dummy plugin declaration to register the configuration options @@ -1554,6 +1586,7 @@ public: pages.push_back (std::make_pair (tl::to_string (QObject::tr ("Application|Tracking")), new LayoutViewConfigPage2d (parent))); pages.push_back (std::make_pair (tl::to_string (QObject::tr ("Application|Layer Properties")), new LayoutViewConfigPage5 (parent))); pages.push_back (std::make_pair (tl::to_string (QObject::tr ("Application|Units")), new LayoutViewConfigPage3c (parent))); + pages.push_back (std::make_pair (tl::to_string (QObject::tr ("Application|Cells")), new LayoutViewConfigPage8 (parent))); pages.push_back (std::make_pair (tl::to_string (QObject::tr ("Navigation|New Cell")), new LayoutViewConfigPage3a (parent))); pages.push_back (std::make_pair (tl::to_string (QObject::tr ("Navigation|Zoom And Pan")), new LayoutViewConfigPage3b (parent))); diff --git a/src/layui/layui/layLayoutViewConfigPages.h b/src/layui/layui/layLayoutViewConfigPages.h index ab6cbece6..3d6c4718d 100644 --- a/src/layui/layui/layLayoutViewConfigPages.h +++ b/src/layui/layui/layLayoutViewConfigPages.h @@ -50,6 +50,7 @@ namespace Ui { class LayoutViewConfigPage6; class LayoutViewConfigPage6a; class LayoutViewConfigPage7; + class LayoutViewConfigPage8; } namespace lay @@ -355,6 +356,22 @@ private: Ui::LayoutViewConfigPage7 *mp_ui; }; +class LayoutViewConfigPage8 + : public lay::ConfigPage +{ +Q_OBJECT + +public: + LayoutViewConfigPage8 (QWidget *parent); + ~LayoutViewConfigPage8 (); + + virtual void setup (lay::Dispatcher *root); + virtual void commit (lay::Dispatcher *root); + +private: + Ui::LayoutViewConfigPage8 *mp_ui; +}; + } #endif diff --git a/src/layui/layui/layui.pro b/src/layui/layui/layui.pro index 00099e914..ed6ac69a0 100644 --- a/src/layui/layui/layui.pro +++ b/src/layui/layui/layui.pro @@ -40,6 +40,7 @@ FORMS = \ LayoutViewConfigPage6.ui \ LayoutViewConfigPage7.ui \ LayoutViewConfigPage.ui \ + LayoutViewConfigPage8.ui \ LibraryCellSelectionForm.ui \ LoadLayoutOptionsDialog.ui \ MarkerBrowserConfigPage2.ui \ diff --git a/src/layview/layview/layLayoutView_qt.cc b/src/layview/layview/layLayoutView_qt.cc index e30283dba..d4f67b772 100644 --- a/src/layview/layview/layLayoutView_qt.cc +++ b/src/layview/layview/layLayoutView_qt.cc @@ -938,6 +938,14 @@ LayoutView::configure (const std::string &name, const std::string &value) } return true; + } else if (name == cfg_copy_cell_mode) { + + if (mp_hierarchy_panel) { + int m = 0; + tl::from_string (value, m); + mp_hierarchy_panel->set_cell_copy_mode (m); + } + } else if (name == cfg_cell_list_sorting) { if (mp_hierarchy_panel) {