[utilities/konsole] src: Add functionality for markers on scrollbar
Kurt Hindenburg
null at kde.org
Wed Jul 17 16:43:57 BST 2024
Git commit d0754cc3e46f35feb3a3891caa7a15be5c01fbca by Kurt Hindenburg, on behalf of Theodore Wang.
Committed on 17/07/2024 at 15:43.
Pushed by hindenburg into branch 'master'.
Add functionality for markers on scrollbar
Users can add markers to the scrollbar by double clicking on the
scrollbar. A user can remove a marker by double clicking on it again.
The position of the marker is stored internally as a percentage offset
of the scrollbar's length and is not attached to any line of output.
This means that on resize, a scrollbar marker originally created at
x percentile of the scrollbar's length from the top will still remain
at x percentile of the scrollbar's length from the top.
In the "Scrolling" tab in the settings, there are options for the
user to change the color of the markers and the size of the markers.
The size of the marker can be specified as a floating point number,
representing the percentage of the entire scrollbar's length it occupies.
GUI:
FEATURE: 338901
M +2 -0 src/profile/Profile.cpp
M +6 -0 src/profile/Profile.h
M +3 -0 src/terminalDisplay/TerminalDisplay.cpp
M +146 -0 src/terminalDisplay/TerminalScrollBar.cpp
M +50 -0 src/terminalDisplay/TerminalScrollBar.h
M +18 -0 src/widgets/EditProfileDialog.cpp
M +3 -0 src/widgets/EditProfileDialog.h
M +34 -0 src/widgets/EditProfileScrollingPage.ui
https://invent.kde.org/utilities/konsole/-/commit/d0754cc3e46f35feb3a3891caa7a15be5c01fbca
diff --git a/src/profile/Profile.cpp b/src/profile/Profile.cpp
index dd86ff5544..dc6e198ad1 100644
--- a/src/profile/Profile.cpp
+++ b/src/profile/Profile.cpp
@@ -124,6 +124,8 @@ const std::vector<Profile::PropertyInfo> Profile::DefaultProperties = {
{ScrollFullPage, "ScrollFullPage", SCROLLING_GROUP, false},
{HighlightScrolledLines, "HighlightScrolledLines", SCROLLING_GROUP, true},
{ReflowLines, "ReflowLines", SCROLLING_GROUP, true},
+ {MarkerColor, "MarkerColor", SCROLLING_GROUP, QColor(Qt::red)},
+ {MarkerSize, "MarkerSize", SCROLLING_GROUP, 2},
// Terminal Features
{UrlHintsModifiers, "UrlHintsModifiers", TERMINAL_GROUP, 0},
diff --git a/src/profile/Profile.h b/src/profile/Profile.h
index 966bcf5436..96e52e4491 100644
--- a/src/profile/Profile.h
+++ b/src/profile/Profile.h
@@ -383,6 +383,12 @@ public:
/** (QFont) Emoji font override
*/
EmojiFont,
+ /** (QColor) Color for scrollbar markers */
+ MarkerColor,
+ /** (double) Size of a scrollbar marker
+ * as a percentage of scrollbar length
+ */
+ MarkerSize,
/** When to show line numbers.
* 0 for Never, 1 when showing URL hints, 2 for always
*/
diff --git a/src/terminalDisplay/TerminalDisplay.cpp b/src/terminalDisplay/TerminalDisplay.cpp
index db2efb3c85..47cde079f0 100644
--- a/src/terminalDisplay/TerminalDisplay.cpp
+++ b/src/terminalDisplay/TerminalDisplay.cpp
@@ -17,6 +17,7 @@
#include <QAction>
#include <QApplication>
#include <QClipboard>
+#include <QColor>
#include <QDesktopServices>
#include <QDrag>
#include <QElapsedTimer>
@@ -3168,6 +3169,8 @@ void TerminalDisplay::applyProfile(const Profile::Ptr &profile)
_displayVerticalLine = profile->verticalLine();
_displayVerticalLineAtChar = profile->verticalLineAtChar();
_scrollBar->setAlternateScrolling(profile->property<bool>(Profile::AlternateScrolling));
+ _scrollBar->setMarkerSize(profile->property<double>(Profile::MarkerSize));
+ _scrollBar->setMarkerColor(profile->property<QColor>(Profile::MarkerColor));
_dimValue = profile->dimValue();
_focusBorderColor = profile->focusBorderColor();
diff --git a/src/terminalDisplay/TerminalScrollBar.cpp b/src/terminalDisplay/TerminalScrollBar.cpp
index 30a0e27bf6..832bfd15b4 100644
--- a/src/terminalDisplay/TerminalScrollBar.cpp
+++ b/src/terminalDisplay/TerminalScrollBar.cpp
@@ -18,6 +18,7 @@
// Qt
#include <QGuiApplication>
+#include <QMouseEvent>
#include <QProxyStyle>
#include <QRect>
@@ -29,6 +30,13 @@ TerminalScrollBar::TerminalScrollBar(QWidget *parent)
connect(this, &QScrollBar::valueChanged, this, &TerminalScrollBar::scrollBarPositionChanged);
}
+TerminalScrollBar::~TerminalScrollBar()
+{
+ for (int i = 0; i < _markers.size(); i++) {
+ delete _markers[i];
+ }
+}
+
void TerminalScrollBar::setScrollBarPosition(Enum::ScrollBarPositionEnum position)
{
if (_scrollbarLocation == position) {
@@ -85,6 +93,20 @@ void TerminalScrollBar::setAlternateScrolling(bool enable)
_alternateScrolling = enable;
}
+void TerminalScrollBar::setMarkerColor(QColor color)
+{
+ _markerColor = color;
+ update();
+}
+
+void TerminalScrollBar::setMarkerSize(double pSize)
+{
+ _markerPSize = pSize;
+
+ regenerateMarkersGeometry();
+ update();
+}
+
void TerminalScrollBar::scrollBarPositionChanged(int)
{
const auto display = qobject_cast<TerminalDisplay *>(this->parent());
@@ -235,6 +257,130 @@ void TerminalScrollBar::updatePalette(const QPalette &pal)
}
}
+void TerminalScrollBar::paintEvent(QPaintEvent *event)
+{
+ QScrollBar::paintEvent(event);
+
+ QPainter p(this);
+
+ for (int i = 0; i < _markers.size(); ++i) {
+ p.setOpacity(0.75);
+ p.fillRect(_markers[i]->geometry, _markerColor);
+ }
+}
+
+void TerminalScrollBar::resizeEvent(QResizeEvent *event)
+{
+ QScrollBar::resizeEvent(event);
+ regenerateMarkersGeometry();
+}
+
+void TerminalScrollBar::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ int position = event->position().y();
+
+ if (markerExists(position)) {
+ removeMarker(position);
+ } else {
+ registerMarker(createMarker(position));
+ }
+}
+
+void TerminalScrollBar::removeMarker(int clickedYCoord)
+{
+ for (int i = 0; i < _markers.size(); ++i) {
+ Marker *marker = _markers[i];
+ double markerTop = marker->geometry.top();
+ double markerHeight = marker->geometry.height();
+
+ if (markerTop > clickedYCoord) {
+ break;
+ }
+
+ if (markerTop <= clickedYCoord && (markerTop + markerHeight >= clickedYCoord)) {
+ _markers.remove(i);
+ delete marker;
+ break;
+ }
+ }
+
+ update();
+}
+
+bool TerminalScrollBar::markerExists(int clickedYCoord)
+{
+ for (Marker *marker : _markers) {
+ double markerTop = marker->geometry.top();
+ double markerHeight = marker->geometry.height();
+
+ if (markerTop >= clickedYCoord) {
+ break;
+ }
+
+ if (markerTop <= clickedYCoord && (markerTop + markerHeight >= clickedYCoord)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void TerminalScrollBar::registerMarker(TerminalScrollBar::Marker *marker)
+{
+ bool added = false;
+
+ for (int i = 0; i < _markers.size(); ++i) {
+ if (marker->position <= _markers[i]->position) {
+ _markers.insert(i, marker);
+ added = true;
+ break;
+ }
+ }
+
+ if (!added) {
+ _markers.append(marker);
+ }
+
+ update();
+}
+
+void TerminalScrollBar::regenerateMarkersGeometry()
+{
+ for (Marker *marker : _markers) {
+ generateMarkerGeometry(marker->position, *marker);
+ }
+}
+
+TerminalScrollBar::Marker *TerminalScrollBar::createMarker(int clickedYCoord)
+{
+ Marker *newMarker = new Marker();
+
+ generateMarkerGeometry((double)clickedYCoord / height() * 100, *newMarker);
+
+ return newMarker;
+}
+
+void TerminalScrollBar::generateMarkerGeometry(double pPosition, TerminalScrollBar::Marker &marker)
+{
+ marker.position = pPosition;
+ double proposedYMidPt = marker.position * height() / 100;
+ double markerSize = markerHeight();
+ double markerYTop = proposedYMidPt - markerSize / 2;
+
+ if (proposedYMidPt + markerSize / 2 > height()) {
+ markerYTop = height() - markerSize;
+ } else if (proposedYMidPt - markerSize / 2 < 0) {
+ markerYTop = 0;
+ }
+
+ marker.geometry.setRect(0, markerYTop, width(), markerSize);
+}
+
+double TerminalScrollBar::markerHeight() const
+{
+ return height() * _markerPSize / 100;
+}
+
} // namespace Konsole
#include "moc_TerminalScrollBar.cpp"
diff --git a/src/terminalDisplay/TerminalScrollBar.h b/src/terminalDisplay/TerminalScrollBar.h
index 4a9a89ceb9..192595857d 100644
--- a/src/terminalDisplay/TerminalScrollBar.h
+++ b/src/terminalDisplay/TerminalScrollBar.h
@@ -29,6 +29,8 @@ class KONSOLEPRIVATE_EXPORT TerminalScrollBar : public QScrollBar
public:
explicit TerminalScrollBar(QWidget *parent);
+ ~TerminalScrollBar() override;
+
/**
* Specifies whether the terminal display has a vertical scroll bar, and if so whether it
* is shown on the left or right side of the display.
@@ -59,6 +61,10 @@ public:
*/
void setAlternateScrolling(bool enable);
+ void setMarkerColor(QColor color);
+
+ void setMarkerSize(double percentageSize);
+
// applies changes to scrollbarLocation to the scroll bar and
// if @propagate is true, propagates size information
void applyScrollBarPosition(bool propagate = true);
@@ -93,13 +99,57 @@ public Q_SLOTS:
void scrollBarPositionChanged(int value);
void highlightScrolledLinesEvent();
+ // Reimplmentation to paint scrollbar markers over the standard drawing
+ void paintEvent(QPaintEvent *event) override;
+
+ // Reimplementation to derive scrollbar marker geometry again.
+ void resizeEvent(QResizeEvent *event) override;
+
+ // Reimplementation to check for input indicating marker addition or removal
+ void mouseDoubleClickEvent(QMouseEvent *event) override;
+
private:
+ class Marker
+ {
+ public:
+ // as a percentage of the scrollbar's height
+ double position;
+
+ QRectF geometry;
+ };
+
+ /**
+ * Given a y-coordinate relative to the scrollbar,
+ * removes any markers encompassing that coordinatte and
+ * redraws the scrollbar and the remaining markers
+ */
+ void removeMarker(int position);
+
+ // Checks if any marker exists at a given y-coordiante on the scrollbar
+ bool markerExists(int position);
+
+ // Adds a marker to the existing list of markers and redraws the scrollbar and the markers
+ void registerMarker(Marker *marker);
+
+ // Creates an object representing a scrollbar marker
+ Marker *createMarker(int position);
+
+ void regenerateMarkersGeometry();
+
+ void generateMarkerGeometry(double pPosition, Marker &marker);
+
+ double markerHeight() const;
+
bool _scrollFullPage = false;
bool _alternateScrolling = false;
Enum::ScrollBarPositionEnum _scrollbarLocation = Enum::ScrollBarRight;
HighlightScrolledLines _highlightScrolledLines;
QPalette _backgroundMatchingPalette;
+ QColor _markerColor;
+ double _markerPSize;
+ QList<Marker *> _markers;
};
+
} // namespace Konsole
#endif
diff --git a/src/widgets/EditProfileDialog.cpp b/src/widgets/EditProfileDialog.cpp
index 359721e764..bfe7ec2ba7 100644
--- a/src/widgets/EditProfileDialog.cpp
+++ b/src/widgets/EditProfileDialog.cpp
@@ -1740,6 +1740,14 @@ void EditProfileDialog::setupScrollingPage(const Profile::Ptr &profile)
_scrollingUi->reflowLinesButton->setChecked(profile->property<bool>(Profile::ReflowLines));
connect(_scrollingUi->reflowLinesButton, &QPushButton::clicked, this, &EditProfileDialog::toggleReflowLines);
+ // setup marker color button
+ _scrollingUi->markerColorButton->setColor(profile->property<QColor>(Profile::MarkerColor));
+ connect(_scrollingUi->markerColorButton, &KColorButton::changed, this, &Konsole::EditProfileDialog::toggleScrollbarMarkerColor);
+
+ // setup marker size widget
+ _scrollingUi->markerSizeWidget->setValue(profile->property<double>(Profile::MarkerSize));
+ connect(_scrollingUi->markerSizeWidget, &QDoubleSpinBox::valueChanged, this, &Konsole::EditProfileDialog::toggleScrollbarMarkerSize);
+
// signals and slots
connect(_scrollingUi->historySizeWidget, &Konsole::HistorySizeWidget::historySizeChanged, this, &Konsole::EditProfileDialog::historySizeChanged);
}
@@ -1774,6 +1782,16 @@ void EditProfileDialog::toggleReflowLines(bool enable)
updateTempProfileProperty(Profile::ReflowLines, enable);
}
+void EditProfileDialog::toggleScrollbarMarkerColor(QColor color)
+{
+ updateTempProfileProperty(Profile::MarkerColor, color);
+}
+
+void EditProfileDialog::toggleScrollbarMarkerSize(double pSize)
+{
+ updateTempProfileProperty(Profile::MarkerSize, pSize);
+}
+
void EditProfileDialog::setupMousePage(const Profile::Ptr &profile)
{
_mouseUi->underlineLinksButton->setChecked(profile->property<bool>(Profile::UnderlineLinksEnabled));
diff --git a/src/widgets/EditProfileDialog.h b/src/widgets/EditProfileDialog.h
index 3be2919814..1ccd73c461 100644
--- a/src/widgets/EditProfileDialog.h
+++ b/src/widgets/EditProfileDialog.h
@@ -185,6 +185,9 @@ private Q_SLOTS:
void toggleHighlightScrolledLines(bool enable);
void toggleReflowLines(bool enable);
+ void toggleScrollbarMarkerColor(QColor color);
+ void toggleScrollbarMarkerSize(double pSize);
+
// keyboard page
void editKeyBinding();
void newKeyBinding();
diff --git a/src/widgets/EditProfileScrollingPage.ui b/src/widgets/EditProfileScrollingPage.ui
index 5dc96165a9..197d01f2b5 100644
--- a/src/widgets/EditProfileScrollingPage.ui
+++ b/src/widgets/EditProfileScrollingPage.ui
@@ -233,6 +233,40 @@
</property>
</widget>
</item>
+ <item row="11" column="0">
+ <widget class="QLabel" name="labelMarkerColor">
+ <property name="text">
+ <string>Color of scrollbar markers:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="11" column="1">
+ <widget class="KColorButton" name="markerColorButton">
+ </widget>
+ </item>
+ <item row="12" column="0">
+ <widget class="QLabel" name="labelMarkerSize">
+ <property name="text">
+ <string>Size of each marker (as a percentage of scrollbar length):</string>
+ </property>
+ </widget>
+ </item>
+ <item row="12" column="1">
+ <widget class="QDoubleSpinBox" name="markerSizeWidget">
+ <property name="decimals">
+ <number>1</number>
+ </property>
+ <property name="minimum">
+ <number>0.1</number>
+ </property>
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="suffix">
+ <string> %</string>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
<item>
More information about the kde-doc-english
mailing list