HAL  v4.5.0-83-g30c8f0afc
The Hardware Analyzer - a comprehensive reverse engineering and manipulation framework for gate-level netlists.
wave_graphics_canvas.cpp
Go to the documentation of this file.
7 #include <QScrollBar>
8 #include <QResizeEvent>
9 #include <QMouseEvent>
10 #include <QWheelEvent>
11 #include <QDebug>
12 #include <QMenu>
13 #include <QInputDialog>
14 #include <QApplication>
15 #include <QClipboard>
16 #include <math.h>
17 
18 namespace hal {
20  : QAbstractScrollArea(parent), mWaveDataList(wdlist), mWaveItemHash(wHash), mMoveCursor(false),
21  mCursorTime(100), mCursorXpos(100), mDragZoom(nullptr)
22  {
23  setContentsMargins(0,0,0,0);
24  mTransform = WaveTransform(0, 3000, 1.);
27  mRenderEngine = new WaveRenderEngine(this,mWaveDataList,mWaveItemHash,viewport());
28  mScrollbar = new WaveScrollbar(&mTransform,this);
29  setHorizontalScrollBar(mScrollbar);
30  mTimescale = new WaveTimescale(&mTransform,mScrollbar,this);
31  mTimescale->show();
32  mCursor = new WaveCursor(&mTransform,mScrollbar,this);
33  mCursor->show();
35  connect(this,&QWidget::customContextMenuRequested,this,&WaveGraphicsCanvas::handleContextMenuRequested);
36  mCursor->recalcTime();
37  }
38 
40  {
41  Q_UNUSED(evt);
42  mRenderEngine->setFixedSize(viewport()->contentsRect().size());
43  mScrollbar->adjust(viewport()->size().width());
44  mTimescale->setScale(viewport()->size().width());
45  mCursor->setViewportHeight(viewport()->size().height());
46  mCursor->recalcTime();
47  int yScrollMax = mRenderEngine->maxHeight()-viewport()->size().height();
48  verticalScrollBar()->setMaximum(yScrollMax<0 ? 0 : yScrollMax);
49  }
50 
52  {
54  if (dx) mCursor->recalcTime();
55  }
56 
58  {
59  if (evt->button() != Qt::LeftButton) return;
60 
61  if (mCursor->labelRect().contains(evt->pos()))
62  mMoveCursor = true;
63  else
64  {
65  mDragZoom = new QWidget(this);
66  mDragZoom->setStyleSheet("background-color: rgba(255,255,255,20);");
67 // mDragZoom->setAttribute(Qt::WA_StyledBackground, true);
68  mDragZoom->setFixedSize(1,height()-28);
69  mDragZoom->move(evt->pos().x(),28);
70  mDragZoom->show();
71  }
72  }
73 
74  void WaveGraphicsCanvas::setCursorPosition(double tCursor, int xpos)
75  {
76  if (mCursorTime == tCursor && mCursorXpos == xpos) return;
77  mCursorTime = tCursor;
78  mCursorXpos = xpos;
79  Q_EMIT cursorMoved(tCursor,xpos);
80  }
81 
82  void WaveGraphicsCanvas::handleContextMenuRequested(const QPoint& pos)
83  {
84  if (mDragZoom)
85  {
86  mDragZoom->deleteLater();
87  mDragZoom = nullptr;
88  }
89  QMenu* menu = new QMenu(this);
90  QAction* act;
91  act = menu->addAction("Enter cursor time value ...");
92  connect(act,&QAction::triggered,this,&WaveGraphicsCanvas::handleEnterCursorTime);
93  act = menu->addAction("Copy cursor time value to clipboard");
94  connect(act,&QAction::triggered,this,&WaveGraphicsCanvas::handleCopyCursorTime);
95  if (mWaveItemHash->firstSelected())
96  {
97  QString wavename = mWaveItemHash->firstSelected()->wavedata()->name();
98  act = menu->addAction("Jump to next transition " + wavename);
99  connect(act,&QAction::triggered,this,&WaveGraphicsCanvas::handleJumpNextTransition);
100  act = menu->addAction("Jump to previous transition " + wavename);
101  connect(act,&QAction::triggered,this,&WaveGraphicsCanvas::handleJumpPreviousTransition);
102  }
103  menu->popup(viewport()->mapToGlobal(pos));
104  }
105 
106  void WaveGraphicsCanvas::handleJumpPreviousTransition()
107  {
108  WaveItem* wi = mWaveItemHash->firstSelected();
109  if (!wi) return;
110  double tCursor = wi->wavedata()->neighborTransition(mCursorTime,false);
111  setCursorTimeInternal(tCursor);
112  }
113 
114  void WaveGraphicsCanvas::handleJumpNextTransition()
115  {
116  WaveItem* wi = mWaveItemHash->firstSelected();
117  if (!wi) return;
118  double tCursor = wi->wavedata()->neighborTransition(mCursorTime,true);
119  setCursorTimeInternal(tCursor);
120  }
121 
122  void WaveGraphicsCanvas::handleCopyCursorTime()
123  {
124  QApplication::clipboard()->setText(QString::number(mCursorTime,'f',0));
125  }
126 
127  void WaveGraphicsCanvas::handleEnterCursorTime()
128  {
129  bool ok;
130  double tCursor = QInputDialog::getDouble(this, "Enter cursor time", "New value:", mCursorTime, mTransform.tMin(), mTransform.tMax(), 0, &ok);
131  if (ok && tCursor != mCursorTime)
132  setCursorTimeInternal(tCursor);
133  }
134 
135  void WaveGraphicsCanvas::setCursorTimeInternal(double tCursor)
136  {
137  if (tCursor < mTransform.tMin()) tCursor = mTransform.tMin();
138  if (tCursor > mTransform.tMax()) tCursor = mTransform.tMax();
139  double wHalf = 0.5 * mScrollbar->viewportWidth();
140  double vpos = mTransform.vPos(tCursor);
141  if (vpos + wHalf > mTransform.vMax()) vpos = mTransform.vMax() - wHalf;
142  if (vpos - wHalf < mTransform.vMin()) vpos = mTransform.vMin() + wHalf;
143  mScrollbar->setVleft(vpos - wHalf);
144  mCursorXpos = mScrollbar->xPosI(tCursor);
145  mTimescale->update();
146  mCursor->setCursorToTime(tCursor);
147  mRenderEngine->update();
148  }
149 
151  {
152  if (mMoveCursor)
153  {
154  mTimescale->update();
155  mCursor->setCursorPosition(evt->pos());
156  }
157  else if (mDragZoom)
158  {
159  int x = evt->pos().x();
160  QRect geo = mDragZoom->geometry();
161  if (x < geo.left())
162  geo.setLeft(x);
163  else if (x > geo.right())
164  geo.setRight(x);
165  else if (x - geo.left() < geo.right() - x)
166  geo.setLeft(x);
167  else
168  geo.setRight(x);
169  mDragZoom->setFixedSize(geo.size());
170  mDragZoom->move(geo.topLeft());
171  }
172  }
173 
175  {
176  if (mMoveCursor)
177  {
178  mTimescale->update();
179  mCursor->setCursorPosition(evt->pos());
180  mMoveCursor = false;
181  }
182  if (mDragZoom)
183  {
184  QRect geo = mDragZoom->geometry();
185  mDragZoom->deleteLater();
186  mDragZoom = nullptr;
187  double t0 = mScrollbar->tPosF(geo.left());
188  double dt = mScrollbar->tPosF(geo.right()) - t0;
189  if (dt > 0)
190  {
191  mTransform.setScale(viewport()->width()/dt);
192  mScrollbar->adjust(viewport()->size().width());
193  mScrollbar->setVleft(mTransform.vPos(t0));
194 // qDebug() << "zoom t0 dt vpos" << t0 << dt << mTransform.vPos(t0);
195  mTimescale->setScale(viewport()->size().width());
196  mCursor->recalcTime();
197  mRenderEngine->update();
198  }
199  }
200  }
201 
203  {
204 // qDebug() << "WaveGraphicsCanvas::callTfc" << tframe->sceneMaxTime() << "=?=" << mTransform.tMax();
205  if (mTransform.tMin() == tframe->sceneMinTime() && mTransform.tMax() == tframe->sceneMaxTime()) return;
206 // qDebug() << "WaveGraphicsCanvas::handleTfc" << tframe->sceneMaxTime();
207  mTransform.setTmin(tframe->sceneMinTime());
208  mTransform.setTmax(tframe->sceneMaxTime());
209  mRenderEngine->update();
210  }
211 
213  {
214  mRenderEngine->update();
215  }
216 
217  void WaveGraphicsCanvas::handleWaveUpdated(int iwave, int groupId)
218  {
219  WaveItemIndex wii(iwave, WaveItemIndex::Wire, groupId);
220  WaveItem* wi = mWaveItemHash->value(wii);
221  if (!wi) return;
222  wi->setWaveData(mWaveDataList->at(iwave));
223  mRenderEngine->update();
224  }
225 
227  {
228  mTimescale->update();
229  mCursor->setCursorPosition(evt->pos());
230  mMoveCursor = false;
231  }
232 
234  {
235  double oldScale = mTransform.scale();
236  double newScale = oldScale;
237  int dz = evt->angleDelta().y();
238  if (dz > 0)
239  newScale *= 1.1;
240  else if (dz < 0)
241  newScale /= 1.1;
242  else
243  return;
244  if (newScale >= 100) return;
245  if (newScale*mTransform.deltaT()*1.2<viewport()->width() && newScale < oldScale) return;
246  double tEvent = (evt->modifiers() & Qt::ShiftModifier)
247  ? mScrollbar->tPosF(evt->pos().x())
248  : mCursorTime;
249 
250  mTransform.setScale(newScale);
251  mScrollbar->updateScale(newScale-oldScale,tEvent,viewport()->width());
252  mRenderEngine->update();
253  mTimescale->setScale(viewport()->size().width());
254  if (evt->modifiers() & Qt::ShiftModifier)
255  mCursor->recalcTime();
256  else
257  {
258  int xpos = mScrollbar->xPosI(mCursorTime);
259  if (xpos < WaveCursor::sWidth/2 || xpos > viewport()->width()-WaveCursor::sWidth/2)
260  mCursor->recalcTime();
261  else
262  mCursor->setCursorToTime(mCursorTime);
263  }
264  }
265 
267  {
268  return !mRenderEngine->zoomHistory().isEmpty();
269  }
270 
272  {
274  }
275 
277  {
278  if (mRenderEngine->zoomHistory().isEmpty()) return;
279  WaveZoomShift lastZoom = mRenderEngine->zoomHistory().takeLast();
280  mTransform.setScale(lastZoom.scale());
281  mScrollbar->setVleft(mTransform.vPos(lastZoom.leftTime()));
282  mRenderEngine->omitHistory();
283  mRenderEngine->update();
284  mTimescale->setScale(viewport()->size().width());
285  mCursor->recalcTime();
286  if (mRenderEngine->zoomHistory().isEmpty())
288  }
289 
290 
292  {
293  // try zoom out
294  int w = viewport()->size().width();
295  double dt = mTransform.deltaT();
296  if (dt <= 0) return;
297  double newScale = w / dt;
298  double vleft = 0;
299  if (dt * mTransform.scale() * 1.0001 < w)
300  {
301  // not using entire screen width, zoom in
302  mTransform.setScale(newScale);
303  }
304  else if (mTransform.scale() <= newScale)
305  {
306  // already zoomed out to max, try zoom in
307  TimeInterval shortest;
308  for (const WaveItem* wi : mWaveItemHash->values())
309  {
310  if (!wi->isVisibile() || ! wi->mVisibleRange) continue;
311  if (wi->mPainted.shortestToggle() < shortest) shortest = wi->mPainted.shortestToggle();
312  }
313  if (shortest.mCenterTime <= 0 || shortest.mDuration <= 0) return;
314  newScale = 6 / shortest.mDuration;
315  if (mTransform.scale() >= newScale) return;
316  mTransform.setScale(newScale);
317  vleft = mTransform.vPos(shortest.mCenterTime) - w/2;
318  if (vleft + w > mTransform.vMax()) vleft = mTransform.vMax() - w;
319  if (vleft < 0) vleft = 0;
320  }
321  else
322  {
323  // zoom out
324  mTransform.setScale(newScale);
325  }
326  mScrollbar->setVleft(vleft);
327  mRenderEngine->update();
328  mTimescale->setScale(viewport()->size().width());
329  mCursor->recalcTime();
330  }
331 
332 }
void setCursorPosition(const QPoint &pos)
Definition: wave_cursor.cpp:85
QRect labelRect() const
Definition: wave_cursor.cpp:64
void setCursorToTime(u64 t)
Definition: wave_cursor.cpp:69
void setViewportHeight(int height)
Definition: wave_cursor.cpp:58
static const int sWidth
Definition: wave_cursor.h:56
virtual u64 neighborTransition(double t, bool next) const
Definition: wave_data.cpp:360
QString name() const
Definition: wave_data.h:104
u64 sceneMaxTime() const
Definition: wave_data.cpp:1228
u64 sceneMinTime() const
Definition: wave_data.cpp:1242
void handleWaveUpdated(int iwave, int groupId)
void mouseDoubleClickEvent(QMouseEvent *) override
void resizeEvent(QResizeEvent *) override
void mouseReleaseEvent(QMouseEvent *) override
WaveGraphicsCanvas(WaveDataList *wdlist, WaveItemHash *wHash, QWidget *parent=nullptr)
void handleTimeframeChanged(const hal::WaveDataTimeframe *tframe)
void wheelEvent(QWheelEvent *) override
void mousePressEvent(QMouseEvent *) override
void mouseMoveEvent(QMouseEvent *) override
void setCursorPosition(double tCursor, int xpos)
void scrollContentsBy(int dx, int dy) override
void cursorMoved(double tCursor, int xpos)
WaveItem * firstSelected() const
Definition: wave_item.h:166
const WaveData * wavedata() const
Definition: wave_item.h:129
void setWaveData(WaveData *wd)
Definition: wave_item.cpp:40
QList< WaveZoomShift > & zoomHistory()
void adjust(quint64 visibleWidth)
double tPosF(int x) const
int xPosI(double t) const
int viewportWidth() const
void setVleft(double v)
void updateScale(double deltaScale, double tEvent, quint64 visibleWidth)
void setScale(int viewportWidth)
quint64 tMin() const
double scale() const
double vMin() const
quint64 deltaT() const
double vPos(double t) const
quint64 tMax() const
void setScale(double m11)
double vMax() const
void setTmin(quint64 t0)
void setTmax(quint64 t1)
double scale() const
quint64 leftTime() const
Definition: defines.h:45
void setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy)
virtual void scrollContentsBy(int dx, int dy)
void setHorizontalScrollBar(QScrollBar *scrollBar)
QScrollBar * verticalScrollBar() const const
void setVerticalScrollBarPolicy(Qt::ScrollBarPolicy)
QWidget * viewport() const const
void setMaximum(int)
void triggered(bool checked)
void setText(const QString &text, QClipboard::Mode mode)
QClipboard * clipboard()
const T value(const Key &key) const const
QList< T > values() const const
double getDouble(QWidget *parent, const QString &title, const QString &label, double value, double min, double max, int decimals, bool *ok, Qt::WindowFlags flags, double step)
Qt::KeyboardModifiers modifiers() const const
const T & at(int i) const const
QAction * addAction(const QString &text)
void popup(const QPoint &p, QAction *atAction)
Qt::MouseButton button() const const
QPoint pos() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void deleteLater()
int x() const const
int y() const const
bool contains(const QRect &rectangle, bool proper) const const
int left() const const
int right() const const
void setLeft(int x)
void setRight(int x)
QSize size() const const
QPoint topLeft() const const
QString number(int n, int base)
CustomContextMenu
ShiftModifier
LeftButton
ScrollBarAlwaysOn
QPoint pos() const const
QPoint angleDelta() const const
QWidget(QWidget *parent, Qt::WindowFlags f)
QRect contentsRect() const const
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
void customContextMenuRequested(const QPoint &pos)
QPoint mapToGlobal(const QPoint &pos) const const
void move(int x, int y)
void setContentsMargins(int left, int top, int right, int bottom)
void setFixedSize(const QSize &s)
void show()
void setStyleSheet(const QString &styleSheet)
void update()