ui: Added single file mode to code view

* Added navigation to top of code view for iterating references and switching between list and single file mode
* current file name and reference count is shown on top in single file mode
* refactored scrolling to location or line via request system
* added parameters animated and toTop to scrolling system
* refactored class hierarchy and removed unused stuff in list mode
This commit is contained in:
Eberhard Graether
2017-01-09 00:48:20 +01:00
parent 79937b21f0
commit 2bdc9b19a2
34 changed files with 1472 additions and 530 deletions
@@ -72,6 +72,7 @@
<code>
<background>#494949</background>
<line>#CCCCCC</line>
<file>
<background>#CCCCCC</background>
+1
View File
@@ -72,6 +72,7 @@
<code>
<background>white</background>
<line>#B2B2B2</line>
<file>
<background>#E0E0E0</background>
+1
View File
@@ -72,6 +72,7 @@
<code>
<background>#272728</background>
<line>#CCC</line>
<file>
<background>#777777</background>
+89 -4
View File
@@ -1,7 +1,69 @@
#code_container, #code_file_list {
#code_navigation, #code_container, #code_container_single, #code_file_list, #code_file_single {
background-color: <color:code/background>;
}
#code_container, #code_file_list {
border: none;
}
#code_container {
border-top: 1px solid <color:code/line>;
}
#code_navigation * {
color: <color:code/file/title/text>;
font-size: <setting:font_size>px;
}
#code_navigation QPushButton {
background: <color:search/button/normal>;
border: none;
color: <color:search/button/icon>;
height: 24px;
width: 24px;
}
#code_navigation QPushButton:hover, #code_navigation QPushButton:checked {
background: <color:search/button/hover>;
}
#code_navigation QPushButton:disabled {
background: <color:search/button/disabled>;
}
#code_navigation QPushButton:pressed {
background: <color:search/button/press>;
}
#code_navigation #reference_button_previous, #code_navigation #reference_button_next {
border-radius: 12px;
}
#code_navigation #references_label {
background-color: <color:code/file/ref_count/background>;
border: none;
border-radius: 10px;
color: <color:code/file/ref_count/text>;
font-size: <setting:font_size>px;
padding: 0px 3px;
margin: 4px 6px 4px 6px;
}
#code_navigation #mode_button_list, #code_navigation #mode_button_single {
padding-left: 3px;
padding-right: 3px;
}
#code_navigation #mode_button_list {
border-bottom-left-radius: 12px;
border-top-left-radius: 12px;
}
#code_navigation #mode_button_single {
border-bottom-right-radius: 12px;
border-top-right-radius: 12px;
}
#code_file {
background-color: <color:code/snippet/background>;
border: 2px solid <color:code/file/background>;
@@ -38,14 +100,14 @@
background-color: <color:code/file/title/press>;
}
#code_file #references_label {
#code_file #references_label, #single_file_title_bar #references_label {
background-color: <color:code/file/ref_count/background>;
border: none;
border-radius: 10px;
color: <color:code/file/ref_count/text>;
font-size: <setting:font_size-2>px;
padding: 0px 3px;
margin: 4px 0px 4px;
margin: 4px 6px 4px 0px;
}
#code_file #code_snippet {
@@ -82,7 +144,7 @@
text-align: left;
}
#code_file #code_snippet #line_number_area {
#line_number_area {
background-color: <color:code/snippet/line_number/background>;
border: none;
color: <color:code/snippet/line_number/text>;
@@ -128,3 +190,26 @@
#code_file #minimize_button:enabled {
border-image: url(<setting:gui_path>code_view/images/minimize_active.png);
}
#single_file_title_bar {
background-color: <color:code/file/background>;
padding-right: 5px;
}
#single_file_title_bar #file_title {
background-color: <color:code/file/title/normal>;
border: none;
border-radius: 3px;
color: <color:code/file/title/text>;
font-size: <setting:font_size>px;
padding: 2px 4px;
margin: 3px 8px;
}
#single_file_title_bar #file_title:hover {
background-color: <color:code/file/title/hover>;
}
#single_file_title_bar #file_title:pressed {
background-color: <color:code/file/title/press>;
}
@@ -57,6 +57,8 @@
<snap_range><!-- INTEGER: max amount of lines that the current snippet will be extended to snap to scope start/end --></snap_range>
<expand_range><!-- INTEGER: amount of lines that the snippet range (not snapped) will be extended --></expand_range>
</snippet>
<view_mode_single><!-- BOOL: whether code view is used in single or list mode --></view_mode_single>
</code>
<user>
+1 -1
View File
@@ -90,7 +90,7 @@ std::shared_ptr<Application> Application::s_instance;
Application::Application(bool withGUI)
: m_hasGUI(withGUI)
, m_isInTrial(false)
, m_isInTrial(true)
{
LicenseChecker::createInstance();
}
@@ -166,6 +166,11 @@ void CodeController::handleMessage(MessageChangeFileView* message)
{
TRACE("code change file");
if (!m_collection)
{
return;
}
CodeView* view = getView();
switch (message->state)
@@ -177,8 +182,18 @@ void CodeController::handleMessage(MessageChangeFileView* message)
case MessageChangeFileView::FILE_SNIPPETS:
if (message->needsData)
{
view->addCodeSnippets(getSnippetsForFile(
m_collection->getTokenLocationFileByPath(message->filePath), !message->showErrors), false);
std::shared_ptr<TokenLocationFile> file = m_collection->getTokenLocationFileByPath(message->filePath);
if (!file)
{
return;
}
if (message->showErrors)
{
file->isWholeCopy = false;
}
view->addCodeSnippets(getSnippetsForFile(file, !message->showErrors), false);
}
view->setFileState(message->filePath, CodeView::FILE_SNIPPETS);
break;
@@ -198,6 +213,10 @@ void CodeController::handleMessage(MessageChangeFileView* message)
if (message->showErrors)
{
params.locationFile = m_collection->getTokenLocationFileByPath(message->filePath);
if (!params.locationFile)
{
return;
}
params.locationFile->isWholeCopy = true;
}
else
@@ -221,6 +240,7 @@ void CodeController::handleMessage(MessageChangeFileView* message)
getView()->addCodeSnippets(std::vector<CodeSnippetParams>(1, params), false);
}
view->setFileState(message->filePath, CodeView::FILE_MAXIMIZED);
break;
}
@@ -256,7 +276,7 @@ void CodeController::handleMessage(MessageFocusOut* message)
void CodeController::handleMessage(MessageCodeViewExpandedInitialFiles* message)
{
if (m_scrollToDefinition)
if (m_scrollToDefinition || (message && message->scrollToDefinition))
{
getView()->scrollToDefinition();
m_scrollToDefinition = false;
@@ -264,7 +284,7 @@ void CodeController::handleMessage(MessageCodeViewExpandedInitialFiles* message)
if (m_scrollToValue != -1)
{
getView()->scrollToValue(m_scrollToValue);
getView()->scrollToValue(m_scrollToValue, m_scrollInListMode);
m_scrollToValue = -1;
}
}
@@ -294,6 +314,7 @@ void CodeController::handleMessage(MessageScrollCode* message)
if (message->isReplayed())
{
m_scrollToValue = message->value;
m_scrollInListMode = message->inListMode;
}
}
@@ -97,6 +97,7 @@ private:
bool m_scrollToDefinition;
int m_scrollToValue;
bool m_scrollInListMode;
};
#endif // CODE_CONTROLLER_H
+1 -1
View File
@@ -49,7 +49,7 @@ public:
virtual void showContents() = 0;
virtual void scrollToValue(int value) = 0;
virtual void scrollToValue(int value, bool inListMode) = 0;
virtual void scrollToLine(const FilePath filePath, unsigned int line) = 0;
virtual void scrollToDefinition() = 0;
+10
View File
@@ -301,6 +301,16 @@ void ApplicationSettings::setCodeSnippetExpandRange(int range)
setValue<int>("code/snippet/expand_range", range);
}
bool ApplicationSettings::getCodeViewModeSingle() const
{
return getValue<bool>("code/view_mode_single", false);
}
void ApplicationSettings::setCodeViewModeSingle(bool enabled)
{
setValue<bool>("code/view_mode_single", enabled);
}
std::vector<FilePath> ApplicationSettings::getRecentProjects() const
{
std::vector<FilePath> recentProjects;
+3
View File
@@ -91,6 +91,9 @@ public:
int getCodeSnippetExpandRange() const;
void setCodeSnippetExpandRange(int range);
bool getCodeViewModeSingle() const;
void setCodeViewModeSingle(bool enabled);
// user
std::vector<FilePath> getRecentProjects() const;
bool setRecentProjects(const std::vector<FilePath>& recentProjects);
@@ -7,7 +7,8 @@ class MessageCodeViewExpandedInitialFiles
: public Message<MessageCodeViewExpandedInitialFiles>
{
public:
MessageCodeViewExpandedInitialFiles()
MessageCodeViewExpandedInitialFiles(bool scrollToDefinition)
: scrollToDefinition(scrollToDefinition)
{
}
@@ -15,6 +16,8 @@ public:
{
return "MessageCodeViewExpandedInitialFiles";
}
bool scrollToDefinition;
};
#endif // MESSAGE_CODE_VIEW_EXPANDED_INITIAL_FILES_H
@@ -7,8 +7,9 @@ class MessageScrollCode
: public Message<MessageScrollCode>
{
public:
MessageScrollCode(int value)
MessageScrollCode(int value, bool inListMode)
: value(value)
, inListMode(inListMode)
{
setIsLogged(false);
}
@@ -19,6 +20,7 @@ public:
}
int value;
bool inListMode;
};
#endif // MESSAGE_SCROLL_CODE_H
+6
View File
@@ -14,6 +14,12 @@ add_files(
qt/element/QtCodeFile.h
qt/element/QtCodeFileList.cpp
qt/element/QtCodeFileList.h
qt/element/QtCodeFileSingle.cpp
qt/element/QtCodeFileSingle.h
qt/element/QtCodeFileTitleButton.cpp
qt/element/QtCodeFileTitleButton.h
qt/element/QtCodeNavigateable.cpp
qt/element/QtCodeNavigateable.h
qt/element/QtCodeNavigator.cpp
qt/element/QtCodeNavigator.h
qt/element/QtCodeSnippet.cpp
+56 -18
View File
@@ -1,5 +1,7 @@
#include "qt/element/QtCodeArea.h"
#include <algorithm>
#include <QApplication>
#include <QFont>
#include <QHBoxLayout>
@@ -151,21 +153,24 @@ QtCodeArea::~QtCodeArea()
QSize QtCodeArea::sizeHint() const
{
QTextBlock block = firstVisibleBlock();
float height = blockBoundingGeometry(block).translated(contentOffset()).top();
QTextBlock block = document()->firstBlock();
double height = 0;
double width = lineNumberAreaWidth() + blockBoundingGeometry(block).translated(contentOffset()).left();
while (block.isValid())
{
height += blockBoundingRect(block).height();
width = std::max(blockBoundingRect(block).width(), width);
block = block.next();
}
if (horizontalScrollBar()->isVisible())
if (horizontalScrollBar()->minimum() != horizontalScrollBar()->maximum())
{
height += horizontalScrollBar()->height();
}
return QSize(0, height + 5);
return QSize(width + 1, height + 5);
}
uint QtCodeArea::getStartLineNumber() const
@@ -275,31 +280,65 @@ uint QtCodeArea::getLineNumberForLocationId(Id locationId) const
return 0;
}
int QtCodeArea::getStartLineNumberOfFirstActiveScope() const
uint QtCodeArea::getStartLineNumberOfFirstActiveLocationOfTokenId(Id tokenId) const
{
int firstActiveLine = 0;
for (const Annotation& annotation : m_annotations)
{
if (annotation.locationType == LocationType::LOCATION_SCOPE && annotation.isActive)
if (annotation.locationType == LocationType::LOCATION_TOKEN && annotation.isActive)
{
if (firstActiveLine && firstActiveLine != annotation.startLine)
if (annotation.tokenId == tokenId)
{
return annotation.startLine;
if (!firstActiveLine || firstActiveLine == annotation.startLine)
{
return getStartLineNumber();
}
else
{
return annotation.startLine;
}
}
else
{
return getStartLineNumber();
firstActiveLine = annotation.startLine;
}
}
else if (annotation.isActive)
{
firstActiveLine = annotation.startLine;
}
}
return 0;
}
Id QtCodeArea::getLocationIdOfFirstActiveLocationOfTokenId(Id tokenId) const
{
for (const Annotation& annotation : m_annotations)
{
if (annotation.locationType == LocationType::LOCATION_TOKEN && annotation.isActive)
{
if (annotation.tokenId == tokenId)
{
return annotation.locationId;
}
}
}
return 0;
}
uint QtCodeArea::getActiveLocationCount() const
{
uint count = 0;
for (const Annotation& annotation : m_annotations)
{
if (annotation.locationType == LocationType::LOCATION_TOKEN && (annotation.isActive || annotation.isFocused))
{
count++;
}
}
return count;
}
QRectF QtCodeArea::getLineRectForLineNumber(uint lineNumber) const
{
if (lineNumber < getStartLineNumber())
@@ -338,8 +377,6 @@ void QtCodeArea::showEvent(QShowEvent* event)
{
int tabWidth = ApplicationSettings::getInstance()->getCodeTabWidth();
setTabStopWidth(tabWidth * fontMetrics().width('9'));
setFixedHeight(sizeHint().height());
}
void QtCodeArea::paintEvent(QPaintEvent* event)
@@ -563,12 +600,13 @@ void QtCodeArea::clearSelection()
QTextCursor cursor = textCursor();
cursor.clearSelection();
QScrollBar* scrollbar = horizontalScrollBar();
int scrollValue = horizontalScrollBar()->value();
int horizontalValue = horizontalScrollBar()->value();
int verticalValue = verticalScrollBar()->value();
setTextCursor(cursor);
scrollbar->setValue(scrollValue);
horizontalScrollBar()->setValue(horizontalValue);
verticalScrollBar()->setValue(verticalValue);
}
void QtCodeArea::setIDECursorPosition()
+4 -1
View File
@@ -83,7 +83,10 @@ public:
void setIsActiveFile(bool isActiveFile);
uint getLineNumberForLocationId(Id locationId) const;
int getStartLineNumberOfFirstActiveScope() const;
uint getStartLineNumberOfFirstActiveLocationOfTokenId(Id tokenId) const;
Id getLocationIdOfFirstActiveLocationOfTokenId(Id tokenId) const;
uint getActiveLocationCount() const;
QRectF getLineRectForLineNumber(uint lineNumber) const;
std::string getCode() const;
+23 -95
View File
@@ -4,25 +4,19 @@
#include <QPushButton>
#include <QVBoxLayout>
#include "utility/ResourcePaths.h"
#include "utility/file/FileSystem.h"
#include "utility/logging/logging.h"
#include "utility/messaging/type/MessageActivateFile.h"
#include "utility/messaging/type/MessageChangeFileView.h"
#include "utility/messaging/type/MessageProjectEdit.h"
#include "Application.h"
#include "data/location/TokenLocation.h"
#include "data/location/TokenLocationFile.h"
#include "qt/element/QtCodeFileTitleButton.h"
#include "qt/element/QtCodeNavigator.h"
#include "qt/element/QtCodeSnippet.h"
#include "qt/utility/utilityQt.h"
#include "settings/ColorScheme.h"
QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator)
: QFrame()
, m_navigator(navigator)
, m_filePath(filePath)
, m_isWholeFile(false)
, m_isCollapsed(true)
, m_contentRequested(false)
{
setObjectName("code_file");
@@ -44,20 +38,11 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator)
titleLayout->setAlignment(Qt::AlignLeft);
m_titleBar->setLayout(titleLayout);
m_title = new QPushButton(filePath.fileName().c_str(), this);
m_title->setObjectName("title_label");
m_title->minimumSizeHint(); // force font loading
m_title->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
m_title->setToolTip(QString::fromStdString(filePath.str()));
m_title->setFixedHeight(std::max(m_title->fontMetrics().height() * 1.2, 28.0));
m_title->setSizePolicy(m_title->sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
std::string text = ResourcePaths::getGuiPath() + "graph_view/images/file.png";
m_title->setIcon(utility::colorizePixmap(
QPixmap(text.c_str()),
ColorScheme::getInstance()->getColor("code/file/title/icon").c_str()
));
m_title = new QtCodeFileTitleButton(this);
if (!m_filePath.empty())
{
m_title->setFilePath(filePath);
}
titleLayout->addWidget(m_title);
@@ -93,7 +78,6 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator)
m_maximizeButton->setEnabled(false);
connect(m_titleBar, SIGNAL(clicked()), this, SLOT(clickedTitleBar()));
connect(m_title, SIGNAL(clicked()), this, SLOT(clickedTitle()));
connect(m_minimizeButton, SIGNAL(clicked()), this, SLOT(clickedMinimizeButton()));
connect(m_snippetButton, SIGNAL(clicked()), this, SLOT(clickedSnippetButton()));
connect(m_maximizeButton, SIGNAL(clicked()), this, SLOT(clickedMaximizeButton()));
@@ -108,13 +92,9 @@ QtCodeFile::~QtCodeFile()
{
}
void QtCodeFile::setModificationTime(TimePoint modificationTime)
void QtCodeFile::setModificationTime(const TimePoint modificationTime)
{
if (modificationTime.isValid())
{
m_modificationTime = modificationTime;
updateTitleBar();
}
m_title->setModificationTime(modificationTime);
}
const FilePath& QtCodeFile::getFilePath() const
@@ -129,39 +109,13 @@ std::string QtCodeFile::getFileName() const
QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params)
{
m_locationFile.reset();
m_isCollapsed = false;
std::shared_ptr<QtCodeSnippet> snippet(new QtCodeSnippet(params, m_navigator, this));
if (params.reduced)
{
m_title->hide();
QPushButton* title = new QPushButton(params.title.c_str(), this);
title->setObjectName("title_label");
title->minimumSizeHint(); // force font loading
title->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
title->setFixedHeight(std::max(title->fontMetrics().height() * 1.2, 28.0));
title->setSizePolicy(title->sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
if (Application::getInstance()->isInTrial())
{
title->setEnabled(false);
}
else
{
std::string text = ResourcePaths::getGuiPath() + "code_view/images/edit.png";
title->setToolTip("edit project");
title->setIcon(utility::colorizePixmap(
QPixmap(text.c_str()),
ColorScheme::getInstance()->getColor("code/file/title/icon").c_str()
));
connect(title, SIGNAL(clicked()), this, SLOT(editProject()));
}
dynamic_cast<QHBoxLayout*>(m_titleBar->layout())->insertWidget(1, title);
m_title->setProject(params.title);
}
m_snippetLayout->addWidget(snippet.get());
@@ -196,7 +150,7 @@ QtCodeSnippet* QtCodeFile::addCodeSnippet(const CodeSnippetParams& params)
QtCodeSnippet* QtCodeFile::insertCodeSnippet(const CodeSnippetParams& params)
{
m_locationFile.reset();
m_isCollapsed = false;
std::shared_ptr<QtCodeSnippet> snippet(new QtCodeSnippet(params, m_navigator, this));
@@ -273,13 +227,13 @@ QtCodeSnippet* QtCodeFile::getFileSnippet() const
return m_fileSnippet.get();
}
std::pair<QtCodeSnippet*, int> QtCodeFile::getFirstSnippetWithActiveScope() const
std::pair<QtCodeSnippet*, uint> QtCodeFile::getFirstSnippetWithActiveLocation(Id tokenId) const
{
std::pair<QtCodeSnippet*, int> result(nullptr, 0);
std::pair<QtCodeSnippet*, uint> result(nullptr, 0);
for (std::shared_ptr<QtCodeSnippet> snippet : m_snippets)
{
int startLineNumber = snippet->getStartLineNumberOfFirstActiveScope();
uint startLineNumber = snippet->getStartLineNumberOfFirstActiveLocationOfTokenId(tokenId);
if (startLineNumber != 0)
{
result.first = snippet.get();
@@ -293,7 +247,7 @@ std::pair<QtCodeSnippet*, int> QtCodeFile::getFirstSnippetWithActiveScope() cons
bool QtCodeFile::isCollapsed() const
{
return m_locationFile != nullptr;
return m_isCollapsed;
}
void QtCodeFile::requestContent() const
@@ -307,7 +261,7 @@ void QtCodeFile::requestContent() const
MessageChangeFileView msg(
m_filePath,
m_locationFile->isWholeCopy ? MessageChangeFileView::FILE_MAXIMIZED : MessageChangeFileView::FILE_SNIPPETS,
m_isWholeFile ? MessageChangeFileView::FILE_MAXIMIZED : MessageChangeFileView::FILE_SNIPPETS,
isCollapsed(),
m_navigator->hasErrors()
);
@@ -331,12 +285,12 @@ void QtCodeFile::updateContent()
}
}
void QtCodeFile::setLocationFile(std::shared_ptr<TokenLocationFile> locationFile, int refCount)
void QtCodeFile::setWholeFile(bool isWholeFile, int refCount)
{
m_locationFile = locationFile;
m_isWholeFile = isWholeFile;
setMinimized();
updateRefCount(locationFile->isWholeCopy ? 0 : refCount);
updateRefCount(isWholeFile ? 0 : refCount);
}
void QtCodeFile::setMinimized()
@@ -352,7 +306,7 @@ void QtCodeFile::setMinimized()
}
m_minimizeButton->setEnabled(false);
m_snippetButton->setEnabled(m_snippets.size() || (isCollapsed() && !m_locationFile->isWholeCopy));
m_snippetButton->setEnabled(m_snippets.size() || (isCollapsed() && !m_isWholeFile));
m_maximizeButton->setEnabled(true);
}
@@ -422,23 +376,7 @@ void QtCodeFile::updateSnippets()
void QtCodeFile::updateTitleBar()
{
if (Application::getInstance()->isInTrial())
{
return;
}
// cannot use m_filePath.exists() here since it is only checked when FilePath is constructed.
if ((!FileSystem::exists(m_filePath.str())) ||
(FileSystem::getLastWriteTime(m_filePath) > m_modificationTime))
{
m_title->setText(QString(m_filePath.fileName().c_str()) + "*");
m_title->setToolTip(QString::fromStdString("out of date: " + m_filePath.str()));
}
else
{
m_title->setText(m_filePath.fileName().c_str());
m_title->setToolTip(QString::fromStdString(m_filePath.str()));
}
m_title->checkModification();
}
void QtCodeFile::clickedMinimizeButton() const
@@ -487,16 +425,6 @@ void QtCodeFile::clickedTitleBar()
}
}
void QtCodeFile::clickedTitle()
{
MessageActivateFile(m_filePath).dispatch();
}
void QtCodeFile::editProject()
{
MessageProjectEdit().dispatch();
}
void QtCodeFile::updateRefCount(int refCount)
{
if (refCount > 0)
+10 -14
View File
@@ -7,19 +7,16 @@
#include <QFrame>
#include "utility/file/FilePath.h"
#include "utility/TimePoint.h"
#include "utility/types.h"
#include "data/ErrorInfo.h"
#include "component/view/helper/CodeSnippetParams.h"
#include "utility/file/FilePath.h"
class QLabel;
class QPushButton;
class QtCodeFileTitleButton;
class QtCodeNavigator;
class QtCodeSnippet;
class QVBoxLayout;
class TokenLocationFile;
class TimePoint;
class QtCodeFile
: public QFrame
@@ -30,7 +27,7 @@ public:
QtCodeFile(const FilePath& filePath, QtCodeNavigator* navigator);
virtual ~QtCodeFile();
void setModificationTime(TimePoint modificationTime);
void setModificationTime(const TimePoint modificationTime);
const FilePath& getFilePath() const;
std::string getFileName() const;
@@ -42,14 +39,14 @@ public:
QtCodeSnippet* getSnippetForLine(unsigned int line) const;
QtCodeSnippet* getFileSnippet() const;
std::pair<QtCodeSnippet*, int> getFirstSnippetWithActiveScope() const;
std::pair<QtCodeSnippet*, uint> getFirstSnippetWithActiveLocation(Id tokenId) const;
bool isCollapsed() const;
void requestContent() const;
void updateContent();
void setLocationFile(std::shared_ptr<TokenLocationFile> locationFile, int refCount);
void setWholeFile(bool isWholeFile, int refCount);
void setMinimized();
void setSnippets();
@@ -66,8 +63,6 @@ public slots:
private slots:
void clickedTitleBar();
void clickedTitle();
void editProject();
private:
void updateRefCount(int refCount);
@@ -75,7 +70,7 @@ private:
QtCodeNavigator* m_navigator;
QPushButton* m_titleBar;
QPushButton* m_title;
QtCodeFileTitleButton* m_title;
QLabel* m_referenceCount;
QPushButton* m_minimizeButton;
@@ -87,9 +82,10 @@ private:
std::shared_ptr<QtCodeSnippet> m_fileSnippet;
const FilePath m_filePath;
TimePoint m_modificationTime;
std::shared_ptr<TokenLocationFile> m_locationFile;
bool m_isWholeFile;
bool m_isCollapsed;
mutable bool m_contentRequested;
};
+125 -52
View File
@@ -1,5 +1,6 @@
#include "qt/element/QtCodeFileList.h"
#include <QScrollBar>
#include <QVBoxLayout>
#include "utility/file/FileSystem.h"
@@ -10,22 +11,77 @@
#include "qt/element/QtCodeSnippet.h"
QtCodeFileList::QtCodeFileList(QtCodeNavigator* navigator)
: QFrame()
: QScrollArea()
, m_navigator(navigator)
{
setObjectName("code_file_list");
setObjectName("code_container");
setWidgetResizable(true);
m_filesArea = new QFrame();
m_filesArea->setObjectName("code_file_list");
QVBoxLayout* layout = new QVBoxLayout();
layout->setSpacing(8);
layout->setContentsMargins(8, 8, 8, 8);
layout->setAlignment(Qt::AlignTop);
setLayout(layout);
m_filesArea->setLayout(layout);
setWidget(m_filesArea);
m_scrollSpeedChangeListener.setScrollBar(verticalScrollBar());
connect(verticalScrollBar(), SIGNAL(valueChanged(int)), m_navigator, SLOT(scrolled(int)));
}
QtCodeFileList::~QtCodeFileList()
{
}
void QtCodeFileList::clear()
{
m_files.clear();
verticalScrollBar()->setValue(0);
}
QtCodeFile* QtCodeFileList::getFile(const FilePath filePath)
{
QtCodeFile* file = nullptr;
for (std::shared_ptr<QtCodeFile> filePtr : m_files)
{
if (filePtr->getFilePath() == filePath)
{
file = filePtr.get();
break;
}
}
if (!file)
{
std::shared_ptr<QtCodeFile> filePtr = std::make_shared<QtCodeFile>(filePath, m_navigator);
m_files.push_back(filePtr);
file = filePtr.get();
m_filesArea->layout()->addWidget(file);
file->hide();
}
return file;
}
void QtCodeFileList::addFile(const FilePath& filePath, bool isWholeFile, int refCount, TimePoint modificationTime)
{
QtCodeFile* file = getFile(filePath);
file->setWholeFile(isWholeFile, refCount);
file->setModificationTime(modificationTime);
}
QScrollArea* QtCodeFileList::getScrollArea()
{
return this;
}
void QtCodeFileList::addCodeSnippet(
const CodeSnippetParams& params,
bool insert
@@ -45,36 +101,65 @@ void QtCodeFileList::addCodeSnippet(
file->setModificationTime(params.modificationTime);
}
void QtCodeFileList::addFile(std::shared_ptr<TokenLocationFile> locationFile, int refCount, TimePoint modificationTime)
{
QtCodeFile* file = getFile(locationFile->getFilePath());
file->setLocationFile(locationFile, refCount);
file->setModificationTime(modificationTime);
}
void QtCodeFileList::clearCodeSnippets()
{
m_files.clear();
}
void QtCodeFileList::requestFileContent(const FilePath& filePath)
{
getFile(filePath)->requestContent();
}
void QtCodeFileList::setFileMinimized(const FilePath path)
bool QtCodeFileList::requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop)
{
getFile(path)->setMinimized();
}
QtCodeFile* file = getFile(filePath);
if (!file)
{
return true;
}
void QtCodeFileList::setFileSnippets(const FilePath path)
{
getFile(path)->setSnippets();
}
if (file->isCollapsed())
{
file->requestContent();
return false;
}
void QtCodeFileList::setFileMaximized(const FilePath path)
{
getFile(path)->setMaximized();
QtCodeSnippet* snippet = nullptr;
if (locationId)
{
snippet = file->getSnippetForLocationId(locationId);
}
else if (lineNumber)
{
snippet = file->getSnippetForLine(lineNumber);
}
else
{
snippet = file->getFileSnippet();
}
if (!snippet)
{
return true;
}
if (!snippet->isVisible())
{
file->setSnippets();
}
if (!lineNumber)
{
if (locationId)
{
lineNumber = snippet->getLineNumberForLocationId(locationId);
}
else
{
lineNumber = 1;
}
}
ensureWidgetVisibleAnimated(m_filesArea, snippet, snippet->getLineRectForLineNumber(lineNumber), animated, onTop);
return true;
}
void QtCodeFileList::updateFiles()
@@ -101,36 +186,24 @@ void QtCodeFileList::onWindowFocus()
}
}
QtCodeFile* QtCodeFileList::getFile(const FilePath filePath)
void QtCodeFileList::setFileMinimized(const FilePath path)
{
QtCodeFile* file = nullptr;
for (std::shared_ptr<QtCodeFile> filePtr : m_files)
{
if (filePtr->getFilePath() == filePath)
{
file = filePtr.get();
break;
}
}
if (!file)
{
std::shared_ptr<QtCodeFile> filePtr = std::make_shared<QtCodeFile>(filePath, m_navigator);
m_files.push_back(filePtr);
file = filePtr.get();
layout()->addWidget(file);
file->hide();
}
return file;
getFile(path)->setMinimized();
}
std::pair<QtCodeSnippet*, int> QtCodeFileList::getFirstSnippetWithActiveScope() const
void QtCodeFileList::setFileSnippets(const FilePath path)
{
std::pair<QtCodeSnippet*, int> result(nullptr, 0);
getFile(path)->setSnippets();
}
void QtCodeFileList::setFileMaximized(const FilePath path)
{
getFile(path)->setMaximized();
}
std::pair<QtCodeSnippet*, uint> QtCodeFileList::getFirstSnippetWithActiveLocation(Id tokenId) const
{
std::pair<QtCodeSnippet*, uint> result(nullptr, 0);
for (std::shared_ptr<QtCodeFile> filePtr : m_files)
{
@@ -139,7 +212,7 @@ std::pair<QtCodeSnippet*, int> QtCodeFileList::getFirstSnippetWithActiveScope()
continue;
}
result = filePtr->getFirstSnippetWithActiveScope();
result = filePtr->getFirstSnippetWithActiveLocation(tokenId);
if (result.first != nullptr)
{
break;
+24 -22
View File
@@ -5,21 +5,19 @@
#include <vector>
#include <QFrame>
#include <QScrollArea>
#include "utility/file/FilePath.h"
#include "utility/TimePoint.h"
#include "utility/types.h"
#include "data/ErrorInfo.h"
#include "component/view/helper/CodeSnippetParams.h"
#include "qt/element/QtCodeNavigateable.h"
#include "qt/utility/QtScrollSpeedChangeListener.h"
class QtCodeFile;
class QtCodeNavigator;
class QtCodeSnippet;
class TokenLocationFile;
class QtCodeFileList
: public QFrame
: public QScrollArea
, public QtCodeNavigateable
{
Q_OBJECT
@@ -27,33 +25,37 @@ public:
QtCodeFileList(QtCodeNavigator* navigator);
virtual ~QtCodeFileList();
void addCodeSnippet(const CodeSnippetParams& params, bool insert = false);
void addFile(std::shared_ptr<TokenLocationFile> locationFile, int refCount, TimePoint modificationTime);
void clear();
void clearCodeSnippets();
QtCodeFile* getFile(const FilePath filePath);
void addFile(const FilePath& filePath, bool isWholeFile, int refCount, TimePoint modificationTime);
void requestFileContent(const FilePath& filePath);
// QtCodeNaviatebale implementation
virtual QScrollArea* getScrollArea();
virtual void addCodeSnippet(const CodeSnippetParams& params, bool insert = false);
virtual void requestFileContent(const FilePath& filePath);
virtual bool requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop);
virtual void updateFiles();
virtual void showContents();
virtual void onWindowFocus();
void setFileMinimized(const FilePath path);
void setFileSnippets(const FilePath path);
void setFileMaximized(const FilePath path);
void updateFiles();
void showContents();
void onWindowFocus();
QtCodeFile* getFile(const FilePath filePath);
std::pair<QtCodeSnippet*, int> getFirstSnippetWithActiveScope() const;
std::pair<QtCodeSnippet*, uint> getFirstSnippetWithActiveLocation(Id tokenId) const;
private:
QtCodeSnippet* getFirstActiveSnippet() const;
void expandActiveSnippetFile(bool scrollTo);
QtCodeNavigator* m_navigator;
QFrame* m_filesArea;
std::vector<std::shared_ptr<QtCodeFile>> m_files;
QtScrollSpeedChangeListener m_scrollSpeedChangeListener;
};
#endif // QT_CODE_FILE_LIST
+306
View File
@@ -0,0 +1,306 @@
#include "qt/element/QtCodeFileSingle.h"
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QScrollBar>
#include <QVBoxLayout>
#include "utility/logging/logging.h"
#include "utility/messaging/type/MessageChangeFileView.h"
#include "utility/ResourcePaths.h"
#include "data/location/TokenLocationFile.h"
#include "qt/element/QtCodeArea.h"
#include "qt/element/QtCodeFileTitleButton.h"
#include "qt/element/QtCodeNavigator.h"
#include "qt/utility/utilityQt.h"
#include "settings/ColorScheme.h"
QtCodeFileSingle::QtCodeFileSingle(QtCodeNavigator* navigator, QWidget* parent)
: m_navigator(navigator)
, m_contentRequested(false)
{
setObjectName("code_container_single");
setLayout(new QVBoxLayout(this));
layout()->setContentsMargins(0, 0, 0, 0);
layout()->setSpacing(0);
{
QWidget* titleBar = new QWidget();
titleBar->setObjectName("single_file_title_bar");
QHBoxLayout* titleLayout = new QHBoxLayout();
titleLayout->setSpacing(0);
titleLayout->setMargin(0);
m_title = new QtCodeFileTitleButton();
m_title->setObjectName("file_title");
titleLayout->addWidget(m_title);
m_title->hide();
m_referenceCount = new QLabel();
m_referenceCount->setObjectName("references_label");
m_referenceCount->hide();
titleLayout->addWidget(m_referenceCount);
QPushButton* filler = new QPushButton();
filler->setObjectName("file_title");
filler->setEnabled(false);
titleLayout->addWidget(filler);
titleLayout->addStretch();
titleBar->setLayout(titleLayout);
layout()->addWidget(titleBar);
}
m_areaWrapper = new QWidget();
m_areaWrapper->setObjectName("code_file_single");
m_areaWrapper->setSizePolicy(m_areaWrapper->sizePolicy().horizontalPolicy(), QSizePolicy::Expanding);
m_areaWrapper->setLayout(new QVBoxLayout());
m_areaWrapper->layout()->setMargin(0);
m_areaWrapper->layout()->setSpacing(0);
layout()->addWidget(m_areaWrapper);
}
QtCodeFileSingle::~QtCodeFileSingle()
{
}
QAbstractScrollArea* QtCodeFileSingle::getScrollArea()
{
return m_area;
}
void QtCodeFileSingle::clearCache()
{
setFileData(FileData());
m_fileDatas.clear();
m_filePaths.clear();
}
void QtCodeFileSingle::addCodeSnippet(const CodeSnippetParams& params, bool insert)
{
if (!params.locationFile->isWholeCopy)
{
LOG_ERROR("Snippet params passed are not for whole file.");
return;
}
FileData file = getFileData(params.locationFile->getFilePath());
if (file.area)
{
setFileData(file);
return;
}
file.filePath = params.locationFile->getFilePath();
file.modificationTime = params.modificationTime;
if (params.reduced)
{
file.title = params.title;
}
file.area = std::make_shared<QtCodeArea>(1, params.code, params.locationFile, m_navigator, this);
connect(file.area->verticalScrollBar(), SIGNAL(valueChanged(int)), m_navigator, SLOT(scrolled(int)));
m_fileDatas.emplace(file.filePath, file);
m_filePaths.push_back(file.filePath);
setFileData(file);
m_contentRequested = false;
if (m_filePaths.size() > 100)
{
FilePath toDelete = m_filePaths.front();
m_filePaths.pop_front();
m_fileDatas.erase(m_fileDatas.find(toDelete));
}
}
void QtCodeFileSingle::requestFileContent(const FilePath& filePath)
{
if (m_contentRequested)
{
return;
}
FileData file = getFileData(filePath);
if (file.area)
{
setFileData(file);
return;
}
m_contentRequested = true;
MessageChangeFileView msg(
filePath,
MessageChangeFileView::FILE_MAXIMIZED,
true,
m_navigator->hasErrors()
);
msg.setIsReplayed(true);
msg.dispatch();
}
bool QtCodeFileSingle::requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop)
{
FileData file = getFileData(filePath);
if (file.area)
{
setFileData(file);
}
else
{
requestFileContent(filePath);
return false;
}
if (!lineNumber)
{
if (locationId)
{
lineNumber = m_area->getLineNumberForLocationId(locationId);
}
else
{
lineNumber = 1;
}
}
ensurePercentVisibleAnimated(double(lineNumber - 1) / m_area->getEndLineNumber(), animated, onTop);
return true;
}
void QtCodeFileSingle::updateFiles()
{
if (m_area)
{
m_area->updateContent();
}
}
void QtCodeFileSingle::showContents()
{
if (m_area)
{
m_area->show();
}
}
void QtCodeFileSingle::onWindowFocus()
{
m_title->checkModification();
}
const FilePath& QtCodeFileSingle::getCurrentFilePath() const
{
return m_currentFilePath;
}
Id QtCodeFileSingle::getLocationIdOfFirstActiveLocationOfTokenId(Id tokenId) const
{
if (!m_area)
{
return 0;
}
return m_area->getLocationIdOfFirstActiveLocationOfTokenId(tokenId);
}
QtCodeFileSingle::FileData QtCodeFileSingle::getFileData(const FilePath& filePath) const
{
std::map<FilePath, FileData>::const_iterator it = m_fileDatas.find(filePath);
if (it != m_fileDatas.end())
{
return it->second;
}
return FileData();
}
void QtCodeFileSingle::setFileData(const FileData& file)
{
if (file.area.get() == m_area)
{
if (m_area)
{
updateRefCount(m_area->getActiveLocationCount());
}
return;
}
if (m_area)
{
m_area->hide();
m_area = nullptr;
m_currentFilePath = FilePath();
}
m_areaWrapper->layout()->takeAt(0);
if (file.area)
{
m_area = file.area.get();
m_area->setSizePolicy(m_area->sizePolicy().horizontalPolicy(), QSizePolicy::Expanding);
m_areaWrapper->layout()->addWidget(m_area);
m_area->updateContent();
m_currentFilePath = file.filePath;
if (file.title.size())
{
m_title->setProject(file.title);
}
else
{
m_title->setFilePath(file.filePath);
m_title->setModificationTime(file.modificationTime);
}
updateRefCount(m_area->getActiveLocationCount());
m_title->show();
m_area->show();
}
else
{
m_title->hide();
updateRefCount(0);
}
}
void QtCodeFileSingle::updateRefCount(int refCount)
{
if (refCount > 0)
{
QString label = m_navigator->hasErrors() ? "error" : "reference";
if (refCount > 1)
{
label += "s";
}
size_t fatalErrorCount = m_navigator->getFatalErrorCountForFile(m_currentFilePath);
if (fatalErrorCount > 0)
{
label += " (" + QString::number(fatalErrorCount) + " fatal)";
}
m_referenceCount->setText(QString::number(refCount) + " " + label);
m_referenceCount->show();
}
else
{
m_referenceCount->hide();
}
}
+78
View File
@@ -0,0 +1,78 @@
#ifndef QT_CODE_FILE_SINGLE_H
#define QT_CODE_FILE_SINGLE_H
#include <deque>
#include <map>
#include <QFrame>
#include "utility/TimePoint.h"
#include "qt/element/QtCodeNavigateable.h"
class QLabel;
class QPushButton;
class QtCodeArea;
class QtCodeFileTitleButton;
class QtCodeNavigator;
class QtCodeFileSingle
: public QFrame
, public QtCodeNavigateable
{
Q_OBJECT
public:
QtCodeFileSingle(QtCodeNavigator* navigator, QWidget* parent = nullptr);
virtual ~QtCodeFileSingle();
void clearCache();
// QtCodeNaviatebale implementation
virtual QAbstractScrollArea* getScrollArea() override;
virtual void addCodeSnippet(const CodeSnippetParams& params, bool insert = false) override;
virtual void requestFileContent(const FilePath& filePath) override;
virtual bool requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop) override;
virtual void updateFiles() override;
virtual void showContents() override;
virtual void onWindowFocus() override;
const FilePath& getCurrentFilePath() const;
Id getLocationIdOfFirstActiveLocationOfTokenId(Id tokenId) const;
private:
struct FileData
{
FilePath filePath;
TimePoint modificationTime;
std::string title;
std::shared_ptr<QtCodeArea> area;
};
FileData getFileData(const FilePath& filePath) const;
void setFileData(const FileData& file);
void updateRefCount(int refCount);
QtCodeNavigator* m_navigator;
QWidget* m_areaWrapper;
FilePath m_currentFilePath;
QtCodeFileTitleButton* m_title;
QLabel* m_referenceCount;
QtCodeArea* m_area;
std::map<FilePath, FileData> m_fileDatas;
std::deque<FilePath> m_filePaths;
bool m_contentRequested;
};
#endif // QT_CODE_FILE_SINGLE_H
@@ -0,0 +1,104 @@
#include "qt/element/QtCodeFileTitleButton.h"
#include "utility/file/FileSystem.h"
#include "utility/messaging/type/MessageActivateFile.h"
#include "utility/messaging/type/MessageProjectEdit.h"
#include "Application.h"
#include "qt/utility/utilityQt.h"
#include "settings/ColorScheme.h"
#include "utility/ResourcePaths.h"
QtCodeFileTitleButton::QtCodeFileTitleButton(QWidget* parent)
: QPushButton(parent)
{
setObjectName("title_label");
minimumSizeHint(); // force font loading
setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
setFixedHeight(std::max(fontMetrics().height() * 1.2, 28.0));
setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
connect(this, SIGNAL(clicked()), this, SLOT(clickedTitle()));
}
QtCodeFileTitleButton::~QtCodeFileTitleButton()
{
}
void QtCodeFileTitleButton::setFilePath(const FilePath& filePath)
{
m_filePath = filePath;
setText(filePath.fileName().c_str());
setToolTip(filePath.str().c_str());
std::string text = ResourcePaths::getGuiPath() + "graph_view/images/file.png";
setIcon(utility::colorizePixmap(
QPixmap(text.c_str()),
ColorScheme::getInstance()->getColor("code/file/title/icon").c_str()
));
}
void QtCodeFileTitleButton::setModificationTime(const TimePoint modificationTime)
{
if (modificationTime.isValid())
{
m_modificationTime = modificationTime;
checkModification();
}
}
void QtCodeFileTitleButton::setProject(const std::string& name)
{
setText(name.c_str());
if (Application::getInstance()->isInTrial())
{
setEnabled(false);
}
else
{
std::string text = ResourcePaths::getGuiPath() + "code_view/images/edit.png";
setToolTip("edit project");
setIcon(utility::colorizePixmap(
QPixmap(text.c_str()),
ColorScheme::getInstance()->getColor("code/file/title/icon").c_str()
));
}
}
void QtCodeFileTitleButton::checkModification()
{
if (Application::getInstance()->isInTrial() || m_filePath.empty())
{
return;
}
// cannot use m_filePath.exists() here since it is only checked when FilePath is constructed.
if ((!FileSystem::exists(m_filePath.str())) ||
(FileSystem::getLastWriteTime(m_filePath) > m_modificationTime))
{
setText(QString(m_filePath.fileName().c_str()) + "*");
setToolTip(QString::fromStdString("out of date: " + m_filePath.str()));
}
else
{
setText(m_filePath.fileName().c_str());
setToolTip(QString::fromStdString(m_filePath.str()));
}
}
void QtCodeFileTitleButton::clickedTitle()
{
if (!m_filePath.empty())
{
MessageActivateFile(m_filePath).dispatch();
}
else if (text().size())
{
MessageProjectEdit().dispatch();
}
}
@@ -0,0 +1,32 @@
#ifndef QT_CODE_FILE_TITLE_BUTTON_H
#define QT_CODE_FILE_TITLE_BUTTON_H
#include <QPushButton>
#include "utility/file/FilePath.h"
#include "utility/TimePoint.h"
class QtCodeFileTitleButton
: public QPushButton
{
Q_OBJECT
public:
QtCodeFileTitleButton(QWidget* parent = nullptr);
virtual ~QtCodeFileTitleButton();
void setFilePath(const FilePath& filePath);
void setModificationTime(const TimePoint modificationTime);
void setProject(const std::string& name);
void checkModification();
private slots:
void clickedTitle();
private:
FilePath m_filePath;
TimePoint m_modificationTime;
};
#endif // QT_CODE_FILE_TITLE_BUTTON_H
@@ -0,0 +1,103 @@
#include "qt/element/QtCodeNavigateable.h"
#include <QPropertyAnimation>
#include <QScrollArea>
#include <QScrollBar>
QtCodeNavigateable::~QtCodeNavigateable()
{
}
void QtCodeNavigateable::ensureWidgetVisibleAnimated(
QWidget* parentWidget, QWidget *childWidget, QRectF rect, bool animated, bool onTop)
{
QAbstractScrollArea* area = getScrollArea();
if (!area || !parentWidget->isAncestorOf(childWidget))
{
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());
const QRect visibleRect(-parentWidget->pos(), area->viewport()->size());
if (rect.height() > 0)
{
focusRect = QRect(childWidget->mapTo(parentWidget, rect.topLeft().toPoint()), rect.size().toSize());
focusRect.adjust(0, 0, 0, 100);
}
QScrollBar* scrollBar = area->verticalScrollBar();
int value = focusRect.center().y() - visibleRect.center().y();
if (onTop)
{
value = focusRect.top() - visibleRect.top();
}
if (scrollBar && (value > 50 || value < -50))
{
if (animated)
{
QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value");
anim->setDuration(300);
anim->setStartValue(scrollBar->value());
anim->setEndValue(scrollBar->value() + value);
anim->setEasingCurve(QEasingCurve::InOutQuad);
anim->start();
}
else
{
scrollBar->setValue(scrollBar->value() + value);
}
}
}
void QtCodeNavigateable::ensurePercentVisibleAnimated(double percent, bool animated, bool onTop)
{
QAbstractScrollArea* area = getScrollArea();
if (!area)
{
return;
}
int totalHeight = area->sizeHint().height();
int visibleHeight = area->viewport()->height();
int scrollableHeight = totalHeight - visibleHeight;
if (scrollableHeight < 0)
{
return;
}
int scrollHeight = totalHeight * percent;
if (!onTop)
{
scrollHeight -= visibleHeight / 3;
}
else
{
scrollHeight -= 20;
}
QScrollBar* scrollBar = area->verticalScrollBar();
double scrollFactor = double(scrollBar->maximum()) / scrollableHeight;
int value = scrollHeight * scrollFactor;
if (animated)
{
QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value");
anim->setDuration(300);
anim->setStartValue(scrollBar->value());
anim->setEndValue(value);
anim->setEasingCurve(QEasingCurve::InOutQuad);
anim->start();
}
else
{
scrollBar->setValue(value);
}
}
@@ -0,0 +1,38 @@
#ifndef QT_CODE_NAVIGATEABLE_H
#define QT_CODE_NAVIGATEABLE_H
#include <set>
#include "utility/file/FilePath.h"
#include "utility/TimePoint.h"
#include "utility/types.h"
#include "component/view/helper/CodeSnippetParams.h"
class QRectF;
class QAbstractScrollArea;
class QWidget;
class QtCodeNavigateable
{
public:
virtual ~QtCodeNavigateable();
virtual QAbstractScrollArea* getScrollArea() = 0;
virtual void addCodeSnippet(const CodeSnippetParams& params, bool insert = false) = 0;
virtual void requestFileContent(const FilePath& filePath) = 0;
virtual bool requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop) = 0;
virtual void updateFiles() = 0;
virtual void showContents() = 0;
virtual void onWindowFocus() = 0;
protected:
void ensureWidgetVisibleAnimated(QWidget* parentWidget, QWidget *childWidget, QRectF rect, bool animated, bool onTop);
void ensurePercentVisibleAnimated(double percent, bool animated, bool onTop);
};
#endif // QT_CODE_NAVIGATEABLE_H
+296 -228
View File
@@ -2,7 +2,6 @@
#include <QHBoxLayout>
#include <QLabel>
#include <QPropertyAnimation>
#include <QPushButton>
#include <QScrollBar>
#include <QTimer>
@@ -16,16 +15,17 @@
#include "utility/messaging/type/MessageScrollCode.h"
#include "utility/messaging/type/MessageShowReference.h"
#include "settings/ApplicationSettings.h"
#include "qt/element/QtCodeFile.h"
#include "qt/element/QtCodeSnippet.h"
#include "qt/utility/utilityQt.h"
QtCodeNavigator::QtCodeNavigator(QWidget* parent)
: QWidget(parent)
, m_mode(MODE_NONE)
, m_value(0)
, m_refIndex(0)
, m_scrollToFile(nullptr)
, m_scrollToLine(0)
, m_scrollToLocationId(0)
, m_singleHasNewFile(false)
{
QVBoxLayout* layout = new QVBoxLayout();
layout->setSpacing(0);
@@ -35,27 +35,19 @@ QtCodeNavigator::QtCodeNavigator(QWidget* parent)
{
QWidget* navigation = new QWidget();
navigation->setObjectName("code_navigation");
QHBoxLayout* navLayout = new QHBoxLayout();
navLayout->setSpacing(3);
navLayout->setSpacing(2);
navLayout->setContentsMargins(7, 7, 7, 7);
QPushButton* listButton = new QPushButton("list");
navLayout->addWidget(listButton);
QPushButton* fileButton = new QPushButton("file");
fileButton->setEnabled(false);
navLayout->addWidget(fileButton);
navLayout->addStretch();
m_refLabel = new QLabel("0/0 references");
navLayout->addWidget(m_refLabel);
navLayout->addStretch();
m_prevButton = new QPushButton("<");
m_nextButton = new QPushButton(">");
m_prevButton->setObjectName("reference_button_previous");
m_nextButton->setObjectName("reference_button_next");
m_prevButton->setToolTip("previous reference");
m_nextButton->setToolTip("next reference");
@@ -65,26 +57,50 @@ QtCodeNavigator::QtCodeNavigator(QWidget* parent)
connect(m_prevButton, SIGNAL(clicked()), this, SLOT(previousReference()));
connect(m_nextButton, SIGNAL(clicked()), this, SLOT(nextReference()));
m_refLabel = new QLabel("0/0 references");
m_refLabel->setObjectName("references_label");
navLayout->addWidget(m_refLabel);
navLayout->addStretch();
m_listButton = new QPushButton("list");
m_fileButton = new QPushButton("file");
m_listButton->setObjectName("mode_button_list");
m_fileButton->setObjectName("mode_button_single");
m_listButton->setCheckable(true);
m_fileButton->setCheckable(true);
navLayout->addWidget(m_listButton);
navLayout->addWidget(m_fileButton);
connect(m_listButton, SIGNAL(clicked()), this, SLOT(setModeList()));
connect(m_fileButton, SIGNAL(clicked()), this, SLOT(setModeSingle()));
navigation->setLayout(navLayout);
layout->addWidget(navigation);
navigation->hide();
}
m_scrollArea = new QScrollArea(this);
m_scrollArea->setObjectName("code_container");
m_list = new QtCodeFileList(this);
layout->addWidget(m_scrollArea);
layout->addWidget(m_list);
m_scrollArea->setWidgetResizable(true);
m_scrollArea->setWidget(m_list);
m_single = new QtCodeFileSingle(this);
layout->addWidget(m_single);
m_scrollSpeedChangeListener.setScrollBar(m_scrollArea->verticalScrollBar());
if (ApplicationSettings::getInstance()->getCodeViewModeSingle())
{
setModeSingle();
}
else
{
setModeList();
}
connect(m_scrollArea->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(scrolled(int)));
connect(this, SIGNAL(shouldScrollToSnippet(QtCodeSnippet*, uint, bool)),
this, SLOT(scrollToSnippet(QtCodeSnippet*, uint, bool)), Qt::QueuedConnection);
connect(this, SIGNAL(scrollRequest()), this, SLOT(handleScrollRequest()), Qt::QueuedConnection);
}
QtCodeNavigator::~QtCodeNavigator()
@@ -93,12 +109,20 @@ QtCodeNavigator::~QtCodeNavigator()
void QtCodeNavigator::addCodeSnippet(const CodeSnippetParams& params, bool insert)
{
m_list->addCodeSnippet(params, insert);
if (params.reduced)
{
m_list->addCodeSnippet(params, insert);
m_single->addCodeSnippet(params, insert);
}
else
{
m_current->addCodeSnippet(params, insert);
}
}
void QtCodeNavigator::addFile(std::shared_ptr<TokenLocationFile> locationFile, int refCount, TimePoint modificationTime)
{
m_list->addFile(locationFile, refCount, modificationTime);
m_list->addFile(locationFile->getFilePath(), locationFile->isWholeCopy, refCount, modificationTime);
if (locationFile->isWholeCopy)
{
@@ -106,6 +130,7 @@ void QtCodeNavigator::addFile(std::shared_ptr<TokenLocationFile> locationFile, i
ref.filePath = locationFile->getFilePath();
ref.tokenId = 0;
ref.locationId = 0;
ref.locationType = LOCATION_TOKEN;
m_references.push_back(ref);
}
@@ -120,6 +145,7 @@ void QtCodeNavigator::addFile(std::shared_ptr<TokenLocationFile> locationFile, i
ref.filePath = location->getFilePath();
ref.tokenId = location->getTokenId();
ref.locationId = location->getId();
ref.locationType = location->getType();
m_references.push_back(ref);
}
@@ -128,10 +154,17 @@ void QtCodeNavigator::addFile(std::shared_ptr<TokenLocationFile> locationFile, i
}
}
void QtCodeNavigator::addedFiles()
{
if (m_references.size() && m_references[0].locationType != LOCATION_TOKEN)
{
clearCaches();
}
}
void QtCodeNavigator::clearCodeSnippets()
{
m_list->clearCodeSnippets();
m_scrollArea->verticalScrollBar()->setValue(0);
m_list->clear();
m_currentActiveTokenIds.clear();
m_activeTokenIds.clear();
@@ -139,8 +172,20 @@ void QtCodeNavigator::clearCodeSnippets()
m_focusedTokenIds.clear();
m_errorInfos.clear();
if (m_references.size() && m_references[0].locationType != LOCATION_TOKEN)
{
clearCaches();
}
m_references.clear();
m_refIndex = 0;
m_singleHasNewFile = false;
}
void QtCodeNavigator::clearCaches()
{
m_single->clearCache();
}
const std::vector<Id>& QtCodeNavigator::getCurrentActiveTokenIds() const
@@ -252,23 +297,20 @@ void QtCodeNavigator::showActiveSnippet(
std::vector<Id> locationIds;
Id firstLocationId = 0;
FilePath firstFilePath;
Reference firstReference;
std::set<FilePath> filePathsToExpand;
std::map<FilePath, size_t> filePathOrder;
for (size_t i = 0; i < m_references.size(); i++)
for (const Reference& ref : m_references)
{
const Reference& ref = m_references[i];
if (ref.tokenId == tokenId)
{
locationIds.push_back(ref.locationId);
if (!firstLocationId)
if (!firstReference.tokenId)
{
firstLocationId = ref.locationId;
firstFilePath = ref.filePath;
firstReference = ref;
}
}
@@ -288,10 +330,11 @@ void QtCodeNavigator::showActiveSnippet(
locationIds.push_back(location->getId());
filePathsToExpand.insert(location->getFilePath());
if (firstFilePath.empty() || filePathOrder[location->getFilePath()] < filePathOrder[firstFilePath])
if (!firstReference.tokenId || filePathOrder[location->getFilePath()] < filePathOrder[firstReference.filePath])
{
firstFilePath = location->getFilePath();
firstLocationId = location->getId();
firstReference.tokenId = location->getTokenId();
firstReference.locationId = location->getId();
firstReference.filePath = location->getFilePath();
}
}
);
@@ -300,14 +343,18 @@ void QtCodeNavigator::showActiveSnippet(
setCurrentActiveLocationIds(locationIds);
updateFiles();
for (const FilePath& filePath : filePathsToExpand)
if (m_mode == MODE_LIST)
{
m_list->requestFileContent(filePath);
for (const FilePath& filePath : filePathsToExpand)
{
m_list->requestFileContent(filePath);
}
}
if (firstLocationId)
if (firstReference.tokenId)
{
showLocation(firstFilePath, firstLocationId, scrollTo);
requestScroll(firstReference.filePath, 0, firstReference.locationId, true, false);
emit scrollRequest();
m_refIndex = 0;
updateRefLabel();
@@ -343,183 +390,177 @@ void QtCodeNavigator::setFileMaximized(const FilePath path)
void QtCodeNavigator::setupFiles()
{
std::set<FilePath> filePathsToExpand;
for (const Reference& ref : m_references)
if (m_mode == MODE_LIST)
{
if (filePathsToExpand.find(ref.filePath) == filePathsToExpand.end())
std::set<FilePath> filePathsToExpand;
for (const Reference& ref : m_references)
{
m_list->requestFileContent(ref.filePath);
filePathsToExpand.insert(ref.filePath);
if (filePathsToExpand.size() >= 3)
if (filePathsToExpand.find(ref.filePath) == filePathsToExpand.end())
{
break;
m_list->requestFileContent(ref.filePath);
filePathsToExpand.insert(ref.filePath);
if (filePathsToExpand.size() >= 3)
{
break;
}
}
}
}
if (filePathsToExpand.size())
if (filePathsToExpand.size())
{
MessageCodeViewExpandedInitialFiles(m_refIndex != 0).dispatch();
}
}
else if (m_references.size())
{
MessageCodeViewExpandedInitialFiles().dispatch();
m_singleHasNewFile = (m_single->getCurrentFilePath() != m_references.front().filePath);
m_single->requestFileContent(m_references.front().filePath);
MessageCodeViewExpandedInitialFiles(true).dispatch();
}
m_refIndex = 0;
updateRefLabel();
if (m_refIndex == 0)
{
updateRefLabel();
}
}
void QtCodeNavigator::updateFiles()
{
m_list->updateFiles();
m_current->updateFiles();
}
void QtCodeNavigator::showContents()
{
m_list->showContents();
m_current->showContents();
}
void QtCodeNavigator::showLocation(const FilePath& filePath, Id locationId, bool scrollTo)
void QtCodeNavigator::scrollToValue(int value, bool inListMode)
{
updateFiles();
QtCodeFile* file = m_list->getFile(filePath);
if (file->isCollapsed())
if ((m_mode == MODE_LIST) == inListMode)
{
file->requestContent();
if (scrollTo)
{
m_scrollToFile = file;
m_scrollToLocationId = locationId;
}
m_value = value;
QTimer::singleShot(1000, this, SLOT(setValue()));
}
else
{
scrollToLocation(file, locationId, scrollTo);
}
}
void QtCodeNavigator::scrollToValue(int value)
{
m_value = value;
QTimer::singleShot(1000, this, SLOT(setValue()));
}
void QtCodeNavigator::scrollToLine(const FilePath& filePath, unsigned int line)
{
QtCodeFile* file = m_list->getFile(filePath);
if (!file)
{
return;
}
if (file->isCollapsed())
{
file->requestContent();
m_scrollToFile = file;
m_scrollToLine = line;
}
else if (file->getFileSnippet())
{
emit shouldScrollToSnippet(file->getFileSnippet(), line, false);
}
else
{
m_scrollToFile = file;
m_scrollToLine = line;
scrollToSnippetIfRequested();
}
}
void QtCodeNavigator::scrollToLocation(QtCodeFile* file, Id locationId, bool scrollTo)
{
QtCodeSnippet* snippet = nullptr;
if (locationId)
{
snippet = file->getSnippetForLocationId(locationId);
}
else
{
snippet = file->getFileSnippet();
}
if (!snippet)
{
return;
}
if (!snippet->isVisible())
{
file->setSnippets();
}
if (scrollTo)
{
if (locationId)
{
emit shouldScrollToSnippet(snippet, snippet->getLineNumberForLocationId(locationId), false);
}
else
{
emit shouldScrollToSnippet(snippet, 1, false);
}
}
requestScroll(filePath, line, 0, false, false);
}
void QtCodeNavigator::scrollToDefinition()
{
std::pair<QtCodeSnippet*, int> result = m_list->getFirstSnippetWithActiveScope();
if (result.first != nullptr)
if (m_refIndex != 0)
{
emit shouldScrollToSnippet(result.first, result.second, true);
showCurrentReference(false);
return;
}
if (!m_activeTokenIds.size())
{
return;
}
Id tokenId = m_activeTokenIds[0]; // The first active tokenId is the one of the active symbol itself.
if (m_mode == MODE_LIST)
{
std::pair<QtCodeSnippet*, uint> result = m_list->getFirstSnippetWithActiveLocation(tokenId);
if (result.first != nullptr)
{
requestScroll(result.first->getFile()->getFilePath(), result.second, 0, false, true);
emit scrollRequest();
}
}
else
{
Id locationId = m_single->getLocationIdOfFirstActiveLocationOfTokenId(tokenId);
if (locationId)
{
for (size_t i = 0; i < m_references.size(); i++)
{
if (m_references[i].locationId == locationId)
{
m_refIndex = i + 1;
showCurrentReference(false);
}
}
}
else if (m_references.size())
{
nextReference(false);
}
}
m_singleHasNewFile = false;
}
void QtCodeNavigator::scrollToSnippetIfRequested()
{
if (m_scrollToFile && m_scrollToLine)
{
emit shouldScrollToSnippet(m_scrollToFile->getSnippetForLine(m_scrollToLine), m_scrollToLine, false);
}
else if (m_scrollToFile && m_scrollToFile->hasSnippets())
{
scrollToLocation(m_scrollToFile, m_scrollToLocationId, true);
}
m_scrollToFile = nullptr;
m_scrollToLocationId = 0;
m_scrollToLine = 0;
emit scrollRequest();
}
void QtCodeNavigator::requestScrollToLine(QtCodeFile* file, unsigned int line)
void QtCodeNavigator::requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop)
{
m_scrollToFile = file;
m_scrollToLine = line;
ScrollRequest req;
req.filePath = filePath;
req.lineNumber = lineNumber;
req.locationId = locationId;
req.animated = animated;
req.onTop = onTop;
if (m_mode == MODE_SINGLE)
{
if (req.lineNumber || m_singleHasNewFile)
{
req.animated = false;
}
else
{
req.animated = (m_single->getCurrentFilePath() == filePath);
}
}
if (m_scrollRequest.filePath.empty())
{
m_scrollRequest = req;
}
m_singleHasNewFile = false;
}
void QtCodeNavigator::handleScrollRequest()
{
const ScrollRequest& req = m_scrollRequest;
if (req.filePath.empty())
{
return;
}
bool done = m_current->requestScroll(req.filePath, req.lineNumber, req.locationId, req.animated, req.onTop);
if (done)
{
m_scrollRequest = ScrollRequest();
}
}
void QtCodeNavigator::scrolled(int value)
{
MessageScrollCode(value).dispatch();
}
void QtCodeNavigator::scrollToSnippet(QtCodeSnippet* snippet, uint lineNumber, bool onTop)
{
if (lineNumber)
{
this->ensureWidgetVisibleAnimated(snippet, snippet->getLineRectForLineNumber(lineNumber), onTop);
}
MessageScrollCode(value, m_mode == MODE_LIST).dispatch();
}
void QtCodeNavigator::setValue()
{
m_scrollArea->verticalScrollBar()->setValue(m_value);
QAbstractScrollArea* area = m_current->getScrollArea();
if (area)
{
area->verticalScrollBar()->setValue(m_value);
}
}
void QtCodeNavigator::previousReference()
void QtCodeNavigator::previousReference(bool fromUI)
{
if (!m_references.size())
{
@@ -535,10 +576,10 @@ void QtCodeNavigator::previousReference()
m_refIndex--;
}
showCurrentReference();
showCurrentReference(fromUI);
}
void QtCodeNavigator::nextReference()
void QtCodeNavigator::nextReference(bool fromUI)
{
if (!m_references.size())
{
@@ -552,19 +593,71 @@ void QtCodeNavigator::nextReference()
m_refIndex = 1;
}
showCurrentReference();
showCurrentReference(fromUI);
}
void QtCodeNavigator::showCurrentReference()
void QtCodeNavigator::setModeList()
{
setMode(MODE_LIST);
}
void QtCodeNavigator::setModeSingle()
{
setMode(MODE_SINGLE);
}
void QtCodeNavigator::setMode(Mode mode)
{
if (m_mode == mode)
{
return;
}
m_mode = mode;
m_listButton->setChecked(mode == MODE_LIST);
m_fileButton->setChecked(mode == MODE_SINGLE);
switch (mode)
{
case MODE_SINGLE:
m_list->hide();
m_single->show();
m_current = m_single;
break;
case MODE_LIST:
m_single->hide();
m_list->show();
m_current = m_list;
break;
default:
LOG_ERROR("Wrong mode set in code navigator");
return;
}
ApplicationSettings::getInstance()->setCodeViewModeSingle(m_mode == MODE_SINGLE);
ApplicationSettings::getInstance()->save();
setupFiles();
showContents();
}
void QtCodeNavigator::showCurrentReference(bool fromUI)
{
const Reference& ref = m_references[m_refIndex - 1];
setCurrentActiveLocationIds(std::vector<Id>(1, ref.locationId));
showLocation(ref.filePath, ref.locationId, true);
updateFiles();
requestScroll(ref.filePath, 0, ref.locationId, fromUI, false);
emit scrollRequest();
updateRefLabel();
MessageShowReference(m_refIndex, ref.tokenId, ref.locationId).dispatch();
if (fromUI)
{
MessageShowReference(m_refIndex - 1, ref.tokenId, ref.locationId).dispatch();
}
}
void QtCodeNavigator::updateRefLabel()
@@ -585,51 +678,6 @@ void QtCodeNavigator::updateRefLabel()
m_nextButton->setEnabled(n > 1);
}
void QtCodeNavigator::ensureWidgetVisibleAnimated(QWidget *childWidget, QRectF rect, bool onTop)
{
QScrollArea* area = m_scrollArea;
if (!area->widget()->isAncestorOf(childWidget))
{
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(area->widget(), microFocus.topLeft()), microFocus.size())
: QRect(childWidget->mapTo(area->widget(), QPoint(0, 0)), childWidget->size());
const QRect visibleRect(-area->widget()->pos(), area->viewport()->size());
if (rect.height() > 0)
{
focusRect = QRect(childWidget->mapTo(area->widget(), rect.topLeft().toPoint()), rect.size().toSize());
focusRect.adjust(0, 0, 0, 100);
}
QScrollBar* scrollBar = area->verticalScrollBar();
int value = focusRect.center().y() - visibleRect.center().y();
if (onTop)
{
value = focusRect.top() - visibleRect.top();
if (value < 50)
{
value = 0;
}
}
if (scrollBar && value != 0)
{
QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value");
anim->setDuration(300);
anim->setStartValue(scrollBar->value());
anim->setEndValue(scrollBar->value() + value);
anim->setEasingCurve(QEasingCurve::InOutQuad);
anim->start();
}
}
void QtCodeNavigator::handleMessage(MessageCodeReference* message)
{
MessageCodeReference::ReferenceType type = message->type;
@@ -649,12 +697,32 @@ void QtCodeNavigator::handleMessage(MessageCodeReference* message)
);
}
void QtCodeNavigator::handleMessage(MessageFinishedParsing* message)
{
m_onQtThread(
[=]()
{
clearCaches();
}
);
}
void QtCodeNavigator::handleMessage(MessageSwitchColorScheme* message)
{
m_onQtThread(
[=]()
{
clearCaches();
}
);
}
void QtCodeNavigator::handleMessage(MessageWindowFocus* message)
{
m_onQtThread(
[=]()
{
m_list->onWindowFocus();
m_current->onWindowFocus();
}
);
}
+64 -19
View File
@@ -2,13 +2,16 @@
#define QT_CODE_NAVIGATOR_H
#include <QWidget>
#include <QScrollArea>
#include "data/ErrorInfo.h"
#include "data/location/LocationType.h"
#include "qt/element/QtCodeFileList.h"
#include "qt/utility/QtScrollSpeedChangeListener.h"
#include "qt/element/QtCodeFileSingle.h"
#include "qt/utility/QtThreadedFunctor.h"
#include "utility/messaging/MessageListener.h"
#include "utility/messaging/type/MessageCodeReference.h"
#include "utility/messaging/type/MessageFinishedParsing.h"
#include "utility/messaging/type/MessageSwitchColorScheme.h"
#include "utility/messaging/type/MessageWindowFocus.h"
class QLabel;
@@ -19,6 +22,8 @@ class TokenLocationFile;
class QtCodeNavigator
: public QWidget
, public MessageListener<MessageCodeReference>
, public MessageListener<MessageFinishedParsing>
, public MessageListener<MessageSwitchColorScheme>
, public MessageListener<MessageWindowFocus>
{
Q_OBJECT
@@ -30,7 +35,10 @@ public:
void addCodeSnippet(const CodeSnippetParams& params, bool insert = false);
void addFile(std::shared_ptr<TokenLocationFile> locationFile, int refCount, TimePoint modificationTime);
void addedFiles();
void clearCodeSnippets();
void clearCaches();
const std::vector<Id>& getCurrentActiveTokenIds() const;
void setCurrentActiveTokenIds(const std::vector<Id>& currentActiveTokenIds);
@@ -67,47 +75,85 @@ public:
void updateFiles();
void showContents();
void showLocation(const FilePath& filePath, Id locationId, bool scrollTo);
void scrollToValue(int value);
void scrollToValue(int value, bool inListMode);
void scrollToLine(const FilePath& filePath, unsigned int line);
void scrollToLocation(QtCodeFile* file, Id locationId, bool scrollTo);
void scrollToDefinition();
void scrollToSnippetIfRequested();
void requestScrollToLine(QtCodeFile* file, unsigned int line);
void requestScroll(const FilePath& filePath, uint lineNumber, Id locationId, bool animated, bool onTop);
signals:
void shouldScrollToSnippet(QtCodeSnippet* widget, uint lineNumber, bool onTop);
void scrollRequest();
private slots:
void handleScrollRequest();
void scrolled(int value);
void scrollToSnippet(QtCodeSnippet* snippet, uint lineNumber, bool onTop);
void setValue();
void previousReference();
void nextReference();
void previousReference(bool fromUI = true);
void nextReference(bool fromUI = true);
void setModeList();
void setModeSingle();
private:
enum Mode
{
MODE_NONE,
MODE_LIST,
MODE_SINGLE
};
void setMode(Mode mode);
struct Reference
{
Reference()
: tokenId(0)
, locationId(0)
{
}
FilePath filePath;
Id tokenId;
Id locationId;
LocationType locationType;
};
void showCurrentReference();
void showCurrentReference(bool fromUI);
void updateRefLabel();
void ensureWidgetVisibleAnimated(QWidget *childWidget, QRectF rect, bool onTop);
struct ScrollRequest
{
ScrollRequest()
: lineNumber(0)
, locationId(0)
, animated(false)
, onTop(false)
{
}
FilePath filePath;
uint lineNumber;
Id locationId;
bool animated;
bool onTop;
};
void handleMessage(MessageCodeReference* message);
void handleMessage(MessageFinishedParsing* message);
void handleMessage(MessageSwitchColorScheme* message);
void handleMessage(MessageWindowFocus* message);
QtThreadedLambdaFunctor m_onQtThread;
QScrollArea* m_scrollArea;
QtCodeNavigateable* m_current;
QtCodeFileList* m_list;
QtCodeFileSingle* m_single;
Mode m_mode;
std::vector<Id> m_currentActiveTokenIds;
std::vector<Id> m_currentActiveLocationIds;
@@ -119,6 +165,8 @@ private:
int m_value;
QPushButton* m_listButton;
QPushButton* m_fileButton;
QLabel* m_refLabel;
QPushButton* m_prevButton;
QPushButton* m_nextButton;
@@ -126,11 +174,8 @@ private:
std::vector<Reference> m_references;
size_t m_refIndex;
QtCodeFile* m_scrollToFile;
uint m_scrollToLine;
Id m_scrollToLocationId;
QtScrollSpeedChangeListener m_scrollSpeedChangeListener;
ScrollRequest m_scrollRequest;
bool m_singleHasNewFile;
};
#endif // QT_CODE_NAVIGATOR_H
+9 -4
View File
@@ -123,6 +123,11 @@ QtCodeFile* QtCodeSnippet::getFile() const
return m_file;
}
QtCodeArea* QtCodeSnippet::getArea() const
{
return m_codeArea.get();
}
uint QtCodeSnippet::getStartLineNumber() const
{
return m_codeArea->getStartLineNumber();
@@ -160,9 +165,9 @@ uint QtCodeSnippet::getLineNumberForLocationId(Id locationId) const
return m_codeArea->getLineNumberForLocationId(locationId);
}
int QtCodeSnippet::getStartLineNumberOfFirstActiveScope() const
uint QtCodeSnippet::getStartLineNumberOfFirstActiveLocationOfTokenId(Id tokenId) const
{
return m_codeArea->getStartLineNumberOfFirstActiveScope();
return m_codeArea->getStartLineNumberOfFirstActiveLocationOfTokenId(tokenId);
}
QRectF QtCodeSnippet::getLineRectForLineNumber(uint lineNumber) const
@@ -186,7 +191,7 @@ void QtCodeSnippet::clickedTitle()
getFile()->clickedMaximizeButton();
}
m_navigator->requestScrollToLine(getFile(), getStartLineNumber());
m_navigator->requestScroll(getFile()->getFilePath(), getStartLineNumber(), 0, true, false);
}
void QtCodeSnippet::clickedFooter()
@@ -195,7 +200,7 @@ void QtCodeSnippet::clickedFooter()
{
MessageShowScope(m_footerId, m_navigator->hasErrors()).dispatch();
m_navigator->requestScrollToLine(getFile(), getEndLineNumber());
m_navigator->requestScroll(getFile()->getFilePath(), getEndLineNumber(), 0, true, false);
}
}
+2 -1
View File
@@ -31,6 +31,7 @@ public:
virtual ~QtCodeSnippet();
QtCodeFile* getFile() const;
QtCodeArea* getArea() const;
uint getStartLineNumber() const;
uint getEndLineNumber() const;
@@ -43,7 +44,7 @@ public:
void setIsActiveFile(bool isActiveFile);
uint getLineNumberForLocationId(Id locationId) const;
int getStartLineNumberOfFirstActiveScope() const;
uint getStartLineNumberOfFirstActiveLocationOfTokenId(Id tokenId) const;
QRectF getLineRectForLineNumber(uint lineNumber) const;
std::string getCode() const;
+1
View File
@@ -6,6 +6,7 @@
#include <QFile>
#include <QFontDatabase>
#include <QPainter>
#include <QWidget>
#include "utility/file/FileSystem.h"
#include "utility/logging/logging.h"
+6 -2
View File
@@ -1,8 +1,12 @@
#ifndef UTILITY_QT_H
#define UTILITY_QT_H
#include <memory>
#include <qwidget.h>
#include <string>
class QColor;
class QPixmap;
class QString;
class QWidget;
namespace utility
{
+42 -46
View File
@@ -12,8 +12,6 @@
QtCodeView::QtCodeView(ViewLayout* viewLayout)
: CodeView(viewLayout)
, m_refreshViewFunctor(std::bind(&QtCodeView::doRefreshView, this))
, m_clearFunctor(std::bind(&QtCodeView::doClear, this))
, m_showCodeSnippetsFunctor(
std::bind(&QtCodeView::doShowCodeSnippets, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3))
, m_addCodeSnippetsFunctor(std::bind(&QtCodeView::doAddCodeSnippets, this, std::placeholders::_1, std::placeholders::_2))
@@ -23,10 +21,6 @@ QtCodeView::QtCodeView(ViewLayout* viewLayout)
, m_doShowActiveTokenIdsFunctor(std::bind(&QtCodeView::doShowActiveTokenIds, this, std::placeholders::_1))
, m_doShowActiveLocalSymbolIdsFunctor(std::bind(&QtCodeView::doShowActiveLocalSymbolIds, this, std::placeholders::_1))
, m_focusTokenIdsFunctor(std::bind(&QtCodeView::doFocusTokenIds, this, std::placeholders::_1))
, m_defocusTokenIdsFunctor(std::bind(&QtCodeView::doDefocusTokenIds, this))
, m_showContentsFunctor(std::bind(&QtCodeView::doShowContents, this))
, m_scrollToValueFunctor(std::bind(&QtCodeView::doScrollToValue, this, std::placeholders::_1))
, m_scrollToLineFunctor(std::bind(&QtCodeView::doScrollToLine, this, std::placeholders::_1, std::placeholders::_2))
{
m_widget = new QtCodeNavigator();
setStyleSheet();
@@ -47,12 +41,25 @@ void QtCodeView::initView()
void QtCodeView::refreshView()
{
m_refreshViewFunctor();
m_onQtThread(
[=]()
{
setStyleSheet();
QtCodeArea::clearAnnotationColors();
QtHighlighter::clearHighlightingRules();
}
);
}
void QtCodeView::clear()
{
m_clearFunctor();
m_onQtThread(
[=]()
{
m_widget->clearCodeSnippets();
}
);
m_errorInfos.clear();
}
@@ -106,22 +113,42 @@ void QtCodeView::focusTokenIds(const std::vector<Id>& focusedTokenIds)
void QtCodeView::defocusTokenIds()
{
m_defocusTokenIdsFunctor();
m_onQtThread(
[=]()
{
m_widget->defocusTokenIds();
}
);
}
void QtCodeView::showContents()
{
m_showContentsFunctor();
m_onQtThread(
[=]()
{
m_widget->showContents();
}
);
}
void QtCodeView::scrollToValue(int value)
void QtCodeView::scrollToValue(int value, bool inListMode)
{
m_scrollToValueFunctor(value);
m_onQtThread(
[=]()
{
m_widget->scrollToValue(value, inListMode);
}
);
}
void QtCodeView::scrollToLine(const FilePath filePath, unsigned int line)
{
m_scrollToLineFunctor(filePath, line);
m_onQtThread(
[=]()
{
m_widget->scrollToLine(filePath, line);
}
);
}
void QtCodeView::scrollToDefinition()
@@ -134,19 +161,6 @@ void QtCodeView::scrollToDefinition()
);
}
void QtCodeView::doRefreshView()
{
setStyleSheet();
QtCodeArea::clearAnnotationColors();
QtHighlighter::clearHighlightingRules();
}
void QtCodeView::doClear()
{
m_widget->clearCodeSnippets();
}
void QtCodeView::doShowCodeSnippets(
const std::vector<CodeSnippetParams>& snippets, const std::vector<Id>& activeTokenIds, bool setupFiles)
{
@@ -165,6 +179,8 @@ void QtCodeView::doShowCodeSnippets(
}
}
m_widget->addedFiles();
if (setupFiles)
{
m_widget->setupFiles();
@@ -228,26 +244,6 @@ void QtCodeView::doFocusTokenIds(const std::vector<Id>& focusedTokenIds)
m_widget->focusTokenIds(focusedTokenIds);
}
void QtCodeView::doDefocusTokenIds()
{
m_widget->defocusTokenIds();
}
void QtCodeView::doShowContents()
{
m_widget->showContents();
}
void QtCodeView::doScrollToValue(int value)
{
m_widget->scrollToValue(value);
}
void QtCodeView::doScrollToLine(const FilePath filePath, unsigned int line)
{
m_widget->scrollToLine(filePath, line);
}
void QtCodeView::setStyleSheet() const
{
utility::setWidgetBackgroundColor(m_widget, ColorScheme::getInstance()->getColor("code/background"));
+1 -16
View File
@@ -47,14 +47,11 @@ public:
virtual void showContents();
virtual void scrollToValue(int value);
virtual void scrollToValue(int value, bool inListMode);
virtual void scrollToLine(const FilePath filePath, unsigned int line);
virtual void scrollToDefinition();
private:
void doRefreshView();
void doClear();
void doShowCodeSnippets(
const std::vector<CodeSnippetParams>& snippets, const std::vector<Id>& activeTokenIds, bool setupFiles);
void doAddCodeSnippets(const std::vector<CodeSnippetParams>& snippets, bool insert);
@@ -67,17 +64,9 @@ private:
void doShowActiveLocalSymbolIds(const std::vector<Id>& localSymbolIds);
void doFocusTokenIds(const std::vector<Id>& focusedTokenIds);
void doDefocusTokenIds();
void doShowContents();
void doScrollToValue(int value);
void doScrollToLine(const FilePath filePath, unsigned int line);
void setStyleSheet() const;
QtThreadedFunctor<> m_refreshViewFunctor;
QtThreadedFunctor<> m_clearFunctor;
QtThreadedFunctor<const std::vector<CodeSnippetParams>&, const std::vector<Id>&, bool> m_showCodeSnippetsFunctor;
QtThreadedFunctor<const std::vector<CodeSnippetParams>&, bool> m_addCodeSnippetsFunctor;
QtThreadedFunctor<const FilePath, FileState> m_setFileStateFunctor;
@@ -85,10 +74,6 @@ private:
QtThreadedFunctor<const std::vector<Id>&> m_doShowActiveTokenIdsFunctor;
QtThreadedFunctor<const std::vector<Id>&> m_doShowActiveLocalSymbolIdsFunctor;
QtThreadedFunctor<const std::vector<Id>&> m_focusTokenIdsFunctor;
QtThreadedFunctor<> m_defocusTokenIdsFunctor;
QtThreadedFunctor<> m_showContentsFunctor;
QtThreadedFunctor<int> m_scrollToValueFunctor;
QtThreadedFunctor<const FilePath, unsigned int> m_scrollToLineFunctor;
QtThreadedLambdaFunctor m_onQtThread;