ui: Improved scrolling and layouting in QtCodeView and colored locations of active TokenId differently

This commit is contained in:
Eberhard Graether
2014-07-04 15:33:51 +02:00
parent 610aa2eb09
commit a70a9009cc
15 changed files with 142 additions and 33 deletions
+1
View File
@@ -5,5 +5,6 @@
<FontName>Courier</FontName> <FontName>Courier</FontName>
<FontSize>12</FontSize> <FontSize>12</FontSize>
<LinkColor>255 255 0 100</LinkColor> <LinkColor>255 255 0 100</LinkColor>
<ActiveLinkColor>0 255 0 100</ActiveLinkColor>
</code> </code>
</config> </config>
+4
View File
@@ -0,0 +1,4 @@
int main();
void foo();
int sum(int a, int b);
int diff(int a, int b);
+21 -1
View File
@@ -1,5 +1,9 @@
#include "header.h"
int main(); int main();
void foo(); void foo();
int sum(int a, int b);
int diff(int a, int b);
int main() int main()
{ {
@@ -9,7 +13,23 @@ int main()
return 0; return 0;
} }
int sum(int a, int b);
int diff(int a, int b);
void foo() void foo()
{ {
std::string foo = "bar"; std::string foo = "bar";
} }
int diff(int a, int b);
int sum(int a, int b)
{
return a + b;
}
int diff(int a, int b)
{
return a - b;
}
+6 -3
View File
@@ -13,6 +13,7 @@ QtCodeFile::QtCodeFile(QtCodeView* parentView, const std::string& fileName, QWid
QVBoxLayout* layout = new QVBoxLayout(this); QVBoxLayout* layout = new QVBoxLayout(this);
layout->setMargin(0); layout->setMargin(0);
layout->setSpacing(2); layout->setSpacing(2);
layout->setAlignment(Qt::AlignTop);
setLayout(layout); setLayout(layout);
QLabel* label = new QLabel(fileName.c_str(), this); QLabel* label = new QLabel(fileName.c_str(), this);
@@ -20,6 +21,7 @@ QtCodeFile::QtCodeFile(QtCodeView* parentView, const std::string& fileName, QWid
label->setStyleSheet("background-color: #E1E1E1; padding: 3px;"); label->setStyleSheet("background-color: #E1E1E1; padding: 3px;");
label->setFixedWidth(metrics.boundingRect(fileName.c_str()).width() + 12); label->setFixedWidth(metrics.boundingRect(fileName.c_str()).width() + 12);
label->setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
layout->addWidget(label); layout->addWidget(label);
} }
@@ -32,10 +34,11 @@ const std::string& QtCodeFile::getFileName() const
return m_fileName; return m_fileName;
} }
void QtCodeFile::addCodeSnippet(const std::string& str, const TokenLocationFile& locationFile, int startLineNumber) void QtCodeFile::addCodeSnippet(
{ const std::string& str, const TokenLocationFile& locationFile, int startLineNumber, Id activeTokenId
){
std::shared_ptr<QtCodeSnippet> snippet = std::shared_ptr<QtCodeSnippet> snippet =
std::make_shared<QtCodeSnippet>(m_parentView, str, locationFile, startLineNumber, this); std::make_shared<QtCodeSnippet>(m_parentView, str, locationFile, startLineNumber, activeTokenId, this);
layout()->addWidget(snippet.get()); layout()->addWidget(snippet.get());
m_snippets.push_back(snippet); m_snippets.push_back(snippet);
} }
+5 -1
View File
@@ -7,6 +7,8 @@
#include <QWidget> #include <QWidget>
#include "utility/types.h"
class QtCodeSnippet; class QtCodeSnippet;
class QtCodeView; class QtCodeView;
class TokenLocationFile; class TokenLocationFile;
@@ -19,7 +21,9 @@ public:
const std::string& getFileName() const; const std::string& getFileName() const;
void addCodeSnippet(const std::string& str, const TokenLocationFile& locationFile, int startLineNumber); void addCodeSnippet(
const std::string& str, const TokenLocationFile& locationFile, int startLineNumber, Id activeTokenId
);
private: private:
QtCodeView* m_parentView; QtCodeView* m_parentView;
+34 -4
View File
@@ -36,21 +36,26 @@ QtCodeSnippet::QtCodeSnippet(
const std::string& code, const std::string& code,
const TokenLocationFile& locationFile, const TokenLocationFile& locationFile,
int startLineNumber, int startLineNumber,
Id activeTokenId,
QWidget *parent QWidget *parent
) )
: QPlainTextEdit(parent) : QPlainTextEdit(parent)
, m_parentView(parentView) , m_parentView(parentView)
, m_startLineNumber(startLineNumber) , m_startLineNumber(startLineNumber)
, m_activeTokenId(activeTokenId)
{ {
m_lineNumberArea = new LineNumberArea(this); m_lineNumberArea = new LineNumberArea(this);
setReadOnly(true); setReadOnly(true);
setFrameStyle(QFrame::NoFrame); setFrameStyle(QFrame::NoFrame);
setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setLineWrapMode(QPlainTextEdit::NoWrap);
QFont font; QFont font;
font.setFamily(ApplicationSettings::getInstance()->getCodeFontName().c_str()); font.setFamily(ApplicationSettings::getInstance()->getCodeFontName().c_str());
font.setFixedPitch(true);
font.setPointSize(ApplicationSettings::getInstance()->getCodeFontSize()); font.setPointSize(ApplicationSettings::getInstance()->getCodeFontSize());
font.setFixedPitch(true);
setFont(font); setFont(font);
int tabWidth = ApplicationSettings::getInstance()->getCodeTabWidth(); int tabWidth = ApplicationSettings::getInstance()->getCodeTabWidth();
@@ -58,7 +63,14 @@ QtCodeSnippet::QtCodeSnippet(
setTabStopWidth(tabWidth * metrics.width(' ')); setTabStopWidth(tabWidth * metrics.width(' '));
m_highlighter = new QtHighlighter(document()); m_highlighter = new QtHighlighter(document());
setPlainText(QString::fromUtf8(code.c_str()));
std::string displayCode = code;
if (*code.rbegin() == '\n')
{
displayCode.pop_back();
}
setPlainText(QString::fromUtf8(displayCode.c_str()));
annotateText(locationFile); annotateText(locationFile);
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
@@ -66,6 +78,8 @@ QtCodeSnippet::QtCodeSnippet(
connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(clickTokenLocation())); connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(clickTokenLocation()));
connect(this, SIGNAL(selectionChanged()), this, SLOT(clearSelection())); connect(this, SIGNAL(selectionChanged()), this, SLOT(clearSelection()));
setMaximumHeight(sizeHint().height());
updateLineNumberAreaWidth(0); updateLineNumberAreaWidth(0);
} }
@@ -73,6 +87,13 @@ QtCodeSnippet::~QtCodeSnippet()
{ {
} }
QSize QtCodeSnippet::sizeHint() const
{
int width = lineNumberAreaWidth() + document()->size().width();
int height = (document()->size().height() + 1) * QFontMetrics(font()).lineSpacing();
return QSize(width, height);
}
void QtCodeSnippet::lineNumberAreaPaintEvent(QPaintEvent *event) void QtCodeSnippet::lineNumberAreaPaintEvent(QPaintEvent *event)
{ {
QPainter painter(m_lineNumberArea); QPainter painter(m_lineNumberArea);
@@ -99,7 +120,7 @@ void QtCodeSnippet::lineNumberAreaPaintEvent(QPaintEvent *event)
} }
} }
int QtCodeSnippet::lineNumberAreaWidth() int QtCodeSnippet::lineNumberAreaWidth() const
{ {
int digits = 1; int digits = 1;
int max = qMax(1, m_startLineNumber + blockCount()); int max = qMax(1, m_startLineNumber + blockCount());
@@ -138,7 +159,16 @@ void QtCodeSnippet::annotateText(const TokenLocationFile& locationFile)
QTextEdit::ExtraSelection selection; QTextEdit::ExtraSelection selection;
Colori color = ApplicationSettings::getInstance()->getCodeLinkColor(); Colori color;
if (location->getTokenId() == m_activeTokenId)
{
color = ApplicationSettings::getInstance()->getCodeActiveLinkColor();
}
else
{
color = ApplicationSettings::getInstance()->getCodeLinkColor();
}
selection.format.setBackground(QColor(color.r, color.g, color.b, color.a)); selection.format.setBackground(QColor(color.r, color.g, color.b, color.a));
selection.cursor = textCursor(); selection.cursor = textCursor();
+5 -1
View File
@@ -40,12 +40,15 @@ public:
const std::string& code, const std::string& code,
const TokenLocationFile& locationFile, const TokenLocationFile& locationFile,
int startLineNumber, int startLineNumber,
Id activeTokenId,
QWidget *parent = 0 QWidget *parent = 0
); );
virtual ~QtCodeSnippet(); virtual ~QtCodeSnippet();
QSize sizeHint() const;
void lineNumberAreaPaintEvent(QPaintEvent *event); void lineNumberAreaPaintEvent(QPaintEvent *event);
int lineNumberAreaWidth(); int lineNumberAreaWidth() const;
void annotateText(const TokenLocationFile& locationFile); void annotateText(const TokenLocationFile& locationFile);
@@ -73,6 +76,7 @@ private:
QWidget *m_lineNumberArea; QWidget *m_lineNumberArea;
const int m_startLineNumber; const int m_startLineNumber;
const Id m_activeTokenId;
std::vector<Annotation> m_annotations; std::vector<Annotation> m_annotations;
}; };
+21 -13
View File
@@ -1,7 +1,8 @@
#include "qt/view/QtCodeView.h" #include "qt/view/QtCodeView.h"
#include <iostream> #include <QFrame>
#include <QtWidgets> #include <QScrollArea>
#include <QVBoxLayout>
#include "data/location/TokenLocationFile.h" #include "data/location/TokenLocationFile.h"
#include "qt/element/QtCodeFile.h" #include "qt/element/QtCodeFile.h"
@@ -13,7 +14,7 @@
QtCodeView::QtCodeView(ViewLayout* viewLayout) QtCodeView::QtCodeView(ViewLayout* viewLayout)
: CodeView(viewLayout) : CodeView(viewLayout)
, m_clearCodeSnippetsFunctor(std::bind(&QtCodeView::doClearCodeSnippets, this)) , m_clearCodeSnippetsFunctor(std::bind(&QtCodeView::doClearCodeSnippets, this))
, m_addCodeSnippetFunctor(std::bind(&QtCodeView::doAddCodeSnippet, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)) , m_addCodeSnippetFunctor(std::bind(&QtCodeView::doAddCodeSnippet, this, std::placeholders::_1))
{ {
} }
@@ -23,7 +24,7 @@ QtCodeView::~QtCodeView()
void QtCodeView::createWidgetWrapper() void QtCodeView::createWidgetWrapper()
{ {
setWidgetWrapper(std::make_shared<QtWidgetWrapper>(std::make_shared<QFrame>())); setWidgetWrapper(std::make_shared<QtWidgetWrapper>(std::make_shared<QScrollArea>()));
} }
void QtCodeView::initGui() void QtCodeView::initGui()
@@ -31,15 +32,22 @@ void QtCodeView::initGui()
QWidget* widget = QtWidgetWrapper::getWidgetOfView(this); QWidget* widget = QtWidgetWrapper::getWidgetOfView(this);
utility::setWidgetBackgroundColor(widget, Colori(255, 125, 0, 255)); utility::setWidgetBackgroundColor(widget, Colori(255, 125, 0, 255));
QBoxLayout* layout = new QBoxLayout(QBoxLayout::TopToBottom); QScrollArea* scroll = dynamic_cast<QScrollArea*>(widget);
layout->setSpacing(3); m_frame = std::make_shared<QFrame>(scroll);
QVBoxLayout* layout = new QVBoxLayout(m_frame.get());
layout->setSpacing(10);
layout->setContentsMargins(3, 3, 3, 3); layout->setContentsMargins(3, 3, 3, 3);
widget->setLayout(layout); layout->setAlignment(Qt::AlignTop);
m_frame->setLayout(layout);
scroll->setWidgetResizable(true);
scroll->setWidget(m_frame.get());
} }
void QtCodeView::addCodeSnippet(const std::string& str, const TokenLocationFile& locationFile, int startLineNumber) void QtCodeView::addCodeSnippet(const CodeSnippetParams params)
{ {
m_addCodeSnippetFunctor(str, locationFile, startLineNumber); m_addCodeSnippetFunctor(params);
} }
void QtCodeView::clearCodeSnippets() void QtCodeView::clearCodeSnippets()
@@ -53,9 +61,9 @@ void QtCodeView::activateToken(Id tokenId) const
message.dispatch(); message.dispatch();
} }
void QtCodeView::doAddCodeSnippet(const std::string& str, const TokenLocationFile& locationFile, int startLineNumber) void QtCodeView::doAddCodeSnippet(const CodeSnippetParams params)
{ {
std::string fileName = FileSystem::fileName(locationFile.getFilePath()); std::string fileName = FileSystem::fileName(params.locationFile.getFilePath());
QtCodeFile* file = nullptr; QtCodeFile* file = nullptr;
for (std::shared_ptr<QtCodeFile> filePtr : m_files) for (std::shared_ptr<QtCodeFile> filePtr : m_files)
@@ -74,10 +82,10 @@ void QtCodeView::doAddCodeSnippet(const std::string& str, const TokenLocationFil
m_files.push_back(filePtr); m_files.push_back(filePtr);
file = filePtr.get(); file = filePtr.get();
widget->layout()->addWidget(file); m_frame->layout()->addWidget(file);
} }
file->addCodeSnippet(str, locationFile, startLineNumber); file->addCodeSnippet(params.code, params.locationFile, params.startLineNumber, params.activeTokenId);
} }
void QtCodeView::doClearCodeSnippets() void QtCodeView::doClearCodeSnippets()
+5 -3
View File
@@ -8,6 +8,7 @@
#include "qt/utility/QtThreadedFunctor.h" #include "qt/utility/QtThreadedFunctor.h"
#include "utility/types.h" #include "utility/types.h"
class QFrame;
class QtCodeFile; class QtCodeFile;
class QtCodeView: public CodeView class QtCodeView: public CodeView
@@ -21,19 +22,20 @@ public:
virtual void initGui(); virtual void initGui();
// CodeView implementation // CodeView implementation
virtual void addCodeSnippet(const std::string& str, const TokenLocationFile& locationFile, int startLineNumber); virtual void addCodeSnippet(const CodeSnippetParams params);
virtual void clearCodeSnippets(); virtual void clearCodeSnippets();
void activateToken(Id tokenId) const; void activateToken(Id tokenId) const;
private: private:
void doAddCodeSnippet(const std::string& str, const TokenLocationFile& locationFile, int startLineNumber); void doAddCodeSnippet(const CodeSnippetParams params);
void doClearCodeSnippets(); void doClearCodeSnippets();
std::shared_ptr<QFrame> m_frame;
std::vector<std::shared_ptr<QtCodeFile> > m_files; std::vector<std::shared_ptr<QtCodeFile> > m_files;
QtThreadedFunctor<void> m_clearCodeSnippetsFunctor; QtThreadedFunctor<void> m_clearCodeSnippetsFunctor;
QtThreadedFunctor<const std::string&, const TokenLocationFile&, int> m_addCodeSnippetFunctor; QtThreadedFunctor<const CodeSnippetParams> m_addCodeSnippetFunctor;
}; };
# endif // QT_CODE_VIEW_H # endif // QT_CODE_VIEW_H
+10
View File
@@ -58,6 +58,16 @@ void ApplicationSettings::setCodeLinkColor(Colori codeLinkColor)
setValue<std::string>("code/LinkColor", codeLinkColor.toString()); setValue<std::string>("code/LinkColor", codeLinkColor.toString());
} }
Colori ApplicationSettings::getCodeActiveLinkColor() const
{
return Colori::fromString(getValue<std::string>("code/ActiveLinkColor", Colori(0, 255, 0, 100).toString()));
}
void ApplicationSettings::setCodeActiveLinkColor(Colori codeLinkColor)
{
setValue<std::string>("code/ActiveLinkColor", codeLinkColor.toString());
}
ApplicationSettings::ApplicationSettings() ApplicationSettings::ApplicationSettings()
{ {
} }
+3
View File
@@ -25,6 +25,9 @@ public:
Colori getCodeLinkColor() const; Colori getCodeLinkColor() const;
void setCodeLinkColor(Colori codeLinkColor); void setCodeLinkColor(Colori codeLinkColor);
Colori getCodeActiveLinkColor() const;
void setCodeActiveLinkColor(Colori codeLinkColor);
private: private:
ApplicationSettings(); ApplicationSettings();
ApplicationSettings(const ApplicationSettings&); ApplicationSettings(const ApplicationSettings&);
@@ -29,6 +29,7 @@ void CodeController::setActiveTokenId(Id id)
collection.forEachTokenLocation([&] (TokenLocation* tokenLocation) -> void { collection.forEachTokenLocation([&] (TokenLocation* tokenLocation) -> void {
if (tokenLocation->isStartTokenLocation()) if (tokenLocation->isStartTokenLocation())
{ {
CodeView::CodeSnippetParams params;
const std::string filePath = tokenLocation->getFilePath(); const std::string filePath = tokenLocation->getFilePath();
std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(filePath); std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(filePath);
@@ -37,14 +38,17 @@ void CodeController::setActiveTokenId(Id id)
textAccess->getLineCount(), tokenLocation->getEndTokenLocation()->getLineNumber() + lineRadius textAccess->getLineCount(), tokenLocation->getEndTokenLocation()->getLineNumber() + lineRadius
); );
std::string text;
for (std::string line: textAccess->getLines(firstLineNumber, lastLineNumber)) for (std::string line: textAccess->getLines(firstLineNumber, lastLineNumber))
{ {
text += line; params.code += line;
} }
TokenLocationFile tokenLocationFile = m_locationAccess->getTokenLocationsForLinesInFile(filePath, firstLineNumber, lastLineNumber); params.startLineNumber = firstLineNumber;
getView()->addCodeSnippet(text, tokenLocationFile, firstLineNumber); params.locationFile =
m_locationAccess->getTokenLocationsForLinesInFile(filePath, firstLineNumber, lastLineNumber);
params.activeTokenId = id;
getView()->addCodeSnippet(params);
} }
}); });
} }
+5
View File
@@ -2,6 +2,11 @@
#include "component/controller/CodeController.h" #include "component/controller/CodeController.h"
CodeView::CodeSnippetParams::CodeSnippetParams()
: locationFile("")
{
}
CodeView::CodeView(ViewLayout* viewLayout) CodeView::CodeView(ViewLayout* viewLayout)
: View(viewLayout, Vec2i(100, 100)) : View(viewLayout, Vec2i(100, 100))
{ {
+13 -2
View File
@@ -2,19 +2,30 @@
#define CODE_VIEW_H #define CODE_VIEW_H
#include "component/view/View.h" #include "component/view/View.h"
#include "data/location/TokenLocationFile.h"
#include "utility/types.h"
class CodeController; class CodeController;
class TokenLocationFile;
class CodeView: public View class CodeView: public View
{ {
public: public:
struct CodeSnippetParams
{
CodeSnippetParams();
std::string code;
TokenLocationFile locationFile;
int startLineNumber;
Id activeTokenId;
};
CodeView(ViewLayout* viewLayout); CodeView(ViewLayout* viewLayout);
virtual ~CodeView(); virtual ~CodeView();
virtual std::string getName() const; virtual std::string getName() const;
virtual void addCodeSnippet(const std::string& str, const TokenLocationFile& locationFile, int startLineNumber) = 0; virtual void addCodeSnippet(const CodeSnippetParams params) = 0;
virtual void clearCodeSnippets() = 0; virtual void clearCodeSnippets() = 0;
private: private:
+1 -1
View File
@@ -44,7 +44,7 @@ private:
TokenLocationLine* createTokenLocationLine(unsigned int lineNumber); TokenLocationLine* createTokenLocationLine(unsigned int lineNumber);
std::map<unsigned int, std::shared_ptr<TokenLocationLine> > m_lines; std::map<unsigned int, std::shared_ptr<TokenLocationLine> > m_lines;
const std::string m_filePath; std::string m_filePath;
}; };
std::ostream& operator<<(std::ostream& ostream, const TokenLocationFile& file); std::ostream& operator<<(std::ostream& ostream, const TokenLocationFile& file);