ui: Show title bar at top and scroll bar at bottom in code view snippet list if necessary (issues #432, #479)

* Show title bar at top of snippet list if first file is cut off
* Show scrollbar at bottom of snippet list if last snippet if cut off and horizontally scrollable
* Extended scrollRequest API to different ScrollTarget modes
* Fixed snippet extension broken if maximized first
* Split off title bar functionality to separate class QtCodeFileTitleBar
This commit is contained in:
Eberhard Graether
2017-12-17 13:25:11 +01:00
parent c91f5282f5
commit 8672d14319
17 changed files with 736 additions and 289 deletions
+2
View File
@@ -22,6 +22,8 @@ add_files(
qt/element/QtCodeFileList.h
qt/element/QtCodeFileSingle.cpp
qt/element/QtCodeFileSingle.h
qt/element/QtCodeFileTitleBar.cpp
qt/element/QtCodeFileTitleBar.h
qt/element/QtCodeFileTitleButton.cpp
qt/element/QtCodeFileTitleButton.h
qt/element/QtCodeNavigateable.cpp
+52 -168
View File
@@ -1,14 +1,11 @@
#include "qt/element/QtCodeFile.h"
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include "utility/messaging/type/MessageChangeFileView.h"
#include "utility/ResourcePaths.h"
#include "data/location/SourceLocationFile.h"
#include "qt/element/QtCodeFileTitleButton.h"
#include "qt/element/QtCodeFileTitleBar.h"
#include "qt/element/QtCodeNavigator.h"
#include "qt/element/QtCodeSnippet.h"
@@ -17,7 +14,6 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator)
, m_navigator(navigator)
, m_filePath(filePath)
, m_isWholeFile(false)
, m_isCollapsed(true)
, m_contentRequested(false)
{
setObjectName("code_file");
@@ -29,84 +25,17 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator)
layout->setAlignment(Qt::AlignTop);
setLayout(layout);
m_titleBar = new QtHoverButton(this);
m_titleBar->setObjectName("title_widget");
m_titleBar->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
m_titleBar = new QtCodeFileTitleBar();
layout->addWidget(m_titleBar);
connect(dynamic_cast<QtHoverButton*>(m_titleBar), &QtHoverButton::hoveredIn, this, &QtCodeFile::enteredTitleBar);
connect(dynamic_cast<QtHoverButton*>(m_titleBar), &QtHoverButton::hoveredOut, this, &QtCodeFile::leftTitleBar);
QHBoxLayout* titleLayout = new QHBoxLayout();
titleLayout->setMargin(0);
titleLayout->setSpacing(0);
titleLayout->setAlignment(Qt::AlignLeft);
m_titleBar->setLayout(titleLayout);
m_title = new QtCodeFileTitleButton(this);
if (!m_filePath.empty())
{
m_title->setFilePath(filePath);
m_titleBar->getTitleButton()->setFilePath(filePath);
}
titleLayout->addWidget(m_title);
m_titleBar->setMinimumHeight(m_title->height() + 4);
m_referenceCount = new QLabel(this);
m_referenceCount->setObjectName("references_label");
m_referenceCount->hide();
titleLayout->addWidget(m_referenceCount);
titleLayout->addStretch(3);
m_minimizeButton = new QtIconStateButton(this);
m_minimizeButton->addState(QtIconStateButton::STATE_DEFAULT, (ResourcePaths::getGuiPath().str() + "code_view/images/minimize_active.png").c_str());
// m_minimizeButton->addState(QtIconStateButton::STATE_HOVERED, (ResourcePaths::getGuiPath().str() + "code_view/images/minimize_inactive.png").c_str(), "#5E5D5D");
m_minimizeButton->addState(QtIconStateButton::STATE_HOVERED, (ResourcePaths::getGuiPath().str() + "code_view/images/minimize_inactive.png").c_str(), QColor(0x5E, 0x5D, 0x5D));
m_minimizeButton->addState(QtIconStateButton::STATE_DISABLED, (ResourcePaths::getGuiPath().str() + "code_view/images/minimize_inactive.png").c_str());
m_minimizeButton->setIconSize(QSize(16, 16));
m_minimizeButton->setObjectName("file_button");
m_minimizeButton->setToolTip("minimize");
titleLayout->addWidget(m_minimizeButton);
m_snippetButton = new QtIconStateButton(this);
m_snippetButton->addState(QtIconStateButton::STATE_DEFAULT, (ResourcePaths::getGuiPath().str() + "code_view/images/snippet_active.png").c_str());
// m_snippetButton->addState(QtIconStateButton::STATE_HOVERED, (ResourcePaths::getGuiPath().str() + "code_view/images/snippet_inactive.png").c_str(), "#5E5D5D");
m_snippetButton->addState(QtIconStateButton::STATE_HOVERED, (ResourcePaths::getGuiPath().str() + "code_view/images/snippet_inactive.png").c_str(), QColor(0x5E, 0x5D, 0x5D));
m_snippetButton->addState(QtIconStateButton::STATE_DISABLED, (ResourcePaths::getGuiPath().str() + "code_view/images/snippet_inactive.png").c_str());
m_snippetButton->setIconSize(QSize(16, 16));
m_snippetButton->setObjectName("file_button");
m_snippetButton->setToolTip("show snippets");
titleLayout->addWidget(m_snippetButton);
m_maximizeButton = new QtIconStateButton(this);
m_maximizeButton->addState(QtIconStateButton::STATE_DEFAULT, (ResourcePaths::getGuiPath().str() + "code_view/images/maximize_active.png").c_str());
// m_maximizeButton->addState(QtIconStateButton::STATE_HOVERED, (ResourcePaths::getGuiPath().str() + "code_view/images/maximize_inactive.png").c_str(), "#5E5D5D");
m_maximizeButton->addState(QtIconStateButton::STATE_HOVERED, (ResourcePaths::getGuiPath().str() + "code_view/images/maximize_inactive.png").c_str(), QColor(0x5E, 0x5D, 0x5D));
m_maximizeButton->addState(QtIconStateButton::STATE_DISABLED, (ResourcePaths::getGuiPath().str() + "code_view/images/maximize_inactive.png").c_str());
m_maximizeButton->setIconSize(QSize(16, 16));
m_maximizeButton->setObjectName("file_button");
m_maximizeButton->setToolTip("maximize");
titleLayout->addWidget(m_maximizeButton);
connect(m_minimizeButton, &QtIconStateButton::hoveredIn, this, &QtCodeFile::leftTitleBar);
connect(m_minimizeButton, &QtIconStateButton::hoveredOut, this, &QtCodeFile::enteredTitleBar);
connect(m_snippetButton, &QtIconStateButton::hoveredIn, this, &QtCodeFile::leftTitleBar);
connect(m_snippetButton, &QtIconStateButton::hoveredOut, this, &QtCodeFile::enteredTitleBar);
connect(m_maximizeButton, &QtIconStateButton::hoveredIn, this, &QtCodeFile::leftTitleBar);
connect(m_maximizeButton, &QtIconStateButton::hoveredOut, this, &QtCodeFile::enteredTitleBar);
titleLayout->addSpacing(3);
m_minimizeButton->setEnabled(false);
m_snippetButton->setEnabled(false);
m_maximizeButton->setEnabled(false);
connect(m_titleBar, &QPushButton::clicked, this, &QtCodeFile::clickedTitleBar);
connect(m_minimizeButton, &QtIconStateButton::clicked, this, &QtCodeFile::clickedMinimizeButton);
connect(m_snippetButton, &QtIconStateButton::clicked, this, &QtCodeFile::clickedSnippetButton);
connect(m_maximizeButton, &QtIconStateButton::clicked, this, &QtCodeFile::clickedMaximizeButton);
connect(m_titleBar, &QtCodeFileTitleBar::minimize, this, &QtCodeFile::clickedMinimizeButton);
connect(m_titleBar, &QtCodeFileTitleBar::snippet, this, &QtCodeFile::clickedSnippetButton);
connect(m_titleBar, &QtCodeFileTitleBar::maximize, this, &QtCodeFile::clickedMaximizeButton);
m_snippetLayout = new QVBoxLayout();
m_snippetLayout->setContentsMargins(0, 0, 0, 0);
@@ -122,7 +51,7 @@ QtCodeFile::~QtCodeFile()
void QtCodeFile::setModificationTime(const TimeStamp modificationTime)
{
m_title->setModificationTime(modificationTime);
m_titleBar->getTitleButton()->setModificationTime(modificationTime);
}
const FilePath& QtCodeFile::getFilePath() const
@@ -135,6 +64,11 @@ std::string QtCodeFile::getFileName() const
return m_filePath.fileName();
}
const QtCodeFileTitleBar* QtCodeFile::getTitleBar() const
{
return m_titleBar;
}
QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params)
{
for (const std::shared_ptr<QtCodeSnippet>& snippet : m_snippets)
@@ -146,12 +80,12 @@ QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params)
}
}
m_isCollapsed = false;
std::shared_ptr<QtCodeSnippet> snippet(new QtCodeSnippet(params, m_navigator, this));
if (params.reduced)
{
m_title->setProject(params.title);
m_titleBar->getTitleButton()->setProject(params.title);
m_isWholeFile = true;
}
m_snippetLayout->addWidget(snippet.get());
@@ -185,8 +119,6 @@ QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params)
QtCodeSnippet* QtCodeFile::insertCodeSnippet(const CodeSnippetParams& params)
{
m_isCollapsed = false;
std::shared_ptr<QtCodeSnippet> snippet(new QtCodeSnippet(params, m_navigator, this));
size_t i = 0;
@@ -225,6 +157,26 @@ QtCodeSnippet* QtCodeFile::insertCodeSnippet(const CodeSnippetParams& params)
return snippet.get();
}
std::vector<QtCodeSnippet*> QtCodeFile::getVisibleSnippets() const
{
if (m_fileSnippet && m_fileSnippet->isVisible())
{
return { m_fileSnippet.get() };
}
std::vector<QtCodeSnippet*> snippets;
for (const std::shared_ptr<QtCodeSnippet>& snippet : m_snippets)
{
if (snippet->isVisible())
{
snippets.push_back(snippet.get());
}
}
return snippets;
}
QtCodeSnippet* QtCodeFile::getSnippetForLocationId(Id locationId) const
{
if (m_fileSnippet && m_fileSnippet->isVisible() && m_fileSnippet->getLineNumberForLocationId(locationId))
@@ -286,7 +238,7 @@ std::pair<QtCodeSnippet*, Id> QtCodeFile::getFirstSnippetWithActiveLocationId(Id
bool QtCodeFile::isCollapsed() const
{
return m_isCollapsed;
return !getFileSnippet() && !m_snippets.size();
}
void QtCodeFile::requestContent()
@@ -302,7 +254,9 @@ void QtCodeFile::requestContent()
MessageChangeFileView::FileState state =
m_isWholeFile ? MessageChangeFileView::FILE_MAXIMIZED : MessageChangeFileView::FILE_SNIPPETS;
MessageChangeFileView(m_filePath, state, isCollapsed(), m_navigator->hasErrors()).dispatch();
bool needsData = (state == MessageChangeFileView::FILE_MAXIMIZED) ? (getFileSnippet() == nullptr) : (m_snippets.size() == 0);
MessageChangeFileView(m_filePath, state, needsData, m_navigator->hasErrors()).dispatch();
}
void QtCodeFile::updateContent()
@@ -330,7 +284,7 @@ void QtCodeFile::setWholeFile(bool isWholeFile, int refCount)
void QtCodeFile::setIsComplete(bool isComplete)
{
m_title->setIsComplete(isComplete);
m_titleBar->getTitleButton()->setIsComplete(isComplete);
}
void QtCodeFile::setMinimized()
@@ -345,13 +299,7 @@ void QtCodeFile::setMinimized()
m_fileSnippet->hide();
}
m_minimizeButton->setEnabled(false);
m_snippetButton->setEnabled(m_snippets.size() || (isCollapsed() && !m_isWholeFile));
m_maximizeButton->setEnabled(true);
m_minimizeButton->hoverOut();
m_snippetButton->hoverOut();
m_maximizeButton->hoverOut();
m_titleBar->setMinimized(!m_isWholeFile);
setStyleSheet("#code_file { padding-bottom: 0; } #code_file #title_widget { border-radius: 7px; }");
}
@@ -368,13 +316,7 @@ void QtCodeFile::setSnippets()
m_fileSnippet->hide();
}
m_minimizeButton->setEnabled(true);
m_snippetButton->setEnabled(false);
m_maximizeButton->setEnabled(true);
m_minimizeButton->hoverOut();
m_snippetButton->hoverOut();
m_maximizeButton->hoverOut();
m_titleBar->setSnippets();
setStyleSheet("");
}
@@ -391,13 +333,7 @@ void QtCodeFile::setMaximized()
m_fileSnippet->show();
}
m_minimizeButton->setEnabled(true);
m_snippetButton->setEnabled(m_snippets.size() || (isCollapsed() && !m_isWholeFile));
m_maximizeButton->setEnabled(false);
m_minimizeButton->hoverOut();
m_snippetButton->hoverOut();
m_maximizeButton->hoverOut();
m_titleBar->setMaximized(!m_isWholeFile);
setStyleSheet("");
}
@@ -438,7 +374,7 @@ void QtCodeFile::updateSnippets()
void QtCodeFile::updateTitleBar()
{
m_title->updateTexts();
m_titleBar->getTitleButton()->updateTexts();
}
void QtCodeFile::findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches)
@@ -467,6 +403,8 @@ void QtCodeFile::clickedMinimizeButton()
return;
}
m_navigator->requestScroll(m_filePath, 0, 0, false, QtCodeNavigateable::SCROLL_VISIBLE);
MessageChangeFileView(
m_filePath,
MessageChangeFileView::FILE_MINIMIZED,
@@ -477,10 +415,12 @@ void QtCodeFile::clickedMinimizeButton()
void QtCodeFile::clickedSnippetButton()
{
m_navigator->requestScroll(m_filePath, 0, 0, false, QtCodeNavigateable::SCROLL_VISIBLE);
MessageChangeFileView(
m_filePath,
MessageChangeFileView::FILE_SNIPPETS,
isCollapsed(),
!m_snippets.size(),
m_navigator->hasErrors()
).dispatch();
}
@@ -494,6 +434,8 @@ void QtCodeFile::clickedMaximizeButton()
return;
}
m_navigator->requestScroll(m_filePath, 0, 0, false, QtCodeNavigateable::SCROLL_VISIBLE);
MessageChangeFileView(
m_filePath,
MessageChangeFileView::FILE_MAXIMIZED,
@@ -502,63 +444,6 @@ void QtCodeFile::clickedMaximizeButton()
).dispatch();
}
void QtCodeFile::enteredTitleBar(QPushButton* button)
{
if (m_minimizeButton->isEnabled())
{
m_minimizeButton->hoverIn();
}
else if (m_snippetButton->isEnabled())
{
m_snippetButton->hoverIn();
}
else if (m_maximizeButton->isEnabled())
{
m_maximizeButton->hoverIn();
}
}
void QtCodeFile::leftTitleBar(QPushButton* button)
{
if (m_minimizeButton->isEnabled())
{
if (m_minimizeButton != button)
{
m_minimizeButton->hoverOut();
}
}
else if (m_snippetButton->isEnabled())
{
if (m_snippetButton != button)
{
m_snippetButton->hoverOut();
}
}
else if (m_maximizeButton->isEnabled())
{
if (m_maximizeButton != button)
{
m_maximizeButton->hoverOut();
}
}
}
void QtCodeFile::clickedTitleBar()
{
if (m_minimizeButton->isEnabled())
{
clickedMinimizeButton();
}
else if (m_snippetButton->isEnabled())
{
clickedSnippetButton();
}
else
{
clickedMaximizeButton();
}
}
void QtCodeFile::updateRefCount(int refCount)
{
if (refCount > 0 && !m_isWholeFile)
@@ -580,11 +465,10 @@ void QtCodeFile::updateRefCount(int refCount)
}
}
m_referenceCount->setText(QString::number(refCount) + " " + label);
m_referenceCount->show();
m_titleBar->setRefString(QString::number(refCount) + " " + label);
}
else
{
m_referenceCount->hide();
m_titleBar->setRefString("");
}
}
+5 -19
View File
@@ -10,12 +10,9 @@
#include "utility/file/FilePath.h"
#include "component/view/helper/CodeSnippetParams.h"
#include "qt/element/QtIconButton.h"
class QLabel;
class QPushButton;
class QtCodeArea;
class QtCodeFileTitleButton;
class QtCodeFileTitleBar;
class QtCodeNavigator;
class QtCodeSnippet;
class QVBoxLayout;
@@ -35,9 +32,12 @@ public:
const FilePath& getFilePath() const;
std::string getFileName() const;
const QtCodeFileTitleBar* getTitleBar() const;
QtCodeSnippet* addCodeSnippet(const CodeSnippetParams& params);
QtCodeSnippet* insertCodeSnippet(const CodeSnippetParams& params);
std::vector<QtCodeSnippet*> getVisibleSnippets() const;
QtCodeSnippet* getSnippetForLocationId(Id locationId) const;
QtCodeSnippet* getSnippetForLine(unsigned int line) const;
QtCodeSnippet* getFileSnippet() const;
@@ -67,33 +67,19 @@ public slots:
void clickedSnippetButton();
void clickedMaximizeButton();
void enteredTitleBar(QPushButton* button);
void leftTitleBar(QPushButton* button);
private slots:
void clickedTitleBar();
private:
void updateRefCount(int refCount);
QtCodeNavigator* m_navigator;
QPushButton* m_titleBar;
QtCodeFileTitleButton* m_title;
QLabel* m_referenceCount;
QtIconStateButton* m_minimizeButton;
QtIconStateButton* m_snippetButton;
QtIconStateButton* m_maximizeButton;
QtCodeFileTitleBar* m_titleBar;
QVBoxLayout* m_snippetLayout;
std::vector<std::shared_ptr<QtCodeSnippet>> m_snippets;
std::shared_ptr<QtCodeSnippet> m_fileSnippet;
const FilePath m_filePath;
bool m_isWholeFile;
bool m_isCollapsed;
mutable bool m_contentRequested;
};
+206 -17
View File
@@ -4,33 +4,58 @@
#include <QVBoxLayout>
#include "utility/file/FilePath.h"
#include "utility/utilityApp.h"
#include "data/location/SourceLocationFile.h"
#include "qt/element/QtCodeFile.h"
#include "qt/element/QtCodeFileTitleBar.h"
#include "qt/element/QtCodeNavigator.h"
#include "qt/element/QtCodeSnippet.h"
QtCodeFileList::QtCodeFileList(QtCodeNavigator* navigator)
: QScrollArea()
: QFrame()
, m_navigator(navigator)
, m_mirroredTitleBar(nullptr)
, m_mirroredSnippetScrollBar(nullptr)
{
setObjectName("code_container");
setWidgetResizable(true);
m_scrollArea = new QScrollArea();
m_scrollArea->setObjectName("code_container");
m_scrollArea->setWidgetResizable(true);
m_filesArea = new QFrame();
m_filesArea->setObjectName("code_file_list");
QVBoxLayout* innerLayout = new QVBoxLayout();
innerLayout->setSpacing(8);
innerLayout->setContentsMargins(8, 8, 8, 8);
innerLayout->setAlignment(Qt::AlignTop);
m_filesArea->setLayout(innerLayout);
m_scrollArea->setWidget(m_filesArea);
m_firstSnippetTitleBar = new QtCodeFileTitleBar(m_scrollArea, true);
m_firstSnippetTitleBar->hide();
m_lastSnippetScrollBar = new QScrollBar(Qt::Horizontal, m_scrollArea);
if (utility::getOsType() != OS_MAC) // don't manipulate scrollbar style on macOS
{
m_lastSnippetScrollBar->setObjectName("last_scroll_bar");
}
m_lastSnippetScrollBar->hide();
connect(m_lastSnippetScrollBar, &QScrollBar::valueChanged, this, &QtCodeFileList::scrollLastSnippet);
QVBoxLayout* layout = new QVBoxLayout();
layout->setSpacing(8);
layout->setContentsMargins(8, 8, 8, 8);
layout->setAlignment(Qt::AlignTop);
m_filesArea->setLayout(layout);
layout->setSpacing(0);
layout->setContentsMargins(0, 0, 0, 0);
layout->addWidget(m_scrollArea);
setLayout(layout);
setWidget(m_filesArea);
m_scrollSpeedChangeListener.setScrollBar(m_scrollArea->verticalScrollBar());
m_scrollSpeedChangeListener.setScrollBar(verticalScrollBar());
connect(verticalScrollBar(), &QScrollBar::valueChanged, m_navigator, &QtCodeNavigator::scrolled);
connect(m_scrollArea->verticalScrollBar(), &QScrollBar::valueChanged, this, &QtCodeFileList::updateSnippetTitleAndScrollBar);
connect(m_scrollArea->verticalScrollBar(), &QScrollBar::valueChanged, m_navigator, &QtCodeNavigator::scrolled);
}
QtCodeFileList::~QtCodeFileList()
@@ -45,7 +70,10 @@ void QtCodeFileList::clear()
}
m_files.clear();
verticalScrollBar()->setValue(0);
m_scrollArea->verticalScrollBar()->setValue(0);
updateFirstSnippetTitleBar(nullptr);
updateLastSnippetScrollBar(nullptr);
}
QtCodeFile* QtCodeFileList::getFile(const FilePath filePath)
@@ -83,7 +111,7 @@ void QtCodeFileList::addFile(const FilePath& filePath, bool isWholeFile, int ref
QScrollArea* QtCodeFileList::getScrollArea()
{
return this;
return m_scrollArea;
}
void QtCodeFileList::addCodeSnippet(const CodeSnippetParams& params)
@@ -108,7 +136,7 @@ void QtCodeFileList::requestFileContent(const FilePath& filePath)
getFile(filePath)->requestContent();
}
bool QtCodeFileList::requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop)
bool QtCodeFileList::requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, ScrollTarget target)
{
QtCodeFile* file = getFile(filePath);
if (!file)
@@ -132,19 +160,21 @@ bool QtCodeFileList::requestScroll(const FilePath& filePath, uint lineNumber, Id
{
snippet = file->getSnippetForLine(lineNumber);
}
else
else if (file->getFileSnippet() && file->getFileSnippet()->isVisible())
{
snippet = file->getFileSnippet();
}
if (!snippet)
{
ensureWidgetVisibleAnimated(m_filesArea, file->getTitleBar(), QRect(), animated, target);
return true;
}
if (!snippet->isVisible())
{
file->setSnippets();
return true;
}
uint endLineNumber = 0;
@@ -173,8 +203,7 @@ bool QtCodeFileList::requestScroll(const FilePath& filePath, uint lineNumber, Id
lineRect |= snippet->getLineRectForLineNumber(endLineNumber);
}
ensureWidgetVisibleAnimated(m_filesArea, snippet, lineRect, animated, onTop);
ensureWidgetVisibleAnimated(m_filesArea, snippet, lineRect, animated, target);
return true;
}
@@ -184,6 +213,8 @@ void QtCodeFileList::updateFiles()
{
file->updateContent();
}
updateSnippetTitleAndScrollBar();
}
void QtCodeFileList::showContents()
@@ -200,6 +231,11 @@ void QtCodeFileList::onWindowFocus()
{
file->updateTitleBar();
}
if (m_firstSnippetTitleBar->isVisible())
{
m_firstSnippetTitleBar->getTitleButton()->updateTexts();
}
}
void QtCodeFileList::findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches)
@@ -245,3 +281,156 @@ std::pair<QtCodeSnippet*, Id> QtCodeFileList::getFirstSnippetWithActiveLocationI
return result;
}
void QtCodeFileList::resizeEvent(QResizeEvent* event)
{
updateFirstSnippetTitleBar(nullptr);
updateLastSnippetScrollBar(nullptr);
updateSnippetTitleAndScrollBar();
}
void QtCodeFileList::updateSnippetTitleAndScrollBar(int value)
{
QtCodeFile* firstFile = nullptr;
QScrollBar* lastSnippetScrollBar = nullptr;
int fileTitleBarOffset = 0;
const QRect visibleRect(-m_filesArea->pos(), m_scrollArea->viewport()->size());
for (QtCodeFile* file : m_files)
{
QRect fileRect = getFocusRectForWidget(file, m_filesArea);
if (!firstFile && visibleRect.top() > fileRect.top() + 2 &&
visibleRect.top() < fileRect.bottom() - 10 &&
file->getVisibleSnippets().size())
{
firstFile = file;
fileTitleBarOffset = std::min(0, fileRect.bottom() - 10 - (visibleRect.top() + m_firstSnippetTitleBar->height()));
}
if (visibleRect.bottom() > fileRect.top() && fileRect.bottom() > visibleRect.bottom())
{
for (QtCodeSnippet* snippet : file->getVisibleSnippets())
{
QScrollBar* scrollbar = snippet->getArea()->horizontalScrollBar();
if (!scrollbar || scrollbar->minimum() == scrollbar->maximum())
{
continue;
}
QRect snippetRect = getFocusRectForWidget(snippet, m_filesArea);
if (visibleRect.bottom() > snippetRect.top() + scrollbar->height() &&
snippetRect.bottom() - scrollbar->height() > visibleRect.bottom())
{
lastSnippetScrollBar = scrollbar;
break;
}
}
}
if (lastSnippetScrollBar)
{
break;
}
}
updateFirstSnippetTitleBar(firstFile, fileTitleBarOffset);
updateLastSnippetScrollBar(lastSnippetScrollBar);
}
void QtCodeFileList::scrollLastSnippet(int value)
{
if (m_mirroredSnippetScrollBar && m_mirroredSnippetScrollBar->value() != value)
{
m_mirroredSnippetScrollBar->setValue(value);
}
}
void QtCodeFileList::scrollLastSnippetScrollBar(int value)
{
if (m_lastSnippetScrollBar->value() != value)
{
m_lastSnippetScrollBar->setValue(value);
}
}
void QtCodeFileList::updateFirstSnippetTitleBar(const QtCodeFile* file, int fileTitleBarOffset)
{
const QtCodeFileTitleBar* mirroredTitleBar = file ? file->getTitleBar() : nullptr;
if (m_mirroredTitleBar != mirroredTitleBar)
{
m_mirroredTitleBar = mirroredTitleBar;
if (m_mirroredTitleBar && file)
{
m_firstSnippetTitleBar->updateFromOther(mirroredTitleBar);
connect(m_firstSnippetTitleBar, &QtCodeFileTitleBar::minimize, file, &QtCodeFile::clickedMinimizeButton);
connect(m_firstSnippetTitleBar, &QtCodeFileTitleBar::snippet, file, &QtCodeFile::clickedSnippetButton);
connect(m_firstSnippetTitleBar, &QtCodeFileTitleBar::maximize, file, &QtCodeFile::clickedMaximizeButton);
m_firstSnippetTitleBar->setGeometry(
file->pos().x() + mirroredTitleBar->pos().x(),
0,
mirroredTitleBar->width(),
mirroredTitleBar->height()
);
m_firstSnippetTitleBar->show();
}
else
{
m_firstSnippetTitleBar->hide();
}
}
if (m_firstSnippetTitleBar->isVisible())
{
QRect rect = m_firstSnippetTitleBar->geometry();
int height = rect.height();
if (fileTitleBarOffset != rect.y())
{
rect.setY(fileTitleBarOffset);
rect.setHeight(height);
m_firstSnippetTitleBar->setGeometry(rect);
m_firstSnippetTitleBar->update();
}
}
}
void QtCodeFileList::updateLastSnippetScrollBar(QScrollBar* mirroredScrollBar)
{
if (m_mirroredSnippetScrollBar != mirroredScrollBar)
{
if (m_mirroredSnippetScrollBar)
{
m_mirroredSnippetScrollBar->disconnect(this);
}
m_mirroredSnippetScrollBar = mirroredScrollBar;
if (mirroredScrollBar)
{
connect(mirroredScrollBar, &QScrollBar::valueChanged, this, &QtCodeFileList::scrollLastSnippetScrollBar);
m_lastSnippetScrollBar->setMinimum(mirroredScrollBar->minimum());
m_lastSnippetScrollBar->setMaximum(mirroredScrollBar->maximum());
m_lastSnippetScrollBar->setValue(mirroredScrollBar->value());
m_lastSnippetScrollBar->setPageStep(mirroredScrollBar->pageStep());
m_lastSnippetScrollBar->setSingleStep(mirroredScrollBar->singleStep());
m_lastSnippetScrollBar->setGeometry(
mirroredScrollBar->mapTo(m_scrollArea, mirroredScrollBar->pos()).x(),
m_scrollArea->viewport()->size().height() - mirroredScrollBar->height(),
mirroredScrollBar->width(),
mirroredScrollBar->height()
);
m_lastSnippetScrollBar->show();
}
else
{
m_lastSnippetScrollBar->hide();
}
}
}
+21 -2
View File
@@ -11,11 +11,12 @@
#include "qt/utility/QtScrollSpeedChangeListener.h"
class QtCodeFile;
class QtCodeFileTitleBar;
class QtCodeNavigator;
class QtCodeSnippet;
class QtCodeFileList
: public QScrollArea
: public QFrame
, public QtCodeNavigateable
{
Q_OBJECT
@@ -35,7 +36,7 @@ public:
virtual void addCodeSnippet(const CodeSnippetParams& params);
virtual void requestFileContent(const FilePath& filePath);
virtual bool requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop);
virtual bool requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, ScrollTarget target);
virtual void updateFiles();
virtual void showContents();
@@ -50,12 +51,30 @@ public:
std::pair<QtCodeSnippet*, Id> getFirstSnippetWithActiveLocationId(Id tokenId) const;
protected:
virtual void resizeEvent(QResizeEvent* event);
private slots:
void updateSnippetTitleAndScrollBar(int value = 0);
void scrollLastSnippet(int value);
void scrollLastSnippetScrollBar(int value);
private:
void updateFirstSnippetTitleBar(const QtCodeFile* file, int fileTitleBarOffset = 0);
void updateLastSnippetScrollBar(QScrollBar* mirroredScrollBar);
QtCodeNavigator* m_navigator;
QScrollArea* m_scrollArea;
QFrame* m_filesArea;
std::vector<QtCodeFile*> m_files;
QtCodeFileTitleBar* m_firstSnippetTitleBar;
const QtCodeFileTitleBar* m_mirroredTitleBar;
QScrollBar* m_lastSnippetScrollBar;
QScrollBar* m_mirroredSnippetScrollBar;
QtScrollSpeedChangeListener m_scrollSpeedChangeListener;
};
+3 -2
View File
@@ -166,7 +166,8 @@ void QtCodeFileSingle::requestFileContent(const FilePath& filePath)
).dispatch();
}
bool QtCodeFileSingle::requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop)
bool QtCodeFileSingle::requestScroll(
const FilePath& filePath, uint lineNumber, Id locationId, bool animated, ScrollTarget target)
{
FileData file = getFileData(filePath);
if (file.area)
@@ -207,7 +208,7 @@ bool QtCodeFileSingle::requestScroll(const FilePath& filePath, uint lineNumber,
double percentA = double(lineNumber - 1) / m_area->getEndLineNumber();
double percentB = endLineNumber ? double(endLineNumber - 1) / m_area->getEndLineNumber() : 0.0f;
ensurePercentVisibleAnimated(percentA, percentB, animated, onTop);
ensurePercentVisibleAnimated(percentA, percentB, animated, target);
m_scrollRequested = true;
+4 -2
View File
@@ -36,14 +36,16 @@ public:
virtual void addCodeSnippet(const CodeSnippetParams& params) override;
virtual void requestFileContent(const FilePath& filePath) override;
virtual bool requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop) override;
virtual bool requestScroll(
const FilePath& filePath, uint lineNumber, Id locationId, bool animated, ScrollTarget target) override;
virtual void updateFiles() override;
virtual void showContents() override;
virtual void onWindowFocus() override;
virtual void findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches) override;
virtual void findScreenMatches(
const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches) override;
const FilePath& getCurrentFilePath() const;
bool hasFileCached(const FilePath& filePath) const;
@@ -0,0 +1,230 @@
#include "qt/element/QtCodeFileTitleBar.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QVariant>
#include "utility/ResourcePaths.h"
QtCodeFileTitleBar::QtCodeFileTitleBar(QWidget* parent, bool isHovering)
: QtHoverButton(parent)
{
setObjectName("title_widget");
setProperty("hovering", isHovering);
setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
QHBoxLayout* titleLayout = new QHBoxLayout();
titleLayout->setMargin(0);
titleLayout->setSpacing(0);
titleLayout->setAlignment(Qt::AlignLeft);
setLayout(titleLayout);
m_titleButton = new QtCodeFileTitleButton(this);
titleLayout->addWidget(m_titleButton);
setMinimumHeight(m_titleButton->height() + 4);
m_referenceCount = new QLabel(this);
m_referenceCount->setObjectName("references_label");
m_referenceCount->hide();
titleLayout->addWidget(m_referenceCount);
titleLayout->addStretch(3);
std::string imageDir = ResourcePaths::getGuiPath().str() + "code_view/images/";
m_minimizeButton = new QtIconStateButton(this);
m_minimizeButton->addState(QtIconStateButton::STATE_DEFAULT, (imageDir + "minimize_active.png").c_str());
// m_minimizeButton->addState(QtIconStateButton::STATE_HOVERED, (imageDir + "minimize_inactive.png").c_str(), "#5E5D5D");
m_minimizeButton->addState(QtIconStateButton::STATE_HOVERED, (imageDir + "minimize_inactive.png").c_str(), QColor(0x5E, 0x5D, 0x5D));
m_minimizeButton->addState(QtIconStateButton::STATE_DISABLED, (imageDir + "minimize_inactive.png").c_str());
m_minimizeButton->setIconSize(QSize(16, 16));
m_minimizeButton->setObjectName("file_button");
m_minimizeButton->setToolTip("minimize");
titleLayout->addWidget(m_minimizeButton);
m_snippetButton = new QtIconStateButton(this);
m_snippetButton->addState(QtIconStateButton::STATE_DEFAULT, (imageDir + "snippet_active.png").c_str());
// m_snippetButton->addState(QtIconStateButton::STATE_HOVERED, (imageDir + "snippet_inactive.png").c_str(), "#5E5D5D");
m_snippetButton->addState(QtIconStateButton::STATE_HOVERED, (imageDir + "snippet_inactive.png").c_str(), QColor(0x5E, 0x5D, 0x5D));
m_snippetButton->addState(QtIconStateButton::STATE_DISABLED, (imageDir + "snippet_inactive.png").c_str());
m_snippetButton->setIconSize(QSize(16, 16));
m_snippetButton->setObjectName("file_button");
m_snippetButton->setToolTip("show snippets");
titleLayout->addWidget(m_snippetButton);
m_maximizeButton = new QtIconStateButton(this);
m_maximizeButton->addState(QtIconStateButton::STATE_DEFAULT, (imageDir + "maximize_active.png").c_str());
// m_maximizeButton->addState(QtIconStateButton::STATE_HOVERED, (imageDir + "maximize_inactive.png").c_str(), "#5E5D5D");
m_maximizeButton->addState(QtIconStateButton::STATE_HOVERED, (imageDir + "maximize_inactive.png").c_str(), QColor(0x5E, 0x5D, 0x5D));
m_maximizeButton->addState(QtIconStateButton::STATE_DISABLED, (imageDir + "maximize_inactive.png").c_str());
m_maximizeButton->setIconSize(QSize(16, 16));
m_maximizeButton->setObjectName("file_button");
m_maximizeButton->setToolTip("maximize");
titleLayout->addWidget(m_maximizeButton);
titleLayout->addSpacing(3);
connect(this, &QPushButton::clicked, this, &QtCodeFileTitleBar::clickedTitleBar);
connect(this, &QtHoverButton::hoveredIn, this, &QtCodeFileTitleBar::enteredTitleBar);
connect(this, &QtHoverButton::hoveredOut, this, &QtCodeFileTitleBar::leftTitleBar);
connect(m_minimizeButton, &QtIconStateButton::hoveredIn, this, &QtCodeFileTitleBar::leftTitleBar);
connect(m_minimizeButton, &QtIconStateButton::hoveredOut, this, &QtCodeFileTitleBar::enteredTitleBar);
connect(m_minimizeButton, &QtIconStateButton::clicked, this, &QtCodeFileTitleBar::clickedMinimizeButton);
connect(m_snippetButton, &QtIconStateButton::hoveredIn, this, &QtCodeFileTitleBar::leftTitleBar);
connect(m_snippetButton, &QtIconStateButton::hoveredOut, this, &QtCodeFileTitleBar::enteredTitleBar);
connect(m_snippetButton, &QtIconStateButton::clicked, this, &QtCodeFileTitleBar::clickedSnippetButton);
connect(m_maximizeButton, &QtIconStateButton::hoveredIn, this, &QtCodeFileTitleBar::leftTitleBar);
connect(m_maximizeButton, &QtIconStateButton::hoveredOut, this, &QtCodeFileTitleBar::enteredTitleBar);
connect(m_maximizeButton, &QtIconStateButton::clicked, this, &QtCodeFileTitleBar::clickedMaximizeButton);
m_minimizeButton->setEnabled(false);
m_snippetButton->setEnabled(false);
m_maximizeButton->setEnabled(false);
}
QtCodeFileTitleButton* QtCodeFileTitleBar::getTitleButton() const
{
return m_titleButton;
}
void QtCodeFileTitleBar::setRefString(const QString& refString)
{
if (refString.size())
{
m_referenceCount->setText(refString);
m_referenceCount->show();
}
else
{
m_referenceCount->hide();
}
}
void QtCodeFileTitleBar::setMinimized(bool hasSnippets)
{
m_minimizeButton->setEnabled(false);
m_snippetButton->setEnabled(hasSnippets);
m_maximizeButton->setEnabled(true);
m_minimizeButton->hoverOut();
m_snippetButton->hoverOut();
m_maximizeButton->hoverOut();
}
void QtCodeFileTitleBar::setSnippets()
{
m_minimizeButton->setEnabled(true);
m_snippetButton->setEnabled(false);
m_maximizeButton->setEnabled(true);
m_minimizeButton->hoverOut();
m_snippetButton->hoverOut();
m_maximizeButton->hoverOut();
}
void QtCodeFileTitleBar::setMaximized(bool hasSnippets)
{
m_minimizeButton->setEnabled(true);
m_snippetButton->setEnabled(hasSnippets);
m_maximizeButton->setEnabled(false);
m_minimizeButton->hoverOut();
m_snippetButton->hoverOut();
m_maximizeButton->hoverOut();
}
void QtCodeFileTitleBar::updateFromOther(const QtCodeFileTitleBar* other)
{
m_titleButton->updateFromOther(other->getTitleButton());
setRefString(other->m_referenceCount->text());
m_minimizeButton->setEnabled(other->m_minimizeButton->isEnabled());
m_snippetButton->setEnabled(other->m_snippetButton->isEnabled());
m_maximizeButton->setEnabled(other->m_maximizeButton->isEnabled());
m_minimizeButton->hoverOut();
m_snippetButton->hoverOut();
m_maximizeButton->hoverOut();
disconnect();
connect(this, &QPushButton::clicked, this, &QtCodeFileTitleBar::clickedTitleBar);
connect(this, &QtHoverButton::hoveredIn, this, &QtCodeFileTitleBar::enteredTitleBar);
connect(this, &QtHoverButton::hoveredOut, this, &QtCodeFileTitleBar::leftTitleBar);
}
void QtCodeFileTitleBar::clickedTitleBar()
{
if (m_minimizeButton->isEnabled())
{
emit minimize();
}
else if (m_snippetButton->isEnabled())
{
emit snippet();
}
else
{
emit maximize();
}
}
void QtCodeFileTitleBar::enteredTitleBar(QPushButton* button)
{
if (m_minimizeButton->isEnabled())
{
m_minimizeButton->hoverIn();
}
else if (m_snippetButton->isEnabled())
{
m_snippetButton->hoverIn();
}
else if (m_maximizeButton->isEnabled())
{
m_maximizeButton->hoverIn();
}
}
void QtCodeFileTitleBar::leftTitleBar(QPushButton* button)
{
if (m_minimizeButton->isEnabled())
{
if (m_minimizeButton != button)
{
m_minimizeButton->hoverOut();
}
}
else if (m_snippetButton->isEnabled())
{
if (m_snippetButton != button)
{
m_snippetButton->hoverOut();
}
}
else if (m_maximizeButton->isEnabled())
{
if (m_maximizeButton != button)
{
m_maximizeButton->hoverOut();
}
}
}
void QtCodeFileTitleBar::clickedMinimizeButton()
{
emit minimize();
}
void QtCodeFileTitleBar::clickedSnippetButton()
{
emit snippet();
}
void QtCodeFileTitleBar::clickedMaximizeButton()
{
emit maximize();
}
@@ -0,0 +1,53 @@
#ifndef QT_CODE_FILE_TITLE_BAR_H
#define QT_CODE_FILE_TITLE_BAR_H
#include "qt/element/QtCodeFileTitleButton.h"
#include "qt/element/QtIconButton.h"
class QLabel;
class QtCodeFileTitleButton;
class QtIconStateButton;
class QtCodeFileTitleBar
: public QtHoverButton
{
Q_OBJECT
signals:
void minimize();
void snippet();
void maximize();
public:
QtCodeFileTitleBar(QWidget* parent = nullptr, bool isHovering = false);
QtCodeFileTitleButton* getTitleButton() const;
void setRefString(const QString& refString);
void setMinimized(bool hasSnippets);
void setSnippets();
void setMaximized(bool hasSnippets);
void updateFromOther(const QtCodeFileTitleBar* other);
private slots:
void clickedTitleBar();
void enteredTitleBar(QPushButton* button);
void leftTitleBar(QPushButton* button);
void clickedMinimizeButton();
void clickedSnippetButton();
void clickedMaximizeButton();
private:
QtCodeFileTitleButton* m_titleButton;
QLabel* m_referenceCount;
QtIconStateButton* m_minimizeButton;
QtIconStateButton* m_snippetButton;
QtIconStateButton* m_maximizeButton;
};
#endif // QT_CODE_FILE_TITLE_BAR_H
@@ -126,6 +126,21 @@ void QtCodeFileTitleButton::updateTexts()
setToolTip(toolTip.c_str());
}
void QtCodeFileTitleButton::updateFromOther(const QtCodeFileTitleButton* other)
{
if (!other->m_filePath.empty())
{
setFilePath(other->m_filePath);
}
else
{
setProject(other->text().toStdString());
}
setModificationTime(other->m_modificationTime);
setIsComplete(other->m_isComplete);
}
void QtCodeFileTitleButton::contextMenuEvent(QContextMenuEvent* event)
{
FilePath path = m_filePath;
@@ -22,6 +22,8 @@ public:
void updateTexts();
void updateFromOther(const QtCodeFileTitleButton* other);
protected:
void contextMenuEvent(QContextMenuEvent* event);
+84 -47
View File
@@ -11,7 +11,7 @@ QtCodeNavigateable::~QtCodeNavigateable()
}
void QtCodeNavigateable::ensureWidgetVisibleAnimated(
QWidget* parentWidget, QWidget *childWidget, QRectF rect, bool animated, bool onTop)
const QWidget* parentWidget, const QWidget *childWidget, QRectF rect, bool animated, ScrollTarget target)
{
QAbstractScrollArea* area = getScrollArea();
if (!area || !parentWidget->isAncestorOf(childWidget))
@@ -19,11 +19,7 @@ void QtCodeNavigateable::ensureWidgetVisibleAnimated(
return;
}
const QRect microFocus = childWidget->inputMethodQuery(Qt::ImCursorRectangle).toRect();
const QRect defaultMicroFocus = childWidget->QWidget::inputMethodQuery(Qt::ImCursorRectangle).toRect();
QRect focusRect = (microFocus != defaultMicroFocus)
? QRect(childWidget->mapTo(parentWidget, microFocus.topLeft()), microFocus.size())
: QRect(childWidget->mapTo(parentWidget, QPoint(0, 0)), childWidget->size());
QRect focusRect = getFocusRectForWidget(childWidget, parentWidget);
const QRect visibleRect(-parentWidget->pos(), area->viewport()->size());
if (rect.height() > 0)
@@ -36,15 +32,42 @@ void QtCodeNavigateable::ensureWidgetVisibleAnimated(
}
}
QScrollBar* scrollBar = area->verticalScrollBar();
int value = focusRect.center().y() - visibleRect.center().y();
if (onTop || focusRect.height() > visibleRect.height())
// scroll to top if widget is bigger than view
if (focusRect.height() > visibleRect.height())
{
value = focusRect.top() - visibleRect.top() - 20;
target = SCROLL_TOP;
}
if (scrollBar && (value > 50 || value < -50))
int value = 0;
switch (target)
{
case SCROLL_VISIBLE:
if (focusRect.top() < visibleRect.top())
{
value = focusRect.top() - visibleRect.top() - 20;
}
else if (focusRect.bottom() > visibleRect.bottom())
{
value = focusRect.bottom() - visibleRect.bottom() + 20;
}
break;
case SCROLL_CENTER:
value = focusRect.center().y() - visibleRect.center().y();
if (abs(value) < 50)
{
value = 0;
}
break;
case SCROLL_TOP:
value = focusRect.top() - visibleRect.top() - 50;
break;
}
QScrollBar* scrollBar = area->verticalScrollBar();
if (scrollBar && value)
{
if (animated && ApplicationSettings::getInstance()->getUseAnimations())
{
@@ -62,7 +85,7 @@ void QtCodeNavigateable::ensureWidgetVisibleAnimated(
}
}
void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double percentB, bool animated, bool onTop)
void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double percentB, bool animated, ScrollTarget target)
{
QAbstractScrollArea* area = getScrollArea();
if (!area)
@@ -78,45 +101,43 @@ void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double pe
return;
}
int scrollHeight = totalHeight * percentA;
if (!onTop)
{
if (percentB)
{
int scrollHeightB = totalHeight * percentB;
int rectHeight = scrollHeightB - scrollHeight;
if (rectHeight < visibleHeight)
{
if (rectHeight < visibleHeight / 2)
{
scrollHeight -= visibleHeight / 4;
}
else
{
scrollHeight += rectHeight / 2 - visibleHeight / 2;
}
}
else
{
scrollHeight -= 20;
}
}
else
{
scrollHeight -= visibleHeight / 4;
}
}
else
{
scrollHeight -= 20;
}
QScrollBar* scrollBar = area->verticalScrollBar();
double scrollFactor = double(scrollBar->maximum()) / scrollableHeight;
int value = scrollHeight * scrollFactor;
int visibleY = double(scrollBar->value()) / scrollFactor;
int scrollY = totalHeight * percentA;
int rectHeight = percentB ? (totalHeight * percentB) - scrollY : 0;
if (rectHeight > visibleHeight)
{
target = SCROLL_TOP;
}
switch (target)
{
case SCROLL_VISIBLE:
if (scrollY > visibleY && scrollY + rectHeight < visibleY + scrollableHeight)
{
return;
}
case SCROLL_CENTER:
if (rectHeight < visibleHeight / 2)
{
scrollY -= visibleHeight / 4;
}
else
{
scrollY += rectHeight / 2 - visibleHeight / 2;
}
break;
case SCROLL_TOP:
scrollY -= 20;
break;
}
int value = scrollY * scrollFactor;
int diff = value - scrollBar->value();
if (diff > 5 || diff < -5)
{
@@ -135,3 +156,19 @@ void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double pe
}
}
}
QRect QtCodeNavigateable::getFocusRectForWidget(const QWidget* childWidget, const QWidget* parentWidget) const
{
const QRect microFocus = childWidget->inputMethodQuery(Qt::ImCursorRectangle).toRect();
const QRect defaultMicroFocus = childWidget->QWidget::inputMethodQuery(Qt::ImCursorRectangle).toRect();
if (microFocus != defaultMicroFocus)
{
return QRect(childWidget->mapTo(parentWidget, microFocus.topLeft()), microFocus.size());
}
else
{
return QRect(childWidget->mapTo(parentWidget, QPoint(0, 0)), childWidget->size());
}
}
+13 -3
View File
@@ -10,12 +10,20 @@
class FilePath;
class QRectF;
class QAbstractScrollArea;
class QRect;
class QtCodeArea;
class QWidget;
class QtCodeNavigateable
{
public:
enum ScrollTarget
{
SCROLL_VISIBLE,
SCROLL_CENTER,
SCROLL_TOP
};
virtual ~QtCodeNavigateable();
virtual QAbstractScrollArea* getScrollArea() = 0;
@@ -23,7 +31,7 @@ public:
virtual void addCodeSnippet(const CodeSnippetParams& params) = 0;
virtual void requestFileContent(const FilePath& filePath) = 0;
virtual bool requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop) = 0;
virtual bool requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, ScrollTarget target) = 0;
virtual void updateFiles() = 0;
virtual void showContents() = 0;
@@ -33,8 +41,10 @@ public:
virtual void findScreenMatches(const std::string& query, std::vector<std::pair<QtCodeArea*, Id>>* screenMatches) = 0;
protected:
void ensureWidgetVisibleAnimated(QWidget* parentWidget, QWidget *childWidget, QRectF rect, bool animated, bool onTop);
void ensurePercentVisibleAnimated(double percentA, double percentB, bool animated, bool onTop);
void ensureWidgetVisibleAnimated(const QWidget* parentWidget, const QWidget *childWidget, QRectF rect, bool animated, ScrollTarget target);
void ensurePercentVisibleAnimated(double percentA, double percentB, bool animated, ScrollTarget target);
QRect getFocusRectForWidget(const QWidget* childWidget, const QWidget* parentWidget) const;
};
#endif // QT_CODE_NAVIGATEABLE_H
+21 -14
View File
@@ -451,7 +451,7 @@ void QtCodeNavigator::showActiveSnippet(
{
if (scrollTo)
{
requestScroll(firstReference.filePath, 0, firstReference.locationId, true, false);
requestScroll(firstReference.filePath, 0, firstReference.locationId, true, QtCodeNavigateable::SCROLL_CENTER);
emit scrollRequest();
}
@@ -569,7 +569,8 @@ void QtCodeNavigator::activateScreenMatch(size_t matchIndex)
m_currentActiveLocationIds.insert(m_activeScreenMatchId);
p.first->updateContent();
requestScroll(p.first->getSourceLocationFile()->getFilePath(), 0, m_activeScreenMatchId, true, false);
requestScroll(
p.first->getSourceLocationFile()->getFilePath(), 0, m_activeScreenMatchId, true, QtCodeNavigateable::SCROLL_CENTER);
emit scrollRequest();
}
@@ -614,7 +615,7 @@ void QtCodeNavigator::scrollToValue(int value, bool inListMode)
void QtCodeNavigator::scrollToLine(const FilePath& filePath, unsigned int line)
{
requestScroll(filePath, line, 0, false, false);
requestScroll(filePath, line, 0, false, QtCodeNavigateable::SCROLL_CENTER);
emit scrollRequest();
}
@@ -634,7 +635,7 @@ void QtCodeNavigator::scrollToDefinition(bool animated, bool ignoreActiveReferen
m_list->requestFileContent(m_activeReference.filePath);
}
requestScroll(m_activeReference.filePath, 0, m_activeReference.locationId, true, false);
requestScroll(m_activeReference.filePath, 0, m_activeReference.locationId, true, QtCodeNavigateable::SCROLL_CENTER);
emit scrollRequest();
updateRefLabel();
@@ -651,7 +652,8 @@ void QtCodeNavigator::scrollToDefinition(bool animated, bool ignoreActiveReferen
{
if (m_references.size() && m_references.front().locationType != LOCATION_TOKEN)
{
requestScroll(m_references.front().filePath, 0, m_references.front().locationId, false, false);
requestScroll(
m_references.front().filePath, 0, m_references.front().locationId, false, QtCodeNavigateable::SCROLL_CENTER);
emit scrollRequest();
}
return;
@@ -662,7 +664,8 @@ void QtCodeNavigator::scrollToDefinition(bool animated, bool ignoreActiveReferen
std::pair<QtCodeSnippet*, Id> result = m_list->getFirstSnippetWithActiveLocationId(m_activeTokenId);
if (result.first != nullptr)
{
requestScroll(result.first->getFile()->getFilePath(), 0, result.second, animated, false);
requestScroll(
result.first->getFile()->getFilePath(), 0, result.second, animated, QtCodeNavigateable::SCROLL_CENTER);
emit scrollRequest();
return;
}
@@ -672,7 +675,7 @@ void QtCodeNavigator::scrollToDefinition(bool animated, bool ignoreActiveReferen
Id locationId = m_single->getLocationIdOfFirstActiveLocationOfTokenId(m_activeTokenId);
if (locationId)
{
requestScroll(m_single->getCurrentFilePath(), 0, locationId, true, false);
requestScroll(m_single->getCurrentFilePath(), 0, locationId, true, QtCodeNavigateable::SCROLL_CENTER);
emit scrollRequest();
return;
}
@@ -681,7 +684,7 @@ void QtCodeNavigator::scrollToDefinition(bool animated, bool ignoreActiveReferen
if (m_references.size())
{
m_current->requestFileContent(m_references.front().filePath);
requestScroll(m_references.front().filePath, 0, m_references.front().locationId, false, false);
requestScroll(m_references.front().filePath, 0, m_references.front().locationId, false, QtCodeNavigateable::SCROLL_CENTER);
emit scrollRequest();
}
}
@@ -691,14 +694,15 @@ void QtCodeNavigator::scrollToSnippetIfRequested()
emit scrollRequest();
}
void QtCodeNavigator::requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop)
void QtCodeNavigator::requestScroll(
const FilePath& filePath, uint lineNumber, Id locationId, bool animated, QtCodeNavigateable::ScrollTarget target)
{
ScrollRequest req;
req.filePath = filePath;
req.lineNumber = lineNumber;
req.locationId = locationId;
req.animated = animated;
req.onTop = onTop;
req.target = target;
if (m_mode == MODE_SINGLE)
{
@@ -709,9 +713,9 @@ void QtCodeNavigator::requestScroll(const FilePath& filePath, uint lineNumber, I
}
// std::cout << "scroll request: " << req.filePath.str() << " " << req.lineNumber << " " << req.locationId;
// std::cout << " " << req.animated << " " << req.onTop << std::endl;
// std::cout << " " << req.animated << " " << req.target << std::endl;
if ((!m_scrollRequest.lineNumber || !m_scrollRequest.locationId) && (req.lineNumber || req.locationId))
if ((!m_scrollRequest.lineNumber || !m_scrollRequest.locationId) && !req.filePath.empty())
{
m_scrollRequest = req;
}
@@ -727,7 +731,10 @@ void QtCodeNavigator::handleScrollRequest()
return;
}
bool done = m_current->requestScroll(req.filePath, req.lineNumber, req.locationId, req.animated, req.onTop);
// std::cout << "handle scroll request: " << req.filePath.str() << " " << req.lineNumber << " " << req.locationId;
// std::cout << " " << req.animated << " " << req.target << std::endl;
bool done = m_current->requestScroll(req.filePath, req.lineNumber, req.locationId, req.animated, req.target);
if (done)
{
m_scrollRequest = ScrollRequest();
@@ -907,7 +914,7 @@ void QtCodeNavigator::handleMessage(MessageShowReference* message)
setCurrentActiveLocationIds(std::vector<Id>(1, ref.locationId));
updateFiles();
requestScroll(ref.filePath, 0, ref.locationId, true, false);
requestScroll(ref.filePath, 0, ref.locationId, true, QtCodeNavigateable::SCROLL_CENTER);
emit scrollRequest();
if (ref.locationType == LOCATION_ERROR)
+4 -3
View File
@@ -94,7 +94,8 @@ public:
void scrollToSnippetIfRequested();
void requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop);
void requestScroll(
const FilePath& filePath, uint lineNumber, Id locationId, bool animated, QtCodeNavigateable::ScrollTarget target);
signals:
void scrollRequest();
@@ -146,7 +147,7 @@ private:
: lineNumber(0)
, locationId(0)
, animated(false)
, onTop(false)
, target(QtCodeNavigateable::SCROLL_VISIBLE)
{
}
@@ -155,7 +156,7 @@ private:
Id locationId;
bool animated;
bool onTop;
QtCodeNavigateable::ScrollTarget target;
};
void handleMessage(MessageCodeReference* message);
+2 -2
View File
@@ -203,7 +203,7 @@ void QtCodeSnippet::clickedTitle()
getFile()->clickedMaximizeButton();
}
m_navigator->requestScroll(getFile()->getFilePath(), getStartLineNumber(), 0, true, false);
m_navigator->requestScroll(getFile()->getFilePath(), getStartLineNumber(), 0, true, QtCodeNavigateable::SCROLL_CENTER);
}
void QtCodeSnippet::clickedFooter()
@@ -212,7 +212,7 @@ void QtCodeSnippet::clickedFooter()
{
MessageShowScope(m_footerId, m_navigator->hasErrors()).dispatch();
m_navigator->requestScroll(getFile()->getFilePath(), getEndLineNumber(), 0, true, false);
m_navigator->requestScroll(getFile()->getFilePath(), getEndLineNumber(), 0, true, QtCodeNavigateable::SCROLL_CENTER);
}
}