Port decorated scrollbar widget class from QtCreator

Allows decorating scrollbars with colored highlight bars
This commit is contained in:
Nyall Dawson 2024-05-08 11:26:43 +10:00
parent 09364b1945
commit e59c0df8a8
9 changed files with 967 additions and 0 deletions

View File

@ -0,0 +1,9 @@
# The following has been generated automatically from src/gui/qgsdecoratedscrollbar.h
# monkey patching scoped based enum
QgsScrollBarHighlight.Priority.Invalid.__doc__ = "Invalid"
QgsScrollBarHighlight.Priority.LowPriority.__doc__ = "Low priority, rendered below all other highlights"
QgsScrollBarHighlight.Priority.NormalPriority.__doc__ = "Normal priority"
QgsScrollBarHighlight.Priority.HighPriority.__doc__ = "High priority"
QgsScrollBarHighlight.Priority.HighestPriority.__doc__ = "Highest priority, rendered above all other highlights"
QgsScrollBarHighlight.Priority.__doc__ = "Priority, which dictates how overlapping highlights are rendered\n\n" + '* ``Invalid``: ' + QgsScrollBarHighlight.Priority.Invalid.__doc__ + '\n' + '* ``LowPriority``: ' + QgsScrollBarHighlight.Priority.LowPriority.__doc__ + '\n' + '* ``NormalPriority``: ' + QgsScrollBarHighlight.Priority.NormalPriority.__doc__ + '\n' + '* ``HighPriority``: ' + QgsScrollBarHighlight.Priority.HighPriority.__doc__ + '\n' + '* ``HighestPriority``: ' + QgsScrollBarHighlight.Priority.HighestPriority.__doc__
# --

View File

@ -0,0 +1,153 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsdecoratedscrollbar.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsScrollBarHighlight
{
%Docstring(signature="appended")
Encapsulates the details of a highlight in a scrollbar, used alongside :py:class:`QgsScrollBarHighlightController`.
.. versionadded:: 3.38
%End
%TypeHeaderCode
#include "qgsdecoratedscrollbar.h"
%End
public:
enum class Priority /BaseType=IntEnum/
{
Invalid,
LowPriority,
NormalPriority,
HighPriority,
HighestPriority
};
QgsScrollBarHighlight( int category, int position, const QColor &color, QgsScrollBarHighlight::Priority priority = QgsScrollBarHighlight::Priority::NormalPriority );
%Docstring
Constructor for QgsScrollBarHighlight.
%End
QgsScrollBarHighlight();
int category;
int position;
QColor color;
QgsScrollBarHighlight::Priority priority;
};
class QgsScrollBarHighlightController
{
%Docstring(signature="appended")
Adds highlights (colored markers) to a scrollbar.
.. versionadded:: 3.38
%End
%TypeHeaderCode
#include "qgsdecoratedscrollbar.h"
%End
public:
QgsScrollBarHighlightController();
~QgsScrollBarHighlightController();
QScrollBar *scrollBar() const;
%Docstring
Returns the associated scroll bar.
%End
QAbstractScrollArea *scrollArea() const;
%Docstring
Returns the associated scroll area.
.. seealso:: :py:func:`setScrollArea`
%End
void setScrollArea( QAbstractScrollArea *scrollArea );
%Docstring
Sets the associated scroll bar.
.. seealso:: :py:func:`scrollArea`
%End
double lineHeight() const;
%Docstring
Returns the line height for text associated with the scroll area.
.. seealso:: :py:func:`setLineHeight`
%End
void setLineHeight( double height );
%Docstring
Sets the line ``height`` for text associated with the scroll area.
.. seealso:: :py:func:`lineHeight`
%End
double visibleRange() const;
%Docstring
Returns the visible range of the scroll area (i.e. the viewport's height).
.. seealso:: :py:func:`setVisibleRange`
%End
void setVisibleRange( double visibleRange );
%Docstring
Sets the visible range of the scroll area (i.e. the viewport's height).
.. seealso:: :py:func:`visibleRange`
%End
double margin() const;
%Docstring
Returns the document margins for the associated viewport.
.. seealso:: :py:func:`setMargin`
%End
void setMargin( double margin );
%Docstring
Sets the document ``margin`` for the associated viewport.
.. seealso:: :py:func:`margin`
%End
void addHighlight( const QgsScrollBarHighlight &highlight );
%Docstring
Adds a ``highlight`` to the scrollbar.
%End
void removeHighlights( int category );
%Docstring
Removes all highlights with matching ``category`` from the scrollbar.
%End
void removeAllHighlights();
%Docstring
Removes all highlights from the scroll bar.
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsdecoratedscrollbar.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -46,6 +46,7 @@
%Include auto_generated/qgsdataitemguiproviderregistry.sip
%Include auto_generated/qgsdatasourceselectdialog.sip
%Include auto_generated/qgsdbrelationshipwidget.sip
%Include auto_generated/qgsdecoratedscrollbar.sip
%Include auto_generated/qgsnewdatabasetablenamewidget.sip
%Include auto_generated/qgsdetaileditemdata.sip
%Include auto_generated/qgsdetaileditemdelegate.sip

View File

@ -0,0 +1,9 @@
# The following has been generated automatically from src/gui/qgsdecoratedscrollbar.h
# monkey patching scoped based enum
QgsScrollBarHighlight.Priority.Invalid.__doc__ = "Invalid"
QgsScrollBarHighlight.Priority.LowPriority.__doc__ = "Low priority, rendered below all other highlights"
QgsScrollBarHighlight.Priority.NormalPriority.__doc__ = "Normal priority"
QgsScrollBarHighlight.Priority.HighPriority.__doc__ = "High priority"
QgsScrollBarHighlight.Priority.HighestPriority.__doc__ = "Highest priority, rendered above all other highlights"
QgsScrollBarHighlight.Priority.__doc__ = "Priority, which dictates how overlapping highlights are rendered\n\n" + '* ``Invalid``: ' + QgsScrollBarHighlight.Priority.Invalid.__doc__ + '\n' + '* ``LowPriority``: ' + QgsScrollBarHighlight.Priority.LowPriority.__doc__ + '\n' + '* ``NormalPriority``: ' + QgsScrollBarHighlight.Priority.NormalPriority.__doc__ + '\n' + '* ``HighPriority``: ' + QgsScrollBarHighlight.Priority.HighPriority.__doc__ + '\n' + '* ``HighestPriority``: ' + QgsScrollBarHighlight.Priority.HighestPriority.__doc__
# --

View File

@ -0,0 +1,153 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsdecoratedscrollbar.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsScrollBarHighlight
{
%Docstring(signature="appended")
Encapsulates the details of a highlight in a scrollbar, used alongside :py:class:`QgsScrollBarHighlightController`.
.. versionadded:: 3.38
%End
%TypeHeaderCode
#include "qgsdecoratedscrollbar.h"
%End
public:
enum class Priority
{
Invalid,
LowPriority,
NormalPriority,
HighPriority,
HighestPriority
};
QgsScrollBarHighlight( int category, int position, const QColor &color, QgsScrollBarHighlight::Priority priority = QgsScrollBarHighlight::Priority::NormalPriority );
%Docstring
Constructor for QgsScrollBarHighlight.
%End
QgsScrollBarHighlight();
int category;
int position;
QColor color;
QgsScrollBarHighlight::Priority priority;
};
class QgsScrollBarHighlightController
{
%Docstring(signature="appended")
Adds highlights (colored markers) to a scrollbar.
.. versionadded:: 3.38
%End
%TypeHeaderCode
#include "qgsdecoratedscrollbar.h"
%End
public:
QgsScrollBarHighlightController();
~QgsScrollBarHighlightController();
QScrollBar *scrollBar() const;
%Docstring
Returns the associated scroll bar.
%End
QAbstractScrollArea *scrollArea() const;
%Docstring
Returns the associated scroll area.
.. seealso:: :py:func:`setScrollArea`
%End
void setScrollArea( QAbstractScrollArea *scrollArea );
%Docstring
Sets the associated scroll bar.
.. seealso:: :py:func:`scrollArea`
%End
double lineHeight() const;
%Docstring
Returns the line height for text associated with the scroll area.
.. seealso:: :py:func:`setLineHeight`
%End
void setLineHeight( double height );
%Docstring
Sets the line ``height`` for text associated with the scroll area.
.. seealso:: :py:func:`lineHeight`
%End
double visibleRange() const;
%Docstring
Returns the visible range of the scroll area (i.e. the viewport's height).
.. seealso:: :py:func:`setVisibleRange`
%End
void setVisibleRange( double visibleRange );
%Docstring
Sets the visible range of the scroll area (i.e. the viewport's height).
.. seealso:: :py:func:`visibleRange`
%End
double margin() const;
%Docstring
Returns the document margins for the associated viewport.
.. seealso:: :py:func:`setMargin`
%End
void setMargin( double margin );
%Docstring
Sets the document ``margin`` for the associated viewport.
.. seealso:: :py:func:`margin`
%End
void addHighlight( const QgsScrollBarHighlight &highlight );
%Docstring
Adds a ``highlight`` to the scrollbar.
%End
void removeHighlights( int category );
%Docstring
Removes all highlights with matching ``category`` from the scrollbar.
%End
void removeAllHighlights();
%Docstring
Removes all highlights from the scroll bar.
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/qgsdecoratedscrollbar.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -46,6 +46,7 @@
%Include auto_generated/qgsdataitemguiproviderregistry.sip
%Include auto_generated/qgsdatasourceselectdialog.sip
%Include auto_generated/qgsdbrelationshipwidget.sip
%Include auto_generated/qgsdecoratedscrollbar.sip
%Include auto_generated/qgsnewdatabasetablenamewidget.sip
%Include auto_generated/qgsdetaileditemdata.sip
%Include auto_generated/qgsdetaileditemdelegate.sip

View File

@ -554,6 +554,7 @@ set(QGIS_GUI_SRCS
qgsdatasourceselectdialog.cpp
qgsdbqueryhistoryprovider.cpp
qgsdbrelationshipwidget.cpp
qgsdecoratedscrollbar.cpp
qgsdetaileditemdata.cpp
qgsdetaileditemdelegate.cpp
qgsdetaileditemwidget.cpp
@ -825,6 +826,7 @@ set(QGIS_GUI_HDRS
qgsdatasourceselectdialog.h
qgsdbqueryhistoryprovider.h
qgsdbrelationshipwidget.h
qgsdecoratedscrollbar.h
qgsnewdatabasetablenamewidget.h
qgsdetaileditemdata.h
qgsdetaileditemdelegate.h

View File

@ -0,0 +1,424 @@
/***************************************************************************
qgsdecoratedscrollbar.cpp
--------------------------------------
Date : May 2024
Copyright : (C) 2024 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsdecoratedscrollbar.h"
#include <QAbstractScrollArea>
#include <QScrollBar>
#include <QPainter>
#include <QEvent>
#include <QStyleOptionSlider>
#include <cmath>
///@cond PRIVATE
//
// QgsScrollBarHighlightOverlay
//
QgsScrollBarHighlightOverlay::QgsScrollBarHighlightOverlay( QgsScrollBarHighlightController *scrollBarController )
: QWidget( scrollBarController->scrollArea() )
, mHighlightController( scrollBarController )
{
setAttribute( Qt::WA_TransparentForMouseEvents );
scrollBar()->parentWidget()->installEventFilter( this );
doResize();
doMove();
setVisible( scrollBar()->isVisible() );
}
void QgsScrollBarHighlightOverlay::doResize()
{
resize( scrollBar()->size() );
}
void QgsScrollBarHighlightOverlay::doMove()
{
move( parentWidget()->mapFromGlobal( scrollBar()->mapToGlobal( scrollBar()->pos() ) ) );
}
void QgsScrollBarHighlightOverlay::scheduleUpdate()
{
if ( mIsCacheUpdateScheduled )
return;
mIsCacheUpdateScheduled = true;
QMetaObject::invokeMethod( this, QOverload<>::of( &QWidget::update ), Qt::QueuedConnection );
}
void QgsScrollBarHighlightOverlay::paintEvent( QPaintEvent *paintEvent )
{
QWidget::paintEvent( paintEvent );
updateCache();
if ( mHighlightCache.isEmpty() )
return;
QPainter painter( this );
painter.setRenderHint( QPainter::Antialiasing, false );
const QRect &gRect = overlayRect();
const QRect &hRect = handleRect();
constexpr int marginX = 3;
constexpr int marginH = -2 * marginX + 1;
const QRect aboveHandleRect = QRect( gRect.x() + marginX,
gRect.y(),
gRect.width() + marginH,
hRect.y() - gRect.y() );
const QRect handleRect = QRect( gRect.x() + marginX,
hRect.y(),
gRect.width() + marginH,
hRect.height() );
const QRect belowHandleRect = QRect( gRect.x() + marginX,
hRect.y() + hRect.height(),
gRect.width() + marginH,
gRect.height() - hRect.height() + gRect.y() - hRect.y() );
const int aboveValue = scrollBar()->value();
const int belowValue = scrollBar()->maximum() - scrollBar()->value();
const int sizeDocAbove = int( aboveValue * mHighlightController->lineHeight() );
const int sizeDocBelow = int( belowValue * mHighlightController->lineHeight() );
const int sizeDocVisible = int( mHighlightController->visibleRange() );
const int scrollBarBackgroundHeight = aboveHandleRect.height() + belowHandleRect.height();
const int sizeDocInvisible = sizeDocAbove + sizeDocBelow;
const double backgroundRatio = sizeDocInvisible
? ( ( double )scrollBarBackgroundHeight / sizeDocInvisible ) : 0;
if ( aboveValue )
{
drawHighlights( &painter,
0,
sizeDocAbove,
backgroundRatio,
0,
aboveHandleRect );
}
if ( belowValue )
{
// This is the hypothetical handle height if the handle would
// be stretched using the background ratio.
const double handleVirtualHeight = sizeDocVisible * backgroundRatio;
// Skip the doc above and visible part.
const int offset = qRound( aboveHandleRect.height() + handleVirtualHeight );
drawHighlights( &painter,
sizeDocAbove + sizeDocVisible,
sizeDocBelow,
backgroundRatio,
offset,
belowHandleRect );
}
const double handleRatio = sizeDocVisible
? ( ( double )handleRect.height() / sizeDocVisible ) : 0;
// This is the hypothetical handle position if the background would
// be stretched using the handle ratio.
const double aboveVirtualHeight = sizeDocAbove * handleRatio;
// This is the accurate handle position (double)
const double accurateHandlePos = sizeDocAbove * backgroundRatio;
// The correction between handle position (int) and accurate position (double)
const double correction = aboveHandleRect.height() - accurateHandlePos;
// Skip the doc above and apply correction
const int offset = qRound( aboveVirtualHeight + correction );
drawHighlights( &painter,
sizeDocAbove,
sizeDocVisible,
handleRatio,
offset,
handleRect );
}
void QgsScrollBarHighlightOverlay::drawHighlights( QPainter *painter,
int docStart,
int docSize,
double docSizeToHandleSizeRatio,
int handleOffset,
const QRect &viewport )
{
if ( docSize <= 0 )
return;
painter->save();
painter->setClipRect( viewport );
const double lineHeight = mHighlightController->lineHeight();
for ( const QMap<QRgb, QMap<int, int>> &colors : std::as_const( mHighlightCache ) )
{
const auto itColorEnd = colors.constEnd();
for ( auto itColor = colors.constBegin(); itColor != itColorEnd; ++itColor )
{
const QColor color = itColor.key();
const QMap<int, int> &positions = itColor.value();
const auto itPosEnd = positions.constEnd();
const auto firstPos = int( docStart / lineHeight );
auto itPos = positions.upperBound( firstPos );
if ( itPos != positions.constBegin() )
--itPos;
while ( itPos != itPosEnd )
{
const double posStart = itPos.key() * lineHeight;
const double posEnd = ( itPos.value() + 1 ) * lineHeight;
if ( posEnd < docStart )
{
++itPos;
continue;
}
if ( posStart > docStart + docSize )
break;
const int height = qMax( qRound( ( posEnd - posStart ) * docSizeToHandleSizeRatio ), 1 );
const int top = qRound( posStart * docSizeToHandleSizeRatio ) - handleOffset + viewport.y();
const QRect rect( viewport.left(), top, viewport.width(), height );
painter->fillRect( rect, color );
++itPos;
}
}
}
painter->restore();
}
bool QgsScrollBarHighlightOverlay::eventFilter( QObject *object, QEvent *event )
{
switch ( event->type() )
{
case QEvent::Move:
doMove();
break;
case QEvent::Resize:
doResize();
break;
case QEvent::ZOrderChange:
raise();
break;
case QEvent::Show:
show();
break;
case QEvent::Hide:
hide();
break;
default:
break;
}
return QWidget::eventFilter( object, event );
}
static void insertPosition( QMap<int, int> *map, int position )
{
auto itNext = map->upperBound( position );
bool gluedWithPrev = false;
if ( itNext != map->begin() )
{
auto itPrev = std::prev( itNext );
const int keyStart = itPrev.key();
const int keyEnd = itPrev.value();
if ( position >= keyStart && position <= keyEnd )
return; // pos is already included
if ( keyEnd + 1 == position )
{
// glue with prev
( *itPrev )++;
gluedWithPrev = true;
}
}
if ( itNext != map->end() && itNext.key() == position + 1 )
{
const int keyEnd = itNext.value();
itNext = map->erase( itNext );
if ( gluedWithPrev )
{
// glue with prev and next
auto itPrev = std::prev( itNext );
*itPrev = keyEnd;
}
else
{
// glue with next
itNext = map->insert( itNext, position, keyEnd );
}
return; // glued
}
if ( gluedWithPrev )
return; // glued
map->insert( position, position );
}
void QgsScrollBarHighlightOverlay::updateCache()
{
if ( !mIsCacheUpdateScheduled )
return;
mHighlightCache.clear();
const QHash<int, QVector<QgsScrollBarHighlight>> highlightsForId = mHighlightController->highlights();
for ( const QVector<QgsScrollBarHighlight> &highlights : highlightsForId )
{
for ( const QgsScrollBarHighlight &highlight : highlights )
{
QMap<int, int> &highlightMap = mHighlightCache[highlight.priority][highlight.color.rgba()];
insertPosition( &highlightMap, highlight.position );
}
}
mIsCacheUpdateScheduled = false;
}
QRect QgsScrollBarHighlightOverlay::overlayRect() const
{
QStyleOptionSlider opt = qt_qscrollbarStyleOption( scrollBar() );
return scrollBar()->style()->subControlRect( QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarGroove, scrollBar() );
}
QRect QgsScrollBarHighlightOverlay::handleRect() const
{
QStyleOptionSlider opt = qt_qscrollbarStyleOption( scrollBar() );
return scrollBar()->style()->subControlRect( QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarSlider, scrollBar() );
}
///@endcond PRIVATE
//
// QgsScrollBarHighlight
//
QgsScrollBarHighlight::QgsScrollBarHighlight( int category, int position,
const QColor &color, QgsScrollBarHighlight::Priority priority )
: category( category )
, position( position )
, color( color )
, priority( priority )
{
}
//
// QgsScrollBarHighlightController
//
QgsScrollBarHighlightController::QgsScrollBarHighlightController() = default;
QgsScrollBarHighlightController::~QgsScrollBarHighlightController()
{
if ( mOverlay )
delete mOverlay;
}
QScrollBar *QgsScrollBarHighlightController::scrollBar() const
{
if ( mScrollArea )
return mScrollArea->verticalScrollBar();
return nullptr;
}
QAbstractScrollArea *QgsScrollBarHighlightController::scrollArea() const
{
return mScrollArea;
}
void QgsScrollBarHighlightController::setScrollArea( QAbstractScrollArea *scrollArea )
{
if ( mScrollArea == scrollArea )
return;
if ( mOverlay )
{
delete mOverlay;
mOverlay = nullptr;
}
mScrollArea = scrollArea;
if ( mScrollArea )
{
mOverlay = new QgsScrollBarHighlightOverlay( this );
mOverlay->scheduleUpdate();
}
}
double QgsScrollBarHighlightController::lineHeight() const
{
return std::ceil( mLineHeight );
}
void QgsScrollBarHighlightController::setLineHeight( double lineHeight )
{
mLineHeight = lineHeight;
}
double QgsScrollBarHighlightController::visibleRange() const
{
return mVisibleRange;
}
void QgsScrollBarHighlightController::setVisibleRange( double visibleRange )
{
mVisibleRange = visibleRange;
}
double QgsScrollBarHighlightController::margin() const
{
return mMargin;
}
void QgsScrollBarHighlightController::setMargin( double margin )
{
mMargin = margin;
}
QHash<int, QVector<QgsScrollBarHighlight>> QgsScrollBarHighlightController::highlights() const
{
return mHighlights;
}
void QgsScrollBarHighlightController::addHighlight( const QgsScrollBarHighlight &highlight )
{
if ( !mOverlay )
return;
mHighlights[highlight.category] << highlight;
mOverlay->scheduleUpdate();
}
void QgsScrollBarHighlightController::removeHighlights( int category )
{
if ( !mOverlay )
return;
mHighlights.remove( category );
mOverlay->scheduleUpdate();
}
void QgsScrollBarHighlightController::removeAllHighlights()
{
if ( !mOverlay )
return;
mHighlights.clear();
mOverlay->scheduleUpdate();
}

View File

@ -0,0 +1,215 @@
/***************************************************************************
qgsdecoratedscrollbar.h
--------------------------------------
Date : May 2024
Copyright : (C) 2024 by Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSDECORATEDSCROLLBAR_H
#define QGSDECORATEDSCROLLBAR_H
#include "qgis_gui.h"
#include "qgis_sip.h"
#include <QColor>
#include <QHash>
#include <QPointer>
#include <QWidget>
#include <QMap>
class QScrollBar;
class QAbstractScrollArea;
class QgsScrollBarHighlightOverlay;
// ported from QtCreator's HighlightScrollBarController implementation
/**
* \ingroup gui
* \brief Encapsulates the details of a highlight in a scrollbar, used alongside QgsScrollBarHighlightController.
* \since QGIS 3.38
*/
class GUI_EXPORT QgsScrollBarHighlight
{
public:
/**
* Priority, which dictates how overlapping highlights are rendered
*/
enum class Priority : int
{
Invalid = -1, //!< Invalid
LowPriority = 0, //!< Low priority, rendered below all other highlights
NormalPriority = 1, //!< Normal priority
HighPriority = 2, //!< High priority
HighestPriority = 3 //!< Highest priority, rendered above all other highlights
};
/**
* Constructor for QgsScrollBarHighlight.
*/
QgsScrollBarHighlight( int category, int position, const QColor &color, QgsScrollBarHighlight::Priority priority = QgsScrollBarHighlight::Priority::NormalPriority );
QgsScrollBarHighlight() = default;
//! Category ID
int category = -1;
//! Position in scroll bar
int position = -1;
//! Highlight color
QColor color;
//! Priority, which dictates how overlapping highlights are rendered
QgsScrollBarHighlight::Priority priority = QgsScrollBarHighlight::Priority::Invalid;
};
/**
* \ingroup gui
* \brief Adds highlights (colored markers) to a scrollbar.
* \since QGIS 3.38
*/
class GUI_EXPORT QgsScrollBarHighlightController
{
public:
QgsScrollBarHighlightController();
~QgsScrollBarHighlightController();
/**
* Returns the associated scroll bar.
*/
QScrollBar *scrollBar() const;
/**
* Returns the associated scroll area.
*
* \see setScrollArea()
*/
QAbstractScrollArea *scrollArea() const;
/**
* Sets the associated scroll bar.
*
* \see scrollArea()
*/
void setScrollArea( QAbstractScrollArea *scrollArea );
/**
* Returns the line height for text associated with the scroll area.
*
* \see setLineHeight()
*/
double lineHeight() const;
/**
* Sets the line \a height for text associated with the scroll area.
*
* \see lineHeight()
*/
void setLineHeight( double height );
/**
* Returns the visible range of the scroll area (i.e. the viewport's height).
*
* \see setVisibleRange()
*/
double visibleRange() const;
/**
* Sets the visible range of the scroll area (i.e. the viewport's height).
*
* \see visibleRange()
*/
void setVisibleRange( double visibleRange );
/**
* Returns the document margins for the associated viewport.
*
* \see setMargin()
*/
double margin() const;
/**
* Sets the document \a margin for the associated viewport.
*
* \see margin()
*/
void setMargin( double margin );
/**
* Returns the hash of all highlights in the scrollbar, with highlight categories as hash keys.
*
* \note Not available in Python bindings
*/
QHash<int, QVector<QgsScrollBarHighlight>> highlights() const SIP_SKIP;
/**
* Adds a \a highlight to the scrollbar.
*/
void addHighlight( const QgsScrollBarHighlight &highlight );
/**
* Removes all highlights with matching \a category from the scrollbar.
*/
void removeHighlights( int category );
/**
* Removes all highlights from the scroll bar.
*/
void removeAllHighlights();
private:
QHash<int, QVector<QgsScrollBarHighlight> > mHighlights;
double mLineHeight = 0.0;
double mVisibleRange = 0.0; // in pixels
double mMargin = 0.0; // in pixels
QAbstractScrollArea *mScrollArea = nullptr;
QPointer<QgsScrollBarHighlightOverlay> mOverlay;
};
///@cond PRIVATE
#ifndef SIP_RUN
class QgsScrollBarHighlightOverlay : public QWidget
{
public:
QgsScrollBarHighlightOverlay( QgsScrollBarHighlightController *scrollBarController );
void doResize();
void doMove();
void scheduleUpdate();
protected:
void paintEvent( QPaintEvent *paintEvent ) override;
bool eventFilter( QObject *object, QEvent *event ) override;
private:
void drawHighlights( QPainter *painter,
int docStart,
int docSize,
double docSizeToHandleSizeRatio,
int handleOffset,
const QRect &viewport );
void updateCache();
QRect overlayRect() const;
QRect handleRect() const;
// line start to line end
QMap<QgsScrollBarHighlight::Priority, QMap<QRgb, QMap<int, int>>> mHighlightCache;
inline QScrollBar *scrollBar() const { return mHighlightController->scrollBar(); }
QgsScrollBarHighlightController *mHighlightController = nullptr;
bool mIsCacheUpdateScheduled = true;
};
#endif
///@endcond PRIVATE
#endif // QGSDECORATEDSCROLLBAR_H