Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

237 look at making seers console a tab in the breakpoints area #246

Merged
Merged
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
Loading