HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
module_widget.cpp
Go to the documentation of this file.
2 
5 #include "gui/gui_globals.h"
7 #include "gui/toolbar/toolbar.h"
10 #include "hal_core/netlist/gate.h"
12 #include "hal_core/netlist/net.h"
17 
18 #include <QApplication>
19 #include <QHeaderView>
20 #include <QItemSelectionModel>
21 #include <QMenu>
22 #include <QModelIndex>
23 #include <QRegExp>
24 #include <QScrollBar>
25 #include <QSet>
26 #include <QShortcut>
27 #include <QTreeView>
28 #include <QVBoxLayout>
29 #include <QInputDialog>
30 #include <QClipboard>
31 
32 namespace hal
33 {
35  : ContentWidget("Modules", parent),
36  mTreeView(new ModuleTreeView(this)),
37  mSearchbar(new Searchbar(this)),
38  mToggleNetsAction(new QAction(this)),
39  mToggleGatesAction(new QAction(this)),
40  mRenameAction(new QAction(this)),
41  mDeleteAction(new QAction(this)),
42  mToggleExpandTreeAction(new QAction(this)),
43  mModuleProxyModel(new ModuleProxyModel(this))
44 
45  {
47 
49 
50  mToggleNetsAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mHideNetsIconPath));
51  mToggleGatesAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mHideGatesIconPath));
52  mSearchAction->setIcon(gui_utility::getStyledSvgIcon(mSearchIconStyle, mSearchIconPath));
53  mRenameAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mRenameIconPath));
54  mToggleExpandTreeAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mExpandedIconPath));
55 
56  mToggleNetsAction->setToolTip("Toggle net visibility");
57  mToggleGatesAction->setToolTip("Toggle gate visibility");
58  mDeleteAction->setToolTip("Delete module");
59  mSearchAction->setToolTip("Search");
60  mRenameAction->setToolTip("Rename");
61  mToggleExpandTreeAction->setToolTip("Toggle expand all / collapse all");
62 
63  mModuleModel = new ModuleModel(this);
64  mModuleProxyModel->setSourceModel(mModuleModel);
65 
66  mTreeView->setModel(mModuleProxyModel);
67  mTreeView->setDefaultColumnWidth();
68  mTreeView->setSortingEnabled(true);
69  mTreeView->sortByColumn(0, Qt::AscendingOrder);
72  mTreeView->setFrameStyle(QFrame::NoFrame);
73  //mTreeView->header()->close();
74  mTreeView->setExpandsOnDoubleClick(false);
75  // all rows are plain single line text, so the view must not measure each of them separately
76  mTreeView->setUniformRowHeights(true);
79  mContentLayout->addWidget(mTreeView);
80 
81  mSearchbar->setColumnNames(mModuleModel->headerLabels());
82  mContentLayout->addWidget(mSearchbar);
83  mSearchbar->hide();
84 
85  enableDeleteAction(false); // enable upon selected module
86  mIgnoreSelectionChange = false;
87 
89 
90  //connect(mSearchbar, &Searchbar::textEdited, this, &ModuleWidget::filter);
96 
98 
100  connect(mSearchbar, &Searchbar::triggerNewSearch, mModuleProxyModel, &ModuleProxyModel::startSearch);
101 
102  mShortCutDeleteItem = new QShortcut(ContentManager::sSettingDeleteItem->value().toString(), this);
103  mShortCutDeleteItem->setEnabled(false);
104 
106  connect(mShortCutDeleteItem, &QShortcut::activated, this, &ModuleWidget::deleteSelectedItem);
107  connect(mDeleteAction, &QAction::triggered, this, &ModuleWidget::deleteSelectedItem);
108 
109  connect(qApp, &QApplication::focusChanged, this, &ModuleWidget::handleDeleteShortcutOnFocusChanged);
110 
111 
112  connect(mToggleNetsAction, &QAction::triggered, this, &ModuleWidget::handleToggleNetsClicked);
113  connect(mToggleGatesAction, &QAction::triggered, this, &ModuleWidget::handleToggleGatesClicked);
114  connect(mToggleExpandTreeAction, &QAction::triggered, this, &ModuleWidget::handleToggleExpandTreeClicked);
115  connect(mRenameAction, &QAction::triggered, this, &ModuleWidget::handleRenameClicked);
116 
117  mModuleModel->populateTree({gNetlist->get_top_module()->get_id()});
118  mTreeView->expandAllModules();
119  }
120 
121  void ModuleWidget::enableDeleteAction(bool enable)
122  {
123  mDeleteAction->setEnabled(enable);
124  mDeleteAction->setIcon(gui_utility::getStyledSvgIcon(enable?mActiveIconStyle:mDisabledIconStyle, mDeleteIconPath));
125  }
126 
127  void ModuleWidget::handleToggleNetsClicked()
128  {
129  if(mModuleProxyModel->toggleFilterNets())
130  {
131  mToggleNetsAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mHideNetsIconPath));
132  }
133  else
134  {
135  mToggleNetsAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mShowNetsIconPath));
136  }
137  }
138 
139  void ModuleWidget::handleToggleGatesClicked()
140  {
141  if(mModuleProxyModel->toggleFilterGates())
142  {
143  mToggleGatesAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mHideGatesIconPath));
144  }
145  else
146  {
147  mToggleGatesAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mShowGatesIconPath));
148  }
149  }
150 
151  void ModuleWidget::handleToggleExpandTreeClicked()
152  {
153  if (mTreeView->toggleStateExpanded())
154  {
155  mTreeView->collapseAllModules();
156  mToggleExpandTreeAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mCollapsedIconPath));
157  }
158  else
159  {
160  mTreeView->expandAllModules();
161  mToggleExpandTreeAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mExpandedIconPath));
162  }
163  }
164 
165  void ModuleWidget::handleRenameClicked()
166  {
167  ModuleItem* item = getModuleItemFromIndex(mTreeView->currentIndex());
168  gNetlistRelay->changeElementNameDialog(item->getType(), item->id());
169  }
170 
172  {
173  toolbar->addAction(mToggleNetsAction);
174  toolbar->addAction(mToggleGatesAction);
175  toolbar->addAction(mRenameAction);
176  toolbar->addAction(mDeleteAction);
177  toolbar->addAction(mSearchAction);
178  toolbar->addAction(mToggleExpandTreeAction);
179  }
180 
182  {
185 
186  QList<QShortcut*> list;
187  list.append(mSearchShortcut);
188 
189  return list;
190  }
191 
193  {
194  if (!mSearchAction->isEnabled())
195  return;
196 
197  if (mSearchbar->isHidden())
198  {
199  mSearchbar->show();
200  mSearchbar->setFocus();
201  }
202  else
203  {
204  mSearchbar->hide();
205  setFocus();
206  }
207  }
208 
209  void ModuleWidget::filter(const QString& text)
210  {
211  QRegularExpression* regex = new QRegularExpression(text);
212  if (regex->isValid())
213  {
214  mModuleProxyModel->setFilterRegularExpression(*regex);
215  mTreeView->expandAllModules();
216  QString output = "navigation regular expression '" + text + "' entered.";
217  log_info("user", output.toStdString());
218  }
219  }
220 
222  {
223  QModelIndex index = mTreeView->indexAt(point);
224  if (!index.isValid())
225  return;
226 
227  ModuleItem* item = getModuleItemFromIndex(index);
229  u32 id = item->id();
230 
231  QMenu context_menu;
232 
234  ModuleContextMenu::addModuleSubmenu(&context_menu, id);
236  ModuleContextMenu::addGateSubmenu(&context_menu, id);
238  ModuleContextMenu::addNetSubmenu(&context_menu, id);
239 
241  type==ModuleItem::TreeItemType::Module ? std::vector<u32>({id}) : std::vector<u32>(),
242  type==ModuleItem::TreeItemType::Gate ? std::vector<u32>({id}) : std::vector<u32>(),
243  type==ModuleItem::TreeItemType::Net ? std::vector<u32>({id}) : std::vector<u32>());
244 
245  context_menu.exec(mTreeView->viewport()->mapToGlobal(point));
246  }
247 
249  {
250  UNUSED(module);
251  UNUSED(module_id);
252 
253  //prevents the execution of "handleTreeSelectionChanged"
254  //when a module is (re)moved the corresponding item in the tree is deleted and deselected, thus also triggering "handleTreeSelectionChanged"
255  //this call due to the selection model signals is unwanted behavior because "handleTreeSelectionChanged" is ment to only react to an "real" action performed by the user on the tree itself
256  mIgnoreSelectionChange = true;
257  }
258 
259  void ModuleWidget::handleCurrentChanged(const QModelIndex& current, const QModelIndex& previous)
260  {
261  Q_UNUSED(previous);
262  ModuleItem* mi = getModuleItemFromIndex(current);
263  if (!mi)
264  enableDeleteAction(false);
265  else
266  enableDeleteAction(mi->getType() == ModuleItem::TreeItemType::Module);
267  }
268 
270  {
271  Q_UNUSED(selected)
272  Q_UNUSED(deselected)
273 
274  if (mIgnoreSelectionChange || mModuleModel->isModifying())
275  return;
276 
278 
279  QModelIndexList current_selection = mTreeView->selectionModel()->selectedIndexes();
280 
281  QSet<int> selectedMods;
282  QSet<int> selectedGats;
283  for (const auto& index : current_selection)
284  {
285  ModuleItem* mi = getModuleItemFromIndex(index);
286  switch (mi->getType()) {
288  selectedMods.insert(mi->id());
289  gSelectionRelay->addModule(mi->id());
290  break;
292  selectedGats.insert(mi->id());
293  gSelectionRelay->addGate(mi->id());
294  break;
296  gSelectionRelay->addNet(mi->id());
297  break;
298  }
299  }
300 
301  if (selectedMods.size() == 1)
302  {
304  enableDeleteAction(true);
305  }
306  else if (selectedGats.size() == 1)
307  {
309  enableDeleteAction(false);
310  }
311  else
312  {
313  enableDeleteAction(false);
314  }
315 
317  }
318 
320  {
321  ModuleItem* mi = getModuleItemFromIndex(index);
322  switch(mi->getType()){
326  }
327  }
328 
330  {
331  if (sender == this)
332  return;
333 
334  mIgnoreSelectionChange = true;
335 
336  QItemSelection module_selection;
337 
338  for (auto module_id : gSelectionRelay->selectedModulesList())
339  {
340  for(ModuleItem* item : mModuleModel->getItems(module_id))
341  {
342  if(item)
343  {
344  QModelIndex index = mModuleProxyModel->mapFromSource(mModuleModel->getIndexFromItem(item));
345  module_selection.select(index, index);
346  }
347  }
348  }
349 
350  mTreeView->selectionModel()->select(module_selection, QItemSelectionModel::SelectionFlag::ClearAndSelect);
351 
352  mIgnoreSelectionChange = false;
353  }
354 
355  ModuleItem* ModuleWidget::getModuleItemFromIndex(const QModelIndex& index)
356  {
357  return mModuleModel->getItem(mModuleProxyModel->mapToSource(index));
358  }
359 
361  {
362  if (mSearchbar->filterApplied() && mSearchbar->isVisible())
363  mSearchAction->setIcon(gui_utility::getStyledSvgIcon(mSearchActiveIconStyle, mSearchIconPath));
364  else
365  mSearchAction->setIcon(gui_utility::getStyledSvgIcon(mSearchIconStyle, mSearchIconPath));
366  }
367 
369  {
370  return mModuleModel;
371  }
372 
374  {
375  return mDisabledIconStyle;
376  }
377 
379  {
380  return mActiveIconStyle;
381  }
382 
384  {
385  return mModuleProxyModel;
386  }
387 
389  {
390  return mShowNetsIconPath;
391  }
392 
394  {
395  return mHideNetsIconPath;
396  }
397 
399  {
400  return mShowGatesIconPath;
401  }
402 
404  {
405  return mHideGatesIconPath;
406  }
407 
409  {
410  return mSearchIconPath;
411  }
412 
414  {
415  return mSearchIconStyle;
416  }
417 
419  {
420  return mSearchActiveIconStyle;
421  }
422 
424  {
425  return mDeleteIconPath;
426  }
427 
429  {
430  return mRenameIconPath;
431  }
432 
434  {
435  return mExpandedIconPath;
436  }
437 
439  {
440  return mCollapsedIconPath;
441  }
442 
444  {
445  mDisabledIconStyle = style;
446  }
447 
449  {
450  mActiveIconStyle = style;
451  }
452 
454  {
455  mShowNetsIconPath = path;
456  }
457 
459  {
460  mHideNetsIconPath = path;
461  }
462 
464  {
465  mShowGatesIconPath = path;
466  }
467 
469  {
470  mHideGatesIconPath = path;
471  }
472 
474  {
475  mSearchIconPath = path;
476  }
477 
479  {
480  mSearchIconStyle = style;
481  }
482 
484  {
485  mSearchActiveIconStyle = style;
486  }
487 
489  {
490  mDeleteIconPath = path;
491  }
492 
494  {
495  mRenameIconPath = path;
496  }
497 
499  {
500  mExpandedIconPath = path;
501  }
502 
504  {
505  mCollapsedIconPath = path;
506  }
507 
508  void ModuleWidget::deleteSelectedItem()
509  {
510  if(!mTreeView->currentIndex().isValid())
511  {
512  return;
513  }
514 
515  ModuleItem* selectedItem = getModuleItemFromIndex(mTreeView->currentIndex());
516  if(selectedItem->getParent() != nullptr)
517  {
518  if (getModuleItemFromIndex(mTreeView->currentIndex())->getType() == ModuleItem::TreeItemType::Module)
519  {
520  auto module = gNetlist->get_module_by_id(selectedItem->id());
521  if(!module->is_top_module())
522  gNetlistRelay->deleteModule(getModuleItemFromIndex(mTreeView->currentIndex())->id());
523  }
524  }
525  }
526 
527  void ModuleWidget::handleDeleteShortcutOnFocusChanged(QWidget* oldWidget, QWidget* newWidget)
528  {
529  Q_UNUSED(oldWidget);
530  if(!newWidget) return;
531  if(newWidget->parent() == this)
532  {
533  mShortCutDeleteItem->setEnabled(true);
534  return;
535  }
536  else
537  {
538  mShortCutDeleteItem->setEnabled(false);
539  return;
540  }
541  }
542 }
QModelIndex getIndexFromItem(BaseTreeItem *item) const
QStringList headerLabels() const
static SettingsItemKeybind * sSettingDeleteItem
Abstract class for Widgets within HAL's ContentArea.
QKeySequence mSearchKeysequence
QString name() const
QShortcut * mSearchShortcut
QVBoxLayout * mContentLayout
void openModuleInView(u32 moduleId, bool unfold)
static void addPluginSubmenus(QMenu *contextMenu, Netlist *netlist, const std::vector< u32 > &modules, const std::vector< u32 > &gates, const std::vector< u32 > &nets)
static void addModuleSubmenu(QMenu *contextMenu, u32 id)
static void addGateSubmenu(QMenu *contextMenu, u32 id)
static void addNetSubmenu(QMenu *contextMenu, u32 id)
bool is_top_module() const
Definition: module.cpp:314
An item in the ModuleModel.
Definition: module_item.h:48
u32 id() const
TreeItemType getType() const
A model for displaying multiple netlist elements.
Definition: module_model.h:54
QList< ModuleItem * > getItems(const u32 id, ModuleItem::TreeItemType type=ModuleItem::TreeItemType::Module) const
ModuleItem * getItem(const QModelIndex &index) const
void populateTree(const QVector< u32 > &modIds={}, const QVector< u32 > &gatIds={}, const QVector< u32 > &netIds={})
Enables filtering in the ModuleModel.
void startSearch(QString text, int options) override
Wraps the QTreeView used for the ModuleWidget.
bool toggleStateExpanded() const
void handleTreeSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
void setSearchIconPath(const QString &path)
void setSearchIconStyle(const QString &style)
QString activeIconStyle() const
void setExpandedIconPath(const QString &path)
void setHideGatesIconPath(const QString &path)
QString renameIconPath() const
void setDisabledIconStyle(const QString &style)
QString searchIconPath() const
void filter(const QString &text)
QString expandedIconPath() const
void handleSelectionChanged(void *sender)
QString disabledIconStyle() const
void setShowNetsIconPath(const QString &path)
QString hideNetsIconPath() const
void handleTreeViewContextMenuRequested(const QPoint &point)
void setDeleteIconPath(const QString &path)
QString showNetsIconPath() const
virtual QList< QShortcut * > createShortcuts() override
QString searchIconStyle() const
ModuleProxyModel * proxyModel()
void setShowGatesIconPath(const QString &path)
void setCollapsedIconPath(const QString &path)
void handleItemDoubleClicked(const QModelIndex &index)
void handleCurrentChanged(const QModelIndex &current, const QModelIndex &previous=QModelIndex())
ModuleWidget(QWidget *parent=nullptr)
void setRenameIconPath(const QString &path)
void setSearchActiveIconStyle(const QString &style)
QString showGatesIconPath() const
void handleModuleRemoved(Module *module, u32 module_id)
void setHideNetsIconPath(const QString &path)
QString deleteIconPath() const
QString collapsedIconPath() const
void setActiveIconStyle(const QString &style)
QString hideGatesIconPath() const
ModuleModel * getModuleModel() const
QString searchActiveIconStyle() const
virtual void setupToolbar(Toolbar *toolbar) override
Module * get_top_module() const
Definition: netlist.cpp:608
Module * get_module_by_id(u32 module_id) const
Definition: netlist.cpp:613
void deleteModule(const u32 id)
void changeElementNameDialog(ModuleItem::TreeItemType type, u32 id)
void moduleSubmoduleRemoved(Module *m, const u32 removed_module) const
A QFrame with a QLineEdit that can be used to input a substring to search for.
Definition: searchbar.h:48
bool filterApplied()
Definition: searchbar.cpp:259
void setColumnNames(QList< QString > list)
Definition: searchbar.cpp:130
void triggerNewSearch(const QString &text, int searchOptions)
void setFocus(ItemType ftype, u32 fid, Subfocus sfoc=Subfocus::None, u32 sfinx=0)
void selectionChanged(void *sender)
void relaySelectionChanged(void *sender)
QList< u32 > selectedModulesList() const
void registerSender(void *sender, QString name)
void keySequenceChanged(QKeySequence value)
Toolbar for all ContentFrames and ContentWidgets.
Definition: toolbar.h:39
uint32_t u32
Definition: defines.h:41
#define UNUSED(expr)
Definition: defines.h:49
#define log_info(channel,...)
Definition: log.h:70
const Module * module(const Gate *g, const NodeBoxes &boxes)
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
GraphContextManager * gGraphContextManager
Definition: plugin_gui.cpp:85
SelectionRelay * gSelectionRelay
Definition: plugin_gui.cpp:83
Netlist * gNetlist
Definition: gui_globals.h:69
NetlistRelay * gNetlistRelay
Definition: gui_globals.h:74
PinType type
QModelIndex currentIndex() const const
void doubleClicked(const QModelIndex &index)
void setEditTriggers(QAbstractItemView::EditTriggers triggers)
void setSelectionBehavior(QAbstractItemView::SelectionBehavior behavior)
void setSelectionMode(QAbstractItemView::SelectionMode mode)
QItemSelectionModel * selectionModel() const const
QWidget * viewport() const const
void setEnabled(bool)
void setIcon(const QIcon &icon)
void setToolTip(const QString &tip)
void trigger()
void triggered(bool checked)
void focusChanged(QWidget *old, QWidget *now)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
void setFrameStyle(int style)
void select(const QModelIndex &topLeft, const QModelIndex &bottomRight)
void currentChanged(const QModelIndex &current, const QModelIndex &previous)
virtual void select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command)
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
void append(const T &value)
QAction * exec()
bool isValid() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
QObject * sender() const const
bool isValid() const const
QSet::iterator begin()
QSet::iterator insert(const T &value)
int size() const const
void activated()
void setEnabled(bool enable)
void setKey(const QKeySequence &key)
virtual QModelIndex mapFromSource(const QModelIndex &sourceIndex) const const override
virtual QModelIndex mapToSource(const QModelIndex &proxyIndex) const const override
void setFilterRegularExpression(const QString &pattern)
virtual void setSourceModel(QAbstractItemModel *sourceModel) override
QueuedConnection
CustomContextMenu
AscendingOrder
QAction * addAction(const QString &text)
void sortByColumn(int column)
void setExpandsOnDoubleClick(bool enable)
virtual QModelIndex indexAt(const QPoint &point) const const override
virtual void setModel(QAbstractItemModel *model) override
void setSortingEnabled(bool enable)
void setUniformRowHeights(bool uniform)
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
void customContextMenuRequested(const QPoint &pos)
void ensurePolished() const const
void hide()
bool isHidden() const const
QPoint mapToGlobal(const QPoint &pos) const const
void setFocus()
void show()
QStyle * style() const const
bool isVisible() const const