Support ConEnmu progress OSC

The 9;4 sequences can be used to show and hide progress on the tab bar.
The error, indeterminate, and paused states are not implemented yet.

If a tab has a custom color, its color is used for the progress, otherwise
the standard highlight color is used.

[1] https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC
This commit is contained in:
Kai Uwe Broulik
2025-12-23 19:11:15 +01:00
parent a41a4a7b4c
commit b5dc442531
15 changed files with 365 additions and 140 deletions

View File

@@ -428,6 +428,20 @@ Q_SIGNALS:
*/
void updateDroppedLines(int droppedLines);
/**
* Emitted after receiving the escape sequence which asks to
* display progress.
*
* @param progress The progress in percent (0-100)
*/
void progressChanged(int progress);
/**
* Emitted after receiving the escape sequence which asks to
* hide progress.
*/
void progressHidden();
protected:
virtual void setMode(int mode) = 0;
virtual void resetMode(int mode) = 0;

View File

@@ -6,6 +6,7 @@
// Own
#include "MainWindow.h"
#include "config-konsole.h"
// Qt
#include <QMenu>
@@ -13,6 +14,10 @@
#include <QMouseEvent>
#include <QScreen>
#include <QWindow>
#if HAVE_DBUS
#include <QDBusConnection>
#include <QDBusMessage>
#endif
// KDE
#include <KAcceleratorManager>
@@ -229,6 +234,7 @@ void MainWindow::disconnectController(SessionController *controller)
disconnect(controller, &Konsole::SessionController::titleChanged, this, &Konsole::MainWindow::activeViewTitleChanged);
disconnect(controller, &Konsole::SessionController::rawTitleChanged, this, &Konsole::MainWindow::updateWindowCaption);
disconnect(controller, &Konsole::SessionController::iconChanged, this, &Konsole::MainWindow::updateWindowIcon);
disconnect(controller, &Konsole::SessionController::progressChanged, this, &Konsole::MainWindow::updateProgress);
if (auto view = controller->view()) {
view->removeEventFilter(this);
@@ -275,6 +281,7 @@ void MainWindow::activeViewChanged(SessionController *controller)
connect(controller, &Konsole::SessionController::titleChanged, this, &Konsole::MainWindow::activeViewTitleChanged);
connect(controller, &Konsole::SessionController::rawTitleChanged, this, &Konsole::MainWindow::updateWindowCaption);
connect(controller, &Konsole::SessionController::iconChanged, this, &Konsole::MainWindow::updateWindowIcon);
connect(controller, &Konsole::SessionController::progressChanged, this, &Konsole::MainWindow::updateProgress);
// to prevent shortcuts conflict
if (auto hamburgerMenu = _hamburgerMenu->menu()) {
@@ -287,8 +294,9 @@ void MainWindow::activeViewChanged(SessionController *controller)
// update session title to match newly activated session
activeViewTitleChanged(controller);
// Update window icon to newly activated session's icon
// Update window icon and progress to newly activated session's icon
updateWindowIcon();
updateProgress();
for (IKonsolePlugin *plugin : _plugins) {
plugin->activeViewChanged(controller, this);
@@ -331,6 +339,43 @@ void MainWindow::updateWindowIcon()
}
}
void MainWindow::updateProgress()
{
#if HAVE_DBUS
std::optional<int> progress;
if (KonsoleSettings::showProgressInTaskBar() && _pluggedController) {
progress = _pluggedController->progress();
}
if (_progress == progress) {
return;
}
_progress = progress;
QString launcherId;
launcherId.append(QLatin1String("application://"));
launcherId.append(qApp->desktopFileName());
if (constexpr QLatin1String suffix{".desktop"}; !launcherId.endsWith(suffix)) {
launcherId.append(suffix);
}
QVariantMap properties;
if (progress) {
properties.insert(QStringLiteral("progress"), *progress / 100.0);
properties.insert(QStringLiteral("progress-visible"), true);
} else {
properties.insert(QStringLiteral("progress-visible"), false);
}
QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/org/kde/konsole/UnityLauncher"),
QStringLiteral("com.canonical.Unity.LauncherEntry"),
QStringLiteral("Update"));
message.setArguments({launcherId, properties});
QDBusConnection::sessionBus().send(message);
#endif
}
void MainWindow::setupActions()
{
KActionCollection *collection = actionCollection();
@@ -947,6 +992,7 @@ void MainWindow::applyKonsoleSettings()
setAutoSaveSettings();
updateWindowCaption();
updateProgress();
}
void MainWindow::activateMenuBar()

View File

@@ -13,6 +13,9 @@
#include <QPointer>
#include <QUrl>
// STL
#include <optional>
// KDE
#include <KXmlGuiWindow>
@@ -173,6 +176,7 @@ private Q_SLOTS:
void updateWindowIcon();
void updateWindowCaption();
void updateProgress();
void openUrls(const QList<QUrl> &urls);
// Sets the list of profiles to be displayed under the "New Tab" action
@@ -225,6 +229,7 @@ private:
QPointer<SessionController> _pluggedController;
std::vector<IKonsolePlugin *> _plugins;
QList<QAction *> _pluginsActions;
std::optional<int> _progress;
bool _blurEnabled = false;
bool _firstShowEvent = true;

View File

@@ -86,6 +86,14 @@ void ViewProperties::setIdentifier(int id)
_viewProperties.insert(id, this);
}
void ViewProperties::setProgress(const std::optional<int> &progress)
{
if (_progress != progress) {
_progress = progress;
Q_EMIT progressChanged(this);
}
}
QString ViewProperties::title() const
{
return _title;
@@ -106,4 +114,9 @@ QColor ViewProperties::color() const
return _color;
}
std::optional<int> ViewProperties::progress() const
{
return _progress;
}
#include "moc_ViewProperties.cpp"

View File

@@ -14,6 +14,9 @@
#include <QObject>
#include <QUrl>
// STL
#include <optional>
// Konsole
#include "konsoleprivate_export.h"
#include "session/Session.h"
@@ -41,6 +44,8 @@ public:
QString title() const;
/** Returns the color associated with a view */
QColor color() const;
/** Returns the progress associated with a view */
std::optional<int> progress() const;
/**
* Returns the URL current associated with a view.
@@ -89,6 +94,8 @@ Q_SIGNALS:
void readOnlyChanged(ViewProperties *item);
/** Emitted when "copy input" state changes */
void copyInputChanged(ViewProperties *item);
/** Emitted when the progress changes */
void progressChanged(ViewProperties *item);
public Q_SLOTS:
/**
@@ -119,6 +126,8 @@ protected:
void setColor(const QColor &color);
/** Subclasses may call this method to change the identifier. */
void setIdentifier(int id);
/** Subclass may call this method to change the progress. */
void setProgress(const std::optional<int> &progress);
private:
Q_DISABLE_COPY(ViewProperties)
@@ -127,7 +136,7 @@ private:
QString _title;
QColor _color;
int _identifier;
std::optional<int> _progress;
static QHash<int, ViewProperties *> _viewProperties;
};
}

View File

@@ -1678,6 +1678,43 @@ void Vt102Emulation::processSessionAttributeRequest(const int tokenSize, const u
int rows = -1, cols = -1;
_currentScreen->addPlacement(pixmap, rows, cols, -1, -1, TerminalGraphicsPlacement_t::iTerm, true, moveCursor);
}
if (attribute == ConEmu) {
const auto list = QStringView(value).split(QLatin1Char(';'));
if (list.size() >= 2) {
// Progress indicator.
if (list.at(0) == QLatin1Char('4')) {
bool ok;
const int st = list.at(1).toInt(&ok);
if (ok) {
switch (st) {
case 0:
Q_EMIT progressHidden();
break;
case 1:
if (list.size() >= 3) {
const int pr = list.at(2).toInt(&ok);
if (ok && pr >= 0 && pr <= 100) {
Q_EMIT progressChanged(pr);
}
}
break;
case 2:
// TODO error state.
break;
case 3:
// TODO indeterminate state.
Q_EMIT progressHidden();
break;
case 4:
// TODO paused state.
break;
}
}
}
}
}
_pendingSessionAttributesUpdates[attribute] = value;
_sessionAttributesUpdateTimer->start(20);
}

View File

@@ -190,6 +190,8 @@ private:
// https://chromium.googlesource.com/apps/libapps/+/master/hterm/doc/ControlSequences.md#OSC
Notification = 777,
Image = 1337,
// https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC
ConEmu = 9,
};
ParserStates _state = Ground;

View File

@@ -230,6 +230,13 @@ SessionController::SessionController(Session *sessionParam, TerminalDisplay *vie
// xterm '11;?' request
connect(session(), &Konsole::Session::getBackgroundColor, this, &Konsole::SessionController::sendBackgroundColor);
connect(session()->emulation(), &Konsole::Emulation::progressChanged, this, [this](int progress) {
setProgress(progress);
});
connect(session()->emulation(), &Konsole::Emulation::progressHidden, this, [this] {
setProgress(std::nullopt);
});
_allControllers.insert(this);
// A list of programs that accept Ctrl+C to clear command line used

View File

@@ -6,6 +6,7 @@
// Own
#include "GeneralSettings.h"
#include "config-konsole.h"
#include <KMessageBox>
@@ -15,6 +16,9 @@ GeneralSettings::GeneralSettings(QWidget *aParent)
: QWidget(aParent)
{
setupUi(this);
#if !HAVE_DBUS
kcfg_ShowProgressInTaskBar->hide();
#endif
connect(enableAllMessagesButton, &QPushButton::clicked, this, &Konsole::GeneralSettings::slotEnableAllMessages);
}

View File

@@ -37,26 +37,47 @@
<property name="spacing">
<number>6</number>
</property>
<item row="16" column="0" alignment="Qt::AlignmentFlag::AlignRight">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Notifications:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="kcfg_EnableSecuritySensitiveDBusAPI">
<property name="text">
<string>Enable the security sensitive parts of the DBus API</string>
</property>
</widget>
</item>
<item row="12" column="1">
<widget class="QCheckBox" name="kcfg_SearchReverseSearch">
<widget class="QCheckBox" name="kcfg_SearchHighlightMatches">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Sets whether search should start from the bottom</string>
</property>
<property name="text">
<string>Search backwards</string>
<string>Highlight all matches</string>
</property>
</widget>
</item>
<item row="15" column="0" alignment="Qt::AlignmentFlag::AlignRight">
<widget class="QLabel" name="label_3">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Notifications:</string>
<string>Process and window:</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="kcfg_ListenForZModemTerminalCodes">
<property name="text">
<string>Listen for ZModem terminal codes</string>
</property>
</widget>
</item>
@@ -67,6 +88,42 @@
</property>
</widget>
</item>
<item row="15" column="1">
<spacer>
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="kcfg_ShowWindowTitleOnTitleBar">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Show window title on the titlebar</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="kcfg_RemoveWindowTitleBarAndFrame">
<property name="text">
<string>Remove window titlebar and frame</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QCheckBox" name="kcfg_AllowMenuAccelerators">
<property name="sizePolicy">
@@ -80,21 +137,23 @@
</property>
</widget>
</item>
<item row="9" column="0" alignment="Qt::AlignmentFlag::AlignRight">
<widget class="QLabel" name="label_2">
<item row="1" column="1">
<widget class="QCheckBox" name="kcfg_UseSingleInstance">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>When launching Konsole re-use existing process if possible</string>
</property>
<property name="text">
<string comment="@item:intext Search options">Search:</string>
<string>Run all Konsole windows in a single process</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="kcfg_RemoveWindowTitleBarAndFrame">
<property name="text">
<string>Remove window titlebar and frame</string>
</property>
</widget>
</item>
<item row="15" column="1">
<item row="16" column="1">
<layout class="QHBoxLayout" stretch="0,1">
<property name="spacing">
<number>0</number>
@@ -130,49 +189,7 @@
</item>
</layout>
</item>
<item row="11" column="1">
<widget class="QCheckBox" name="kcfg_SearchHighlightMatches">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Highlight all matches</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="kcfg_ShowWindowTitleOnTitleBar">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Show window title on the titlebar</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QCheckBox" name="kcfg_SearchNoWrap">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Sets whether search should stop instead of wrapping</string>
</property>
<property name="text">
<string>No wrap</string>
</property>
</widget>
</item>
<item row="14" column="1">
<item row="9" column="1">
<spacer>
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
@@ -188,18 +205,8 @@
</property>
</spacer>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Process and window:</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QCheckBox" name="kcfg_UseSingleInstance">
<item row="10" column="1">
<widget class="QCheckBox" name="kcfg_SearchCaseSensitive">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -207,10 +214,62 @@
</sizepolicy>
</property>
<property name="toolTip">
<string>When launching Konsole re-use existing process if possible</string>
<string>Sets whether the search is case sensitive</string>
</property>
<property name="text">
<string>Run all Konsole windows in a single process</string>
<string>Case sensitive</string>
</property>
</widget>
</item>
<item row="13" column="1">
<widget class="QCheckBox" name="kcfg_SearchReverseSearch">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Sets whether search should start from the bottom</string>
</property>
<property name="text">
<string>Search backwards</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QCheckBox" name="kcfg_SearchRegExpression">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Match using regular expressions</string>
</property>
</widget>
</item>
<item row="10" column="0" alignment="Qt::AlignmentFlag::AlignRight">
<widget class="QLabel" name="label_2">
<property name="text">
<string comment="@item:intext Search options">Search:</string>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QCheckBox" name="kcfg_SearchNoWrap">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Sets whether search should stop instead of wrapping</string>
</property>
<property name="text">
<string>No wrap</string>
</property>
</widget>
</item>
@@ -230,62 +289,10 @@
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QCheckBox" name="kcfg_EnableSecuritySensitiveDBusAPI">
<property name="text">
<string>Enable the security sensitive parts of the DBus API</string>
</property>
</widget>
</item>
<item row="8" column="1">
<spacer>
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>16</height>
</size>
</property>
</spacer>
</item>
<item row="9" column="1">
<widget class="QCheckBox" name="kcfg_SearchCaseSensitive">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Sets whether the search is case sensitive</string>
</property>
<widget class="QCheckBox" name="kcfg_ShowProgressInTaskBar">
<property name="text">
<string>Case sensitive</string>
</property>
</widget>
</item>
<item row="10" column="1">
<widget class="QCheckBox" name="kcfg_SearchRegExpression">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Match using regular expressions</string>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QCheckBox" name="kcfg_ListenForZModemTerminalCodes">
<property name="text">
<string>Listen for ZModem terminal codes</string>
<string>Show progress in taskbar</string>
</property>
</widget>
</item>

View File

@@ -33,6 +33,11 @@
<tooltip>When launching Konsole re-use existing process if possible</tooltip>
<default>false</default>
</entry>
<entry name="ShowProgressInTaskBar" type="Bool">
<label>Show progress in task bar</label>
<tooltip>When a script reports its progress, it will be shown in the task bar</tooltip>
<default>true</default>
</entry>
<entry name="EnableSecuritySensitiveDBusAPI" type="Bool">
<label>Enable the security sensitive parts of the DBus API</label>
<tooltip>DBus API like runCommand will be enabled</tooltip>

View File

@@ -32,14 +32,41 @@ DetachableTabBar::DetachableTabBar(QWidget *parent)
void DetachableTabBar::setColor(int idx, const QColor &color)
{
setTabData(idx, color);
update();
DetachableTabData data = tabData(idx).value<DetachableTabData>();
if (data.color != color) {
data.color = color;
setDetachableTabData(idx, data);
update(tabRect(idx));
}
}
void DetachableTabBar::removeColor(int idx)
{
setTabData(idx, QVariant());
update();
DetachableTabData data = tabData(idx).value<DetachableTabData>();
if (data.color.isValid()) {
data.color = QColor();
setDetachableTabData(idx, data);
update(tabRect(idx));
}
}
void DetachableTabBar::setProgress(int idx, const std::optional<int> &progress)
{
DetachableTabData data = tabData(idx).value<DetachableTabData>();
if (data.progress != progress) {
data.progress = progress;
setDetachableTabData(idx, data);
update(tabRect(idx));
}
}
void DetachableTabBar::setDetachableTabData(int idx, const DetachableTabData &data)
{
if ((data.color.isValid() && data.color.alpha() > 0) || data.progress.has_value()) {
setTabData(idx, QVariant::fromValue(data));
} else {
setTabData(idx, QVariant());
}
}
void DetachableTabBar::middleMouseButtonClickAt(const QPoint &pos)
@@ -170,18 +197,34 @@ void DetachableTabBar::paintEvent(QPaintEvent *event)
continue;
}
QColor varColor = data.value<QColor>();
if (!varColor.isValid() || varColor.alpha() == 0) {
const DetachableTabData tabData = data.value<DetachableTabData>();
const bool colorValid = tabData.color.isValid() && tabData.color.alpha() > 0;
if (!colorValid && !tabData.progress.has_value()) {
continue;
}
painter.setBrush(varColor);
const QColor color = colorValid ? tabData.color : palette().highlight().color();
painter.setBrush(color);
QRect tRect = tabRect(tabIndex);
tRect.setTop(painter.fontMetrics().height() + 6); // Color bar top position consider a height the font and fixed spacing of 6px
tRect.setHeight(4);
tRect.setLeft(tRect.left() + 6);
tRect.setWidth(tRect.width() - 6);
painter.drawRect(tRect);
// Draw progress, if any, ontop of a faint bar.
if (tabData.progress.has_value()) {
painter.setOpacity(0.3);
painter.drawRect(tRect);
painter.setOpacity(1.0);
tRect.setWidth(tRect.width() * tabData.progress.value() / 100.0);
painter.drawRect(tRect);
} else {
painter.drawRect(tRect);
}
}
}

View File

@@ -10,12 +10,20 @@
#include <QCursor>
#include <QTabBar>
#include <optional>
class QColor;
class QPaintEvent;
namespace Konsole
{
class TabbedViewContainer;
struct DetachableTabData {
QColor color;
std::optional<int> progress;
};
class DetachableTabBar : public QTabBar
{
Q_OBJECT
@@ -30,6 +38,9 @@ public:
void setColor(int idx, const QColor &color);
void removeColor(int idx);
void setProgress(int idx, const std::optional<int> &progress);
Q_SIGNALS:
void detachTab(int index);
void moveTabToWindow(int tabIndex, QWidget *otherWindow);
@@ -47,6 +58,8 @@ protected:
void paintEvent(QPaintEvent *event) override;
private:
void setDetachableTabData(int idx, const DetachableTabData &data);
DragType dragType;
QCursor _originalCursor;
QList<TabbedViewContainer *> _containers;
@@ -54,4 +67,6 @@ private:
};
}
Q_DECLARE_METATYPE(Konsole::DetachableTabData)
#endif

View File

@@ -85,6 +85,8 @@ TabbedViewContainer::TabbedViewContainer(ViewManager *connectedViewManager, QWid
connect(this, &TabbedViewContainer::setColor, tabBarWidget, &DetachableTabBar::setColor);
connect(this, &TabbedViewContainer::removeColor, tabBarWidget, &DetachableTabBar::removeColor);
connect(this, &TabbedViewContainer::setProgress, tabBarWidget, &DetachableTabBar::setProgress);
// The context menu of tab bar
_contextPopupMenu = new QMenu(tabBar());
connect(_contextPopupMenu, &QMenu::aboutToHide, this, [this]() {
@@ -406,6 +408,8 @@ void TabbedViewContainer::connectTerminalDisplay(TerminalDisplay *display)
connect(item, &Konsole::ViewProperties::readOnlyChanged, this, &Konsole::TabbedViewContainer::updateSpecialState);
connect(item, &Konsole::ViewProperties::copyInputChanged, this, &Konsole::TabbedViewContainer::updateSpecialState);
connect(item, &Konsole::ViewProperties::progressChanged, this, &Konsole::TabbedViewContainer::updateProgress);
}
void TabbedViewContainer::disconnectTerminalDisplay(TerminalDisplay *display)
@@ -689,6 +693,15 @@ void TabbedViewContainer::updateSpecialState(ViewProperties *item)
updateIcon(item);
}
void TabbedViewContainer::updateProgress(ViewProperties *item)
{
auto controller = qobject_cast<SessionController *>(item);
auto topLevelSplitter = qobject_cast<ViewSplitter *>(controller->view()->parentWidget())->getToplevelSplitter();
const int index = indexOf(topLevelSplitter);
Q_EMIT setProgress(index, item->progress());
}
void TabbedViewContainer::currentSessionControllerChanged(SessionController *controller)
{
auto topLevelSplitter = qobject_cast<ViewSplitter *>(controller->view()->parentWidget())->getToplevelSplitter();

View File

@@ -77,6 +77,8 @@ public:
void updateNotification(ViewProperties *item, Konsole::Session::Notification notification, bool enabled);
/** Sets tab special state (copy input or read-only) */
void updateSpecialState(ViewProperties *item);
/** Sets tab progress */
void updateProgress(ViewProperties *item);
/** Changes the active view to the next view */
void activateNextView();
@@ -209,6 +211,9 @@ Q_SIGNALS:
/** remove the color tab */
void removeColor(int idx);
/** set the tab progress */
void setProgress(int idx, const std::optional<int> &progress);
protected:
// close tabs and unregister
void closeTerminalTab(int idx);