Skip to content

Commit

Permalink
Merge pull request #246 from epasveer/237-look-at-making-seers-consol…
Browse files Browse the repository at this point in the history
…e-a-tab-in-the-breakpoints-area

237 look at making seers console a tab in the breakpoints area
  • Loading branch information
epasveer authored Sep 3, 2024
2 parents efe8021 + f856fc7 commit 921558b
Show file tree
Hide file tree
Showing 20 changed files with 601 additions and 349 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
## [2.5beta] - 2024-XX-XX
* Starting the 2.5 development cycle.
* Console now supports a subset of ANSI color codes.
* Console can be started in these modes:
- Detached
- Detached and minimized
- Attached in Seer's tab view (with gdb logs and seer logs).

## [2.4] - 2024-03-18
* Changed main icon to a more license friendly one.
Expand Down
1 change: 1 addition & 0 deletions debian/copyright
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ Copyright:
<https://icon-icons.com/users/AmQJzv5e8DpITUWIRmGPz/icon-sets> JohnGardner
<https://icon-icons.com/users/sr18GsT8hXb37mrJn4kOU/icon-sets> FerdiSetiadi
<https://icon-icons.com/users/7VZI9qW3el29z8Ka5fjmo/icon-sets> FreeIcons
<https://icon-icons.com/users/NXDGlLPTpYrqHz13UzsZ4/icon-sets> Unknown
License: CC-BY-4.0

Files:
Expand Down
235 changes: 151 additions & 84 deletions src/QDetachTabWidget.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include "QDetachTabWidget.h"
#include <QtWidgets/QTabBar>
#include <QtWidgets/QMenu>
#include <QtWidgets/QHBoxLayout>
#include <QAction>
#include <QtGui/QCursor>
#include <QtGui/QIcon>
#include <QtCore/QDebug>

QDetachTabWidget::QDetachTabWidget(QWidget* parent) : QTabWidget(parent) {
Expand All @@ -13,6 +15,117 @@ QDetachTabWidget::QDetachTabWidget(QWidget* parent) : QTabWidget(parent) {
QObject::connect(this, &QTabWidget::tabCloseRequested, this, &QDetachTabWidget::handleTabClosedRequested);
}

bool QDetachTabWidget::isDetached (int tabIndex) const {

// Get the tab the user selected.
QWidget* w = widget(tabIndex);

if (w == nullptr) {
return false;
}

// If it's the 'placeholder' it is detached.
if (w->objectName() == "QDetachTabWidgetPlaceholder") {
return true;
}

// Otherwise, it's still attached.
return false;
}

QWidget* QDetachTabWidget::tabWidget (int tabIndex) const {

if (tabIndex < 0 || tabIndex > _tabInfo.size()) {
return nullptr;
}

return _tabInfo[tabIndex]._widget;
}

void QDetachTabWidget::detachTab (int tabIndex) {

// Get the tab the user selected.
QWidget* w = widget(tabIndex);

if (w == nullptr) {
return;
}

// It can't be a 'placeholder' as it was already detached.
if (w->objectName() == "QDetachTabWidgetPlaceholder") {
return;
}

// Create a blank 'placeholder' tab.
QDetachTabWidgetPlaceholder* placeholder = new QDetachTabWidgetPlaceholder(tabIndex);

// Create an entry for the tab cache. Remember the real tab and the 'placeholder' tab. Plus the tab title.
QDetachTabInfo tabinfo(tabText(tabIndex), w, placeholder);
_tabInfo.append(tabinfo);

// Remove the real tab.
removeTab(tabIndex);

// Insert the 'placeholder' in the same position.
insertTab(tabIndex, placeholder, tabinfo._title);

// Tweak the detached tab to make sure it can't be destroyed as it is now a normal window.
w->setParent(0);
Qt::WindowFlags flags = w->windowFlags();
Qt::WindowFlags closeFlag = Qt::WindowCloseButtonHint;
flags = flags & (~closeFlag);
w->setWindowFlags(flags);
w->setWindowTitle(tabinfo._title);
w->setWindowIcon(windowIcon());
w->showMinimized();

// Connect the placeholder's 'reattach' signal to the slot.
QObject::connect(placeholder, &QDetachTabWidgetPlaceholder::reattach, this, &QDetachTabWidget::handleTabClosedRequested);

// Notify listeners the tab was detached.
emit tabDetached(tabIndex);
emit tabDetached(w);
}

void QDetachTabWidget::reattachTab (int tabIndex) {

// Get the tab the user selected to re-attach.
QWidget* w = widget(tabIndex);

if (w == nullptr) {
return;
}

// It must be a 'placeholder'
if (w->objectName() != "QDetachTabWidgetPlaceholder") {
return;
}

// Look for the 'placeholder' tab in the tab cache.
// Note, we do a scan of the cache because a QTabWidget can have isMovable() enabled.
// Using 'tabindex' is not always reliable.
QList<QDetachTabInfo>::iterator it = findPlaceholderWidget(w);
if (it == _tabInfo.end()) {
return;
}

// Remove the 'placeholder' tab.
removeTab(tabIndex); delete w;

// Insert the real tab in the same position.
insertTab(tabIndex, it->_widget, it->_title);

// Save the real tab's widget before we delete the entry.
w = it->_widget;

// Delete the entry from the tab cache.
_tabInfo.erase(it);

// Notify listeners the tab was reattached.
emit tabReattached(tabIndex);
emit tabReattached(w);
}

void QDetachTabWidget::closeEvent (QCloseEvent* e) {

auto it = _tabInfo.begin();
Expand Down Expand Up @@ -61,37 +174,8 @@ void QDetachTabWidget::handleShowContextMenu (const QPoint& point) {
//
if (action == detachAction) {

// Get the tab the user selected.
QWidget* w = widget(tabIndex);

// It can't be a 'placeholder' as it was already detached.
if (w->objectName() == "QDetachTabWidgetPlaceholder") {
return;
}

// Create a blank 'placeholder' tab.
QWidget* placeholder = new QWidget;
placeholder->setObjectName("QDetachTabWidgetPlaceholder");

// Create an entry for the tab cache. Remember the real tab and the 'placeholder' tab. Plus the tab title.
QDetachTabInfo tabinfo(tabText(tabIndex), w, placeholder);
_tabInfo.append(tabinfo);

// Remove the real tab.
removeTab(tabIndex);

// Insert the 'placeholder' in the same position.
insertTab(tabIndex, placeholder, tabinfo._title);

// Tweak the detached tab to make sure it can't be destroyed as it is now a normal window.
w->setParent(0);
Qt::WindowFlags flags = w->windowFlags();
Qt::WindowFlags closeFlag = Qt::WindowCloseButtonHint;
flags = flags & (~closeFlag);
w->setWindowFlags(flags);
w->setWindowTitle(tabinfo._title);
w->setWindowIcon(windowIcon());
w->show();
// Detach the tab.
detachTab(tabIndex);

// Set the tabwidget to the placeholder tab.
setCurrentIndex(tabIndex);
Expand All @@ -102,33 +186,11 @@ void QDetachTabWidget::handleShowContextMenu (const QPoint& point) {
//
if (action == reattachAction) {

// Get the tab the user selected to re-attach.
QWidget* w = widget(tabIndex);

// It must be a 'placeholder'
if (w->objectName() != "QDetachTabWidgetPlaceholder") {
return;
}

// Look for the 'placeholder' tab in the tab cache.
// Note, we do a scan of the cache because a QTabWidget can have isMovable() enabled.
// Using 'tabindex' is not always reliable.
QList<QDetachTabInfo>::iterator it = findPlaceholderWidget(w);
if (it == _tabInfo.end()) {
return;
}

// Remove the 'placeholder' tab.
removeTab(tabIndex); delete w;

// Insert the real tab in the same position.
insertTab(tabIndex, it->_widget, it->_title);
// Reattach the tab.
reattachTab(tabIndex);

// Set the tabwidget to the real tab.
setCurrentIndex(tabIndex);

// Delete the entry from the tab cache.
_tabInfo.erase(it);
}
}

Expand All @@ -140,36 +202,11 @@ void QDetachTabWidget::handleShowContextMenu (const QPoint& point) {
//
void QDetachTabWidget::handleTabClosedRequested (int tabIndex) {

// Get the widget to be closed.
QWidget* w = widget(tabIndex);

//qDebug() << "QDetachTabWidget::handleTabClosedRequested:" << tabIndex << w->objectName();
// Reattach the tab.
reattachTab(tabIndex);

// If the widget is a 'placeholder', reattach the real widget and delete the 'placeholder'.
if (w->objectName() == "QDetachTabWidgetPlaceholder") {

//qDebug() << "Reattaching detached tab.";

// Look for the 'placeholder' tab in the tab cache.
// Note, we do a scan of the cache because a QTabWidget can have isMovable() enabled.
// Using 'tabindex' is not always reliable.
QList<QDetachTabInfo>::iterator it = findPlaceholderWidget(w);
if (it == _tabInfo.end()) {
return;
}

// Remove the 'placeholder' tab.
removeTab(tabIndex); delete w;

// Insert the real tab in the same position.
insertTab(tabIndex, it->_widget, it->_title);

// Set the tabwidget to the real tab.
setCurrentIndex(tabIndex);

// Delete the entry from the tab cache.
_tabInfo.erase(it);
}
// Set the tabwidget to the real tab.
setCurrentIndex(tabIndex);
}

//
Expand Down Expand Up @@ -208,3 +245,33 @@ QList<QDetachTabInfo>::iterator QDetachTabWidget::findPlaceholderWidget (QWidget
return it;
}

//
// A placeholder widget that has a 'reattach' pushbutton.
//
QDetachTabWidgetPlaceholder::QDetachTabWidgetPlaceholder(int tabIndex, QWidget* parent) : QWidget(parent) {

// This the placeholder's object name. Users of this object can focus
// on this name if they need too.
setObjectName("QDetachTabWidgetPlaceholder");

// Create the 'Reattach' button and add a layout to it.
_reattachPushButton = new QPushButton("Reattach", this);
_reattachPushButton->setIcon(QIcon(":/qt-project.org/styles/commonstyle/images/right-16.png"));
_tabIndex = tabIndex;

QHBoxLayout* layout = new QHBoxLayout;
layout->addStretch();
layout->addWidget(_reattachPushButton);
layout->addStretch();

setLayout(layout);

// We'll handle the 'click' signal.
QObject::connect(_reattachPushButton, &QPushButton::clicked, this, &QDetachTabWidgetPlaceholder::handlePushButtonClicked);
}

// Handle the pushbutton 'click' by emitting the 'reattach' signal.
void QDetachTabWidgetPlaceholder::handlePushButtonClicked () {
emit reattach(_tabIndex);
}

32 changes: 32 additions & 0 deletions src/QDetachTabWidget.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once
#include <QtWidgets/QTabWidget>
#include <QtWidgets/QPushButton>
#include <QtCore/QString>
#include <QtCore/QList>

Expand All @@ -20,6 +21,19 @@ class QDetachTabWidget : public QTabWidget {
public:
QDetachTabWidget(QWidget* parent = 0);

bool isDetached (int tabIndex) const;
QWidget* tabWidget (int tabIndex) const;

public slots:
void detachTab (int tabIndex);
void reattachTab (int tabIndex);

signals:
void tabDetached (int tabIndex);
void tabDetached (QWidget* widget);
void tabReattached (int tabIndex);
void tabReattached (QWidget* widget);

protected:
void closeEvent (QCloseEvent* e);

Expand All @@ -34,3 +48,21 @@ class QDetachTabWidget : public QTabWidget {
QList<QDetachTabInfo> _tabInfo;
};

class QDetachTabWidgetPlaceholder : public QWidget {

Q_OBJECT

public:
QDetachTabWidgetPlaceholder(int tabIndex, QWidget* parent = 0);

signals:
void reattach (int tabIndex);

protected slots:
void handlePushButtonClicked ();

private:
QPushButton* _reattachPushButton;
int _tabIndex;
};

Loading

0 comments on commit 921558b

Please sign in to comment.