From d8834e291bdc8613156d5883b5b3975fce9b4372 Mon Sep 17 00:00:00 2001 From: Guido Berhoerster Date: Thu, 27 Oct 2022 11:55:24 +0200 Subject: [PATCH 1/6] Expose ColorSchemeManager and ColorScheme to QML Expose a subset of the ColorSchemeManager to QML in order to allow editing of ColorSchemes from within QML. --- lib/ColorScheme.cpp | 72 ++++++++++++++++++++++-------------- lib/ColorScheme.h | 26 +++++++++---- src/qmltermwidget_plugin.cpp | 11 ++++++ 3 files changed, 74 insertions(+), 35 deletions(-) diff --git a/lib/ColorScheme.cpp b/lib/ColorScheme.cpp index f7b9af2f..971a5611 100644 --- a/lib/ColorScheme.cpp +++ b/lib/ColorScheme.cpp @@ -120,35 +120,12 @@ const char* const ColorScheme::translatedColorNames[TABLE_COLORS] = tr_NOOP("Color 8 (Intense)") }; -ColorScheme::ColorScheme() +ColorScheme::ColorScheme(QObject *parent) : QObject(parent) { _table = nullptr; _randomTable = nullptr; _opacity = 1.0; } -ColorScheme::ColorScheme(const ColorScheme& other) - : _opacity(other._opacity) - ,_table(nullptr) - ,_randomTable(nullptr) -{ - setName(other.name()); - setDescription(other.description()); - - if ( other._table != nullptr ) - { - for ( int i = 0 ; i < TABLE_COLORS ; i++ ) - setColorTableEntry(i,other._table[i]); - } - - if ( other._randomTable != nullptr ) - { - for ( int i = 0 ; i < TABLE_COLORS ; i++ ) - { - const RandomizationRange& range = other._randomTable[i]; - setRandomizationRange(i,range.hue,range.saturation,range.value); - } - } -} ColorScheme::~ColorScheme() { delete[] _table; @@ -206,6 +183,19 @@ ColorEntry ColorScheme::colorEntry(int index , uint randomSeed) const return entry; } +QColor ColorScheme::getColor(int index) const +{ + return colorEntry(index).color; +} +void ColorScheme::setColor(int index, QColor color) +{ + ColorEntry colorEntry = ColorScheme::colorEntry(index); + if (colorEntry.color != color) { + colorEntry.color = color; + setColorTableEntry(index, colorEntry); + Q_EMIT colorChanged(index); + } +} void ColorScheme::getColorTable(ColorEntry* table , uint randomSeed) const { for ( int i = 0 ; i < TABLE_COLORS ; i++ ) @@ -267,7 +257,7 @@ bool ColorScheme::hasDarkBackground() const // so 127 is in the middle, anything less is deemed 'dark' return backgroundColor().value() < 127; } -void ColorScheme::setOpacity(qreal opacity) { _opacity = opacity; } +void ColorScheme::setOpacity(qreal opacity) { _opacity = opacity; opacityChanged(); } qreal ColorScheme::opacity() const { return _opacity; } void ColorScheme::read(const QString & fileName) @@ -284,6 +274,21 @@ void ColorScheme::read(const QString & fileName) readColorEntry(&s, i); } } + +void ColorScheme::write(const QString & fileName) const +{ + QSettings s(fileName, QSettings::IniFormat); + s.beginGroup("General"); + + s.setValue("Description", _description); + s.setValue("Opacity", _opacity); + s.endGroup(); + + for (int i=0 ; i < TABLE_COLORS ; i++) + { + writeColorEntry(&s, i, colorTable()[i]); + } +} #if 0 // implemented upstream - user apps void ColorScheme::read(KConfig& config) @@ -403,6 +408,19 @@ void ColorScheme::readColorEntry(QSettings * s , int index) s->endGroup(); } +void ColorScheme::writeColorEntry(QSettings * s, int index, const ColorEntry& entry) const +{ + s->beginGroup(colorNameForIndex(index)); + QStringList colorList; + colorList << QString::number(entry.color.red()) << QString::number(entry.color.green()) << QString::number(entry.color.blue()); + s->setValue("Color", colorList); + s->setValue("Transparency", (bool)entry.transparent); + if (entry.fontWeight != ColorEntry::UseCurrentFormat) + { + s->setValue("Bold", entry.fontWeight == ColorEntry::Bold); + } + s->endGroup(); +} #if 0 // implemented upstream - user apps void ColorScheme::writeColorEntry(KConfig& config , const QString& colorName, const ColorEntry& entry , const RandomizationRange& random) const @@ -566,7 +584,7 @@ bool ColorSchemeManager::loadColorScheme(const QString& filePath) const QString& schemeName = info.baseName(); - ColorScheme* scheme = new ColorScheme(); + ColorScheme* scheme = new ColorScheme(this); scheme->setName(schemeName); scheme->read(filePath); @@ -649,7 +667,7 @@ QString ColorSchemeManager::findColorSchemePath(const QString& name) const return path; } -const ColorScheme* ColorSchemeManager::findColorScheme(const QString& name) +const Konsole::ColorScheme* ColorSchemeManager::findColorScheme(const QString& name) { if ( name.isEmpty() ) return defaultColorScheme(); diff --git a/lib/ColorScheme.h b/lib/ColorScheme.h index 416fe25b..04359e2e 100644 --- a/lib/ColorScheme.h +++ b/lib/ColorScheme.h @@ -45,15 +45,16 @@ namespace Konsole * The color scheme includes the palette of colors used to draw the text and character backgrounds * in the display and the opacity level of the display background. */ -class ColorScheme +class ColorScheme : public QObject { + Q_OBJECT + public: /** * Constructs a new color scheme which is initialised to the default color set * for Konsole. */ - ColorScheme(); - ColorScheme(const ColorScheme& other); + ColorScheme(QObject *parent = nullptr); ~ColorScheme(); /** Sets the descriptive name of the color scheme. */ @@ -74,6 +75,7 @@ class ColorScheme void write(KConfig& config) const; #endif void read(const QString & filename); + Q_INVOKABLE void write(const QString & filename) const; /** Sets a single entry within the color palette. */ void setColorTableEntry(int index , const ColorEntry& entry); @@ -96,6 +98,10 @@ class ColorScheme */ ColorEntry colorEntry(int index , uint randomSeed = 0) const; + Q_INVOKABLE QColor getColor(int index) const; + Q_INVOKABLE void setColor(int index, QColor color); + Q_SIGNAL void colorChanged(int index); + /** * Convenience method. Returns the * foreground color for this scheme, @@ -126,12 +132,13 @@ class ColorScheme * * TODO: More documentation */ - void setOpacity(qreal opacity); + Q_INVOKABLE void setOpacity(qreal opacity); /** * Returns the opacity level for this color scheme, see setOpacity() * TODO: More documentation */ - qreal opacity() const; + Q_INVOKABLE qreal opacity() const; + Q_SIGNAL void opacityChanged(); /** * Enables randomization of the background color. This will cause @@ -177,6 +184,7 @@ class ColorScheme void writeColorEntry(KConfig& config , const QString& colorName, const ColorEntry& entry,const RandomizationRange& range) const; #endif void readColorEntry(QSettings *s, int index); + void writeColorEntry(QSettings *s, int index, const ColorEntry& entry) const; // sets the amount of randomization allowed for a particular color // in the palette. creates the randomization table if @@ -221,8 +229,10 @@ class AccessibleColorScheme : public ColorScheme * Manages the color schemes available for use by terminal displays. * See ColorScheme */ -class ColorSchemeManager +class ColorSchemeManager : public QObject { + Q_OBJECT + public: /** @@ -251,7 +261,7 @@ class ColorSchemeManager * The first time that a color scheme with a particular name is * requested, the configuration information is loaded from disk. */ - const ColorScheme* findColorScheme(const QString& name); + Q_INVOKABLE const Konsole::ColorScheme* findColorScheme(const QString& name); #if 0 /** @@ -291,7 +301,7 @@ class ColorSchemeManager * @param[in] path The path to KDE 4 .colorscheme or KDE 3 .schema. * @return Whether the color scheme is loaded successfully. */ - bool loadCustomColorScheme(const QString& path); + Q_INVOKABLE bool loadCustomColorScheme(const QString& path); /** * @brief Allows to add a custom location of color schemes. diff --git a/src/qmltermwidget_plugin.cpp b/src/qmltermwidget_plugin.cpp index 656b115e..e9e8b4f1 100644 --- a/src/qmltermwidget_plugin.cpp +++ b/src/qmltermwidget_plugin.cpp @@ -1,5 +1,6 @@ #include "qmltermwidget_plugin.h" +#include "ColorScheme.h" #include "TerminalDisplay.h" #include "ksession.h" @@ -9,11 +10,21 @@ using namespace Konsole; +static QObject *colorschememanager_provider(QQmlEngine *engine, QJSEngine *scriptEngine) +{ + Q_UNUSED(engine) + Q_UNUSED(scriptEngine) + + return ColorSchemeManager::instance(); +} + void QmltermwidgetPlugin::registerTypes(const char *uri) { // @uri org.qterminal.qmlterminal qmlRegisterType(uri, 1, 0, "QMLTermWidget"); qmlRegisterType(uri, 1, 0, "QMLTermSession"); + qmlRegisterUncreatableType(uri, 1, 0, "ColorScheme", QStringLiteral("Not instantiatable")); + qmlRegisterSingletonType(uri, 1, 0, "ColorSchemeManager", colorschememanager_provider); } void QmltermwidgetPlugin::initializeEngine(QQmlEngine *engine, const char *uri) From 75a7a1ae11ff12516e7e53ea29662c1eb4d280d5 Mon Sep 17 00:00:00 2001 From: Guido Berhoerster Date: Fri, 28 Oct 2022 11:15:19 +0200 Subject: [PATCH 2/6] Expose QMLTermWidget foreground and background colors to QML --- lib/TerminalDisplay.cpp | 12 +++++++++++- lib/TerminalDisplay.h | 7 +++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/TerminalDisplay.cpp b/lib/TerminalDisplay.cpp index d84cb87a..f90af518 100644 --- a/lib/TerminalDisplay.cpp +++ b/lib/TerminalDisplay.cpp @@ -162,20 +162,30 @@ void TerminalDisplay::setBackgroundColor(const QColor& color) // Avoid propagating the palette change to the scroll bar _scrollBar->setPalette( QApplication::palette() ); + emit backgroundColorChanged(); update(); } void TerminalDisplay::setForegroundColor(const QColor& color) { _colorTable[DEFAULT_FORE_COLOR].color = color; - + emit foregroundColorChanged(); update(); } +QColor TerminalDisplay::backgroundColor() const +{ + return _colorTable[DEFAULT_BACK_COLOR].color; +} +QColor TerminalDisplay::foregroundColor() const +{ + return _colorTable[DEFAULT_FORE_COLOR].color; +} void TerminalDisplay::setColorTable(const ColorEntry table[]) { for (int i = 0; i < TABLE_COLORS; i++) _colorTable[i] = table[i]; setBackgroundColor(_colorTable[DEFAULT_BACK_COLOR].color); + setForegroundColor(_colorTable[DEFAULT_FORE_COLOR].color); } /* ------------------------------------------------------------------------- */ diff --git a/lib/TerminalDisplay.h b/lib/TerminalDisplay.h index 8e97a5dd..dda130da 100644 --- a/lib/TerminalDisplay.h +++ b/lib/TerminalDisplay.h @@ -94,6 +94,8 @@ class KONSOLEPRIVATE_EXPORT TerminalDisplay : public QQuickPaintedItem Q_PROPERTY(KSession* session READ getSession WRITE setSession NOTIFY sessionChanged ) Q_PROPERTY(QFont font READ getVTFont WRITE setVTFont NOTIFY vtFontChanged ) Q_PROPERTY(QString colorScheme READ colorScheme WRITE setColorScheme NOTIFY colorSchemeChanged ) + Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY backgroundColorChanged ) + Q_PROPERTY(QColor foregroundColor READ foregroundColor NOTIFY foregroundColorChanged ) Q_PROPERTY(QSize terminalSize READ getTerminalSize NOTIFY changedContentSizeSignal) Q_PROPERTY(int lineSpacing READ lineSpacing WRITE setLineSpacing NOTIFY lineSpacingChanged ) Q_PROPERTY(bool terminalUsesMouse READ getUsesMouse NOTIFY usesMouseChanged ) @@ -564,6 +566,9 @@ public slots: */ void setForegroundColor(const QColor& color); + QColor backgroundColor() const; + QColor foregroundColor() const; + void selectionChanged(); // QMLTermWidget @@ -637,6 +642,8 @@ public slots: void lineSpacingChanged(); void availableColorSchemesChanged(); void colorSchemeChanged(); + void backgroundColorChanged(); + void foregroundColorChanged(); void fullCursorHeightChanged(); void blinkingCursorStateChanged(); void boldIntenseChanged(); From b3210f8936dfc4645b5e49c52e02e4385befe742 Mon Sep 17 00:00:00 2001 From: Guido Berhoerster Date: Fri, 28 Oct 2022 11:30:54 +0200 Subject: [PATCH 3/6] Make QmlTermWidget scrollbarCurrentValue property writable --- lib/TerminalDisplay.cpp | 7 +++++++ lib/TerminalDisplay.h | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/TerminalDisplay.cpp b/lib/TerminalDisplay.cpp index f90af518..fe3f4cbc 100644 --- a/lib/TerminalDisplay.cpp +++ b/lib/TerminalDisplay.cpp @@ -3582,6 +3582,13 @@ int TerminalDisplay::getScrollbarValue() return _scrollBar->value(); } +void TerminalDisplay::setScrollbarValue(int value) +{ + if (value != _scrollBar->value()) { + _scrollBar->setValue(value); + } +} + int TerminalDisplay::getScrollbarMaximum() { return _scrollBar->maximum(); diff --git a/lib/TerminalDisplay.h b/lib/TerminalDisplay.h index dda130da..4b0007a6 100644 --- a/lib/TerminalDisplay.h +++ b/lib/TerminalDisplay.h @@ -101,7 +101,7 @@ class KONSOLEPRIVATE_EXPORT TerminalDisplay : public QQuickPaintedItem Q_PROPERTY(bool terminalUsesMouse READ getUsesMouse NOTIFY usesMouseChanged ) Q_PROPERTY(int lines READ lines NOTIFY changedContentSizeSignal) Q_PROPERTY(int columns READ columns NOTIFY changedContentSizeSignal) - Q_PROPERTY(int scrollbarCurrentValue READ getScrollbarValue NOTIFY scrollbarParamsChanged ) + Q_PROPERTY(int scrollbarCurrentValue READ getScrollbarValue WRITE setScrollbarValue NOTIFY scrollbarParamsChanged ) Q_PROPERTY(int scrollbarMaximum READ getScrollbarMaximum NOTIFY scrollbarParamsChanged ) Q_PROPERTY(int scrollbarMinimum READ getScrollbarMinimum NOTIFY scrollbarParamsChanged ) Q_PROPERTY(QSize fontMetrics READ getFontMetrics NOTIFY changedFontMetricSignal ) @@ -956,6 +956,8 @@ private slots: bool getUsesMouse(); int getScrollbarValue(); + void setScrollbarValue(int value); + int getScrollbarMaximum(); int getScrollbarMinimum(); From eae6156cb7b857d07cb2699e0aed9901fe7ca0ed Mon Sep 17 00:00:00 2001 From: Guido Berhoerster Date: Fri, 28 Oct 2022 11:36:27 +0200 Subject: [PATCH 4/6] Add QMLTermWidget methods to query whether clipboard/selection are set --- lib/TerminalDisplay.cpp | 9 +++++++++ lib/TerminalDisplay.h | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/TerminalDisplay.cpp b/lib/TerminalDisplay.cpp index fe3f4cbc..e2d75a2d 100644 --- a/lib/TerminalDisplay.cpp +++ b/lib/TerminalDisplay.cpp @@ -2877,6 +2877,15 @@ void TerminalDisplay::pasteSelection() emitSelection(true,false); } +bool TerminalDisplay::isClipboardEmpty() +{ + return QApplication::clipboard()->text().isEmpty(); +} + +bool TerminalDisplay::isSelectionEmpty() +{ + return _screenWindow->selectedText(_preserveLineBreaks).isEmpty(); +} void TerminalDisplay::setConfirmMultilinePaste(bool confirmMultilinePaste) { _confirmMultilinePaste = confirmMultilinePaste; diff --git a/lib/TerminalDisplay.h b/lib/TerminalDisplay.h index 4b0007a6..5b99da32 100644 --- a/lib/TerminalDisplay.h +++ b/lib/TerminalDisplay.h @@ -504,7 +504,13 @@ public slots: */ void pasteSelection(); - /** + /** Checks if the clipboard is empty */ + bool isClipboardEmpty(); + + /** Checks if the selection is empty */ + bool isSelectionEmpty(); + + /** * Changes whether the flow control warning box should be shown when the flow control * stop key (Ctrl+S) are pressed. */ From ffc6b2b2a20ca785f93300eca93c25c4b74ece17 Mon Sep 17 00:00:00 2001 From: Guido Berhoerster Date: Fri, 28 Oct 2022 13:32:35 +0200 Subject: [PATCH 5/6] Apply color scheme if changed --- lib/TerminalDisplay.cpp | 30 +++++++++++++++++++++--------- lib/TerminalDisplay.h | 2 ++ 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/lib/TerminalDisplay.cpp b/lib/TerminalDisplay.cpp index e2d75a2d..6ce80550 100644 --- a/lib/TerminalDisplay.cpp +++ b/lib/TerminalDisplay.cpp @@ -372,6 +372,7 @@ TerminalDisplay::TerminalDisplay(QQuickItem *parent) ,_flowControlWarningEnabled(false) ,_outputSuspendedLabel(nullptr) ,_lineSpacing(0) +,_colorSchemeRef(0) ,_colorsInverted(false) ,_opacity(static_cast(1)) ,_backgroundMode(None) @@ -3505,24 +3506,24 @@ QStringList TerminalDisplay::availableColorSchemes() void TerminalDisplay::setColorScheme(const QString &name) { if ( name != _colorScheme ) { - const ColorScheme *cs; + if (_colorSchemeRef) { + disconnect(_colorSchemeRef, 0, this, 0); + } // avoid legacy (int) solution if (!availableColorSchemes().contains(name)) - cs = ColorSchemeManager::instance()->defaultColorScheme(); + _colorSchemeRef = ColorSchemeManager::instance()->defaultColorScheme(); else - cs = ColorSchemeManager::instance()->findColorScheme(name); + _colorSchemeRef = ColorSchemeManager::instance()->findColorScheme(name); - if (! cs) + if (! _colorSchemeRef) { qDebug() << "Cannot load color scheme: " << name; return; } - ColorEntry table[TABLE_COLORS]; - cs->getColorTable(table); - setColorTable(table); - - setFillColor(cs->backgroundColor()); + connect(_colorSchemeRef, SIGNAL(colorChanged(int)), this, SLOT(applyColorScheme())); + connect(_colorSchemeRef, SIGNAL(opacityChanged()), this, SLOT(applyColorScheme())); + applyColorScheme(); _colorScheme = name; emit colorSchemeChanged(); } @@ -3533,6 +3534,17 @@ QString TerminalDisplay::colorScheme() const return _colorScheme; } +void TerminalDisplay::applyColorScheme() +{ + ColorEntry table[TABLE_COLORS]; + _colorSchemeRef->getColorTable(table); + setColorTable(table); + QColor backgroundColor = _colorTable[DEFAULT_BACK_COLOR].color; + backgroundColor.setAlphaF(_colorSchemeRef->opacity()); + setBackgroundColor(backgroundColor); + setFillColor(backgroundColor); +} + void TerminalDisplay::simulateKeyPress(int key, int modifiers, bool pressed, quint32 nativeScanCode, const QString &text) { Q_UNUSED(nativeScanCode); diff --git a/lib/TerminalDisplay.h b/lib/TerminalDisplay.h index 5b99da32..ec329f20 100644 --- a/lib/TerminalDisplay.h +++ b/lib/TerminalDisplay.h @@ -717,6 +717,7 @@ protected slots: //Renables bell noises and visuals. Used to disable further bells for a short period of time //after emitting the first in a sequence of bell events. void enableBell(); + void applyColorScheme(); private slots: @@ -893,6 +894,7 @@ private slots: uint _lineSpacing; QString _colorScheme; + const ColorScheme* _colorSchemeRef; bool _colorsInverted; // true during visual bell QSize _size; From f3050bda066575eebdcff70fc1c3a393799e1d6d Mon Sep 17 00:00:00 2001 From: OPNA2608 Date: Wed, 22 Nov 2023 13:14:19 +0100 Subject: [PATCH 6/6] Mark ColorSchemeManager singleton as C++-owned --- src/qmltermwidget_plugin.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/qmltermwidget_plugin.cpp b/src/qmltermwidget_plugin.cpp index e9e8b4f1..e41b58fd 100644 --- a/src/qmltermwidget_plugin.cpp +++ b/src/qmltermwidget_plugin.cpp @@ -15,7 +15,9 @@ static QObject *colorschememanager_provider(QQmlEngine *engine, QJSEngine *scrip Q_UNUSED(engine) Q_UNUSED(scriptEngine) - return ColorSchemeManager::instance(); + QObject* instance = ColorSchemeManager::instance(); + QQmlEngine::setObjectOwnership(instance, QQmlEngine::CppOwnership); + return instance; } void QmltermwidgetPlugin::registerTypes(const char *uri)