HAL  v4.5.0-133-g64838ea8d
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 <QScrollBar>
24 #include <QSet>
25 #include <QShortcut>
26 #include <QTreeView>
27 #include <QVBoxLayout>
28 
29 namespace hal
30 {
32  : ContentWidget("Modules", parent),
33  mTreeView(new ModuleTreeView(this)),
34  mSearchbar(new Searchbar(this)),
35  mToggleNetsAction(new QAction(this)),
36  mToggleGatesAction(new QAction(this)),
37  mRenameAction(new QAction(this)),
38  mDeleteAction(new QAction(this)),
39  mToggleExpandTreeAction(new QAction(this)),
40  mModuleProxyModel(new ModuleProxyModel(this))
41 
42  {
44 
46 
47  mToggleNetsAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mHideNetsIconPath));
48  mToggleGatesAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mHideGatesIconPath));
49  mSearchAction->setIcon(gui_utility::getStyledSvgIcon(mSearchIconStyle, mSearchIconPath));
50  mRenameAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mRenameIconPath));
51  mToggleExpandTreeAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mExpandedIconPath));
52 
53  mToggleNetsAction->setToolTip("Toggle net visibility");
54  mToggleGatesAction->setToolTip("Toggle gate visibility");
55  mDeleteAction->setToolTip("Delete module");
56  mSearchAction->setToolTip("Search");
57  mRenameAction->setToolTip("Rename");
58  mToggleExpandTreeAction->setToolTip("Toggle expand all / collapse all");
59 
60  mModuleModel = new ModuleModel(this);
61  mModuleProxyModel->setSourceModel(mModuleModel);
62 
63  mTreeView->setModel(mModuleProxyModel);
64  mTreeView->setDefaultColumnWidth();
65  mTreeView->setSortingEnabled(true);
66  mTreeView->sortByColumn(0, Qt::AscendingOrder);
69  mTreeView->setFrameStyle(QFrame::NoFrame);
70  //mTreeView->header()->close();
71  mTreeView->setExpandsOnDoubleClick(false);
72  // all rows are plain single line text, so the view must not measure each of them separately
73  mTreeView->setUniformRowHeights(true);
76  mContentLayout->addWidget(mTreeView);
77 
78  mSearchbar->setColumnNames(mModuleModel->headerLabels());
79  mContentLayout->addWidget(mSearchbar);
80  mSearchbar->hide();
81 
82  enableDeleteAction(false); // enable upon selected module
83  mIgnoreSelectionChange = false;
84 
86 
87  //connect(mSearchbar, &Searchbar::textEdited, this, &ModuleWidget::filter);
93 
95 
97  connect(mSearchbar, &Searchbar::triggerNewSearch, mModuleProxyModel, &ModuleProxyModel::startSearch);
98 
99  mShortCutDeleteItem = new QShortcut(ContentManager::sSettingDeleteItem->value().toString(), this);
100  mShortCutDeleteItem->setEnabled(false);
101 
103  connect(mShortCutDeleteItem, &QShortcut::activated, this, &ModuleWidget::deleteSelectedItem);
104  connect(mDeleteAction, &QAction::triggered, this, &ModuleWidget::deleteSelectedItem);
105 
106  connect(qApp, &QApplication::focusChanged, this, &ModuleWidget::handleDeleteShortcutOnFocusChanged);
107 
108 
109  connect(mToggleNetsAction, &QAction::triggered, this, &ModuleWidget::handleToggleNetsClicked);
110  connect(mToggleGatesAction, &QAction::triggered, this, &ModuleWidget::handleToggleGatesClicked);
111  connect(mToggleExpandTreeAction, &QAction::triggered, this, &ModuleWidget::handleToggleExpandTreeClicked);
112  connect(mRenameAction, &QAction::triggered, this, &ModuleWidget::handleRenameClicked);
113 
114  mModuleModel->populateTree({gNetlist->get_top_module()->get_id()});
115  mTreeView->expandAllModules();
116  }
117 
118  void ModuleWidget::enableDeleteAction(bool enable)
119  {
120  mDeleteAction->setEnabled(enable);
121  mDeleteAction->setIcon(gui_utility::getStyledSvgIcon(enable?mActiveIconStyle:mDisabledIconStyle, mDeleteIconPath));
122  }
123 
124  void ModuleWidget::handleToggleNetsClicked()
125  {
126  if(mModuleProxyModel->toggleFilterNets())
127  {
128  mToggleNetsAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mHideNetsIconPath));
129  }
130  else
131  {
132  mToggleNetsAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mShowNetsIconPath));
133  }
134  }
135 
136  void ModuleWidget::handleToggleGatesClicked()
137  {
138  if(mModuleProxyModel->toggleFilterGates())
139  {
140  mToggleGatesAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mHideGatesIconPath));
141  }
142  else
143  {
144  mToggleGatesAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mShowGatesIconPath));
145  }
146  }
147 
148  void ModuleWidget::handleToggleExpandTreeClicked()
149  {
150  if (mTreeView->toggleStateExpanded())
151  {
152  mTreeView->collapseAllModules();
153  mToggleExpandTreeAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mCollapsedIconPath));
154  }
155  else
156  {
157  mTreeView->expandAllModules();
158  mToggleExpandTreeAction->setIcon(gui_utility::getStyledSvgIcon(mActiveIconStyle, mExpandedIconPath));
159  }
160  }
161 
162  void ModuleWidget::handleRenameClicked()
163  {
164  ModuleItem* item = getModuleItemFromIndex(mTreeView->currentIndex());
165  gNetlistRelay->changeElementNameDialog(item->getType(), item->id());
166  }
167 
169  {
170  toolbar->addAction(mToggleNetsAction);
171  toolbar->addAction(mToggleGatesAction);
172  toolbar->addAction(mRenameAction);
173  toolbar->addAction(mDeleteAction);
174  toolbar->addAction(mSearchAction);
175  toolbar->addAction(mToggleExpandTreeAction);
176  }
177 
179  {
182 
183  QList<QShortcut*> list;
184  list.append(mSearchShortcut);
185 
186  return list;
187  }
188 
190  {
191  if (!mSearchAction->isEnabled())
192  return;
193 
194  if (mSearchbar->isHidden())
195  {
196  mSearchbar->show();
197  mSearchbar->setFocus();
198  }
199  else
200  {
201  mSearchbar->hide();
202  setFocus();
203  }
204  }
205 
206  void ModuleWidget::filter(const QString& text)
207  {
208  QRegularExpression* regex = new QRegularExpression(text);
209  if (regex->isValid())
210  {
211  mModuleProxyModel->setFilterRegularExpression(*regex);
212  mTreeView->expandAllModules();
213  QString output = "navigation regular expression '" + text + "' entered.";
214  log_info("user", output.toStdString());
215  }
216  }
217 
219  {
220  QModelIndex index = mTreeView->indexAt(point);
221  if (!index.isValid())
222  return;
223 
224  ModuleItem* item = getModuleItemFromIndex(index);
226  u32 id = item->id();
227 
228  QMenu context_menu;
229 
231  ModuleContextMenu::addModuleSubmenu(&context_menu, id);
233  ModuleContextMenu::addGateSubmenu(&context_menu, id);
235  ModuleContextMenu::addNetSubmenu(&context_menu, id);
236 
238  type==ModuleItem::TreeItemType::Module ? std::vector<u32>({id}) : std::vector<u32>(),
239  type==ModuleItem::TreeItemType::Gate ? std::vector<u32>({id}) : std::vector<u32>(),
240  type==ModuleItem::TreeItemType::Net ? std::vector<u32>({id}) : std::vector<u32>());
241 
242  context_menu.exec(mTreeView->viewport()->mapToGlobal(point));
243  }
244 
246  {
247  UNUSED(module);
248  UNUSED(module_id);
249 
250  //prevents the execution of "handleTreeSelectionChanged"
251  //when a module is (re)moved the corresponding item in the tree is deleted and deselected, thus also triggering "handleTreeSelectionChanged"
252  //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
253  mIgnoreSelectionChange = true;
254  }
255 
256  void ModuleWidget::handleCurrentChanged(const QModelIndex& current, const QModelIndex& previous)
257  {
258  Q_UNUSED(previous);
259  ModuleItem* mi = getModuleItemFromIndex(current);
260  if (!mi)
261  enableDeleteAction(false);
262  else
263  enableDeleteAction(mi->getType() == ModuleItem::TreeItemType::Module);
264  }
265 
267  {
268  Q_UNUSED(selected)
269  Q_UNUSED(deselected)
270 
271  if (mIgnoreSelectionChange || mModuleModel->isModifying())
272  return;
273 
275 
276  QModelIndexList current_selection = mTreeView->selectionModel()->selectedIndexes();
277 
278  QSet<int> selectedMods;
279  QSet<int> selectedGats;
280  for (const auto& index : current_selection)
281  {
282  ModuleItem* mi = getModuleItemFromIndex(index);
283  switch (mi->getType()) {
285  selectedMods.insert(mi->id());
286  gSelectionRelay->addModule(mi->id());
287  break;
289  selectedGats.insert(mi->id());
290  gSelectionRelay->addGate(mi->id());
291  break;
293  gSelectionRelay->addNet(mi->id());
294  break;
295  }
296  }
297 
298  if (selectedMods.size() == 1)
299  {
301  enableDeleteAction(true);
302  }
303  else if (selectedGats.size() == 1)
304  {
306  enableDeleteAction(false);
307  }
308  else
309  {
310  enableDeleteAction(false);
311  }
312 
314  }
315 
317  {
318  ModuleItem* mi = getModuleItemFromIndex(index);
319  switch(mi->getType()){
323  }
324  }
325 
327  {
328  if (sender == this)
329  return;
330 
331  mIgnoreSelectionChange = true;
332 
333  QItemSelection module_selection;
334 
335  for (auto module_id : gSelectionRelay->selectedModulesList())
336  {
337  for(ModuleItem* item : mModuleModel->getItems(module_id))
338  {
339  if(item)
340  {
341  QModelIndex index = mModuleProxyModel->mapFromSource(mModuleModel->getIndexFromItem(item));
342  module_selection.select(index, index);
343  }
344  }
345  }
346 
347  mTreeView->selectionModel()->select(module_selection, QItemSelectionModel::SelectionFlag::ClearAndSelect);
348 
349  mIgnoreSelectionChange = false;
350  }
351 
352  ModuleItem* ModuleWidget::getModuleItemFromIndex(const QModelIndex& index)
353  {
354  return mModuleModel->getItem(mModuleProxyModel->mapToSource(index));
355  }
356 
358  {
359  if (mSearchbar->filterApplied() && mSearchbar->isVisible())
360  mSearchAction->setIcon(gui_utility::getStyledSvgIcon(mSearchActiveIconStyle, mSearchIconPath));
361  else
362  mSearchAction->setIcon(gui_utility::getStyledSvgIcon(mSearchIconStyle, mSearchIconPath));
363  }
364 
366  {
367  return mModuleModel;
368  }
369 
371  {
372  return mDisabledIconStyle;
373  }
374 
376  {
377  return mActiveIconStyle;
378  }
379 
381  {
382  return mModuleProxyModel;
383  }
384 
386  {
387  return mShowNetsIconPath;
388  }
389 
391  {
392  return mHideNetsIconPath;
393  }
394 
396  {
397  return mShowGatesIconPath;
398  }
399 
401  {
402  return mHideGatesIconPath;
403  }
404 
406  {
407  return mSearchIconPath;
408  }
409 
411  {
412  return mSearchIconStyle;
413  }
414 
416  {
417  return mSearchActiveIconStyle;
418  }
419 
421  {
422  return mDeleteIconPath;
423  }
424 
426  {
427  return mRenameIconPath;
428  }
429 
431  {
432  return mExpandedIconPath;
433  }
434 
436  {
437  return mCollapsedIconPath;
438  }
439 
441  {
442  mDisabledIconStyle = style;
443  }
444 
446  {
447  mActiveIconStyle = style;
448  }
449 
451  {
452  mShowNetsIconPath = path;
453  }
454 
456  {
457  mHideNetsIconPath = path;
458  }
459 
461  {
462  mShowGatesIconPath = path;
463  }
464 
466  {
467  mHideGatesIconPath = path;
468  }
469 
471  {
472  mSearchIconPath = path;
473  }
474 
476  {
477  mSearchIconStyle = style;
478  }
479 
481  {
482  mSearchActiveIconStyle = style;
483  }
484 
486  {
487  mDeleteIconPath = path;
488  }
489 
491  {
492  mRenameIconPath = path;
493  }
494 
496  {
497  mExpandedIconPath = path;
498  }
499 
501  {
502  mCollapsedIconPath = path;
503  }
504 
505  void ModuleWidget::deleteSelectedItem()
506  {
507  if(!mTreeView->currentIndex().isValid())
508  {
509  return;
510  }
511 
512  ModuleItem* selectedItem = getModuleItemFromIndex(mTreeView->currentIndex());
513  if(selectedItem->getParent() != nullptr)
514  {
515  if (getModuleItemFromIndex(mTreeView->currentIndex())->getType() == ModuleItem::TreeItemType::Module)
516  {
517  auto module = gNetlist->get_module_by_id(selectedItem->id());
518  if(!module->is_top_module())
519  gNetlistRelay->deleteModule(getModuleItemFromIndex(mTreeView->currentIndex())->id());
520  }
521  }
522  }
523 
524  void ModuleWidget::handleDeleteShortcutOnFocusChanged(QWidget* oldWidget, QWidget* newWidget)
525  {
526  Q_UNUSED(oldWidget);
527  if(!newWidget) return;
528  if(newWidget->parent() == this)
529  {
530  mShortCutDeleteItem->setEnabled(true);
531  return;
532  }
533  else
534  {
535  mShortCutDeleteItem->setEnabled(false);
536  return;
537  }
538  }
539 }
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:321
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:610
Module * get_module_by_id(u32 module_id) const
Definition: netlist.cpp:615
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:86
SelectionRelay * gSelectionRelay
Definition: plugin_gui.cpp:84
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