ui: clicking snippet title to show full scope

This change lets the user click the snippet title in the CodeView to insert the full scope. The existing snippets are
merged with the new lines accordingly.
This commit is contained in:
Eberhard Graether
2015-07-20 00:57:19 +02:00
parent e5a8609d7a
commit 73aa6080aa
23 changed files with 313 additions and 26 deletions
+17 -1
View File
@@ -52,6 +52,7 @@ QtCodeArea::QtCodeArea(
: QPlainTextEdit(parent)
, m_fileWidget(file)
, m_startLineNumber(startLineNumber)
, m_locationFile(locationFile)
, m_hoveredAnnotation(nullptr)
, m_digits(0)
{
@@ -102,6 +103,21 @@ QSize QtCodeArea::sizeHint() const
return QSize(320, height + 1);
}
uint QtCodeArea::getStartLineNumber() const
{
return m_startLineNumber;
}
uint QtCodeArea::getEndLineNumber() const
{
return m_startLineNumber + blockCount() - 1;
}
std::shared_ptr<TokenLocationFile> QtCodeArea::getTokenLocationFile() const
{
return m_locationFile;
}
void QtCodeArea::lineNumberAreaPaintEvent(QPaintEvent *event)
{
QPainter painter(m_lineNumberArea);
@@ -331,7 +347,7 @@ void QtCodeArea::createAnnotations(std::shared_ptr<TokenLocationFile> locationFi
[&](TokenLocation* startLocation)
{
Annotation annotation;
unsigned int endLineNumber = m_startLineNumber + blockCount() - 1;
uint endLineNumber = getEndLineNumber();
if (startLocation->getLineNumber() <= endLineNumber)
{
if (startLocation->getLineNumber() < m_startLineNumber)
+7
View File
@@ -51,6 +51,11 @@ public:
virtual QSize sizeHint() const;
uint getStartLineNumber() const;
uint getEndLineNumber() const;
std::shared_ptr<TokenLocationFile> getTokenLocationFile() const;
void lineNumberAreaPaintEvent(QPaintEvent *event);
int lineNumberDigits() const;
int lineNumberAreaWidth() const;
@@ -115,6 +120,8 @@ private:
const uint m_startLineNumber;
std::shared_ptr<TokenLocationFile> m_locationFile;
std::vector<Annotation> m_annotations;
std::vector<ScopeAnnotation> m_scopeAnnotations;
+70 -17
View File
@@ -78,6 +78,9 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeFileList* parent)
m_minimizePlaceholder->setMinimumHeight(5);
layout->addWidget(m_minimizePlaceholder);
m_snippetLayout = new QVBoxLayout();
layout->addLayout(m_snippetLayout);
update();
}
@@ -113,13 +116,14 @@ const std::vector<std::string>& QtCodeFile::getErrorMessages() const
void QtCodeFile::addCodeSnippet(
uint startLineNumber,
const std::string& title,
Id titleId,
const std::string& code,
std::shared_ptr<TokenLocationFile> locationFile
){
std::shared_ptr<QtCodeSnippet> snippet(
new QtCodeSnippet(startLineNumber, title, code, locationFile, this));
new QtCodeSnippet(startLineNumber, title, titleId, code, locationFile, this));
layout()->addWidget(snippet.get());
m_snippetLayout->addWidget(snippet.get());
if (locationFile->isWholeCopy)
{
@@ -132,26 +136,53 @@ void QtCodeFile::addCodeSnippet(
m_snippets.push_back(snippet);
if (m_snippets.size() == 1)
updateSnippets();
}
QWidget* QtCodeFile::insertCodeSnippet(
uint startLineNumber,
const std::string& title,
Id titleId,
const std::string& code,
std::shared_ptr<TokenLocationFile> locationFile
){
std::shared_ptr<QtCodeSnippet> snippet(
new QtCodeSnippet(startLineNumber, title, titleId, code, locationFile, this));
size_t i = 0;
while (i < m_snippets.size())
{
snippet->setProperty("isFirst", true);
uint start = snippet->getStartLineNumber();
uint end = snippet->getEndLineNumber();
std::shared_ptr<QtCodeSnippet> s = m_snippets[i];
if (s->getEndLineNumber() + 1 < start)
{
i++;
continue;
}
else if (s->getStartLineNumber() > end + 1)
{
break;
}
else if (s->getStartLineNumber() < start || s->getEndLineNumber() > end)
{
snippet = QtCodeSnippet::merged(snippet.get(), s.get(), this);
}
s->hide();
m_snippetLayout->removeWidget(s.get());
m_snippets.erase(m_snippets.begin() + i);
}
int maxDigits = 1;
for (std::shared_ptr<QtCodeSnippet> snippet : m_snippets)
{
snippet->setProperty("isLast", false);
maxDigits = qMax(maxDigits, snippet->lineNumberDigits());
}
m_snippetLayout->insertWidget(i, snippet.get());
m_snippets.insert(m_snippets.begin() + i, snippet);
for (std::shared_ptr<QtCodeSnippet> snippet : m_snippets)
{
snippet->updateLineNumberAreaWidthForDigits(maxDigits);
}
updateSnippets();
snippet->setProperty("isLast", true);
clickedSnippetButton();
return snippet.get();
}
QWidget* QtCodeFile::findFirstActiveSnippet() const
@@ -251,3 +282,25 @@ void QtCodeFile::clickedMaximizeButton()
m_minimizePlaceholder->hide();
}
void QtCodeFile::updateSnippets()
{
int maxDigits = 1;
for (std::shared_ptr<QtCodeSnippet> snippet : m_snippets)
{
snippet->setProperty("isFirst", false);
snippet->setProperty("isLast", false);
maxDigits = qMax(maxDigits, snippet->lineNumberDigits());
}
for (std::shared_ptr<QtCodeSnippet> snippet : m_snippets)
{
snippet->updateLineNumberAreaWidthForDigits(maxDigits);
}
m_snippets.front()->setProperty("isFirst", true);
m_snippets.back()->setProperty("isLast", true);
clickedSnippetButton();
}
+13
View File
@@ -13,6 +13,7 @@
class QPushButton;
class QtCodeFileList;
class QtCodeSnippet;
class QVBoxLayout;
class TokenLocationFile;
class QtCodeFile
@@ -33,6 +34,15 @@ public:
void addCodeSnippet(
uint startLineNumber,
const std::string& title,
Id titleId,
const std::string& code,
std::shared_ptr<TokenLocationFile> locationFile
);
QWidget* insertCodeSnippet(
uint startLineNumber,
const std::string& title,
Id titleId,
const std::string& code,
std::shared_ptr<TokenLocationFile> locationFile
);
@@ -50,6 +60,8 @@ private slots:
void clickedMaximizeButton();
private:
void updateSnippets();
QtCodeFileList* m_parent;
QPushButton* m_title;
@@ -57,6 +69,7 @@ private:
QPushButton* m_snippetButton;
QPushButton* m_maximizeButton;
QVBoxLayout* m_snippetLayout;
std::vector<std::shared_ptr<QtCodeSnippet>> m_snippets;
std::shared_ptr<QtCodeSnippet> m_fileSnippet;
QWidget* m_minimizePlaceholder;
+12 -2
View File
@@ -43,8 +43,10 @@ QSize QtCodeFileList::sizeHint() const
void QtCodeFileList::addCodeSnippet(
uint startLineNumber,
const std::string& title,
Id titleId,
const std::string& code,
std::shared_ptr<TokenLocationFile> locationFile
std::shared_ptr<TokenLocationFile> locationFile,
bool insert
){
FilePath filePath = locationFile->getFilePath();
QtCodeFile* file = nullptr;
@@ -67,7 +69,15 @@ void QtCodeFileList::addCodeSnippet(
m_frame->layout()->addWidget(file);
}
file->addCodeSnippet(startLineNumber, title, code, locationFile);
if (insert)
{
QWidget* snippet = file->insertCodeSnippet(startLineNumber, title, titleId, code, locationFile);
emit shouldScrollToSnippet(snippet);
}
else
{
file->addCodeSnippet(startLineNumber, title, titleId, code, locationFile);
}
}
void QtCodeFileList::clearCodeSnippets()
+3 -1
View File
@@ -29,8 +29,10 @@ public:
void addCodeSnippet(
uint startLineNumber,
const std::string& title,
Id titleId,
const std::string& code,
std::shared_ptr<TokenLocationFile> locationFile
std::shared_ptr<TokenLocationFile> locationFile,
bool insert = false
);
void clearCodeSnippets();
+69
View File
@@ -3,16 +3,65 @@
#include <QBoxLayout>
#include <QPushButton>
#include "utility/messaging/type/MessageShowScope.h"
#include "utility/text/TextAccess.h"
#include "data/location/TokenLocationFile.h"
#include "qt/element/QtCodeFile.h"
std::shared_ptr<QtCodeSnippet> QtCodeSnippet::merged(QtCodeSnippet* a, QtCodeSnippet* b, QtCodeFile* file)
{
QtCodeSnippet* first = a->getStartLineNumber() < b->getStartLineNumber() ? a : b;
QtCodeSnippet* second = a->getStartLineNumber() > b->getStartLineNumber() ? a : b;
TokenLocationFile* aFile = a->m_codeArea->getTokenLocationFile().get();
TokenLocationFile* bFile = b->m_codeArea->getTokenLocationFile().get();
std::shared_ptr<TokenLocationFile> locationFile = std::make_shared<TokenLocationFile>(aFile->getFilePath());
aFile->forEachTokenLocation(
[&locationFile](TokenLocation* loc)
{
locationFile->addTokenLocationAsPlainCopy(loc);
}
);
bFile->forEachTokenLocation(
[&locationFile](TokenLocation* loc)
{
locationFile->addTokenLocationAsPlainCopy(loc);
}
);
std::string code;
std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(locationFile->getFilePath().str());
for (const std::string& line: textAccess->getLines(first->getStartLineNumber(), second->getEndLineNumber()))
{
code += line;
}
std::string title = first->m_title ? first->m_title->text().toStdString() : "";
return std::make_shared<QtCodeSnippet>(
first->getStartLineNumber(),
title,
first->m_titleId,
code,
locationFile,
file
);
}
QtCodeSnippet::QtCodeSnippet(
uint startLineNumber,
const std::string& title,
Id titleId,
const std::string& code,
std::shared_ptr<TokenLocationFile> locationFile,
QtCodeFile* file
)
: QFrame(file)
, m_titleId(titleId)
, m_dots(nullptr)
, m_title(nullptr)
, m_codeArea(std::make_shared<QtCodeArea>(startLineNumber, code, locationFile, file, this))
@@ -44,6 +93,8 @@ QtCodeSnippet::QtCodeSnippet(
m_title->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac
m_title->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
titleLayout->addWidget(m_title);
connect(m_title, SIGNAL(clicked()), this, SLOT(clickedTitle()));
}
layout->addWidget(m_codeArea.get());
@@ -54,6 +105,16 @@ QtCodeSnippet::~QtCodeSnippet()
{
}
uint QtCodeSnippet::getStartLineNumber() const
{
return m_codeArea->getStartLineNumber();
}
uint QtCodeSnippet::getEndLineNumber() const
{
return m_codeArea->getEndLineNumber();
}
int QtCodeSnippet::lineNumberDigits() const
{
return m_codeArea->lineNumberDigits();
@@ -76,6 +137,14 @@ bool QtCodeSnippet::isActive() const
return m_codeArea->isActive();
}
void QtCodeSnippet::clickedTitle()
{
if (m_titleId)
{
MessageShowScope(m_titleId).dispatch();
}
}
void QtCodeSnippet::updateDots()
{
if (!m_dots)
+11
View File
@@ -20,15 +20,21 @@ class QtCodeSnippet
Q_OBJECT
public:
static std::shared_ptr<QtCodeSnippet> merged(QtCodeSnippet* a, QtCodeSnippet* b, QtCodeFile* file);
QtCodeSnippet(
uint startLineNumber,
const std::string& title,
Id titleId,
const std::string& code,
std::shared_ptr<TokenLocationFile> locationFile,
QtCodeFile* file
);
virtual ~QtCodeSnippet();
uint getStartLineNumber() const;
uint getEndLineNumber() const;
int lineNumberDigits() const;
void updateLineNumberAreaWidthForDigits(int digits);
@@ -36,9 +42,14 @@ public:
bool isActive() const;
private slots:
void clickedTitle();
private:
void updateDots();
Id m_titleId;
QPushButton* m_dots;
QPushButton* m_title;
std::shared_ptr<QtCodeArea> m_codeArea;
+15 -2
View File
@@ -11,6 +11,7 @@ QtCodeView::QtCodeView(ViewLayout* viewLayout)
: CodeView(viewLayout)
, m_refreshViewFunctor(std::bind(&QtCodeView::doRefreshView, this))
, m_showCodeSnippetsFunctor(std::bind(&QtCodeView::doShowCodeSnippets, this, std::placeholders::_1))
, m_addCodeSnippetFunctor(std::bind(&QtCodeView::doAddCodeSnippet, this, std::placeholders::_1))
, m_showCodeFileFunctor(std::bind(&QtCodeView::doShowCodeFile, this, std::placeholders::_1))
, m_doScrollToFirstActiveSnippetFunctor(std::bind(&QtCodeView::doScrollToFirstActiveSnippet, this))
, m_focusTokenFunctor(std::bind(&QtCodeView::doFocusToken, this, std::placeholders::_1))
@@ -53,6 +54,11 @@ void QtCodeView::showCodeSnippets(const std::vector<CodeSnippetParams>& snippets
m_showCodeSnippetsFunctor(snippets);
}
void QtCodeView::addCodeSnippet(const CodeSnippetParams& snippet)
{
m_addCodeSnippetFunctor(snippet);
}
void QtCodeView::showCodeFile(const CodeSnippetParams& params)
{
m_showCodeFileFunctor(params);
@@ -88,15 +94,22 @@ void QtCodeView::doShowCodeSnippets(const std::vector<CodeSnippetParams>& snippe
for (const CodeSnippetParams& params : snippets)
{
m_widget->addCodeSnippet(params.startLineNumber, params.title, params.code, params.locationFile);
m_widget->addCodeSnippet(params.startLineNumber, params.title, params.titleId, params.code, params.locationFile);
}
setStyleSheet(); // so property "isLast" of QtCodeSnippet is computed correctly
}
void QtCodeView::doAddCodeSnippet(const CodeSnippetParams& snippet)
{
m_widget->addCodeSnippet(snippet.startLineNumber, snippet.title, snippet.titleId, snippet.code, snippet.locationFile, true);
setStyleSheet(); // so property "isLast" of QtCodeSnippet is computed correctly
}
void QtCodeView::doShowCodeFile(const CodeSnippetParams& params)
{
m_widget->addCodeSnippet(1, params.title, params.code, params.locationFile);
m_widget->addCodeSnippet(1, params.title, 0, params.code, params.locationFile);
}
void QtCodeView::doScrollToFirstActiveSnippet()
+3
View File
@@ -30,6 +30,7 @@ public:
virtual void setErrorMessages(const std::vector<std::string>& errorMessages);
virtual void showCodeSnippets(const std::vector<CodeSnippetParams>& snippets);
virtual void addCodeSnippet(const CodeSnippetParams& snippet);
virtual void showCodeFile(const CodeSnippetParams& params);
virtual void scrollToFirstActiveSnippet();
@@ -41,6 +42,7 @@ private:
void doRefreshView();
void doShowCodeSnippets(const std::vector<CodeSnippetParams>& snippets);
void doAddCodeSnippet(const CodeSnippetParams& snippet);
void doShowCodeFile(const CodeSnippetParams& params);
void doScrollToFirstActiveSnippet();
@@ -52,6 +54,7 @@ private:
QtThreadedFunctor<> m_refreshViewFunctor;
QtThreadedFunctor<const std::vector<CodeSnippetParams>&> m_showCodeSnippetsFunctor;
QtThreadedFunctor<const CodeSnippetParams&> m_addCodeSnippetFunctor;
QtThreadedFunctor<const CodeSnippetParams&> m_showCodeFileFunctor;
QtThreadedFunctor<> m_doScrollToFirstActiveSnippetFunctor;
QtThreadedFunctor<const Id&> m_focusTokenFunctor;
+1
View File
@@ -275,6 +275,7 @@ add_files(
utility/messaging/type/MessageSearch.h
utility/messaging/type/MessageSearchAutocomplete.h
utility/messaging/type/MessageShowFile.h
utility/messaging/type/MessageShowScope.h
utility/messaging/type/MessageStatus.h
utility/messaging/type/MessageSwitchColorScheme.h
utility/messaging/type/MessageUndo.h
@@ -114,7 +114,6 @@ void CodeController::handleMessage(MessageShowFile* message)
params.endLineNumber = message->endLineNumber;
std::shared_ptr<TextAccess> textAccess = TextAccess::createFromFile(message->filePath);
params.lineCount = textAccess->getLineCount();
params.code = textAccess->getText();
params.locationFile = m_storageAccess->getTokenLocationsForFile(message->filePath);
@@ -122,6 +121,29 @@ void CodeController::handleMessage(MessageShowFile* message)
getView()->showCodeFile(params);
}
void CodeController::handleMessage(MessageShowScope* message)
{
TokenLocationCollection collection =
m_storageAccess->getTokenLocationsForLocationIds(std::vector<Id>(1, message->scopeLocationId));
TokenLocation* location = collection.findTokenLocationById(message->scopeLocationId);
if (!location || !location->isScopeTokenLocation() || !location->getOtherTokenLocation())
{
LOG_ERROR("MessageShowScope did not contain a valid scope location id");
return;
}
std::vector<CodeView::CodeSnippetParams> snippets = getSnippetsForActiveTokenLocations(collection, 0);
if (snippets.size() != 1)
{
LOG_ERROR("MessageShowScope didn't result in one single snippet to be created");
return;
}
getView()->addCodeSnippet(snippets[0]);
}
CodeView* CodeController::getView()
{
return Controller::getView<CodeView>();
@@ -228,6 +250,7 @@ std::vector<CodeView::CodeSnippetParams> CodeController::getSnippetsForFile(std:
[&](TokenLocation* location)
{
params.title = m_storageAccess->getNameForNodeWithId(location->getTokenId());
params.titleId = location->getId();
}
);
}
@@ -10,6 +10,7 @@
#include "utility/messaging/type/MessageFocusIn.h"
#include "utility/messaging/type/MessageFocusOut.h"
#include "utility/messaging/type/MessageShowFile.h"
#include "utility/messaging/type/MessageShowScope.h"
#include "utility/types.h"
#include "component/controller/helper/SnippetMerger.h"
@@ -27,6 +28,7 @@ class CodeController
, public MessageListener<MessageFocusIn>
, public MessageListener<MessageFocusOut>
, public MessageListener<MessageShowFile>
, public MessageListener<MessageShowScope>
{
public:
CodeController(StorageAccess* storageAccess);
@@ -40,6 +42,7 @@ private:
virtual void handleMessage(MessageFocusIn* message);
virtual void handleMessage(MessageFocusOut* message);
virtual void handleMessage(MessageShowFile* message);
virtual void handleMessage(MessageShowScope* message);
CodeView* getView();
+1 -1
View File
@@ -6,7 +6,7 @@
CodeView::CodeSnippetParams::CodeSnippetParams()
: startLineNumber(0)
, endLineNumber(0)
, lineCount(0)
, titleId(0)
, locationFile(std::make_shared<TokenLocationFile>(""))
, isActive(false)
, isDeclaration(false)
+3 -1
View File
@@ -21,11 +21,12 @@ public:
uint startLineNumber;
uint endLineNumber;
uint lineCount;
std::string title;
std::string code;
Id titleId;
std::shared_ptr<TokenLocationFile> locationFile;
bool isActive;
@@ -41,6 +42,7 @@ public:
virtual void setErrorMessages(const std::vector<std::string>& errorMessages) = 0;
virtual void showCodeSnippets(const std::vector<CodeSnippetParams>& snippets) = 0;
virtual void addCodeSnippet(const CodeSnippetParams& snippet) = 0;
virtual void showCodeFile(const CodeSnippetParams& params) = 0;
virtual void scrollToFirstActiveSnippet() = 0;
+17
View File
@@ -997,6 +997,23 @@ TokenLocationCollection Storage::getTokenLocationsForTokenIds(const std::vector<
return ret;
}
TokenLocationCollection Storage::getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const
{
TokenLocationCollection ret;
for (Id locationId : locationIds)
{
TokenLocation* location = m_locationCollection.findTokenLocationById(locationId);
if (location->getOtherTokenLocation())
{
ret.addTokenLocationAsPlainCopy(location);
ret.addTokenLocationAsPlainCopy(location->getOtherTokenLocation());
}
}
return ret;
}
std::shared_ptr<TokenLocationFile> Storage::getTokenLocationsForFile(const std::string& filePath) const
{
std::shared_ptr<TokenLocationFile> ret = std::make_shared<TokenLocationFile>(filePath);
+1
View File
@@ -126,6 +126,7 @@ public:
virtual std::vector<Id> getTokenIdsForAggregationEdge(Id aggregationId) const;
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const;
virtual TokenLocationCollection getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const;
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForFile(const std::string& filePath) const;
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForLinesInFile(
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
+1
View File
@@ -39,6 +39,7 @@ public:
virtual std::vector<Id> getTokenIdsForAggregationEdge(Id aggregationId) const = 0;
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const = 0;
virtual TokenLocationCollection getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const = 0;
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForFile(const std::string& filePath) const = 0;
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForLinesInFile(
const std::string& filePath, uint firstLineNumber, uint lastLineNumber) const = 0;
@@ -152,6 +152,16 @@ TokenLocationCollection StorageAccessProxy::getTokenLocationsForTokenIds(const s
return TokenLocationCollection();
}
TokenLocationCollection StorageAccessProxy::getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const
{
if (hasSubject())
{
return m_subject->getTokenLocationsForLocationIds(locationIds);
}
return TokenLocationCollection();
}
std::shared_ptr<TokenLocationFile> StorageAccessProxy::getTokenLocationsForFile(const std::string& filePath) const
{
if (hasSubject())
+1
View File
@@ -31,6 +31,7 @@ public:
virtual std::vector<Id> getTokenIdsForAggregationEdge(Id aggregationId) const;
virtual TokenLocationCollection getTokenLocationsForTokenIds(const std::vector<Id>& tokenIds) const;
virtual TokenLocationCollection getTokenLocationsForLocationIds(const std::vector<Id>& locationIds) const;
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForFile(const std::string& filePath) const;
virtual std::shared_ptr<TokenLocationFile> getTokenLocationsForLinesInFile(
const std::string& filePath, uint firstLineNumber, uint lastLineNumber
+5
View File
@@ -177,6 +177,11 @@ bool TokenLocation::isEndTokenLocation() const
return !m_isStart;
}
bool TokenLocation::isScopeTokenLocation() const
{
return m_type == LOCATION_SCOPE;
}
Id TokenLocation::s_locationId = 1;
std::ostream& operator<<(std::ostream& ostream, const TokenLocation& location)
+2
View File
@@ -54,6 +54,8 @@ public:
bool isStartTokenLocation() const;
bool isEndTokenLocation() const;
bool isScopeTokenLocation() const;
private:
static Id s_locationId; // next free own id
@@ -0,0 +1,24 @@
#ifndef MESSAGE_SHOW_SCOPE_H
#define MESSAGE_SHOW_SCOPE_H
#include "utility/messaging/Message.h"
#include "utility/types.h"
class MessageShowScope
: public Message<MessageShowScope>
{
public:
MessageShowScope(Id scopeLocationId)
: scopeLocationId(scopeLocationId)
{
}
static const std::string getStaticType()
{
return "MessageShowScope";
}
const Id scopeLocationId;
};
#endif // MESSAGE_SHOW_SCOPE_H