HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
dot_viewer.cpp
Go to the documentation of this file.
2 
4 #include "gui/toolbar/toolbar.h"
5 #include <QGraphicsView>
6 #include <QVBoxLayout>
7 #include <QInputDialog>
8 #include <QString>
9 #include <QAction>
10 #include <QFileDialog>
11 #include "QGVCore/QGVScene.h"
12 #include "QGVCore/QGVEdge.h"
14 #include <QShortcut>
19 #include <QMessageBox>
20 
21 namespace hal
22 {
23  DotViewer::DotViewer(const QString& pluginName, QObject *parent)
24  : ExternalContentWidget(pluginName, "DotViewer")
25  {
26  mOpenInputfileAction = new QAction(this);
27  mOpenInputfileAction->setToolTip("Open dot file");
28  connect(mOpenInputfileAction, &QAction::triggered, this, &DotViewer::handleOpenInputFileDialog);
29  mOpenInputfileAction->setIcon(gui_utility::getStyledSvgIcon("all->#3192C5",":/icons/folder"));
30 
31  mToggleGridAction = new QAction(this);
32  mToggleGridAction->setToolTip("Toggle grid");
33  connect(mToggleGridAction, &QAction::triggered, this, &DotViewer::handleToggleGrid);
34  mToggleGridAction->setIcon(gui_utility::getStyledSvgIcon("all->#ffffff", ":/icons/toggle-grid"));
35 
36  mColorSelectAction = new Action(this);
37  mColorSelectAction->setToolTip("Select color style");
38  connect(mColorSelectAction, &QAction::triggered, this, &DotViewer::handleColorSelect);
39  mColorSelectAction->setIcon(gui_utility::getStyledSvgIcon("all->#ffffff", ":/icons/color_select"));
40 
41  QShortcut* zoomInShortcut = new QShortcut(GraphTabWidget::sSettingZoomIn->value().toString(), this);
42  QShortcut* zoomOutShortcut = new QShortcut(GraphTabWidget::sSettingZoomOut->value().toString(), this);
45  connect(MainWindow::sSettingStyle, &SettingsItemDropdown::intChanged, this, &DotViewer::handleStyleChanged);
46 
47  mDotGraphicsView = new DotGraphicsView(this);
48 
49  connect(zoomInShortcut, &QShortcut::activated, mDotGraphicsView, &DotGraphicsView::handleZoomInShortcut);
50  connect(zoomOutShortcut, &QShortcut::activated, mDotGraphicsView, &DotGraphicsView::handleZoomOutShortcut);
51 
52  mDotScene = new QGVScene(this);
53  mDotGraphicsView->setScene(mDotScene);
54  mContentLayout->addWidget(mDotGraphicsView);
55  handleStyleChanged(MainWindow::sSettingStyle->value().toInt());
56  }
57 
59  {
60  toolbar->addAction(mOpenInputfileAction);
61  toolbar->addAction(mToggleGridAction);
62  toolbar->addAction(mColorSelectAction);
63  }
64 
66  {;}
67 
69  {
71  auto jt = owMap.find("dot_viewer");
72  if (jt == owMap.end()) return nullptr;
73  return dynamic_cast<DotViewer*>(jt.value());
74  }
75 
76  void DotViewer::handleStyleChanged(int istyle)
77  {
78  switch (istyle)
79  {
80  case MainWindow::StyleSheetOption::Dark:
81  QGVStyle::instance()->changeHalStyle(QGVStyle::Dark);
82  break;
83  case MainWindow::StyleSheetOption::Light:
84  QGVStyle::instance()->changeHalStyle(QGVStyle::Light);
85  break;
86  default:
87  return;
88  }
89  mDotScene->update();
90  }
91 
92  void DotViewer::handleToggleGrid()
93  {
94  mDotScene->toggleDrawGrid();
95  }
96 
97  void DotViewer::handleOpenInputFileDialog()
98  {
99  QString filename = QFileDialog::getOpenFileName(this, "Open dot file", ".", "Dot files (*.dot);;All files (*)");
101  }
102 
103  void DotViewer::handleOpenInputFileByName(const QString& fileName, const QString &creator)
104  {
105  loadDotFile(fileName,creator);
106  }
107 
108  bool DotViewer::loadDotFile(const QString& fileName, const QString &creator)
109  {
110  if (dynamic_cast<PythonThread*>(QThread::currentThread()))
111  {
112  // call from differnt thread, we cannot create GUI objects directly
114  bool retval = dvcft->openInputFileByName(this, fileName, creator);
115  delete dvcft;
116  return retval;
117  }
118 
119  mCreatorPlugin = creator;
120 
121  const char* halComment = "\"created by HAL plugin ";
122 
123  QObject* toDispose = mDotScene;
124  mDotScene = new QGVScene(this);
125  mDotGraphicsView->setScene(mDotScene);
126  toDispose->deleteLater();
127 
128  if (fileName.isEmpty()) {
129  log_warning("dot_viewer", "Cannot load dot file, no file name provided");
130  return false;
131  }
132  QFile ff(fileName);
133  if (!ff.open(QIODevice::ReadOnly)) {
134  log_warning("dot_viewer", "An error occurred loading dot file '{}'", fileName.toStdString());
135  return false;
136  }
137 
138  mFilename = fileName;
139  QByteArray dotfileContent = ff.readAll();
140 
141  // Determine plugin name to construct correct interaction class
142 
143  // 1.Try : plugin name from parameter in function call
144  QGVInteraction* interact = (mCreatorPlugin.isEmpty() || mCreatorPlugin.toLower() == "(none)")
145  ? nullptr
146  : QGVInteraction::construct(mCreatorPlugin,mDotScene);
147 
148  // 2.Try : plugin name from comment in .dot file
149  if (!interact && mCreatorPlugin.toLower() != "(none)")
150  {
151  int pos0;
152  if ((pos0 = dotfileContent.indexOf(halComment)) >= 0)
153  {
154  pos0 += strlen(halComment);
155  int pos1 = dotfileContent.indexOf('"', pos0);
156  Q_ASSERT(pos1 > pos0);
157  mCreatorPlugin = dotfileContent.mid(pos0, pos1-pos0);
158  }
159 
160  interact = QGVInteraction::construct(mCreatorPlugin,mDotScene);
161 
162  // 3.Try : plugin name selected by user
163  if (!interact)
164  {
165  QStringList choices = QGVInteraction::getPlugins();
166  choices.prepend("(none)");
167  mCreatorPlugin = QInputDialog::getItem(this, "Creator of File",
168  "Select plugin which created the .dot file to enable\n"
169  "interactions between HAL GUI and Graphviz viewer.",
170  choices, 0, false);
171  interact = QGVInteraction::construct(mCreatorPlugin,mDotScene);
172  if (!interact) mCreatorPlugin.clear();
173  }
174  }
175 
176  // interact might be nullptr but that is OK (no interactions in this case)
177  mDotScene->loadLayout(dotfileContent, interact);
178  return true;
179  }
180 
181  void DotViewer::handleColorSelect()
182  {
183  QMenu menu;
184  const char* target[] = {"node", "edge", nullptr };
185  for (int i=0; target[i]; i++)
186  {
187  QAction* act = menu.addAction(QString("HAL color style overwrites %1 attibute").arg(target[i]));
188  act->setCheckable(true);
189  act->setChecked(QGVStyle::instance()->getStyle((QGVStyle::StyleTarget)i) != QGVStyle::Graphviz);
190  connect (act, &QAction::triggered, this, [target,i,this](bool checked){
191  std::cerr << QString("HAL color style overwrites %1 attibute => %2").arg(target[i]).arg(checked?"true":"false").toStdString() << std::endl;
192  if (checked)
193  QGVStyle::instance()->setStyle((QGVStyle::StyleTarget)i, (QGVStyle::StyleType) MainWindow::sSettingStyle->value().toInt());
194  else
195  QGVStyle::instance()->setStyle((QGVStyle::StyleTarget)i, QGVStyle::Graphviz);
196  this->mDotScene->update();
197  });
198  }
199  menu.exec(QCursor::pos());
200  }
201 
203  {
204  for (QObject* obj : mDotScene->children())
205  {
206  QGVInteraction* interact = dynamic_cast<QGVInteraction*>(obj);
207  if (interact) interact->disableHandler();
208  }
209  }
210 
212  {
213  if (!callee) return false;
215  Q_EMIT callOpenInputFileByName(filename, plugin);
217  return (callee->filename() == filename); // callee will not store filename upon load error
218  }
219 } // namespace hal
Provides an interface for triggerable functionality that can be inserted into widgets and also connec...
Definition: action.h:42
QVBoxLayout * mContentLayout
bool openInputFileByName(DotViewer *callee, QString filename, QString plugin)
Definition: dot_viewer.cpp:211
void callOpenInputFileByName(QString filename, QString plugin)
static DotViewer * getDotviewerInstance()
Definition: dot_viewer.cpp:68
bool loadDotFile(const QString &fileName, const QString &creator=QString())
Definition: dot_viewer.cpp:108
DotViewer(const QString &pluginName, QObject *parent=nullptr)
Definition: dot_viewer.cpp:23
void handleOpenInputFileByName(const QString &fileName, const QString &creator=QString())
Definition: dot_viewer.cpp:103
QString filename() const
Definition: dot_viewer.h:90
void setupToolbar(Toolbar *toolbar)
Definition: dot_viewer.cpp:58
void disableInteractions()
Definition: dot_viewer.cpp:202
static ExternalContent * instance()
QMap< QString, ExternalContentWidget * > openWidgets
static SettingsItemKeybind * sSettingZoomIn
static SettingsItemKeybind * sSettingZoomOut
static SettingsItemDropdown * sSettingStyle
Definition: main_window.h:302
void intChanged(int value)
void keySequenceChanged(QKeySequence value)
Toolbar for all ContentFrames and ContentWidgets.
Definition: toolbar.h:39
#define log_warning(channel,...)
Definition: log.h:76
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
void setCheckable(bool)
void setChecked(bool)
void setIcon(const QIcon &icon)
void setToolTip(const QString &tip)
void triggered(bool checked)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
int indexOf(char ch, int from) const const
QByteArray mid(int pos, int len) const const
QPoint pos()
QString getOpenFileName(QWidget *parent, const QString &caption, const QString &dir, const QString &filter, QString *selectedFilter, QFileDialog::Options options)
void setScene(QGraphicsScene *scene)
QString getItem(QWidget *parent, const QString &title, const QString &label, const QStringList &items, int current, bool editable, bool *ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)
void prepend(const T &value)
QMap::iterator end()
QMap::iterator find(const Key &key)
QAction * addAction(const QString &text)
QAction * exec()
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void deleteLater()
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
void activated()
void setKey(const QKeySequence &key)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
void clear()
bool isEmpty() const const
QString toLower() const const
std::string toStdString() const const
BlockingQueuedConnection
QThread * currentThread()
QAction * addAction(const QString &text)