HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
plugin_parameter_dialog.cpp
Go to the documentation of this file.
9 #include "gui/gui_globals.h"
10 #include <QDebug>
11 #include <QFormLayout>
12 #include <QGridLayout>
13 #include <QHBoxLayout>
14 #include <QLineEdit>
15 #include <QDialogButtonBox>
16 #include <QPushButton>
17 #include <QSpinBox>
18 #include <QCheckBox>
19 #include <QTabWidget>
20 #include <QFileDialog>
21 #include <QTableWidget>
22 #include <QComboBox>
23 
24 namespace hal {
26  : QDialog(parent), mPluginName(pname), mGuiExtensionInterface(geif)
27  {
28  setupHash();
29 
30  QDialogButtonBox* bbox = setupButtonBox();
31 
32  setWindowTitle("Settings for " + mPluginName + " plugin");
33 
34  if (mTabNames.isEmpty())
35  {
36  QFormLayout* layout = new QFormLayout(this);
37  setupForm(layout);
38  layout->addRow(bbox);
39  }
40  else
41  {
42  QGridLayout* grid = new QGridLayout(this);
43  QTabWidget* tabw = new QTabWidget(this);
44  for (auto it = mTabNames.constBegin(); it != mTabNames.constEnd(); ++it)
45  {
46  QWidget* tab = new QWidget(tabw);
47  QFormLayout* layout = new QFormLayout(tab);
48  setupForm(layout,it.key());
49  tabw->addTab(tab,it.value());
50  }
51  grid->addWidget(tabw,0,0,1,2);
52  grid->addWidget(bbox,1,1);
53  }
54  }
55 
56  QDialogButtonBox* PluginParameterDialog::setupButtonBox()
57  {
59  for (const PluginParameter& par : mParameterList)
60  {
61  if (par.get_type() != PluginParameter::PushButton || par.get_tagname().find('/') != std::string::npos) continue;
62  QPushButton* but = static_cast<QPushButton*>(mWidgetMap.value(QString::fromStdString(par.get_tagname())));
63  Q_ASSERT(but);
64  connect(but,&QPushButton::clicked,this,&PluginParameterDialog::handlePushbuttonClicked);
66  }
69  return retval;
70  }
71 
72  void PluginParameterDialog::setupHash()
73  {
74  if (!mGuiExtensionInterface) return;
75  for (PluginParameter par : mGuiExtensionInterface->get_parameter())
76  {
77  if (par.get_type() == PluginParameter::Absent) continue;
78  QString parTagname = QString::fromStdString(par.get_tagname());
79  QString parLabel = QString::fromStdString(par.get_label());
80  QString parDefault = QString::fromStdString(par.get_value());
81 
82  mParameterList.append(par);
83 
84  QStringList tabbed = parTagname.split('/');
85  if (tabbed.size() > 1)
86  {
87  QString tabTag = tabbed.at(0);
88  if (!mTabNames.contains(tabTag))
89  mTabNames[tabTag] = tabTag;
90  }
91 
92  switch (par.get_type())
93  {
95  mTabNames[parTagname] = parLabel;
96  break;
98  mWidgetMap[parTagname] = new QPushButton(parLabel,this);
99  break;
101  {
102  KeyValueTable* kvt = new KeyValueTable(parLabel,this);
103  kvt->setJson(par.get_value());
104  mWidgetMap[parTagname] = kvt;
105  break;
106  }
108  {
109  mWidgetMap[parTagname] = new ColorSelection(parDefault, parLabel, true);
110  break;
111  }
113  {
114  QCheckBox* check = new QCheckBox(parLabel,this);
115  check->setChecked(parDefault.toLower()=="true");
116  mWidgetMap[parTagname] = check;
117  break;
118  }
120  {
121  QSpinBox* intBox = new QSpinBox(this);
122  intBox->setMaximum(1000000000);
123  intBox->setValue(parDefault.toInt());
124  mWidgetMap[parTagname] = intBox;
125  break;
126  }
128  {
129  QDoubleSpinBox* floatBox = new QDoubleSpinBox(this);
130  floatBox->setMaximum(1.E99);
131  floatBox->setValue(parDefault.toDouble());
132  mWidgetMap[parTagname] = floatBox;
133  break;
134  }
136  {
137  QLabel* label = new QLabel(this);
138  label->setText(parDefault);
139  mWidgetMap[parTagname] = label;
140  break;
141  }
143  {
144  QLineEdit* ledit = new QLineEdit(this);
145  ledit->setText(parDefault);
146  mWidgetMap[parTagname] = ledit;
147  break;
148  }
152  mWidgetMap[parTagname] = new PluginParameterFileDialog(par,this);
153  break;
155  mWidgetMap[parTagname] = new PluginParameterNodeDialog(par,this);
156  break;
158  mWidgetMap[parTagname] = new PluginParameterNodeDialog(par,this);
159  break;
161  {
162  QComboBox* cbox = new QComboBox(this);
163  cbox->insertItems(0,QString::fromStdString(par.get_value()).split(';'));
164  if (!par.get_value().empty()) cbox->setCurrentIndex(0);
165  mWidgetMap[parTagname] = cbox;
166  break;
167  }
168  default:
169  break;
170  }
171  }
172  }
173 
174  void PluginParameterDialog::setupForm(QFormLayout* form, const QString& tabTag)
175  {
176  for (const PluginParameter& par : mParameterList)
177  {
178  QString parTagname = QString::fromStdString(par.get_tagname());
179  if (!tabTag.isEmpty() && !parTagname.startsWith(tabTag+ "/")) continue;
180  QWidget* widget = mWidgetMap.value(parTagname);
181  if (!widget) continue;
182 
183  switch (par.get_type())
184  {
185  // push button not in tab are located in button box
187  if (par.get_tagname().find('/')!=std::string::npos)
188  {
189  QPushButton* but = static_cast<QPushButton*>(widget);
190  Q_ASSERT(but);
191  connect(but,&QPushButton::clicked,this,&PluginParameterDialog::handlePushbuttonClicked);
192  form->addRow(but);
193  }
194  break;
195  // without label
198  form->addRow(widget);
199  break;
200  // label + widget
201  default:
202  QString parLabel = QString::fromStdString(par.get_label());
203  form->addRow(parLabel, widget);
204  break;
205  }
206  }
207  }
208 
210  {
211  if (!mGuiExtensionInterface) return;
212  std::vector<PluginParameter> settings;
213  std::string buttonClicked;
214  for (PluginParameter par : mParameterList)
215  {
216  const QWidget* w = mWidgetMap.value(QString::fromStdString(par.get_tagname()));
217  if (!w) continue;
218 
219  switch (par.get_type())
220  {
222  if (par.get_value() == "clicked")
223  {
224  buttonClicked = par.get_tagname();
225  }
226  break;
228  {
229  const KeyValueTable* kvt = static_cast<const KeyValueTable*>(w);
230  par.set_value(kvt->toJson());
231  break;
232  }
234  {
235  const ColorSelection* colsel = static_cast<const ColorSelection*>(w);
236  par.set_value(colsel->colorName().toStdString());
237  break;
238  }
240  {
241  const QCheckBox* check = static_cast<const QCheckBox*>(w);
242  par.set_value(check->checkState()==Qt::Checked ? "true" : "false");
243  break;
244  }
246  {
247  const QSpinBox* intBox = static_cast<const QSpinBox*>(w);
248  par.set_value(QString::number(intBox->value()).toStdString());
249  break;
250  }
252  {
253  const QDoubleSpinBox* floatBox = static_cast<const QDoubleSpinBox*>(w);
254  par.set_value(QString::number(floatBox->value()).toStdString());
255  break;
256  }
258  {
259  par.set_value(std::string());
260  break;
261  }
263  {
264  const QLineEdit* ledit = static_cast<const QLineEdit*>(w);
265  par.set_value(ledit->text().toStdString());
266  break;
267  }
271  {
272  const PluginParameterFileDialog* fileDlg = static_cast<const PluginParameterFileDialog*>(w);
273  par.set_value(fileDlg->getFilename().toStdString());
274  break;
275  }
278  {
279  const PluginParameterNodeDialog* nodeDlg = static_cast<const PluginParameterNodeDialog*>(w);
280  par.set_value(QString::number(nodeDlg->getNodeId()).toStdString());
281  break;
282  }
284  {
285  const QComboBox* cbox = static_cast<const QComboBox*>(w);
286  par.set_value(cbox->currentText().toStdString());
287  break;
288  }
289  default:
290  continue;
291  break;
292  }
293  settings.push_back(par);
294  }
295  QDialog::accept();
296  mGuiExtensionInterface->set_parameter(settings);
297 
298  if (!buttonClicked.empty())
299  {
303  }
304  }
305 
306  void PluginParameterDialog::handlePushbuttonClicked()
307  {
308  for (PluginParameter& par : mParameterList)
309  if (par.get_type() == PluginParameter::PushButton)
310  {
311  const QWidget* w = mWidgetMap.value(QString::fromStdString(par.get_tagname()));
312  if (sender() == w)
313  {
314  par.set_value("clicked");
315  }
316  }
317  accept();
318  }
319 
321  : QWidget(parent), mParameter(par)
322  {
323  QGridLayout* layout = new QGridLayout(this);
324  QString parDefault = QString::fromStdString(mParameter.get_value());
325  mEditor = new QLineEdit(this);
327  mEditor->setMinimumWidth(320);
328  mEditor->setText(parDefault);
329  layout->addWidget(mEditor,0,0);
330 
331  QString iconPath = (mParameter.get_type() == PluginParameter::NewFile)
332  ? ":/icons/folder-down"
333  : ":/icons/folder";
334  mButton = new QPushButton(gui_utility::getStyledSvgIcon("all->#3192C5",iconPath),"",this);
336  connect(mButton,&QPushButton::clicked,this,&PluginParameterFileDialog::handleActivateFileDialog);
337  layout->addWidget(mButton,0,1);
338  }
339 
340  void PluginParameterFileDialog::handleActivateFileDialog()
341  {
342  QString parLabel = QString::fromStdString(mParameter.get_label());
343  QString parDefault = QString::fromStdString(mParameter.get_value());
344  QString dir = QFileInfo(parDefault).isDir() ? parDefault : QFileInfo(parDefault).path();
345  QString filename;
346  switch (mParameter.get_type()) {
348  filename = QFileDialog::getExistingDirectory(this,parLabel,dir);
349  break;
351  filename = QFileDialog::getOpenFileName(this,parLabel,dir);
352  break;
354  filename = QFileDialog::getSaveFileName(this,parLabel,dir);
355  break;
356  default:
357  Q_ASSERT (1==0); // should never happen
358  }
359  if (!filename.isEmpty())
360  mEditor->setText(filename);
361  }
362 
364  {
365  return mEditor->text();
366  }
367 
369  : QWidget(parent), mParameter(par)
370  {
371  QGridLayout* layout = new QGridLayout(this);
372  mNodeId = new QSpinBox(this);
374  layout->addWidget(mNodeId,0,0);
375  mNodeName = new QLabel(this);
377  mNodeName->setMinimumWidth(280);
378  layout->addWidget(mNodeName,0,1);
379 
380  mButton = new QPushButton("",this);
381 
382  u32 defaultId = QString::fromStdString(mParameter.get_value()).toUInt();
383  mNodeId->setValue(defaultId);
384 
385  QString iconPath;
386  switch (mParameter.get_type()) {
388  iconPath = ":/icons/ne_module";
389  setModule(defaultId);
390  connect(mButton,&QPushButton::clicked,this,&PluginParameterNodeDialog::handleActivateModuleDialog);
391  connect(mNodeId,static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),this,&PluginParameterNodeDialog::setModule);
392  mValidIds = gNetlist->get_used_module_ids();
393  break;
395  iconPath = ":/icons/ne_gate";
396  setGate(defaultId);
397  connect(mButton,&QPushButton::clicked,this,&PluginParameterNodeDialog::handleActivateGateDialog);
398  connect(mNodeId,static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),this,&PluginParameterNodeDialog::setGate);
399  mValidIds = gNetlist->get_used_gate_ids();
400  break;
401  default:
402  Q_ASSERT(1==0); // widget must not be created if parameter type not module or gate
403  break;
404  }
405 
406  u32 maxValue = 0;
407  for (u32 id : mValidIds)
408  if (id > maxValue)
409  maxValue = id;
410  mNodeId->setMaximum(maxValue);
411  if (defaultId > maxValue)
412  mNodeId->setValue(0);
413  mButton->setIcon(gui_utility::getStyledSvgIcon("all->#F0F0F1",iconPath));
415  layout->addWidget(mButton,0,2);
416  }
417 
418  void PluginParameterNodeDialog::setGate(int id)
419  {
420  if (!id || !isValidId(id))
421  {
422  mNodeName->setText("(no gate selected)");
423  return;
424  }
425  Gate* g = gNetlist->get_gate_by_id(id);
426  if (g) mNodeName->setText(QString::fromStdString(g->get_name()));
427  }
428 
429  void PluginParameterNodeDialog::setModule(int id)
430  {
431  if (!id || !isValidId(id))
432  {
433  mNodeName->setText("(no module selected)");
434  return;
435  }
436  Module* m = gNetlist->get_module_by_id(id);
437  if (m) mNodeName->setText(QString::fromStdString(m->get_name()));
438  }
439 
440  bool PluginParameterNodeDialog::isValidId(int id) const
441  {
442  return (mValidIds.find(id)!=mValidIds.end());
443  }
444 
445  void PluginParameterNodeDialog::handleActivateModuleDialog()
446  {
447  ModuleDialog md({}, "Select module", false, nullptr, this);
448  if (md.exec() == QDialog::Accepted)
449  {
450  setModule(md.selectedId());
451  mNodeId->setValue(md.selectedId());
452  }
453  }
454 
455  void PluginParameterNodeDialog::handleActivateGateDialog()
456  {
457  GateDialog gd({}, "Select gate", nullptr, this);
458  if (gd.exec() == QDialog::Accepted)
459  {
460  setGate(gd.selectedId());
461  mNodeId->setValue(gd.selectedId());
462  }
463  }
464 
466  {
467  return mNodeId->value();
468  }
469 }
QString colorName() const
virtual void execute_function(std::string tag, Netlist *nl, const std::vector< u32 > &mods, const std::vector< u32 > &gats, const std::vector< u32 > &nets)
virtual void set_parameter(const std::vector< PluginParameter > &params)
virtual std::vector< PluginParameter > get_parameter() const
std::string toJson() const
Gate * get_gate_by_id(const u32 gate_id) const
Definition: netlist.cpp:193
std::set< u32 > get_used_gate_ids() const
Definition: netlist.cpp:741
std::set< u32 > get_used_module_ids() const
Definition: netlist.cpp:801
Module * get_module_by_id(u32 module_id) const
Definition: netlist.cpp:613
PluginParameterDialog(const QString &pname, GuiExtensionInterface *geif, QWidget *parent=nullptr)
PluginParameterFileDialog(const PluginParameter &par, QWidget *parent=nullptr)
std::string get_label() const
std::string get_value() const
ParameterType get_type() const
PluginParameterNodeDialog(const PluginParameter &par, QWidget *parent=nullptr)
PythonThread * pythonThread() const
std::vector< u32 > selectedGatesVector() const
std::vector< u32 > selectedNetsVector() const
std::vector< u32 > selectedModulesVector() const
uint32_t u32
Definition: defines.h:41
QIcon getStyledSvgIcon(const QString &from_to_colors_enabled, const QString &svg_path, QString from_to_colors_disabled=QString())
Definition: graphics.cpp:60
Definition: defines.h:45
PythonContext * gPythonContext
Definition: plugin_gui.cpp:88
SelectionRelay * gSelectionRelay
Definition: plugin_gui.cpp:83
Netlist * gNetlist
Definition: gui_globals.h:69
i32 id
void setChecked(bool)
void clicked(bool checked)
void setIcon(const QIcon &icon)
Qt::CheckState checkState() const const
void setCurrentIndex(int index)
void insertItems(int index, const QStringList &list)
virtual void accept()
virtual void reject()
void addButton(QAbstractButton *button, QDialogButtonBox::ButtonRole role)
void setMaximum(double max)
void setValue(double val)
QString getExistingDirectory(QWidget *parent, const QString &caption, const QString &dir, QFileDialog::Options options)
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
QString getSaveFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
bool isDir() const const
QString path() const const
void addRow(QWidget *label, QWidget *field)
void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
void setText(const QString &)
void addWidget(QWidget *w)
void setText(const QString &)
const T & at(int i) const const
int size() const const
QMap::const_iterator constBegin() const const
QMap::const_iterator constEnd() const const
bool contains(const Key &key) const const
bool isEmpty() const const
const T value(const Key &key, const T &defaultValue) const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * sender() const const
void setMaximum(int max)
void setValue(int val)
void valueChanged(int i)
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QString fromStdString(const std::string &str)
bool isEmpty() const const
QString number(int n, int base)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
double toDouble(bool *ok) const const
int toInt(bool *ok, int base) const const
QString toLower() const const
std::string toStdString() const const
uint toUInt(bool *ok, int base) const const
int addTab(QWidget *page, const QString &label)
QWidget(QWidget *parent, Qt::WindowFlags f)
QLayout * layout() const const
void setMinimumWidth(int minw)
void setSizePolicy(QSizePolicy)
void setWindowTitle(const QString &)