]> git.cworth.org Git - vogl/commitdiff
UI: Fix issue #21: Resizing of vogleditor window is slow depending on trace size
authorPeterLValve <peterl@valvesoftware.com>
Wed, 19 Mar 2014 18:19:00 +0000 (11:19 -0700)
committerCarl Worth <cworth@cworth.org>
Tue, 1 Apr 2014 19:37:30 +0000 (12:37 -0700)
* 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
src/vogleditor/vogleditor_qtimelineview.h
src/vogleditor/vogleditor_timelineitem.cpp
src/vogleditor/vogleditor_timelineitem.h

index 513d2c281de3109b29995165a830d5799c16204f..1bacc084aed79010c146c44af312439168391c86 100644 (file)
@@ -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();
index 9fe85e8be9ad507f0607afc09ac97c2b04f82851..35d5ebe9b66f25a264777140a812bf41f48b7cd0 100644 (file)
@@ -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);
index 14c05861232b0a2038cc6f04147e610b39e4c13f..bd6dd3c879db7d5f617383d7fa71a34294235d65 100644 (file)
@@ -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()
index ef93299542e17285101d5c120e65743290f2634a..f0c9907a1d4acfd684a58532ec0b9adf71effae9 100644 (file)
@@ -88,7 +88,7 @@ private:
     bool m_isSpan;
     float m_maxChildDuration;
 
-    QList<vogleditor_timelineItem*> childItems;
+    QList<vogleditor_timelineItem*> m_childItems;
 
     vogleditor_timelineItem* m_parentItem;
     vogleditor_frameItem* m_pFrameItem;