void vogleditor_apiCallTimelineModel::AddApiCallsToTimeline(vogleditor_apiCallTreeItem *pParentCallTreeItem, vogleditor_timelineItem *pParentTimelineItem)
{
    vogleditor_timelineItem *pNewTimelineItem;

    int numChildren = pParentCallTreeItem->childCount();
    for (int c = 0; c < numChildren; c++)
    {
        vogleditor_apiCallTreeItem *pChildCallTreeItem = pParentCallTreeItem->child(c);

        float beginFloat = u64ToFloat(pChildCallTreeItem->startTime() - m_rawBaseTime);
        float endFloat = u64ToFloat(pChildCallTreeItem->endTime() - m_rawBaseTime);

        if (pChildCallTreeItem->isGroup())
        {
            // Create a group timelineItem with group color
            pNewTimelineItem = new vogleditor_timelineItem(beginFloat, endFloat, m_rootItem, pChildCallTreeItem->groupItem());
            QColor color;
            if (pChildCallTreeItem->isStateChangeGroup())
            {
                color = Qt::green;
            }
            else if (pChildCallTreeItem->isRenderGroup())
            {
                color = Qt::red;
            }
            pNewTimelineItem->setBrush(new QBrush(color, Qt::Dense5Pattern));
        }
        else // (API call)
        {
            // close a timeline parent group if the tree parent group has ended
            if (!pChildCallTreeItem->parent()->isGroup() && pParentTimelineItem->isGroupItem())
            {
                pParentTimelineItem = pParentTimelineItem->parent();
            }

            // Create new timeline apicall item
            pNewTimelineItem = new vogleditor_timelineItem(beginFloat, endFloat, pParentTimelineItem, pChildCallTreeItem->apiCallItem());

            // Add random color for debug marker group parent
            if (g_settings.group_debug_marker_in_use())
            {
                // (For now) only if State/Render groups are enabled so that
                // default timeline display isn't affected (debug marker groups
                // are checked on)
                // TODO: remove check for state/render status if/when consensus
                //       is the debug marker groups should be separately colored
                //       by default (when checked on)
                if (g_settings.group_state_render_stat())
                {
                    if (vogl_is_marker_push_entrypoint(pChildCallTreeItem->entrypoint_id()))
                    {
                        pNewTimelineItem->setBrush(new QBrush(QColor(randomRGB())));
                    }
                }
            }
        }
        AddApiCallsToTimeline(pChildCallTreeItem, pNewTimelineItem);
    }
}
void vogleditor_apiCallTimelineModel::AddApiCallsToTimeline(vogleditor_apiCallTreeItem* pRoot, vogleditor_timelineItem* pDestRoot)
{
   int numChildren = pRoot->childCount();
   for (int c = 0; c < numChildren; c++)
   {
      vogleditor_apiCallTreeItem* pChild = pRoot->child(c);
      if (pChild->apiCallItem() != NULL)
      {
          float beginFloat = u64ToFloat(pChild->apiCallItem()->startTime() - m_rawBaseTime);
          float endFloat = u64ToFloat(pChild->apiCallItem()->endTime() - m_rawBaseTime);

          vogleditor_timelineItem* pNewItem = new vogleditor_timelineItem(beginFloat, endFloat, pDestRoot);
          pNewItem->setApiCallItem(pChild->apiCallItem());
          pDestRoot->appendChild(pNewItem);
          AddApiCallsToTimeline(pChild, pNewItem);
      }
   }
}
void vogleditor_apiCallTimelineModel::refresh()
{
   if (m_pRootApiCall == NULL)
   {
      return;
   }


   float timelineStart = 0;
   float timelineEnd = 1;
   m_rawBaseTime = timelineStart;

   int numChildren = m_pRootApiCall->childCount();
   if (numChildren > 0)
   {
       uint64_t firstStart = 0;
       uint64_t firstEnd = 0;
       m_pRootApiCall->child(0)->frameItem()->getStartEndTimes(firstStart, firstEnd);

       uint64_t lastStart = 0;
       uint64_t lastEnd = 0;
       vogleditor_apiCallTreeItem* pLastChild = m_pRootApiCall->child(numChildren-1);
       pLastChild->frameItem()->getStartEndTimes(lastStart, lastEnd);

       m_rawBaseTime = firstStart;
       timelineStart = u64ToFloat(firstStart - m_rawBaseTime);
       timelineEnd = u64ToFloat(lastEnd - m_rawBaseTime);
   }

   // see if we actually have to update some of this stuff
   bool skipCreation = false;
   if (m_rootItem != NULL)
   {
      if (m_rootItem->getDuration() == timelineEnd - timelineStart &&
          m_rootItem->childCount() == numChildren)
      {
         // no need to make a new root
         skipCreation = true;
      }
   }

   if (!skipCreation)
   {
      if (m_rootItem != NULL)
      {
         delete m_rootItem;
      }

      m_rootItem = new vogleditor_timelineItem(timelineStart, timelineEnd);

      // add markers for the start of each frame
      float frameStart = 0;
      for (int c = 0; c < numChildren; c++)
      {
         vogleditor_apiCallTreeItem* pFrameItem = m_pRootApiCall->child(c);
         if (pFrameItem->childCount() > 0)
         {
            frameStart = u64ToFloat(pFrameItem->child(0)->apiCallItem()->startTime() - m_rawBaseTime);
            vogleditor_timelineItem* pFrameTimelineItem = new vogleditor_timelineItem(frameStart, m_rootItem);
            pFrameTimelineItem->setFrameItem(pFrameItem->frameItem());
            m_rootItem->appendChild(pFrameTimelineItem);
         }
         else
         {
            // if we get here, we are at a frame that had no api calls
         }
      }

      // recursively add each children
      for (int frameIndex = 0; frameIndex < numChildren; frameIndex++)
      {
         vogleditor_apiCallTreeItem* pFrameChild = m_pRootApiCall->child(frameIndex);

         AddApiCallsToTimeline(pFrameChild, m_rootItem);
      }
   }
}