diff --git a/src/plugins/coreplugin/coreplugin.qbs b/src/plugins/coreplugin/coreplugin.qbs index 2a6b1e6d23b..02ae8a768d5 100644 --- a/src/plugins/coreplugin/coreplugin.qbs +++ b/src/plugins/coreplugin/coreplugin.qbs @@ -223,8 +223,8 @@ Project { "findtoolwindow.cpp", "findtoolwindow.h", "findwidget.ui", - "highlightscrollbar.cpp", - "highlightscrollbar.h", + "highlightscrollbarcontroller.cpp", + "highlightscrollbarcontroller.h", "ifindfilter.cpp", "ifindfilter.h", "ifindsupport.cpp", diff --git a/src/plugins/coreplugin/find/find.pri b/src/plugins/coreplugin/find/find.pri index 2657ca39af8..41005912fbf 100644 --- a/src/plugins/coreplugin/find/find.pri +++ b/src/plugins/coreplugin/find/find.pri @@ -4,6 +4,7 @@ HEADERS += \ $$PWD/findplugin.h \ $$PWD/findtoolbar.h \ $$PWD/findtoolwindow.h \ + $$PWD/highlightscrollbarcontroller.h \ $$PWD/ifindfilter.h \ $$PWD/ifindsupport.h \ $$PWD/itemviewfind.h \ @@ -16,7 +17,6 @@ HEADERS += \ $$PWD/searchresultwidget.h \ $$PWD/searchresultwindow.h \ $$PWD/textfindconstants.h \ - $$PWD/highlightscrollbar.h \ $$PWD/searchresultitem.h SOURCES += \ @@ -25,6 +25,7 @@ SOURCES += \ $$PWD/findplugin.cpp \ $$PWD/findtoolbar.cpp \ $$PWD/findtoolwindow.cpp \ + $$PWD/highlightscrollbarcontroller.cpp \ $$PWD/ifindfilter.cpp \ $$PWD/ifindsupport.cpp \ $$PWD/itemviewfind.cpp \ @@ -33,8 +34,7 @@ SOURCES += \ $$PWD/searchresulttreemodel.cpp \ $$PWD/searchresulttreeview.cpp \ $$PWD/searchresultwidget.cpp \ - $$PWD/searchresultwindow.cpp \ - $$PWD/highlightscrollbar.cpp + $$PWD/searchresultwindow.cpp FORMS += \ diff --git a/src/plugins/coreplugin/find/highlightscrollbar.cpp b/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp similarity index 58% rename from src/plugins/coreplugin/find/highlightscrollbar.cpp rename to src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp index 26c8244414f..d4f553cd313 100644 --- a/src/plugins/coreplugin/find/highlightscrollbar.cpp +++ b/src/plugins/coreplugin/find/highlightscrollbarcontroller.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -23,13 +23,14 @@ ** ****************************************************************************/ -#include "highlightscrollbar.h" +#include "highlightscrollbarcontroller.h" #include -#include +#include #include #include +#include #include #include #include @@ -40,164 +41,45 @@ namespace Core { class HighlightScrollBarOverlay : public QWidget { public: - HighlightScrollBarOverlay(HighlightScrollBar *scrollBar) - : QWidget(scrollBar) - , m_visibleRange(0.0) - , m_offset(0.0) - , m_cacheUpdateScheduled(false) - , m_scrollBar(scrollBar) - {} + HighlightScrollBarOverlay(HighlightScrollBarController *scrollBarController) + : QWidget(scrollBarController->scrollArea()) + , m_scrollBar(scrollBarController->scrollBar()) + , m_highlightController(scrollBarController) + { + setAttribute(Qt::WA_TransparentForMouseEvents); + m_scrollBar->parentWidget()->installEventFilter(this); + doResize(); + doMove(); + show(); + } + + void doResize() + { + resize(m_scrollBar->size()); + } + + void doMove() + { + move(parentWidget()->mapFromGlobal(m_scrollBar->mapToGlobal(m_scrollBar->pos()))); + } void scheduleUpdate(); - void updateCache(); - void adjustPosition(); - - float m_visibleRange; - float m_offset; - QHash > m_highlights; - - bool m_cacheUpdateScheduled; - QMap m_cache; protected: void paintEvent(QPaintEvent *paintEvent) override; + bool eventFilter(QObject *object, QEvent *event) override; private: - HighlightScrollBar *m_scrollBar; + void updateCache(); + QRect overlayRect() const; + + bool m_cacheUpdateScheduled = true; + QMap m_cache; + + QScrollBar *m_scrollBar; + HighlightScrollBarController *m_highlightController; }; -HighlightScrollBar::HighlightScrollBar(Qt::Orientation orientation, QWidget *parent) - : QScrollBar(orientation, parent) - , m_widget(parent) - , m_overlay(new HighlightScrollBarOverlay(this)) -{ - connect(m_overlay, &HighlightScrollBarOverlay::destroyed, - this, &HighlightScrollBar::overlayDestroyed); - // valueChanged(0) flashes transient scroll bars, which is needed - // for a correct initialization. - emit valueChanged(0); -} - -HighlightScrollBar::~HighlightScrollBar() -{ - if (!m_overlay || m_overlay->parent() == this) - return; - - delete m_overlay; -} - -void HighlightScrollBar::setVisibleRange(float visibleRange) -{ - if (!m_overlay) - return; - m_overlay->m_visibleRange = visibleRange; -} - -void HighlightScrollBar::setRangeOffset(float offset) -{ - if (!m_overlay) - return; - m_overlay->m_offset = offset; -} - -QRect HighlightScrollBar::overlayRect() -{ - QStyleOptionSlider opt; - initStyleOption(&opt); - return style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarGroove, this); -} - -void HighlightScrollBar::overlayDestroyed() -{ - m_overlay = 0; -} - -void HighlightScrollBar::addHighlight(Highlight highlight) -{ - if (!m_overlay) - return; - m_overlay->m_highlights[highlight.category] << highlight; - m_overlay->scheduleUpdate(); -} - -void HighlightScrollBar::removeHighlights(Id category) -{ - if (!m_overlay) - return; - m_overlay->m_highlights.remove(category); - m_overlay->scheduleUpdate(); -} - -void HighlightScrollBar::removeAllHighlights() -{ - if (!m_overlay) - return; - m_overlay->m_highlights.clear(); - m_overlay->scheduleUpdate(); -} - -bool HighlightScrollBar::eventFilter(QObject *obj, QEvent *event) -{ - if (obj == m_widget && m_overlay && m_widget == m_overlay->parent() && - (event->type() == QEvent::Resize || event->type() == QEvent::Move)) { - QStyleOptionSlider opt; - initStyleOption(&opt); - const int width = style()->pixelMetric(QStyle::PM_ScrollBarExtent, &opt, this); - m_overlay->move(m_widget->width() - width, 0); - resize(width, m_widget->height()); - } - return false; -} - -void HighlightScrollBar::resizeEvent(QResizeEvent *event) -{ - if (!m_overlay) - return; - QScrollBar::resizeEvent(event); - m_overlay->resize(size()); -} - -void HighlightScrollBar::moveEvent(QMoveEvent *event) -{ - if (!m_overlay) - return; - QScrollBar::moveEvent(event); - m_overlay->adjustPosition(); -} - -void HighlightScrollBar::showEvent(QShowEvent *event) -{ - if (!m_overlay) - return; - QScrollBar::showEvent(event); - if (parentWidget() != this) { - m_widget->removeEventFilter(this); - m_overlay->setParent(this); - m_overlay->adjustPosition(); - m_overlay->show(); - } -} - -void HighlightScrollBar::hideEvent(QHideEvent *event) -{ - if (!m_overlay) - return; - QScrollBar::hideEvent(event); - if (parentWidget() != m_widget) { - m_widget->installEventFilter(this); - m_overlay->setParent(m_widget); - m_overlay->adjustPosition(); - m_overlay->show(); - } -} - -void HighlightScrollBar::changeEvent(QEvent *event) -{ - // Workaround for QTBUG-45579 - if (event->type() == QEvent::ParentChange) - setStyle(style()); -} - void HighlightScrollBarOverlay::scheduleUpdate() { if (m_cacheUpdateScheduled) @@ -207,28 +89,6 @@ void HighlightScrollBarOverlay::scheduleUpdate() QTimer::singleShot(0, this, static_cast(&QWidget::update)); } -void HighlightScrollBarOverlay::updateCache() -{ - if (!m_cacheUpdateScheduled) - return; - - m_cache.clear(); - const QList &categories = m_highlights.keys(); - for (const Id &category : categories) { - for (const Highlight &highlight : Utils::asConst(m_highlights[category])) { - Highlight oldHighlight = m_cache[highlight.position]; - if (highlight.priority > oldHighlight.priority) - m_cache[highlight.position] = highlight; - } - } - m_cacheUpdateScheduled = false; -} - -void HighlightScrollBarOverlay::adjustPosition() -{ - move(parentWidget()->mapFromGlobal(m_scrollBar->mapToGlobal(m_scrollBar->pos()))); -} - void HighlightScrollBarOverlay::paintEvent(QPaintEvent *paintEvent) { QWidget::paintEvent(paintEvent); @@ -238,23 +98,23 @@ void HighlightScrollBarOverlay::paintEvent(QPaintEvent *paintEvent) if (m_cache.isEmpty()) return; - const QRect &rect = m_scrollBar->overlayRect(); + const QRect &rect = overlayRect(); Utils::Theme::Color previousColor = Utils::Theme::TextColorNormal; Highlight::Priority previousPriority = Highlight::LowPriority; - QRect *previousRect = 0; + QRect *previousRect = nullptr; const int scrollbarRange = m_scrollBar->maximum() + m_scrollBar->pageStep(); - const int range = qMax(m_visibleRange, float(scrollbarRange)); + const int range = qMax(m_highlightController->visibleRange(), float(scrollbarRange)); const int horizontalMargin = 3; const int resultWidth = rect.width() - 2 * horizontalMargin + 1; const int resultHeight = qMin(int(rect.height() / range) + 1, 4); - const int offset = rect.height() / range * m_offset; + const int offset = rect.height() / range * m_highlightController->rangeOffset(); const int verticalMargin = ((rect.height() / range) - resultHeight) / 2; int previousBottom = -1; QHash > highlights; - for (Highlight currentHighlight : Utils::asConst(m_cache)) { + for (const Highlight ¤tHighlight : Utils::asConst(m_cache)) { // Calculate top and bottom int top = rect.top() + offset + verticalMargin + float(currentHighlight.position) / range * rect.height(); @@ -301,6 +161,50 @@ void HighlightScrollBarOverlay::paintEvent(QPaintEvent *paintEvent) } } +bool HighlightScrollBarOverlay::eventFilter(QObject *object, QEvent *event) +{ + switch (event->type()) { + case QEvent::Move: + doMove(); + break; + case QEvent::Resize: + doResize(); + break; + case QEvent::ZOrderChange: + raise(); + break; + default: + break; + } + return QWidget::eventFilter(object, event); +} + +void HighlightScrollBarOverlay::updateCache() +{ + if (!m_cacheUpdateScheduled) + return; + + m_cache.clear(); + const QHash> highlights = m_highlightController->highlights(); + const QList &categories = highlights.keys(); + for (const Id &category : categories) { + for (const Highlight &highlight : highlights.value(category)) { + const Highlight oldHighlight = m_cache.value(highlight.position); + if (highlight.priority > oldHighlight.priority) + m_cache[highlight.position] = highlight; + } + } + m_cacheUpdateScheduled = false; +} + +QRect HighlightScrollBarOverlay::overlayRect() const +{ + QStyleOptionSlider opt = qt_qscrollbarStyleOption(m_scrollBar); + return m_scrollBar->style()->subControlRect(QStyle::CC_ScrollBar, &opt, QStyle::SC_ScrollBarGroove, m_scrollBar); +} + +///////////// + Highlight::Highlight(Id category_, int position_, Theme::Color color_, Highlight::Priority priority_) : category(category_) @@ -310,4 +214,95 @@ Highlight::Highlight(Id category_, int position_, { } +///////////// + +HighlightScrollBarController::~HighlightScrollBarController() +{ + if (m_overlay) + delete m_overlay; +} + +QScrollBar *HighlightScrollBarController::scrollBar() const +{ + if (m_scrollArea) + return m_scrollArea->verticalScrollBar(); + + return nullptr; +} + +QAbstractScrollArea *HighlightScrollBarController::scrollArea() const +{ + return m_scrollArea; +} + +void HighlightScrollBarController::setScrollArea(QAbstractScrollArea *scrollArea) +{ + if (m_scrollArea == scrollArea) + return; + + if (m_overlay) { + delete m_overlay; + m_overlay = nullptr; + } + + m_scrollArea = scrollArea; + + if (m_scrollArea) { + m_overlay = new HighlightScrollBarOverlay(this); + m_overlay->scheduleUpdate(); + } +} + +float HighlightScrollBarController::visibleRange() const +{ + return m_visibleRange; +} + +void HighlightScrollBarController::setVisibleRange(float visibleRange) +{ + m_visibleRange = visibleRange; +} + +float HighlightScrollBarController::rangeOffset() const +{ + return m_rangeOffset; +} + +void HighlightScrollBarController::setRangeOffset(float offset) +{ + m_rangeOffset = offset; +} + +QHash> HighlightScrollBarController::highlights() const +{ + return m_highlights; +} + +void HighlightScrollBarController::addHighlight(Highlight highlight) +{ + if (!m_overlay) + return; + + m_highlights[highlight.category] << highlight; + m_overlay->scheduleUpdate(); +} + +void HighlightScrollBarController::removeHighlights(Id category) +{ + if (!m_overlay) + return; + + m_highlights.remove(category); + m_overlay->scheduleUpdate(); +} + +void HighlightScrollBarController::removeAllHighlights() +{ + if (!m_overlay) + return; + + m_highlights.clear(); + m_overlay->scheduleUpdate(); +} + } // namespace Core diff --git a/src/plugins/coreplugin/find/highlightscrollbar.h b/src/plugins/coreplugin/find/highlightscrollbarcontroller.h similarity index 72% rename from src/plugins/coreplugin/find/highlightscrollbar.h rename to src/plugins/coreplugin/find/highlightscrollbarcontroller.h index c24434a9766..a20a17e190b 100644 --- a/src/plugins/coreplugin/find/highlightscrollbar.h +++ b/src/plugins/coreplugin/find/highlightscrollbarcontroller.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2017 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of Qt Creator. @@ -25,14 +25,19 @@ #pragma once -#include -#include -#include +#include +#include +#include #include #include #include +QT_BEGIN_NAMESPACE +class QAbstractScrollArea; +class QScrollBar; +QT_END_NAMESPACE + namespace Core { struct CORE_EXPORT Highlight @@ -56,38 +61,34 @@ struct CORE_EXPORT Highlight class HighlightScrollBarOverlay; -class CORE_EXPORT HighlightScrollBar : public QScrollBar +class CORE_EXPORT HighlightScrollBarController { - Q_OBJECT - public: - HighlightScrollBar(Qt::Orientation orientation, QWidget *parent = 0); - ~HighlightScrollBar() override; + HighlightScrollBarController() = default; + ~HighlightScrollBarController(); + QScrollBar *scrollBar() const; + QAbstractScrollArea *scrollArea() const; + void setScrollArea(QAbstractScrollArea *scrollArea); + + float visibleRange() const; void setVisibleRange(float visibleRange); + + float rangeOffset() const; void setRangeOffset(float offset); + QHash> highlights() const; void addHighlight(Highlight highlight); void removeHighlights(Id id); void removeAllHighlights(); - bool eventFilter(QObject *, QEvent *event) override; - -protected: - void moveEvent(QMoveEvent *event) override; - void resizeEvent(QResizeEvent *event) override; - void showEvent(QShowEvent *event) override; - void hideEvent(QHideEvent *event) override; - void changeEvent(QEvent *even) override; - private: - QRect overlayRect(); - void overlayDestroyed(); - - QWidget *m_widget; - HighlightScrollBarOverlay *m_overlay; - friend class HighlightScrollBarOverlay; + QHash > m_highlights; + float m_visibleRange = 0.0; + float m_rangeOffset = 0.0; + QAbstractScrollArea *m_scrollArea = nullptr; + QPointer m_overlay; }; } // namespace Core diff --git a/src/plugins/diffeditor/diffeditor.cpp b/src/plugins/diffeditor/diffeditor.cpp index 8693d235057..0fbb63f27bc 100644 --- a/src/plugins/diffeditor/diffeditor.cpp +++ b/src/plugins/diffeditor/diffeditor.cpp @@ -108,7 +108,6 @@ DescriptionEditorWidget::DescriptionEditorWidget(QWidget *parent) DisplaySettings settings = displaySettings(); settings.m_textWrapping = false; settings.m_displayLineNumbers = false; - settings.m_highlightCurrentLine = false; settings.m_displayFoldingMarkers = false; settings.m_markTextChanges = false; settings.m_highlightBlocks = false; @@ -143,6 +142,8 @@ void DescriptionEditorWidget::setDisplaySettings(const DisplaySettings &ds) { DisplaySettings settings = displaySettings(); settings.m_visualizeWhitespace = ds.m_visualizeWhitespace; + settings.m_scrollBarHighlights = ds.m_scrollBarHighlights; + settings.m_highlightCurrentLine = ds.m_highlightCurrentLine; TextEditorWidget::setDisplaySettings(settings); } diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp index cdaad44d0be..f42acfe8da4 100644 --- a/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp +++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.cpp @@ -42,6 +42,7 @@ #include #include +#include #include #include @@ -98,6 +99,8 @@ signals: int diffFileIndex, int chunkIndex); void foldChanged(int blockNumber, bool folded); + void gotDisplaySettings(); + void gotFocus(); protected: int extraAreaWidth(int *markWidthPtr = nullptr) const override { @@ -124,6 +127,7 @@ protected: const QTextBlock &block, QPointF offset, const QRect &clip) override; + void focusInEvent(QFocusEvent *e) override; private: void paintSeparator(QPainter &painter, QColor &color, const QString &text, @@ -158,7 +162,6 @@ SideDiffEditorWidget::SideDiffEditorWidget(QWidget *parent) DisplaySettings settings = displaySettings(); settings.m_textWrapping = false; settings.m_displayLineNumbers = true; - settings.m_highlightCurrentLine = false; settings.m_markTextChanges = false; settings.m_highlightBlocks = false; SelectableTextEditorWidget::setDisplaySettings(settings); @@ -217,7 +220,10 @@ void SideDiffEditorWidget::setDisplaySettings(const DisplaySettings &ds) DisplaySettings settings = displaySettings(); settings.m_visualizeWhitespace = ds.m_visualizeWhitespace; settings.m_displayFoldingMarkers = ds.m_displayFoldingMarkers; + settings.m_scrollBarHighlights = ds.m_scrollBarHighlights; + settings.m_highlightCurrentLine = ds.m_highlightCurrentLine; SelectableTextEditorWidget::setDisplaySettings(settings); + emit gotDisplaySettings(); } void SideDiffEditorWidget::applyFontSettings() @@ -604,6 +610,12 @@ void SideDiffEditorWidget::drawCollapsedBlockPopup(QPainter &painter, m_drawCollapsedClip = clip; } +void SideDiffEditorWidget::focusInEvent(QFocusEvent *e) +{ + SelectableTextEditorWidget::focusInEvent(e); + emit gotFocus(); +} + ////////////////// SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent) @@ -613,9 +625,6 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent) m_leftEditor = new SideDiffEditorWidget(this); m_leftEditor->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); m_leftEditor->setReadOnly(true); - connect(TextEditorSettings::instance(), &TextEditorSettings::displaySettingsChanged, - m_leftEditor, &SideDiffEditorWidget::setDisplaySettings); - m_leftEditor->setDisplaySettings(TextEditorSettings::displaySettings()); m_leftEditor->setCodeStyle(TextEditorSettings::codeStyle()); connect(m_leftEditor, &SideDiffEditorWidget::jumpToOriginalFileRequested, this, &SideBySideDiffEditorWidget::slotLeftJumpToOriginalFileRequested); @@ -625,9 +634,6 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent) m_rightEditor = new SideDiffEditorWidget(this); m_rightEditor->setReadOnly(true); - connect(TextEditorSettings::instance(), &TextEditorSettings::displaySettingsChanged, - m_rightEditor, &SideDiffEditorWidget::setDisplaySettings); - m_rightEditor->setDisplaySettings(TextEditorSettings::displaySettings()); m_rightEditor->setCodeStyle(TextEditorSettings::codeStyle()); connect(m_rightEditor, &SideDiffEditorWidget::jumpToOriginalFileRequested, this, &SideBySideDiffEditorWidget::slotRightJumpToOriginalFileRequested); @@ -635,6 +641,44 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent) this, &SideBySideDiffEditorWidget::slotRightContextMenuRequested, Qt::DirectConnection); + auto setupHighlightController = [this]() { + HighlightScrollBarController *highlightController = m_leftEditor->highlightScrollBarController(); + if (highlightController) + highlightController->setScrollArea(m_rightEditor); + }; + + setupHighlightController(); + connect(m_leftEditor, &SideDiffEditorWidget::gotDisplaySettings, setupHighlightController); + + m_rightEditor->verticalScrollBar()->setFocusProxy(m_leftEditor); + connect(m_leftEditor, &SideDiffEditorWidget::gotFocus, [this]() { + if (m_rightEditor->verticalScrollBar()->focusProxy() == m_leftEditor) + return; // We already did it before. + + // Hack #1. If the left editor got a focus last time + // we don't want to focus right editor when clicking the right + // scrollbar. + m_rightEditor->verticalScrollBar()->setFocusProxy(m_leftEditor); + + // Hack #2. If the focus is currently not on the scrollbar's proxy + // and we click on the scrollbar, the focus will go to the parent + // of the scrollbar. In order to give the focus to the proxy + // we need to set a click focus policy on the scrollbar. + // See QApplicationPrivate::giveFocusAccordingToFocusPolicy(). + m_rightEditor->verticalScrollBar()->setFocusPolicy(Qt::ClickFocus); + + // Hack #3. Setting the focus policy is not orthogonal to setting + // the focus proxy and unfortuantely it changes the policy of the proxy + // too. We bring back the original policy to keep tab focus working. + m_leftEditor->setFocusPolicy(Qt::StrongFocus); + }); + connect(m_rightEditor, &SideDiffEditorWidget::gotFocus, [this]() { + // Unhack #1. + m_rightEditor->verticalScrollBar()->setFocusProxy(nullptr); + // Unhack #2. + m_rightEditor->verticalScrollBar()->setFocusPolicy(Qt::NoFocus); + }); + connect(TextEditorSettings::instance(), &TextEditorSettings::fontSettingsChanged, this, &SideBySideDiffEditorWidget::setFontSettings); @@ -678,7 +722,7 @@ SideBySideDiffEditorWidget::SideBySideDiffEditorWidget(QWidget *parent) QVBoxLayout *l = new QVBoxLayout(this); l->setMargin(0); l->addWidget(m_splitter); - setFocusProxy(m_rightEditor); + setFocusProxy(m_leftEditor); m_leftContext = new IContext(this); m_leftContext->setWidget(m_leftEditor); @@ -1060,32 +1104,43 @@ void SideBySideDiffEditorWidget::leftCursorPositionChanged() { leftVSliderChanged(); leftHSliderChanged(); - - if (m_controller.m_ignoreCurrentIndexChange) - return; - - const bool oldIgnore = m_controller.m_ignoreCurrentIndexChange; - m_controller.m_ignoreCurrentIndexChange = true; - emit currentDiffFileIndexChanged( - m_leftEditor->fileIndexForBlockNumber(m_leftEditor->textCursor().blockNumber())); - m_controller.m_ignoreCurrentIndexChange = oldIgnore; + handlePositionChange(m_leftEditor, m_rightEditor); } void SideBySideDiffEditorWidget::rightCursorPositionChanged() { rightVSliderChanged(); rightHSliderChanged(); + handlePositionChange(m_rightEditor, m_leftEditor); +} +void SideBySideDiffEditorWidget::handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest) +{ if (m_controller.m_ignoreCurrentIndexChange) return; const bool oldIgnore = m_controller.m_ignoreCurrentIndexChange; m_controller.m_ignoreCurrentIndexChange = true; + syncCursor(source, dest); emit currentDiffFileIndexChanged( - m_rightEditor->fileIndexForBlockNumber(m_rightEditor->textCursor().blockNumber())); + source->fileIndexForBlockNumber(source->textCursor().blockNumber())); m_controller.m_ignoreCurrentIndexChange = oldIgnore; } +void SideBySideDiffEditorWidget::syncCursor(SideDiffEditorWidget *source, SideDiffEditorWidget *dest) +{ + const QTextCursor sourceCursor = source->textCursor(); + const int sourceLine = sourceCursor.blockNumber(); + const int sourceColumn = sourceCursor.positionInBlock(); + QTextCursor destCursor = dest->textCursor(); + const QTextBlock destBlock = dest->document()->findBlockByNumber(sourceLine); + const int destColumn = qMin(sourceColumn, destBlock.length()); + const int destPosition = destBlock.position() + destColumn; + destCursor.setPosition(destPosition); + dest->setTextCursor(destCursor); + +} + } // namespace Internal } // namespace DiffEditor diff --git a/src/plugins/diffeditor/sidebysidediffeditorwidget.h b/src/plugins/diffeditor/sidebysidediffeditorwidget.h index 44f536839ba..ba5c8ef550d 100644 --- a/src/plugins/diffeditor/sidebysidediffeditorwidget.h +++ b/src/plugins/diffeditor/sidebysidediffeditorwidget.h @@ -95,6 +95,8 @@ private: void rightHSliderChanged(); void leftCursorPositionChanged(); void rightCursorPositionChanged(); + void handlePositionChange(SideDiffEditorWidget *source, SideDiffEditorWidget *dest); + void syncCursor(SideDiffEditorWidget *source, SideDiffEditorWidget *dest); void showDiff(); diff --git a/src/plugins/diffeditor/unifieddiffeditorwidget.cpp b/src/plugins/diffeditor/unifieddiffeditorwidget.cpp index e4f949c63f2..dbea4cbfb9c 100644 --- a/src/plugins/diffeditor/unifieddiffeditorwidget.cpp +++ b/src/plugins/diffeditor/unifieddiffeditorwidget.cpp @@ -58,7 +58,6 @@ UnifiedDiffEditorWidget::UnifiedDiffEditorWidget(QWidget *parent) DisplaySettings settings = displaySettings(); settings.m_textWrapping = false; settings.m_displayLineNumbers = true; - settings.m_highlightCurrentLine = false; settings.m_markTextChanges = false; settings.m_highlightBlocks = false; SelectableTextEditorWidget::setDisplaySettings(settings); @@ -133,6 +132,8 @@ void UnifiedDiffEditorWidget::setDisplaySettings(const DisplaySettings &ds) DisplaySettings settings = displaySettings(); settings.m_visualizeWhitespace = ds.m_visualizeWhitespace; settings.m_displayFoldingMarkers = ds.m_displayFoldingMarkers; + settings.m_scrollBarHighlights = ds.m_scrollBarHighlights; + settings.m_highlightCurrentLine = ds.m_highlightCurrentLine; SelectableTextEditorWidget::setDisplaySettings(settings); } diff --git a/src/plugins/texteditor/texteditor.cpp b/src/plugins/texteditor/texteditor.cpp index 54d3cb23180..a0f51c3d573 100644 --- a/src/plugins/texteditor/texteditor.cpp +++ b/src/plugins/texteditor/texteditor.cpp @@ -72,7 +72,7 @@ #include #include #include -#include +#include #include #include #include @@ -759,7 +759,7 @@ public: QFutureWatcher *m_searchWatcher = nullptr; QVector m_searchResults; QTimer m_scrollBarUpdateTimer; - HighlightScrollBar *m_highlightScrollBar = nullptr; + HighlightScrollBarController *m_highlightScrollBarController = nullptr; bool m_scrollBarUpdateScheduled = false; }; @@ -814,6 +814,7 @@ TextEditorWidgetPrivate::~TextEditorWidgetPrivate() this, &TextEditorWidgetPrivate::markRemoved); q->disconnect(this); delete m_toolBar; + delete m_highlightScrollBarController; } } // namespace Internal @@ -904,15 +905,15 @@ void TextEditorWidget::setTextDocument(const QSharedPointer &doc) void TextEditorWidgetPrivate::setupScrollBar() { if (m_displaySettings.m_scrollBarHighlights) { - if (m_highlightScrollBar) - return; - m_highlightScrollBar = new HighlightScrollBar(Qt::Vertical, q); - q->setVerticalScrollBar(m_highlightScrollBar); + if (!m_highlightScrollBarController) + m_highlightScrollBarController = new HighlightScrollBarController(); + + m_highlightScrollBarController->setScrollArea(q); highlightSearchResultsInScrollBar(); scheduleUpdateHighlightScrollBar(); - } else if (m_highlightScrollBar) { - q->setVerticalScrollBar(new QScrollBar(Qt::Vertical, q)); - m_highlightScrollBar = 0; + } else if (m_highlightScrollBarController) { + delete m_highlightScrollBarController; + m_highlightScrollBarController = nullptr; } } @@ -5311,14 +5312,14 @@ void TextEditorWidgetPrivate::updateHighlights() void TextEditorWidgetPrivate::updateCurrentLineInScrollbar() { - if (m_highlightCurrentLine && m_highlightScrollBar) { - m_highlightScrollBar->removeHighlights(Constants::SCROLL_BAR_CURRENT_LINE); - if (m_highlightScrollBar->maximum() > 0) { + if (m_highlightCurrentLine && m_highlightScrollBarController) { + m_highlightScrollBarController->removeHighlights(Constants::SCROLL_BAR_CURRENT_LINE); + if (m_highlightScrollBarController->scrollBar()->maximum() > 0) { const QTextCursor &tc = q->textCursor(); if (QTextLayout *layout = tc.block().layout()) { const int pos = q->textCursor().block().firstLineNumber() + layout->lineForTextPosition(tc.positionInBlock()).lineNumber(); - m_highlightScrollBar->addHighlight({Constants::SCROLL_BAR_CURRENT_LINE, pos, + m_highlightScrollBarController->addHighlight({Constants::SCROLL_BAR_CURRENT_LINE, pos, Theme::TextEditor_CurrentLine_ScrollBarColor, Highlight::HighestPriority}); } @@ -6213,7 +6214,7 @@ void TextEditorWidgetPrivate::highlightSearchResultsSlot(const QString &txt, Fin m_delayedUpdateTimer.start(50); - if (m_highlightScrollBar) + if (m_highlightScrollBarController) m_scrollBarUpdateTimer.start(50); } @@ -6241,22 +6242,22 @@ void TextEditorWidgetPrivate::searchFinished() void TextEditorWidgetPrivate::adjustScrollBarRanges() { - if (!m_highlightScrollBar) + if (!m_highlightScrollBarController) return; const float lineSpacing = QFontMetricsF(q->font()).lineSpacing(); if (lineSpacing == 0) return; const float offset = q->contentOffset().y(); - m_highlightScrollBar->setVisibleRange((q->viewport()->rect().height() - offset) / lineSpacing); - m_highlightScrollBar->setRangeOffset(offset / lineSpacing); + m_highlightScrollBarController->setVisibleRange((q->viewport()->rect().height() - offset) / lineSpacing); + m_highlightScrollBarController->setRangeOffset(offset / lineSpacing); } void TextEditorWidgetPrivate::highlightSearchResultsInScrollBar() { - if (!m_highlightScrollBar) + if (!m_highlightScrollBarController) return; - m_highlightScrollBar->removeHighlights(Constants::SCROLL_BAR_SEARCH_RESULT); + m_highlightScrollBarController->removeHighlights(Constants::SCROLL_BAR_SEARCH_RESULT); m_searchResults.clear(); if (m_searchWatcher) { @@ -6318,7 +6319,7 @@ Highlight::Priority textMarkPrioToScrollBarPrio(const TextMark::Priority &prio) void TextEditorWidgetPrivate::addSearchResultsToScrollBar(QVector results) { - if (!m_highlightScrollBar) + if (!m_highlightScrollBarController) return; foreach (SearchResult result, results) { const QTextBlock &block = q->document()->findBlock(result.start); @@ -6326,7 +6327,7 @@ void TextEditorWidgetPrivate::addSearchResultsToScrollBar(QVector const int firstLine = block.layout()->lineForTextPosition(result.start - block.position()).lineNumber(); const int lastLine = block.layout()->lineForTextPosition(result.start - block.position() + result.length).lineNumber(); for (int line = firstLine; line <= lastLine; ++line) { - m_highlightScrollBar->addHighlight( + m_highlightScrollBarController->addHighlight( {Constants::SCROLL_BAR_SEARCH_RESULT, block.firstLineNumber() + line, Theme::TextEditor_SearchResult_ScrollBarColor, Highlight::HighPriority}); } @@ -6343,10 +6344,10 @@ Highlight markToHighlight(TextMark *mark, int lineNumber) void TextEditorWidgetPrivate::updateHighlightScrollBarNow() { m_scrollBarUpdateScheduled = false; - if (!m_highlightScrollBar) + if (!m_highlightScrollBarController) return; - m_highlightScrollBar->removeAllHighlights(); + m_highlightScrollBarController->removeAllHighlights(); updateCurrentLineInScrollbar(); @@ -6359,7 +6360,7 @@ void TextEditorWidgetPrivate::updateHighlightScrollBarNow() continue; const QTextBlock &block = q->document()->findBlockByNumber(mark->lineNumber() - 1); if (block.isVisible()) - m_highlightScrollBar->addHighlight(markToHighlight(mark, block.firstLineNumber())); + m_highlightScrollBarController->addHighlight(markToHighlight(mark, block.firstLineNumber())); } } @@ -8376,6 +8377,11 @@ int TextEditorWidget::centerVisibleLine() const return block.isValid() ? block.blockNumber() : -1; } +HighlightScrollBarController *TextEditorWidget::highlightScrollBarController() const +{ + return d->m_highlightScrollBarController; +} + bool TextEditorWidget::isMissingSyntaxDefinition() const { return d->m_isMissingSyntaxDefinition; diff --git a/src/plugins/texteditor/texteditor.h b/src/plugins/texteditor/texteditor.h index 2eafc322931..c98a84df005 100644 --- a/src/plugins/texteditor/texteditor.h +++ b/src/plugins/texteditor/texteditor.h @@ -51,6 +51,10 @@ class QRect; class QTextBlock; QT_END_NAMESPACE +namespace Core { +class HighlightScrollBarController; +} + namespace TextEditor { class TextDocument; class BaseHoverHandler; @@ -458,6 +462,8 @@ public: /*! Returns the line visible closest to the vertical center of the editor. */ int centerVisibleLine() const; + Core::HighlightScrollBarController *highlightScrollBarController() const; + signals: void assistFinished(); // Used in tests. void readOnlyChanged();