@@ -886,13 +886,17 @@ bool TTDEventsQueryWidget::isUnused() const
886886
887887// TTDEventsWidget implementation
888888TTDEventsWidget::TTDEventsWidget (QWidget* parent, BinaryViewRef data)
889- : QWidget(parent), m_data(data)
889+ : QWidget(parent), m_data(data), m_isPopulated( false )
890890{
891891 m_controller = DebuggerController::GetController (data);
892892 setupUI ();
893893
894- // Automatically load events for all tabs
895- loadAllEvents ();
894+ // Only automatically load events if the debugger is running
895+ if (m_controller && m_controller->IsConnectedToDebugServer ())
896+ {
897+ loadAllEvents ();
898+ m_isPopulated = true ;
899+ }
896900}
897901
898902TTDEventsWidget::~TTDEventsWidget ()
@@ -906,8 +910,20 @@ void TTDEventsWidget::setupUI()
906910
907911 // Create tab widget
908912 m_tabWidget = new QTabWidget ();
913+ m_tabWidget->setTabsClosable (true );
914+ connect (m_tabWidget, &QTabWidget::tabCloseRequested, this , &TTDEventsWidget::closeTab);
909915 layout->addWidget (m_tabWidget);
910916
917+ // Create "+" button as corner widget
918+ m_newTabButton = new QToolButton (m_tabWidget);
919+ m_newTabButton->setText (" +" );
920+ m_newTabButton->setAutoRaise (true );
921+ m_newTabButton->setToolTip (" New tab" );
922+ connect (m_newTabButton, &QToolButton::clicked, this , &TTDEventsWidget::createNewTab);
923+
924+ // Set the button as corner widget
925+ m_tabWidget->setCornerWidget (m_newTabButton, Qt::TopRightCorner);
926+
911927 // Create the 3 specialized tabs
912928 m_moduleEventsWidget = new TTDEventsQueryWidget (this , m_data, TTDEventsQueryWidget::ModuleEvents);
913929 m_threadEventsWidget = new TTDEventsQueryWidget (this , m_data, TTDEventsQueryWidget::ThreadEvents);
@@ -929,6 +945,73 @@ void TTDEventsWidget::loadAllEvents()
929945 m_exceptionEventsWidget->performInitialQuery ();
930946}
931947
948+ void TTDEventsWidget::refreshAllTabs ()
949+ {
950+ // Only refresh if data is available and we haven't already populated
951+ if (m_controller && m_controller->IsConnectedToDebugServer () && !m_isPopulated)
952+ {
953+ loadAllEvents ();
954+ m_isPopulated = true ;
955+ }
956+ }
957+
958+ void TTDEventsWidget::clearAllTabs ()
959+ {
960+ if (m_moduleEventsWidget)
961+ m_moduleEventsWidget->clearResults ();
962+ if (m_threadEventsWidget)
963+ m_threadEventsWidget->clearResults ();
964+ if (m_exceptionEventsWidget)
965+ m_exceptionEventsWidget->clearResults ();
966+
967+ // Clear all custom tabs as well
968+ for (int i = 3 ; i < m_tabWidget->count (); i++)
969+ {
970+ TTDEventsQueryWidget* widget = qobject_cast<TTDEventsQueryWidget*>(m_tabWidget->widget (i));
971+ if (widget)
972+ widget->clearResults ();
973+ }
974+
975+ m_isPopulated = false ;
976+ }
977+
978+ TTDEventsQueryWidget* TTDEventsWidget::getCurrentOrNewQueryWidget ()
979+ {
980+ // Get current tab widget
981+ TTDEventsQueryWidget* currentWidget = qobject_cast<TTDEventsQueryWidget*>(m_tabWidget->currentWidget ());
982+ if (currentWidget)
983+ return currentWidget;
984+
985+ // If no current widget or cast failed, create a new tab
986+ createNewTab ();
987+ return qobject_cast<TTDEventsQueryWidget*>(m_tabWidget->currentWidget ());
988+ }
989+
990+ void TTDEventsWidget::createNewTab ()
991+ {
992+ // Create new tab with AllEvents type (has filtering controls)
993+ TTDEventsQueryWidget* queryWidget = new TTDEventsQueryWidget (this , m_data, TTDEventsQueryWidget::AllEvents);
994+ int tabIndex = m_tabWidget->addTab (queryWidget, QString (" Query %1" ).arg (m_tabWidget->count () - 2 )); // -2 because we have 3 fixed tabs
995+ m_tabWidget->setCurrentIndex (tabIndex);
996+
997+ // If we've already populated the specialized tabs, also populate this new tab
998+ if (m_isPopulated)
999+ {
1000+ queryWidget->performInitialQuery ();
1001+ }
1002+ }
1003+
1004+ void TTDEventsWidget::closeTab (int index)
1005+ {
1006+ // Don't allow closing the first 3 specialized tabs
1007+ if (index >= 3 && m_tabWidget->count () > 3 )
1008+ {
1009+ QWidget* widget = m_tabWidget->widget (index);
1010+ m_tabWidget->removeTab (index);
1011+ widget->deleteLater ();
1012+ }
1013+ }
1014+
9321015// TTDEventsSidebarWidget implementation
9331016TTDEventsSidebarWidget::TTDEventsSidebarWidget (BinaryViewRef data)
9341017 : SidebarWidget(" TTD Events" ), m_data(data)
@@ -942,10 +1025,44 @@ TTDEventsSidebarWidget::TTDEventsSidebarWidget(BinaryViewRef data)
9421025 layout->addWidget (m_eventsWidget);
9431026
9441027 setLayout (layout);
1028+
1029+ // Register for debugger events
1030+ if (m_controller)
1031+ {
1032+ connect (this , &TTDEventsSidebarWidget::debuggerEvent, this , &TTDEventsSidebarWidget::onDebuggerEvent);
1033+
1034+ m_debuggerEventCallback = m_controller->RegisterEventCallback (
1035+ [&](const DebuggerEvent& event) {
1036+ emit debuggerEvent (event);
1037+ },
1038+ " TTD Events Widget" );
1039+ }
9451040}
9461041
9471042TTDEventsSidebarWidget::~TTDEventsSidebarWidget ()
9481043{
1044+ if (m_controller)
1045+ m_controller->RemoveEventCallback (m_debuggerEventCallback);
1046+ }
1047+
1048+ void TTDEventsSidebarWidget::onDebuggerEvent (const DebuggerEvent& event)
1049+ {
1050+ switch (event.type )
1051+ {
1052+ case TargetStoppedEventType:
1053+ // When target stops, refresh all tabs if not already populated
1054+ if (m_eventsWidget)
1055+ m_eventsWidget->refreshAllTabs ();
1056+ break ;
1057+ case TargetExitedEventType:
1058+ case DetachedEventType:
1059+ // When target exits or is detached, clear all contents
1060+ if (m_eventsWidget)
1061+ m_eventsWidget->clearAllTabs ();
1062+ break ;
1063+ default :
1064+ break ;
1065+ }
9491066}
9501067
9511068// TTDEventsWidgetType implementation
0 commit comments