From f5e103c2d629e19724061c4f92d78def3013d5bb Mon Sep 17 00:00:00 2001 From: PeterLValve Date: Wed, 19 Mar 2014 11:19:00 -0700 Subject: [PATCH] UI: Fix issue #21: Resizing of vogleditor window is slow depending on trace size * If the window is only being resized a small amount (within 20%), the timeline will no longer redraw and simply gets stretched. * When the timeline is redrawn, it will now only draw one timeline item per pixel instead of many sub-pixel items. * Fixed an issue that caused 0-duration items from being scaled to 1 instead of the horizontal scale value (which should be the minimum amount of time needed to appear as a single pixel). This greatly reduced the number of items being drawn. * Fixed deletion of timeline item children. * These improvements reduced the number of drawn items in one particular trace file from ~5.9 million, down to ~1250 in the default window size. When I stretched the editor across two monitors (giving the timeline more pixels to draw into) this increased to ~4500 items - both very reasonable numbers. --- src/vogleditor/vogleditor_qtimelineview.cpp | 90 +++++++++++++++------ src/vogleditor/vogleditor_qtimelineview.h | 2 +- src/vogleditor/vogleditor_timelineitem.cpp | 14 +++- src/vogleditor/vogleditor_timelineitem.h | 2 +- 4 files changed, 76 insertions(+), 32 deletions(-) diff --git a/src/vogleditor/vogleditor_qtimelineview.cpp b/src/vogleditor/vogleditor_qtimelineview.cpp index 513d2c2..1bacc08 100644 --- a/src/vogleditor/vogleditor_qtimelineview.cpp +++ b/src/vogleditor/vogleditor_qtimelineview.cpp @@ -56,6 +56,15 @@ vogleditor_QTimelineView::~vogleditor_QTimelineView() void vogleditor_QTimelineView::paintEvent(QPaintEvent *event) { + // Don't bother drawing if the rect is too small. + // For some reason this is happening at unexpected times. + int rectHeight = event->rect().height(); + int rectWidth = event->rect().width(); + if (rectHeight < 100 || rectWidth < 100) + { + return; + } + QPainter painter; painter.begin(this); paint(&painter, event); @@ -112,8 +121,17 @@ void vogleditor_QTimelineView::paint(QPainter *painter, QPaintEvent *event) if (m_pPixmap != NULL) { - if (m_pPixmap->height() != event->rect().height() || - m_pPixmap->width() != event->rect().width()) + int rectHeight = event->rect().height(); + int rectWidth = event->rect().width(); + int pmHeight = m_pPixmap->height(); + int pmWidth = m_pPixmap->width(); + + float widthPctDelta = (float)(rectWidth - pmWidth) / (float)pmWidth; + float heightPctDelta = (float)(rectHeight - pmHeight) / (float)pmHeight; + + // If the resize is of a 'signficant' amount, then delete the pixmap so that it will be regenerated at the new size. + if (fabs(widthPctDelta) > 0.2 || + fabs(heightPctDelta) > 0.2) { deletePixmap(); } @@ -143,14 +161,15 @@ void vogleditor_QTimelineView::paint(QPainter *painter, QPaintEvent *event) pixmapPainter.setBrush(m_triangleBrush); pixmapPainter.setPen(m_trianglePen); + float minimumOffset = 0; for (int c = 0; c < numChildren; c++) { vogleditor_timelineItem* pChild = m_pModel->get_root_item()->child(c); - drawTimelineItem(&pixmapPainter, pChild, height); + drawTimelineItem(&pixmapPainter, pChild, height, minimumOffset); } } - painter->drawPixmap(event->rect(), *m_pPixmap, event->rect()); + painter->drawPixmap(event->rect(), *m_pPixmap, m_pPixmap->rect()); // translate drawing to vertical center of rect // everything will have a small gap on the left and right sides @@ -187,9 +206,9 @@ void vogleditor_QTimelineView::paint(QPainter *painter, QPaintEvent *event) float vogleditor_QTimelineView::scaleDurationHorizontally(float value) { float scaled = value * m_horizontalScale; - if (scaled <= 0) + if (scaled <= m_horizontalScale) { - scaled = 1; + scaled = m_horizontalScale; } return scaled; @@ -204,7 +223,7 @@ float vogleditor_QTimelineView::scalePositionHorizontally(float value) return offset; } -void vogleditor_QTimelineView::drawTimelineItem(QPainter* painter, vogleditor_timelineItem *pItem, int height) +void vogleditor_QTimelineView::drawTimelineItem(QPainter* painter, vogleditor_timelineItem *pItem, int height, float& minimumOffset) { float duration = pItem->getDuration(); if (duration < 0) @@ -223,25 +242,44 @@ void vogleditor_QTimelineView::drawTimelineItem(QPainter* painter, vogleditor_ti } else { - float durationRatio = duration / m_maxItemDuration; - int intensity = std::min(255, (int)(durationRatio * 255.0f)); - // painter->setBrush(*(pItem->getBrush())); - QColor color(intensity, 255-intensity, 0); - painter->setBrush(QBrush(color)); - painter->setPen(color); - QRectF rect; - rect.setLeft(scalePositionHorizontally(pItem->getBeginTime())); - rect.setTop(-height/2); - rect.setWidth(scaleDurationHorizontally(duration)); - rect.setHeight(height); - painter->drawRect(rect); - - // now draw all children - int numChildren = pItem->childCount(); - for (int c = 0; c < numChildren; c++) - { - drawTimelineItem(painter, pItem->child(c), height-1); - } + // only draw if the item will extend beyond the minimum offset + float leftOffset = scalePositionHorizontally(pItem->getBeginTime()); + float scaledWidth = scaleDurationHorizontally(duration); + if (minimumOffset < leftOffset + scaledWidth) + { + float durationRatio = duration / m_maxItemDuration; + int intensity = std::min(255, (int)(durationRatio * 255.0f)); + // painter->setBrush(*(pItem->getBrush())); + QColor color(intensity, 255-intensity, 0); + painter->setBrush(QBrush(color)); + painter->setPen(color); + + // Clamp the item so that it is 1 pixel wide. + // This is intentionally being done before updating the minimum offset + // so that small items after the current item will not be drawn + if (scaledWidth < 1) + { + scaledWidth = 1; + } + + // update minimum offset + minimumOffset = leftOffset + scaledWidth; + + // draw the colored box that represents this item + QRectF rect; + rect.setLeft(leftOffset); + rect.setTop(-height/2); + rect.setWidth(scaledWidth); + rect.setHeight(height); + painter->drawRect(rect); + + // now draw all children + int numChildren = pItem->childCount(); + for (int c = 0; c < numChildren; c++) + { + drawTimelineItem(painter, pItem->child(c), height-1, minimumOffset); + } + } } painter->restore(); diff --git a/src/vogleditor/vogleditor_qtimelineview.h b/src/vogleditor/vogleditor_qtimelineview.h index 9fe85e8..35d5ebe 100644 --- a/src/vogleditor/vogleditor_qtimelineview.h +++ b/src/vogleditor/vogleditor_qtimelineview.h @@ -101,7 +101,7 @@ private: QPixmap* m_pPixmap; void drawBaseTimeline(QPainter* painter, const QRect& rect, int gap); - void drawTimelineItem(QPainter* painter, vogleditor_timelineItem* pItem, int height); + void drawTimelineItem(QPainter* painter, vogleditor_timelineItem* pItem, int height, float &minimumOffset); float scaleDurationHorizontally(float value); float scalePositionHorizontally(float value); diff --git a/src/vogleditor/vogleditor_timelineitem.cpp b/src/vogleditor/vogleditor_timelineitem.cpp index 14c0586..bd6dd3c 100644 --- a/src/vogleditor/vogleditor_timelineitem.cpp +++ b/src/vogleditor/vogleditor_timelineitem.cpp @@ -52,13 +52,19 @@ vogleditor_timelineItem::vogleditor_timelineItem(float begin, float end, vogledi vogleditor_timelineItem::~vogleditor_timelineItem() { + for (int i = 0; i < m_childItems.size(); i++) + { + delete m_childItems[i]; + m_childItems[i] = NULL; + } + m_childItems.clear(); } void vogleditor_timelineItem::appendChild(vogleditor_timelineItem* child) { - childItems.append(child); + m_childItems.append(child); - if (childItems.size() == 1) + if (m_childItems.size() == 1) { // just added the first child, so overwrite the current maxChildDuration m_maxChildDuration = child->getMaxChildDuration(); @@ -72,12 +78,12 @@ void vogleditor_timelineItem::appendChild(vogleditor_timelineItem* child) vogleditor_timelineItem* vogleditor_timelineItem::child(int row) { - return childItems[row]; + return m_childItems[row]; } int vogleditor_timelineItem::childCount() const { - return childItems.size(); + return m_childItems.size(); } vogleditor_timelineItem* vogleditor_timelineItem::parent() diff --git a/src/vogleditor/vogleditor_timelineitem.h b/src/vogleditor/vogleditor_timelineitem.h index ef93299..f0c9907 100644 --- a/src/vogleditor/vogleditor_timelineitem.h +++ b/src/vogleditor/vogleditor_timelineitem.h @@ -88,7 +88,7 @@ private: bool m_isSpan; float m_maxChildDuration; - QList childItems; + QList m_childItems; vogleditor_timelineItem* m_parentItem; vogleditor_frameItem* m_pFrameItem; -- 2.43.0