@@ -24,6 +24,92 @@ limitations under the License.
2424#include < QMenu>
2525#include < QClipboard>
2626#include < QCheckBox>
27+ #include < QToolButton>
28+ #include < QPropertyAnimation>
29+ #include < QResizeEvent>
30+ #include < QFrame>
31+
32+ // ExpandableGroupBox implementation
33+ ExpandableGroupBox::ExpandableGroupBox (const QString& title, QWidget* parent)
34+ : QWidget(parent), m_contentWidget(nullptr ), m_expanded(true )
35+ {
36+ QVBoxLayout* layout = new QVBoxLayout (this );
37+ layout->setContentsMargins (0 , 0 , 0 , 0 );
38+ layout->setSpacing (0 );
39+
40+ // Create header with toggle button
41+ QHBoxLayout* headerLayout = new QHBoxLayout ();
42+ headerLayout->setContentsMargins (5 , 5 , 5 , 5 );
43+
44+ m_toggleButton = new QToolButton ();
45+ m_toggleButton->setArrowType (Qt::DownArrow);
46+ m_toggleButton->setCheckable (true );
47+ m_toggleButton->setChecked (true );
48+ m_toggleButton->setText (title);
49+ m_toggleButton->setToolButtonStyle (Qt::ToolButtonTextBesideIcon);
50+ m_toggleButton->setStyleSheet (" QToolButton { border: none; font-weight: bold; text-align: left; }" );
51+
52+ connect (m_toggleButton, &QToolButton::clicked, this , &ExpandableGroupBox::toggleExpanded);
53+
54+ headerLayout->addWidget (m_toggleButton);
55+ headerLayout->addStretch ();
56+
57+ layout->addLayout (headerLayout);
58+
59+ // Add a line separator
60+ QFrame* line = new QFrame ();
61+ line->setFrameShape (QFrame::HLine);
62+ line->setFrameShadow (QFrame::Sunken);
63+ layout->addWidget (line);
64+
65+ setLayout (layout);
66+ }
67+
68+ void ExpandableGroupBox::setContentWidget (QWidget* widget)
69+ {
70+ if (m_contentWidget)
71+ {
72+ layout ()->removeWidget (m_contentWidget);
73+ m_contentWidget->deleteLater ();
74+ }
75+
76+ m_contentWidget = widget;
77+ if (m_contentWidget)
78+ {
79+ layout ()->addWidget (m_contentWidget);
80+ setupAnimation ();
81+ }
82+ }
83+
84+ void ExpandableGroupBox::setExpanded (bool expanded)
85+ {
86+ if (m_expanded == expanded)
87+ return ;
88+
89+ m_expanded = expanded;
90+ m_toggleButton->setArrowType (expanded ? Qt::DownArrow : Qt::RightArrow);
91+ m_toggleButton->setChecked (expanded);
92+
93+ if (m_contentWidget)
94+ {
95+ m_contentWidget->setVisible (expanded);
96+ }
97+ }
98+
99+ void ExpandableGroupBox::toggleExpanded ()
100+ {
101+ setExpanded (!m_expanded);
102+ }
103+
104+ void ExpandableGroupBox::setupAnimation ()
105+ {
106+ if (!m_contentWidget)
107+ return ;
108+
109+ m_contentAnimation = new QPropertyAnimation (m_contentWidget, " maximumHeight" );
110+ m_contentAnimation->setDuration (200 );
111+ m_contentAnimation->setEasingCurve (QEasingCurve::InOutQuad);
112+ }
27113
28114// ColumnVisibilityDialog implementation
29115ColumnVisibilityDialog::ColumnVisibilityDialog (QWidget* parent, const QStringList& columnNames, const QList<bool >& visibility)
@@ -50,9 +136,33 @@ ColumnVisibilityDialog::ColumnVisibilityDialog(QWidget* parent, const QStringLis
50136
51137 layout->addWidget (m_columnList);
52138
53- QDialogButtonBox* buttons = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
139+ QDialogButtonBox* buttons = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults );
54140 connect (buttons, &QDialogButtonBox::accepted, this , &QDialog::accept);
55141 connect (buttons, &QDialogButtonBox::rejected, this , &QDialog::reject);
142+
143+ // Handle restore defaults
144+ connect (buttons->button (QDialogButtonBox::RestoreDefaults), &QPushButton::clicked, [this ]() {
145+ // Reset to default visibility (hide Event Type, Time End, Unique Thread ID)
146+ QList<bool > defaultVisibility;
147+ defaultVisibility << true // Index
148+ << false // Event Type (hidden by default)
149+ << true // Time Start
150+ << false // Time End (hidden by default)
151+ << true // Access Type
152+ << true // Address
153+ << true // Size
154+ << true // Value
155+ << true // Thread ID
156+ << false // Unique Thread ID (hidden by default)
157+ << true ; // IP
158+
159+ for (int i = 0 ; i < m_columnList->count () && i < defaultVisibility.size (); ++i)
160+ {
161+ QListWidgetItem* item = m_columnList->item (i);
162+ item->setCheckState (defaultVisibility[i] ? Qt::Checked : Qt::Unchecked);
163+ }
164+ });
165+
56166 layout->addWidget (buttons);
57167}
58168
@@ -103,9 +213,12 @@ void TTDMemoryQueryWidget::setupUI()
103213
104214 QVBoxLayout* mainLayout = new QVBoxLayout (this );
105215
106- // Input controls group
107- QGroupBox* inputGroup = new QGroupBox (" Query Parameters" );
108- QFormLayout* inputLayout = new QFormLayout (inputGroup);
216+ // Create expandable group for query parameters
217+ ExpandableGroupBox* expandableGroup = new ExpandableGroupBox (" Query Parameters" );
218+
219+ // Create content widget for the expandable group
220+ QWidget* inputWidget = new QWidget ();
221+ QFormLayout* inputLayout = new QFormLayout (inputWidget);
109222
110223 // Address range inputs
111224 m_startAddressEdit = new QLineEdit ();
@@ -155,7 +268,10 @@ void TTDMemoryQueryWidget::setupUI()
155268
156269 inputLayout->addRow (" " , buttonLayout);
157270
158- mainLayout->addWidget (inputGroup);
271+ // Set the input widget as the content of the expandable group
272+ expandableGroup->setContentWidget (inputWidget);
273+
274+ mainLayout->addWidget (expandableGroup);
159275
160276 // Results table
161277 setupTable ();
@@ -446,11 +562,13 @@ void TTDMemoryQueryWidget::showContextMenu(const QPoint& position)
446562 QAction* copyTableAction = menu.addAction (" Copy Table" );
447563 menu.addSeparator ();
448564 QAction* columnsAction = menu.addAction (" Columns..." );
565+ QAction* resetColumnsAction = menu.addAction (" Reset Columns to Default" );
449566
450567 connect (copyCellAction, &QAction::triggered, this , &TTDMemoryQueryWidget::copySelectedCell);
451568 connect (copyRowAction, &QAction::triggered, this , &TTDMemoryQueryWidget::copySelectedRow);
452569 connect (copyTableAction, &QAction::triggered, this , &TTDMemoryQueryWidget::copyEntireTable);
453570 connect (columnsAction, &QAction::triggered, this , &TTDMemoryQueryWidget::showColumnVisibilityDialog);
571+ connect (resetColumnsAction, &QAction::triggered, this , &TTDMemoryQueryWidget::resetColumnsToDefault);
454572
455573 // Enable/disable actions based on selection
456574 QTableWidgetItem* item = m_resultsTable->itemAt (position);
@@ -525,6 +643,25 @@ void TTDMemoryQueryWidget::copyEntireTable()
525643 clipboard->setText (tableData.join (" \n " ));
526644}
527645
646+ void TTDMemoryQueryWidget::resetColumnsToDefault ()
647+ {
648+ // Reset to default visibility (hide Event Type, Time End, Unique Thread ID)
649+ m_columnVisibility.clear ();
650+ m_columnVisibility << true // Index
651+ << false // Event Type (hidden by default)
652+ << true // Time Start
653+ << false // Time End (hidden by default)
654+ << true // Access Type
655+ << true // Address
656+ << true // Size
657+ << true // Value
658+ << true // Thread ID
659+ << false // Unique Thread ID (hidden by default)
660+ << true ; // IP
661+
662+ updateColumnVisibility ();
663+ }
664+
528665void TTDMemoryQueryWidget::updateStatus (const QString& message)
529666{
530667 m_statusLabel->setText (message);
@@ -578,32 +715,46 @@ void TTDMemoryWidget::setupUI()
578715
579716 QVBoxLayout* mainLayout = new QVBoxLayout (this );
580717
718+ // Create a horizontal layout to hold the tab widget and + button
719+ QWidget* tabContainer = new QWidget ();
720+ m_tabLayout = new QHBoxLayout (tabContainer);
721+ m_tabLayout->setContentsMargins (0 , 0 , 0 , 0 );
722+ m_tabLayout->setSpacing (0 );
723+
581724 // Tab widget setup
582725 m_tabWidget = new QTabWidget ();
583726 m_tabWidget->setTabsClosable (true );
584727 connect (m_tabWidget, &QTabWidget::tabCloseRequested, this , &TTDMemoryWidget::closeTab);
585728
586- // Create "+" button and set it as corner widget
729+ // Create "+" button
587730 m_newTabButton = new QPushButton (" +" );
588- m_newTabButton->setMaximumSize (30 , 30 );
731+ m_newTabButton->setMaximumSize (25 , 25 );
732+ m_newTabButton->setMinimumSize (25 , 25 );
589733 m_newTabButton->setToolTip (" Create new query tab" );
734+ m_newTabButton->setStyleSheet (" QPushButton { border: 1px solid #555; border-radius: 3px; margin-top: 2px; }" );
590735 connect (m_newTabButton, &QPushButton::clicked, this , &TTDMemoryWidget::createNewTab);
591736
592- // Set the "+" button as a corner widget of the tab widget
593- m_tabWidget->setCornerWidget (m_newTabButton, Qt::TopRightCorner);
737+ // Add tab widget and button to horizontal layout
738+ m_tabLayout->addWidget (m_tabWidget);
739+ m_tabLayout->addWidget (m_newTabButton, 0 , Qt::AlignTop);
594740
595- mainLayout->addWidget (m_tabWidget );
741+ mainLayout->addWidget (tabContainer );
596742 setLayout (mainLayout);
597743
598744 // Create initial tab
599745 createNewTab ();
746+
747+ // Update button position when tabs change
748+ connect (m_tabWidget, &QTabWidget::currentChanged, this , &TTDMemoryWidget::updateNewTabButtonPosition);
749+ connect (m_tabWidget, &QTabWidget::tabBarClicked, this , &TTDMemoryWidget::updateNewTabButtonPosition);
600750}
601751
602752void TTDMemoryWidget::createNewTab ()
603753{
604754 TTDMemoryQueryWidget* queryWidget = new TTDMemoryQueryWidget (this , m_data);
605755 int tabIndex = m_tabWidget->addTab (queryWidget, QString (" Query %1" ).arg (m_tabWidget->count () + 1 ));
606756 m_tabWidget->setCurrentIndex (tabIndex);
757+ updateNewTabButtonPosition ();
607758}
608759
609760void TTDMemoryWidget::closeTab (int index)
@@ -613,9 +764,22 @@ void TTDMemoryWidget::closeTab(int index)
613764 QWidget* widget = m_tabWidget->widget (index);
614765 m_tabWidget->removeTab (index);
615766 widget->deleteLater ();
767+ updateNewTabButtonPosition ();
616768 }
617769}
618770
771+ void TTDMemoryWidget::updateNewTabButtonPosition ()
772+ {
773+ // This will be called to adjust the button position if needed
774+ // For now, the horizontal layout should handle this automatically
775+ }
776+
777+ void TTDMemoryWidget::resizeEvent (QResizeEvent* event)
778+ {
779+ QWidget::resizeEvent (event);
780+ updateNewTabButtonPosition ();
781+ }
782+
619783
620784// TTDMemorySidebarWidget implementation
621785TTDMemorySidebarWidget::TTDMemorySidebarWidget (BinaryViewRef data)
0 commit comments