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:
@@ -72,6 +72,7 @@
|
||||
|
||||
<code>
|
||||
<background>#494949</background>
|
||||
<line>#CCCCCC</line>
|
||||
|
||||
<file>
|
||||
<background>#CCCCCC</background>
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
|
||||
<code>
|
||||
<background>white</background>
|
||||
<line>#B2B2B2</line>
|
||||
|
||||
<file>
|
||||
<background>#E0E0E0</background>
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
|
||||
<code>
|
||||
<background>#272728</background>
|
||||
<line>#CCC</line>
|
||||
|
||||
<file>
|
||||
<background>#777777</background>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <QFile>
|
||||
#include <QFontDatabase>
|
||||
#include <QPainter>
|
||||
#include <QWidget>
|
||||
|
||||
#include "utility/file/FileSystem.h"
|
||||
#include "utility/logging/logging.h"
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user