Skip to content

Commit

Permalink
feat: automatically show and hide close buttons from tab bar
Browse files Browse the repository at this point in the history
This implementation shows and hides all close buttons simultaneously
while mouse cursor hovers over them. A delay was added before close
buttons are hidden again to save the user from a jarring experience
when they off-shoot the mouse cursor reaching for the tab bar.

Ideally we'd only display close buttons for the active tab and the tab
currently being hovered. However, the list of tabs is stored in the
protected side of QTabBar (qtabbar_p.h) and we can't make use of it
without re-inventing the wheel.
  • Loading branch information
Cuperino committed Mar 3, 2025
1 parent f118094 commit ad0bbd3
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 1 deletion.
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ set(PROJECT_SOURCES
knutmain.cpp
knutstyle.h
knutstyle.cpp
knuttabwidget.h
knuttabwidget.cpp
logpanel.h
logpanel.cpp
mainwindow.h
Expand Down
56 changes: 56 additions & 0 deletions src/gui/knuttabwidget.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
This file is part of Knut.
SPDX-FileCopyrightText: 2025 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
SPDX-License-Identifier: GPL-3.0-only
Contact KDAB at <[email protected]> for commercial licensing options.
*/

#include "knuttabwidget.h"

#include <QEvent>
#include <QTabBar>
#include <QTimer>

namespace Gui {

KnutTabBar::KnutTabBar(QWidget *parent)
: QTabBar(parent)
, m_hideCloseTimer(new QTimer(this))
{
// Human moment delay before hiding close buttons
m_hideCloseTimer->setInterval(2000);
connect(m_hideCloseTimer, &QTimer::timeout, this, [this]() {
setTabsClosable(false);
});
}

bool KnutTabBar::event(QEvent *event)
{
switch (event->type()) {
case QEvent::HoverEnter:
m_hideCloseTimer->stop();
setTabsClosable(true);
break;
case QEvent::HoverLeave:
m_hideCloseTimer->start();
break;
case QEvent::Show:
setTabsClosable(false);
break;
default:
break;
}
return QTabBar::event(event);
}

KnutTabWidget::KnutTabWidget(QWidget *parent)
: QTabWidget(parent)
{
auto tabBar = new KnutTabBar(this);
setTabBar(tabBar);
}

} // namespace Gui
40 changes: 40 additions & 0 deletions src/gui/knuttabwidget.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
This file is part of Knut.
SPDX-FileCopyrightText: 2025 Klarälvdalens Datakonsult AB, a KDAB Group company <[email protected]>
SPDX-License-Identifier: GPL-3.0-only
Contact KDAB at <[email protected]> for commercial licensing options.
*/

#pragma once

#include <QObject>
#include <QTabBar>
#include <QTabWidget>
#include <QWidget>

namespace Gui {

class KnutTabBar : public QTabBar
{
Q_OBJECT
public:
KnutTabBar(QWidget *parent);

protected:
bool event(QEvent *event);

private:
QTimer *m_hideCloseTimer;
};

class KnutTabWidget : public QTabWidget
{
Q_OBJECT
public:
KnutTabWidget(QWidget *parent);
};

} // namespace Gui
2 changes: 1 addition & 1 deletion src/gui/mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<number>0</number>
</property>
<item>
<widget class="QTabWidget" name="tabWidget">
<widget class="KnutTabWidget" name="tabWidget">
<property name="documentMode">
<bool>true</bool>
</property>
Expand Down

0 comments on commit ad0bbd3

Please sign in to comment.