WIP: first 'recent options' list, dragging a PCell variant into the canvas makes the editor take a PCell with these parameters.

This commit is contained in:
Matthias Koefferlein 2020-08-15 00:13:17 +02:00
parent 9a2c091f65
commit ee5cd9cb63
13 changed files with 493 additions and 106 deletions

View File

@ -21,7 +21,9 @@ HEADERS = \
edtServiceImpl.h \
edtUtils.h \
edtCommon.h \
edtDistribute.h
edtDistribute.h \
edtRecentConfigurationPage.h \
edtEditorOptionsPage.h
FORMS = \
AlignOptionsDialog.ui \
@ -59,7 +61,9 @@ SOURCES = \
edtServiceImpl.cc \
edtUtils.cc \
gsiDeclEdt.cc \
edtDistribute.cc
edtDistribute.cc \
edtRecentConfigurationPage.cc \
edtEditorOptionsPage.cc
INCLUDEPATH += $$TL_INC $$GSI_INC $$LAYBASIC_INC $$DB_INC
DEPENDPATH += $$TL_INC $$GSI_INC $$LAYBASIC_INC $$DB_INC

View File

@ -0,0 +1,65 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "tlInternational.h"
#include "edtEditorOptionsPage.h"
#include "edtEditorOptionsPages.h"
namespace edt
{
// ------------------------------------------------------------------
// EditorOptionsPage implementation
EditorOptionsPage::EditorOptionsPage (lay::Dispatcher *dispatcher)
: QWidget (0), mp_owner (0), m_active (true), mp_plugin_declaration (0), mp_dispatcher (dispatcher)
{
// nothing yet ..
}
EditorOptionsPage::~EditorOptionsPage ()
{
set_owner (0);
}
void
EditorOptionsPage::set_owner (EditorOptionsPages *owner)
{
if (mp_owner) {
mp_owner->unregister_page (this);
}
mp_owner = owner;
}
void
EditorOptionsPage::activate (bool active)
{
if (m_active != active) {
m_active = active;
if (mp_owner) {
mp_owner->activate_page (this);
}
}
}
}

View File

@ -0,0 +1,86 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_edtEditorOptionsPage
#define HDR_edtEditorOptionsPage
#include <QWidget>
namespace lay
{
class PluginDeclaration;
class Dispatcher;
class Plugin;
}
namespace edt
{
class EditorOptionsPages;
/**
* @brief The base class for a object properties page
*/
class EditorOptionsPage
: public QWidget
{
Q_OBJECT
public:
EditorOptionsPage (lay::Dispatcher *dispatcher);
virtual ~EditorOptionsPage ();
virtual std::string title () const = 0;
virtual int order () const = 0;
virtual void apply (lay::Dispatcher * /*root*/) { }
virtual void setup (lay::Dispatcher * /*root*/) { }
virtual void commit_recent (lay::Dispatcher * /*root*/) { }
bool active () const { return m_active; }
void activate (bool active);
void set_owner (EditorOptionsPages *owner);
const lay::PluginDeclaration *plugin_declaration () const { return mp_plugin_declaration; }
void set_plugin_declaration (const lay::PluginDeclaration *pd) { mp_plugin_declaration = pd; }
protected slots:
void edited ()
{
apply (dispatcher ());
}
protected:
lay::Dispatcher *dispatcher () const
{
return mp_dispatcher;
}
private:
EditorOptionsPages *mp_owner;
bool m_active;
const lay::PluginDeclaration *mp_plugin_declaration;
lay::Dispatcher *mp_dispatcher;
};
}
#endif

View File

@ -49,40 +49,6 @@
namespace edt
{
// ------------------------------------------------------------------
// EditorOptionsPage implementation
EditorOptionsPage::EditorOptionsPage (lay::Dispatcher *dispatcher)
: QWidget (0), mp_owner (0), m_active (true), mp_plugin_declaration (0), mp_dispatcher (dispatcher)
{
// nothing yet ..
}
EditorOptionsPage::~EditorOptionsPage ()
{
set_owner (0);
}
void
EditorOptionsPage::set_owner (EditorOptionsPages *owner)
{
if (mp_owner) {
mp_owner->unregister_page (this);
}
mp_owner = owner;
}
void
EditorOptionsPage::activate (bool active)
{
if (m_active != active) {
m_active = active;
if (mp_owner) {
mp_owner->activate_page (this);
}
}
}
// ------------------------------------------------------------------
// EditorOptionsPages implementation
@ -174,9 +140,9 @@ EditorOptionsPages::update (edt::EditorOptionsPage *page)
if ((*p) == page) {
index = mp_pages->count ();
}
mp_pages->addTab ((*p)->q_frame (), tl::to_qstring ((*p)->title ()));
mp_pages->addTab (*p, tl::to_qstring ((*p)->title ()));
} else {
(*p)->q_frame ()->setParent (0);
(*p)->setParent (0);
}
}
if (index < 0) {

View File

@ -24,6 +24,8 @@
#ifndef HDR_edtEditorOptionsPages
#define HDR_edtEditorOptionsPages
#include "edtEditorOptionsPage.h"
#include <tlVariant.h>
#include <QFrame>
@ -57,52 +59,6 @@ namespace edt
class PCellParametersPage;
class EditorOptionsPages;
/**
* @brief The base class for a object properties page
*/
class EditorOptionsPage
: public QWidget
{
Q_OBJECT
public:
EditorOptionsPage (lay::Dispatcher *dispatcher);
virtual ~EditorOptionsPage ();
virtual QWidget *q_frame () = 0;
virtual std::string title () const = 0;
virtual int order () const = 0;
virtual void apply (lay::Dispatcher *root) = 0;
virtual void setup (lay::Dispatcher *root) = 0;
bool active () const { return m_active; }
void activate (bool active);
void set_owner (EditorOptionsPages *owner);
const lay::PluginDeclaration *plugin_declaration () const { return mp_plugin_declaration; }
void set_plugin_declaration (const lay::PluginDeclaration *pd) { mp_plugin_declaration = pd; }
protected slots:
void edited ()
{
apply (dispatcher ());
}
protected:
lay::Dispatcher *dispatcher () const
{
return mp_dispatcher;
}
private:
EditorOptionsPages *mp_owner;
bool m_active;
const lay::PluginDeclaration *mp_plugin_declaration;
lay::Dispatcher *mp_dispatcher;
};
/**
* @brief The object properties dialog
*/
@ -149,8 +105,6 @@ public:
EditorOptionsGeneric (lay::Dispatcher *dispatcher);
~EditorOptionsGeneric ();
virtual QWidget *q_frame () { return this; }
virtual std::string title () const;
virtual int order () const { return 0; }
void apply (lay::Dispatcher *root);
@ -174,8 +128,6 @@ public:
EditorOptionsText (lay::Dispatcher *dispatcher);
~EditorOptionsText ();
virtual QWidget *q_frame () { return this; }
virtual std::string title () const;
virtual int order () const { return 10; }
void apply (lay::Dispatcher *root);
@ -197,8 +149,6 @@ public:
EditorOptionsPath (lay::Dispatcher *dispatcher);
~EditorOptionsPath ();
virtual QWidget *q_frame () { return this; }
virtual std::string title () const;
virtual int order () const { return 30; }
void apply (lay::Dispatcher *root);
@ -223,8 +173,6 @@ public:
EditorOptionsInst (lay::Dispatcher *root);
~EditorOptionsInst ();
virtual QWidget *q_frame () { return this; }
virtual std::string title () const;
virtual int order () const { return 20; }
void apply (lay::Dispatcher *root);
@ -233,7 +181,6 @@ public:
private slots:
void array_changed ();
void browse_cell ();
void update_pcell_parameters ();
void library_changed ();
void update_cell_edits ();
@ -241,8 +188,6 @@ private:
Ui::EditorOptionsInst *mp_ui;
edt::PCellParametersPage *mp_pcell_parameters;
int m_cv_index;
void update_pcell_parameters (const std::vector <tl::Variant> &parameters);
};
/**
@ -257,8 +202,6 @@ public:
EditorOptionsInstPCellParam (lay::Dispatcher *root);
~EditorOptionsInstPCellParam ();
virtual QWidget *q_frame () { return this; }
virtual std::string title () const;
virtual int order () const { return 21; }
void apply (lay::Dispatcher *root);

View File

@ -29,6 +29,7 @@
#include "edtMainService.h"
#include "edtPartialService.h"
#include "edtEditorOptionsPages.h"
#include "edtRecentConfigurationPage.h"
#include <QApplication>
#include <QLayout>
@ -85,9 +86,26 @@ void get_inst_options (std::vector < std::pair<std::string, std::string> > &opti
options.push_back (std::pair<std::string, std::string> (cfg_edit_show_shapes_of_instances, "true"));
}
edt::RecentConfigurationPage::ConfigurationDescriptor inst_cfg_descriptors[] =
{
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_cell_name, tl::to_string (tr ("Cell name")), edt::RecentConfigurationPage::Text),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_angle, tl::to_string (tr ("Angle")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_mirror, tl::to_string (tr ("Mirror")), edt::RecentConfigurationPage::Bool),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_scale, tl::to_string (tr ("Scale")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_array, tl::to_string (tr ("Array")), edt::RecentConfigurationPage::Bool),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_rows, tl::to_string (tr ("Rows")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_row_x, tl::to_string (tr ("Row step (x)")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_row_y, tl::to_string (tr ("Row step (y)")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_columns, tl::to_string (tr ("Columns")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_column_x, tl::to_string (tr ("Column step (x)")), edt::RecentConfigurationPage::Double),
edt::RecentConfigurationPage::ConfigurationDescriptor (cfg_edit_inst_column_y, tl::to_string (tr ("Column step (y)")), edt::RecentConfigurationPage::Double)
};
static
void get_inst_editor_options_pages (std::vector<edt::EditorOptionsPage *> &ret, lay::Dispatcher *dispatcher)
{
ret.push_back (new RecentConfigurationPage (dispatcher, 22, tl::to_string (tr ("Recent")),
&inst_cfg_descriptors[0], &inst_cfg_descriptors[sizeof (inst_cfg_descriptors) / sizeof (inst_cfg_descriptors[0])]));
ret.push_back (new EditorOptionsInstPCellParam (dispatcher));
ret.push_back (new EditorOptionsInst (dispatcher));
}
@ -422,6 +440,19 @@ setup_pages (lay::LayoutView *view)
}
}
void
commit_recent (lay::LayoutView *view)
{
edt::EditorOptionsPages *eo_pages = get_pages_widget (view);
if (!eo_pages) {
return;
}
for (std::vector<edt::EditorOptionsPage *>::const_iterator op = eo_pages->pages ().begin (); op != eo_pages->pages ().end (); ++op) {
(*op)->commit_recent (view);
}
}
class PartialPluginDeclaration
: public lay::PluginDeclaration
{

View File

@ -65,6 +65,11 @@ namespace edt
* @brief Setup the editor option pages for the given view
*/
void setup_pages (lay::LayoutView *view);
/**
* @brief Commits the current configuration for the recently used configuration list
*/
void commit_recent (lay::LayoutView *view);
}
#endif

View File

@ -0,0 +1,117 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "edtRecentConfigurationPage.h"
#include "layDispatcher.h"
#include <QVBoxLayout>
#include <QHeaderView>
namespace edt
{
void
RecentConfigurationPage::init ()
{
QVBoxLayout *ly = new QVBoxLayout (this);
ly->setMargin (0);
mp_tree_widget = new QTreeWidget (this);
ly->addWidget (mp_tree_widget);
mp_tree_widget->setColumnCount (int (m_cfg.size ()));
QStringList column_labels;
for (std::list<ConfigurationDescriptor>::const_iterator c = m_cfg.begin (); c != m_cfg.end (); ++c) {
column_labels << tl::to_qstring (c->title);
}
mp_tree_widget->setHeaderLabels (column_labels);
update_list ();
}
RecentConfigurationPage::~RecentConfigurationPage ()
{
// .. nothing yet ..
}
void
render_to (QTreeWidgetItem *item, int column, const std::string &v, RecentConfigurationPage::ConfigurationRendering rendering)
{
// @@@ rendering
item->setText (column, tl::to_qstring (v));
}
void
RecentConfigurationPage::update_list ()
{
int row = 0;
for (std::list<std::vector<std::string> >::const_iterator v = m_stored_values.begin (); v != m_stored_values.end (); ++v, ++row) {
QTreeWidgetItem *item = 0;
if (row < mp_tree_widget->topLevelItemCount ()) {
item = mp_tree_widget->topLevelItem (row);
} else {
item = new QTreeWidgetItem (mp_tree_widget);
mp_tree_widget->addTopLevelItem (item);
}
int column = 0;
for (std::list<ConfigurationDescriptor>::const_iterator c = m_cfg.begin (); c != m_cfg.end (); ++c, ++column) {
if (column < int (v->size ())) {
render_to (item, column, (*v) [column], c->rendering);
}
}
}
while (mp_tree_widget->topLevelItemCount () > row) {
delete mp_tree_widget->takeTopLevelItem (row);
}
mp_tree_widget->header ()->resizeSections (QHeaderView::ResizeToContents);
}
void
RecentConfigurationPage::commit_recent (lay::Dispatcher *root)
{
std::vector<std::string> values;
values.reserve (m_cfg.size ());
for (std::list<ConfigurationDescriptor>::const_iterator c = m_cfg.begin (); c != m_cfg.end (); ++c) {
values.push_back (root->config_get (c->cfg_name));
}
for (std::list<std::vector<std::string> >::iterator v = m_stored_values.begin (); v != m_stored_values.end (); ++v) {
if (*v == values) {
m_stored_values.erase (v);
break;
}
}
m_stored_values.push_front (values);
update_list ();
}
}

View File

@ -0,0 +1,97 @@
/*
KLayout Layout Viewer
Copyright (C) 2006-2020 Matthias Koefferlein
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef HDR_edtRecentConfigurationPage
#define HDR_edtRecentConfigurationPage
#include "edtEditorOptionsPage.h"
#include <list>
#include <QTreeWidget>
namespace edt
{
class PCellParametersPage;
class EditorOptionsPages;
/**
* @brief The base class for a object properties page
*/
class RecentConfigurationPage
: public EditorOptionsPage
{
Q_OBJECT
public:
enum ConfigurationRendering
{
Text = 0,
Bool = 1,
Double = 2,
Int = 3,
Layer = 4,
PCellParamters = 5
};
struct ConfigurationDescriptor
{
ConfigurationDescriptor (const std::string &_cfg_name, const std::string &_title, ConfigurationRendering _rendering)
: cfg_name (_cfg_name), title (_title), rendering (_rendering)
{ }
std::string cfg_name, title;
ConfigurationRendering rendering;
};
template <class Iter>
RecentConfigurationPage (lay::Dispatcher *dispatcher, int order, const std::string &title, Iter begin_cfg, Iter end_cfg)
: EditorOptionsPage (dispatcher), m_title (title), m_order (order), m_cfg (begin_cfg, end_cfg)
{
init ();
}
virtual ~RecentConfigurationPage ();
virtual std::string title () const { return m_title; }
virtual int order () const { return m_order; }
virtual void apply (lay::Dispatcher * /*root*/) { }
virtual void setup (lay::Dispatcher * /*root*/) { }
virtual void commit_recent (lay::Dispatcher *root);
private:
std::string m_title;
int m_order;
std::list<ConfigurationDescriptor> m_cfg;
QTreeWidget *mp_tree_widget;
std::list<std::vector<std::string> > m_stored_values;
void init ();
void update_list ();
};
}
#endif

View File

@ -26,6 +26,7 @@
#include "edtPropertiesPages.h"
#include "edtInstPropertiesPage.h"
#include "edtService.h"
#include "edtPlugin.h"
#include "dbEdge.h"
#include "dbLibrary.h"
#include "dbLibraryManager.h"
@ -1165,6 +1166,10 @@ InstService::drag_enter_event (const db::DPoint &p, const lay::DragDropDataBase
m_cell_or_pcell_name = pcell_decl->name ();
}
if (! cd->pcell_params ().empty ()) {
m_pcell_parameters = pcell_decl->named_parameters (cd->pcell_params ());
}
} else if (cd->layout ()->is_valid_cell_index (cd->cell_index ())) {
m_cell_or_pcell_name = cd->layout ()->cell_name (cd->cell_index ());
@ -1452,6 +1457,8 @@ InstService::do_finish_edit ()
cv->layout ().cleanup ();
manager ()->commit ();
commit_recent (view ());
if (m_in_drag_drop) {
lay::ObjectInstPath sel;

View File

@ -28,6 +28,7 @@
#include "dbPCellVariant.h"
#include "dbLibraryProxy.h"
#include "dbLibrary.h"
#include "dbLibraryManager.h"
#include <QTreeView>
#include <QPalette>
@ -604,14 +605,53 @@ CellTreeModel::mimeData(const QModelIndexList &indexes) const
{
for (QModelIndexList::const_iterator i = indexes.begin (); i != indexes.end (); ++i) {
if (i->isValid()) {
if (! i->isValid()) {
continue;
}
if (is_pcell (*i)) {
lay::CellDragDropData data (mp_layout, mp_library, pcell_id (*i), true);
return data.to_mime_data ();
} else {
const db::Cell *c = cell (*i);
if (c) {
// resolve library proxies
const db::Layout *layout = mp_layout;
const db::Library *library = mp_library;
const db::LibraryProxy *lib_proxy;
while (layout != 0 && (lib_proxy = dynamic_cast <const db::LibraryProxy *> (c)) != 0) {
const db::Library *lib = db::LibraryManager::instance ().lib (lib_proxy->lib_id ());
if (! lib) {
break;
}
library = lib;
layout = &lib->layout ();
if (layout->is_valid_cell_index (lib_proxy->library_cell_index ())) {
c = &layout->cell (lib_proxy->library_cell_index ());
} else {
c = 0;
}
}
// identify pcell variants and turn them into PCell drag targets
const db::PCellVariant *pcell_var = dynamic_cast<const db::PCellVariant *> (c);
if (pcell_var) {
lay::CellDragDropData data (layout, library, pcell_var->pcell_id (), true, pcell_var->parameters ());
return data.to_mime_data ();
} else if (c) {
lay::CellDragDropData data (layout, library, c->cell_index (), false);
return data.to_mime_data ();
}
if (is_pcell (*i)) {
lay::CellDragDropData data (mp_layout, mp_library, pcell_id (*i), true);
return data.to_mime_data ();
} else if (cell (*i)) {
lay::CellDragDropData data (mp_layout, mp_library, cell_index (*i), false);
return data.to_mime_data ();
}
}

View File

@ -73,6 +73,10 @@ CellDragDropData::serialized () const
stream << (quintptr) mp_library;
stream << m_cell_index;
stream << m_is_pcell;
stream << int (m_pcell_params.size ());
for (std::vector<tl::Variant>::const_iterator i = m_pcell_params.begin (); i != m_pcell_params.end (); ++i) {
stream << tl::to_qstring (i->to_parsable_string ());
}
return data;
}
@ -94,6 +98,19 @@ CellDragDropData::deserialize (const QByteArray &ba)
mp_library = reinterpret_cast <const db::Library *> (p);
stream >> m_cell_index;
stream >> m_is_pcell;
m_pcell_params.clear ();
int n = 0;
stream >> n;
while (n-- > 0) {
QString s;
stream >> s;
std::string stl_s = tl::to_string (s);
tl::Extractor ex (stl_s.c_str ());
m_pcell_params.push_back (tl::Variant ());
ex.read (m_pcell_params.back ());
}
return true;
} else {

View File

@ -130,8 +130,8 @@ public:
* @param layout the layout where the cell lives in
* @param cell_index The index of the cell
*/
CellDragDropData (const db::Layout *layout, const db::Library *library, db::cell_index_type cell_or_pcell_index, bool is_pcell)
: mp_layout (layout), mp_library (library), m_cell_index (cell_or_pcell_index), m_is_pcell (is_pcell)
CellDragDropData (const db::Layout *layout, const db::Library *library, db::cell_index_type cell_or_pcell_index, bool is_pcell, const std::vector<tl::Variant> &pcell_params = std::vector<tl::Variant> ())
: mp_layout (layout), mp_library (library), m_cell_index (cell_or_pcell_index), m_is_pcell (is_pcell), m_pcell_params (pcell_params)
{
// .. nothing yet ..
}
@ -152,6 +152,14 @@ public:
return mp_library;
}
/**
* @brief PCell parameters
*/
const std::vector<tl::Variant> &pcell_params () const
{
return m_pcell_params;
}
/**
* @brief Gets the index of the cell
*/
@ -185,6 +193,7 @@ private:
const db::Library *mp_library;
db::cell_index_type m_cell_index;
bool m_is_pcell;
std::vector<tl::Variant> m_pcell_params;
};
/**