diff --git a/bin/app/data/gui/code_view/code_view.css b/bin/app/data/gui/code_view/code_view.css index 6f0508c2..e9db87ac 100644 --- a/bin/app/data/gui/code_view/code_view.css +++ b/bin/app/data/gui/code_view/code_view.css @@ -9,13 +9,14 @@ #code_file { background-color: ; border: 2px solid ; - border-radius: 14px; + border-radius: 12px; + padding-bottom: 7px; } #code_file #title_widget { background-color: ; - border-top-left-radius: 10px; - border-top-right-radius: 10px; + border-top-left-radius: 7px; + border-top-right-radius: 7px; padding-right: 5px; } @@ -60,11 +61,6 @@ padding-top: 0px; } -#code_file #code_snippet[isLast=true] { - border-bottom-left-radius: 12px; - border-bottom-right-radius: 12px; -} - #code_file #code_snippet #scope_name, #code_file #code_snippet #dots { background-color: ; color: ; @@ -92,10 +88,6 @@ color: ; } -#code_file #code_snippet[isLast=true] #line_number_area { - border-bottom-left-radius: 12px; -} - #code_area { background-color: transparent; color: ; diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 6106f6a8..72734cff 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -39,6 +39,8 @@ add_files( component/controller/UndoRedoController.cpp component/controller/UndoRedoController.h + component/view/helper/CodeSnippetParams.cpp + component/view/helper/CodeSnippetParams.h component/view/CodeView.cpp component/view/CodeView.h component/view/CompositeView.cpp diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index 1c5426da..3732ff2a 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -29,10 +29,10 @@ const uint CodeController::s_lineRadius = 2; void CodeController::handleMessage(MessageActivateAll* message) { std::vector errorMessages; - std::vector snippets = getSnippetsForErrorLocations(&errorMessages); + std::vector snippets = getSnippetsForErrorLocations(&errorMessages); StorageStats stats = m_storageAccess->getStorageStats(); - CodeView::CodeSnippetParams statsSnippet; + CodeSnippetParams statsSnippet; statsSnippet.startLineNumber = 1; statsSnippet.endLineNumber = 1; @@ -157,9 +157,9 @@ void CodeController::handleMessage(MessageChangeFileView* message) case MessageChangeFileView::FILE_MAXIMIZED: if (message->needsData) { - CodeView::CodeSnippetParams params; - params.startLineNumber = 0; - params.endLineNumber = 0; + CodeSnippetParams params; + params.startLineNumber = 1; + params.refCount = -1; std::shared_ptr textAccess = m_storageAccess->getFileContent(message->filePath); params.code = textAccess->getText(); @@ -213,7 +213,7 @@ void CodeController::handleMessage(MessageScrollCode* message) void CodeController::handleMessage(MessageShowErrors* message) { std::vector errorMessages; - std::vector snippets = getSnippetsForErrorLocations(&errorMessages); + std::vector snippets = getSnippetsForErrorLocations(&errorMessages); CodeView* view = getView(); view->setErrorMessages(errorMessages); @@ -234,7 +234,7 @@ void CodeController::handleMessage(MessageShowScope* message) return; } - std::vector snippets = getSnippetsForActiveTokenLocations(collection.get(), 0); + std::vector snippets = getSnippetsForActiveTokenLocations(collection.get(), 0); if (snippets.size() != 1) { @@ -260,10 +260,10 @@ void CodeController::showContents(MessageBase* message) } } -std::vector CodeController::getSnippetsForActiveTokenLocations( +std::vector CodeController::getSnippetsForActiveTokenLocations( const TokenLocationCollection* collection, Id declarationId ) const { - std::vector snippets; + std::vector snippets; collection->forEachTokenLocationFile( [&](std::shared_ptr file) -> void @@ -281,9 +281,9 @@ std::vector CodeController::getSnippetsForActiveTok if (isDeclarationFile || collection->getTokenLocationFileCount() < 5 || file->isWholeCopy) { - std::vector fileSnippets = getSnippetsForActiveTokenLocationsInFile(file); + std::vector fileSnippets = getSnippetsForActiveTokenLocationsInFile(file); - for (CodeView::CodeSnippetParams& snippet : fileSnippets) + for (CodeSnippetParams& snippet : fileSnippets) { snippet.isDeclaration = isDeclarationFile; } @@ -292,7 +292,7 @@ std::vector CodeController::getSnippetsForActiveTok } else { - CodeView::CodeSnippetParams params; + CodeSnippetParams params; params.locationFile = file; params.refCount = file->getUnscopedStartTokenLocationCount(); params.modificationTime = m_storageAccess->getFileModificationTime(file->getFilePath()); @@ -303,19 +303,19 @@ std::vector CodeController::getSnippetsForActiveTok } ); - std::sort(snippets.begin(), snippets.end(), CodeView::CodeSnippetParams::sort); + std::sort(snippets.begin(), snippets.end(), CodeSnippetParams::sort); return snippets; } -std::vector CodeController::getSnippetsForActiveTokenLocationsInFile( +std::vector CodeController::getSnippetsForActiveTokenLocationsInFile( std::shared_ptr file ) const { - std::vector fileSnippets = getSnippetsForFile(file); + std::vector fileSnippets = getSnippetsForFile(file); if (!file->isWholeCopy) { - for (CodeView::CodeSnippetParams& params : fileSnippets) + for (CodeSnippetParams& params : fileSnippets) { params.locationFile = m_storageAccess->getTokenLocationsForLinesInFile( file->getFilePath().str(), params.startLineNumber, params.endLineNumber); @@ -325,7 +325,7 @@ std::vector CodeController::getSnippetsForActiveTok return fileSnippets; } -std::vector CodeController::getSnippetsForFile(std::shared_ptr file) const +std::vector CodeController::getSnippetsForFile(std::shared_ptr file) const { std::shared_ptr textAccess = m_storageAccess->getFileContent(file->getFilePath()); @@ -365,10 +365,10 @@ std::vector CodeController::getSnippetsForFile(std: } const int snippetExpandRange = ApplicationSettings::getInstance()->getCodeSnippetExpandRange(); - std::vector snippets; + std::vector snippets; for (const SnippetMerger::Range& range: ranges) { - CodeView::CodeSnippetParams params; + CodeSnippetParams params; params.locationFile = file; params.refCount = file->getUnscopedStartTokenLocationCount(); params.startLineNumber = std::max(1, range.start.row - (range.start.strong ? 0 : snippetExpandRange)); @@ -402,6 +402,27 @@ std::vector CodeController::getSnippetsForFile(std: params.title = file->getFilePath().str(); } + + TokenLocationLine* lastUsedLine = nullptr; + for (size_t i = params.endLineNumber; i >= params.startLineNumber && lastUsedLine == nullptr; i--) + { + lastUsedLine = tempFile->findTokenLocationLineByNumber(i); + } + + params.footerId = 0; + if (lastUsedLine && lastUsedLine->getTokenLocations().size()) + { + m_storageAccess->getTokenLocationOfParentScope( + lastUsedLine->getTokenLocations().begin()->second.get() + )->forEachStartTokenLocation( // this TokenLocationFile only contains a single StartTokenLocation. + [&](TokenLocation* location) + { + params.footer = m_storageAccess->getNameHierarchyForNodeWithId(location->getTokenId()).getFullName(); + params.footerId = location->getId(); + } + ); + } + for (const std::string& line: textAccess->getLines(params.startLineNumber, params.endLineNumber)) { params.code += line; @@ -449,17 +470,17 @@ std::shared_ptr CodeController::buildMergerHierarchy( return currentMerger; } -std::vector CodeController::getSnippetsForErrorLocations( +std::vector CodeController::getSnippetsForErrorLocations( std::vector* errorMessages) const { TokenLocationCollection errorCollection = m_storageAccess->getErrorTokenLocations(errorMessages); - std::vector snippets; + std::vector snippets; errorCollection.forEachTokenLocationFile( [&](std::shared_ptr file) -> void { - std::vector fileSnippets = getSnippetsForFile(file); + std::vector fileSnippets = getSnippetsForFile(file); snippets.insert(snippets.end(), fileSnippets.begin(), fileSnippets.end()); } ); diff --git a/src/lib/component/controller/CodeController.h b/src/lib/component/controller/CodeController.h index aa6ba4c2..e86d1dce 100644 --- a/src/lib/component/controller/CodeController.h +++ b/src/lib/component/controller/CodeController.h @@ -56,15 +56,15 @@ private: CodeView* getView(); void showContents(MessageBase* message); - std::vector getSnippetsForActiveTokenLocations( + std::vector getSnippetsForActiveTokenLocations( const TokenLocationCollection* collection, Id declarationId) const; - std::vector getSnippetsForActiveTokenLocationsInFile( + std::vector getSnippetsForActiveTokenLocationsInFile( std::shared_ptr) const; - std::vector getSnippetsForFile(std::shared_ptr file) const; + std::vector getSnippetsForFile(std::shared_ptr file) const; std::shared_ptr buildMergerHierarchy( TokenLocation* location, SnippetMerger& fileScopedMerger, std::map>& mergers) const; - std::vector getSnippetsForErrorLocations(std::vector* errorMessages) const; + std::vector getSnippetsForErrorLocations(std::vector* errorMessages) const; std::vector getProjectDescription(TokenLocationFile* locationFile) const; diff --git a/src/lib/component/view/CodeView.cpp b/src/lib/component/view/CodeView.cpp index 479183d0..467d6372 100644 --- a/src/lib/component/view/CodeView.cpp +++ b/src/lib/component/view/CodeView.cpp @@ -3,71 +3,6 @@ #include "component/controller/CodeController.h" #include "utility/file/FileSystem.h" -CodeView::CodeSnippetParams::CodeSnippetParams() - : startLineNumber(0) - , endLineNumber(0) - , titleId(0) - , locationFile() - , refCount(0) - , isActive(false) - , isDeclaration(false) - , isCollapsed(false) -{ -} - -bool CodeView::CodeSnippetParams::sort(const CodeSnippetParams& a, const CodeSnippetParams& b) -{ - // sort active snippet first - if (a.isActive && !b.isActive) - { - return true; - } - else if (!a.isActive && b.isActive) - { - return false; - } - - // sort declarations - if (a.isDeclaration && !b.isDeclaration) - { - return true; - } - else if (!a.isDeclaration && b.isDeclaration) - { - return false; - } - - // sort whole files - if (a.locationFile->isWholeCopy && !b.locationFile->isWholeCopy) - { - return true; - } - else if (!a.locationFile->isWholeCopy && b.locationFile->isWholeCopy) - { - return false; - } - - const FilePath& aFilePath = a.locationFile->getFilePath(); - const FilePath& bFilePath = b.locationFile->getFilePath(); - - // different files - if (aFilePath != bFilePath) - { - // first header - if (aFilePath.withoutExtension() == bFilePath.withoutExtension()) - { - return aFilePath.extension() > bFilePath.extension(); - } - // alphabetical filepath without extension - else - { - return aFilePath.withoutExtension().fileName() < bFilePath.withoutExtension().fileName(); - } - } - - return a.startLineNumber < b.startLineNumber; -} - CodeView::CodeView(ViewLayout* viewLayout) : View(viewLayout) { diff --git a/src/lib/component/view/CodeView.h b/src/lib/component/view/CodeView.h index dae9da6f..ef54812c 100644 --- a/src/lib/component/view/CodeView.h +++ b/src/lib/component/view/CodeView.h @@ -3,14 +3,15 @@ #include +#include "utility/file/FilePath.h" + +#include "component/view/helper/CodeSnippetParams.h" #include "component/view/View.h" -#include "data/location/TokenLocationFile.h" -#include "utility/TimePoint.h" -#include "utility/types.h" class CodeController; -class CodeView: public View +class CodeView + : public View { public: enum FileState @@ -20,31 +21,6 @@ public: FILE_MAXIMIZED }; - struct CodeSnippetParams - { - CodeSnippetParams(); - - // comparefunction for snippetsorting - static bool sort(const CodeSnippetParams& a, const CodeSnippetParams& b); - - uint startLineNumber; - uint endLineNumber; - - std::string title; - std::string code; - - Id titleId; - TimePoint modificationTime; - - std::shared_ptr locationFile; - - int refCount; - - bool isActive; - bool isDeclaration; - bool isCollapsed; - }; - CodeView(ViewLayout* viewLayout); virtual ~CodeView(); diff --git a/src/lib/component/view/helper/CodeSnippetParams.cpp b/src/lib/component/view/helper/CodeSnippetParams.cpp new file mode 100644 index 00000000..179d92ac --- /dev/null +++ b/src/lib/component/view/helper/CodeSnippetParams.cpp @@ -0,0 +1,69 @@ +#include "component/view/helper/CodeSnippetParams.h" + +#include "data/location/TokenLocationFile.h" + +CodeSnippetParams::CodeSnippetParams() + : startLineNumber(0) + , endLineNumber(0) + , titleId(0) + , footerId(0) + , locationFile() + , refCount(0) + , isActive(false) + , isDeclaration(false) + , isCollapsed(false) +{ +} + +bool CodeSnippetParams::sort(const CodeSnippetParams& a, const CodeSnippetParams& b) +{ + // sort active snippet first + if (a.isActive && !b.isActive) + { + return true; + } + else if (!a.isActive && b.isActive) + { + return false; + } + + // sort declarations + if (a.isDeclaration && !b.isDeclaration) + { + return true; + } + else if (!a.isDeclaration && b.isDeclaration) + { + return false; + } + + // sort whole files + if (a.locationFile->isWholeCopy && !b.locationFile->isWholeCopy) + { + return true; + } + else if (!a.locationFile->isWholeCopy && b.locationFile->isWholeCopy) + { + return false; + } + + const FilePath& aFilePath = a.locationFile->getFilePath(); + const FilePath& bFilePath = b.locationFile->getFilePath(); + + // different files + if (aFilePath != bFilePath) + { + // first header + if (aFilePath.withoutExtension() == bFilePath.withoutExtension()) + { + return aFilePath.extension() > bFilePath.extension(); + } + // alphabetical filepath without extension + else + { + return aFilePath.withoutExtension().fileName() < bFilePath.withoutExtension().fileName(); + } + } + + return a.startLineNumber < b.startLineNumber; +} diff --git a/src/lib/component/view/helper/CodeSnippetParams.h b/src/lib/component/view/helper/CodeSnippetParams.h new file mode 100644 index 00000000..2b436df5 --- /dev/null +++ b/src/lib/component/view/helper/CodeSnippetParams.h @@ -0,0 +1,38 @@ +#ifndef CODE_SNIPPET_PARAMS_H +#define CODE_SNIPPET_PARAMS_H + +#include + +#include "utility/TimePoint.h" +#include "utility/types.h" + +class TokenLocationFile; + +struct CodeSnippetParams +{ + CodeSnippetParams(); + + // comparefunction for snippetsorting + static bool sort(const CodeSnippetParams& a, const CodeSnippetParams& b); + + uint startLineNumber; + uint endLineNumber; + + std::string title; + std::string footer; + std::string code; + + Id titleId; + Id footerId; + TimePoint modificationTime; + + std::shared_ptr locationFile; + + int refCount; + + bool isActive; + bool isDeclaration; + bool isCollapsed; +}; + +#endif // CODE_SNIPPET_PARAMS_H diff --git a/src/lib_gui/qt/element/QtCodeArea.cpp b/src/lib_gui/qt/element/QtCodeArea.cpp index ec5efed1..cea88bfe 100644 --- a/src/lib_gui/qt/element/QtCodeArea.cpp +++ b/src/lib_gui/qt/element/QtCodeArea.cpp @@ -255,18 +255,21 @@ void QtCodeArea::setIsActiveFile(bool isActiveFile) m_isActiveFile = isActiveFile; } -QRectF QtCodeArea::getFirstActiveLineRect() const +uint QtCodeArea::getFirstActiveLineNumber() const { - int lineNumber = 0; for (const Annotation& annotation : m_annotations) { if (annotation.isActive) { - lineNumber = annotation.startLine; - break; + return annotation.startLine; } } + return 0; +} + +QRectF QtCodeArea::getLineRectForLineNumber(uint lineNumber) const +{ QTextBlock block = document()->findBlockByLineNumber(lineNumber - m_startLineNumber); return blockBoundingGeometry(block); } diff --git a/src/lib_gui/qt/element/QtCodeArea.h b/src/lib_gui/qt/element/QtCodeArea.h index 247ffd82..f8dcbd14 100644 --- a/src/lib_gui/qt/element/QtCodeArea.h +++ b/src/lib_gui/qt/element/QtCodeArea.h @@ -84,7 +84,8 @@ public: void setIsActiveFile(bool isActiveFile); - QRectF getFirstActiveLineRect() const; + uint getFirstActiveLineNumber() const; + QRectF getLineRectForLineNumber(uint lineNumber) const; std::string getCode() const; diff --git a/src/lib_gui/qt/element/QtCodeFile.cpp b/src/lib_gui/qt/element/QtCodeFile.cpp index e093ab93..7183e49c 100644 --- a/src/lib_gui/qt/element/QtCodeFile.cpp +++ b/src/lib_gui/qt/element/QtCodeFile.cpp @@ -102,10 +102,6 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeFileList* parent) connect(m_snippetButton, SIGNAL(clicked()), this, SLOT(clickedSnippetButton())); connect(m_maximizeButton, SIGNAL(clicked()), this, SLOT(clickedMaximizeButton())); - m_minimizePlaceholder = new QWidget(this); - m_minimizePlaceholder->setMinimumHeight(5); - layout->addWidget(m_minimizePlaceholder); - m_snippetLayout = new QVBoxLayout(); layout->addLayout(m_snippetLayout); @@ -147,22 +143,15 @@ const std::vector& QtCodeFile::getErrorMessages() const return m_parent->getErrorMessages(); } -void QtCodeFile::addCodeSnippet( - uint startLineNumber, - const std::string& title, - Id titleId, - const std::string& code, - std::shared_ptr locationFile, - int refCount -){ +void QtCodeFile::addCodeSnippet(const CodeSnippetParams& params) +{ m_locationFile.reset(); - std::shared_ptr snippet( - new QtCodeSnippet(startLineNumber, title, titleId, code, locationFile, this)); + std::shared_ptr snippet(new QtCodeSnippet(params, this)); m_snippetLayout->addWidget(snippet.get()); - if (locationFile->isWholeCopy) + if (params.locationFile->isWholeCopy) { snippet->setProperty("isFirst", true); snippet->setProperty("isLast", true); @@ -174,7 +163,7 @@ void QtCodeFile::addCodeSnippet( } setMaximized(); - if (refCount != -1) + if (params.refCount != -1) { updateRefCount(0); } @@ -184,21 +173,14 @@ void QtCodeFile::addCodeSnippet( m_snippets.push_back(snippet); updateSnippets(); - updateRefCount(refCount); + updateRefCount(params.refCount); } -QtCodeSnippet* QtCodeFile::insertCodeSnippet( - uint startLineNumber, - const std::string& title, - Id titleId, - const std::string& code, - std::shared_ptr locationFile, - int refCount -){ +QtCodeSnippet* QtCodeFile::insertCodeSnippet(const CodeSnippetParams& params) +{ m_locationFile.reset(); - std::shared_ptr snippet( - new QtCodeSnippet(startLineNumber, title, titleId, code, locationFile, this)); + std::shared_ptr snippet(new QtCodeSnippet(params, this)); size_t i = 0; while (i < m_snippets.size()) @@ -232,7 +214,7 @@ QtCodeSnippet* QtCodeFile::insertCodeSnippet( m_snippets.insert(m_snippets.begin() + i, snippet); updateSnippets(); - updateRefCount(refCount); + updateRefCount(params.refCount); return snippet.get(); } @@ -325,8 +307,6 @@ void QtCodeFile::setMinimized() m_snippetButton->setEnabled(true); } m_maximizeButton->setEnabled(true); - - m_minimizePlaceholder->show(); } void QtCodeFile::setSnippets() @@ -344,8 +324,6 @@ void QtCodeFile::setSnippets() m_minimizeButton->setEnabled(true); m_snippetButton->setEnabled(false); m_maximizeButton->setEnabled(true); - - m_minimizePlaceholder->hide(); } void QtCodeFile::setMaximized() @@ -366,8 +344,6 @@ void QtCodeFile::setMaximized() m_snippetButton->setEnabled(true); } m_maximizeButton->setEnabled(false); - - m_minimizePlaceholder->hide(); } void QtCodeFile::clickedTitleBar() diff --git a/src/lib_gui/qt/element/QtCodeFile.h b/src/lib_gui/qt/element/QtCodeFile.h index aaec0d96..545076a2 100644 --- a/src/lib_gui/qt/element/QtCodeFile.h +++ b/src/lib_gui/qt/element/QtCodeFile.h @@ -14,6 +14,8 @@ #include "utility/messaging/type/MessageWindowFocus.h" #include "qt/utility/QtThreadedFunctor.h" +#include "component/view/helper/CodeSnippetParams.h" + class QLabel; class QPushButton; class QtCodeFileList; @@ -40,23 +42,8 @@ public: const std::vector& getFocusedTokenIds() const; const std::vector& getErrorMessages() const; - void addCodeSnippet( - uint startLineNumber, - const std::string& title, - Id titleId, - const std::string& code, - std::shared_ptr locationFile, - int refCount - ); - - QtCodeSnippet* insertCodeSnippet( - uint startLineNumber, - const std::string& title, - Id titleId, - const std::string& code, - std::shared_ptr locationFile, - int refCount - ); + void addCodeSnippet(const CodeSnippetParams& params); + QtCodeSnippet* insertCodeSnippet(const CodeSnippetParams& params); QtCodeSnippet* findFirstActiveSnippet() const; bool isCollapsedActiveFile() const; @@ -104,7 +91,6 @@ private: QVBoxLayout* m_snippetLayout; std::vector> m_snippets; std::shared_ptr m_fileSnippet; - QWidget* m_minimizePlaceholder; const FilePath m_filePath; TimePoint m_modificationTime; diff --git a/src/lib_gui/qt/element/QtCodeFileList.cpp b/src/lib_gui/qt/element/QtCodeFileList.cpp index 66125a2b..fe8dd2b6 100644 --- a/src/lib_gui/qt/element/QtCodeFileList.cpp +++ b/src/lib_gui/qt/element/QtCodeFileList.cpp @@ -33,7 +33,7 @@ QtCodeFileList::QtCodeFileList(QWidget* parent) setWidget(m_frame.get()); connect(this->verticalScrollBar(), SIGNAL(valueChanged(int)), this, SLOT(scrolled(int))); - connect(this, SIGNAL(shouldScrollToSnippet(QtCodeSnippet*)), this, SLOT(scrollToSnippet(QtCodeSnippet*)), Qt::QueuedConnection); + connect(this, SIGNAL(shouldScrollToSnippet(QtCodeSnippet*, uint)), this, SLOT(scrollToSnippet(QtCodeSnippet*, uint)), Qt::QueuedConnection); } QtCodeFileList::~QtCodeFileList() @@ -46,27 +46,21 @@ QSize QtCodeFileList::sizeHint() const } void QtCodeFileList::addCodeSnippet( - uint startLineNumber, - const std::string& title, - Id titleId, - const std::string& code, - std::shared_ptr locationFile, - int refCount, - TimePoint modificationTime, + const CodeSnippetParams& params, bool insert ){ - QtCodeFile* file = getFile(locationFile->getFilePath()); + QtCodeFile* file = getFile(params.locationFile->getFilePath()); if (insert) { - QtCodeSnippet* snippet = file->insertCodeSnippet(startLineNumber, title, titleId, code, locationFile, refCount); - emit shouldScrollToSnippet(snippet); + QtCodeSnippet* snippet = file->insertCodeSnippet(params); + emit shouldScrollToSnippet(snippet, params.startLineNumber); } else { - file->addCodeSnippet(startLineNumber, title, titleId, code, locationFile, refCount); + file->addCodeSnippet(params); } - file->setModificationTime(modificationTime); + file->setModificationTime(params.modificationTime); } void QtCodeFileList::addFile(std::shared_ptr locationFile, int refCount, TimePoint modificationTime) @@ -136,7 +130,7 @@ void QtCodeFileList::showFirstActiveSnippet(bool scrollTo) if (scrollTo) { - emit shouldScrollToSnippet(snippet); + emit shouldScrollToSnippet(snippet, 0); } } @@ -207,9 +201,17 @@ void QtCodeFileList::scrolled(int value) MessageScrollCode(value).dispatch(); } -void QtCodeFileList::scrollToSnippet(QtCodeSnippet* snippet) +void QtCodeFileList::scrollToSnippet(QtCodeSnippet* snippet, uint lineNumber) { - this->ensureWidgetVisibleAnimated(snippet, snippet->getFirstActiveLineRect()); + if (lineNumber == 0) + { + lineNumber = snippet->getFirstActiveLineNumber(); + } + + if (lineNumber) + { + this->ensureWidgetVisibleAnimated(snippet, snippet->getLineRectForLineNumber(lineNumber)); + } } void QtCodeFileList::setValue() diff --git a/src/lib_gui/qt/element/QtCodeFileList.h b/src/lib_gui/qt/element/QtCodeFileList.h index 13597fe3..f51158c4 100644 --- a/src/lib_gui/qt/element/QtCodeFileList.h +++ b/src/lib_gui/qt/element/QtCodeFileList.h @@ -11,6 +11,8 @@ #include "utility/TimePoint.h" #include "utility/types.h" +#include "component/view/helper/CodeSnippetParams.h" + class QtCodeFile; class QtCodeSnippet; class TokenLocationFile; @@ -21,7 +23,7 @@ class QtCodeFileList Q_OBJECT signals: - void shouldScrollToSnippet(QtCodeSnippet* widget); + void shouldScrollToSnippet(QtCodeSnippet* widget, uint lineNumber); public: QtCodeFileList(QWidget* parent = 0); @@ -29,17 +31,7 @@ public: virtual QSize sizeHint() const; - void addCodeSnippet( - uint startLineNumber, - const std::string& title, - Id titleId, - const std::string& code, - std::shared_ptr locationFile, - int refCount, - TimePoint modificationTime, - bool insert = false - ); - + void addCodeSnippet(const CodeSnippetParams& params, bool insert = false); void addFile(std::shared_ptr locationFile, int refCount, TimePoint modificationTime); void clearCodeSnippets(); @@ -70,7 +62,7 @@ public: private slots: void scrolled(int value); - void scrollToSnippet(QtCodeSnippet* snippet); + void scrollToSnippet(QtCodeSnippet* snippet, uint lineNumber); void setValue(); private: diff --git a/src/lib_gui/qt/element/QtCodeSnippet.cpp b/src/lib_gui/qt/element/QtCodeSnippet.cpp index b87e2ac0..98ace1c9 100644 --- a/src/lib_gui/qt/element/QtCodeSnippet.cpp +++ b/src/lib_gui/qt/element/QtCodeSnippet.cpp @@ -44,32 +44,27 @@ std::shared_ptr QtCodeSnippet::merged(QtCodeSnippet* a, QtCodeSni } code += secondCode.substr(secondCodeStartIndex, secondCode.npos); - std::string title = first->m_titleString; + CodeSnippetParams params; + params.startLineNumber = first->getStartLineNumber(); + params.title = first->m_titleString; + params.titleId = first->m_titleId; + params.footer = second->m_footerString; + params.footerId = second->m_footerId; + params.code = code; + params.locationFile = locationFile; - return std::shared_ptr(new QtCodeSnippet( - first->getStartLineNumber(), - title, - first->m_titleId, - code, - locationFile, - file - )); + return std::shared_ptr(new QtCodeSnippet(params, file)); } -QtCodeSnippet::QtCodeSnippet( - uint startLineNumber, - const std::string& title, - Id titleId, - const std::string& code, - std::shared_ptr locationFile, - QtCodeFile* file -) +QtCodeSnippet::QtCodeSnippet(const CodeSnippetParams& params, QtCodeFile* file) : QFrame(file) - , m_titleId(titleId) - , m_titleString(title) - , m_dots(nullptr) + , m_titleId(params.titleId) + , m_titleString(params.title) + , m_footerId(params.footerId) + , m_footerString(params.footer) , m_title(nullptr) - , m_codeArea(std::make_shared(startLineNumber, code, locationFile, file, this)) + , m_footer(nullptr) + , m_codeArea(std::make_shared(params.startLineNumber, params.code, params.locationFile, file, this)) { setObjectName("code_snippet"); @@ -81,28 +76,20 @@ QtCodeSnippet::QtCodeSnippet( if (m_titleString.size()) { - QHBoxLayout* titleLayout = new QHBoxLayout(); - titleLayout->setMargin(0); - titleLayout->setSpacing(0); - titleLayout->setAlignment(Qt::AlignLeft); - layout->addLayout(titleLayout); - - m_dots = new QPushButton(this); - m_dots->setObjectName("dots"); - m_dots->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac - titleLayout->addWidget(m_dots); - - m_title = new QPushButton(FilePath(m_titleString).fileName().c_str(), this); - m_title->setObjectName("scope_name"); - m_title->minimumSizeHint(); // force font loading - m_title->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac - m_title->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - titleLayout->addWidget(m_title); - + m_title = createScopeLine(layout); + m_title->setText(FilePath(m_titleString).fileName().c_str()); connect(m_title, SIGNAL(clicked()), this, SLOT(clickedTitle())); } layout->addWidget(m_codeArea.get()); + + if (m_footerString.size()) + { + m_footer = createScopeLine(layout); + m_footer->setText(FilePath(m_footerString).fileName().c_str()); + connect(m_footer, SIGNAL(clicked()), this, SLOT(clickedFooter())); + } + updateDots(); } @@ -152,9 +139,14 @@ void QtCodeSnippet::setIsActiveFile(bool isActiveFile) m_codeArea->setIsActiveFile(isActiveFile); } -QRectF QtCodeSnippet::getFirstActiveLineRect() const +uint QtCodeSnippet::getFirstActiveLineNumber() const { - return m_codeArea->getFirstActiveLineRect(); + return m_codeArea->getFirstActiveLineNumber(); +} + +QRectF QtCodeSnippet::getLineRectForLineNumber(uint lineNumber) const +{ + return m_codeArea->getLineRectForLineNumber(lineNumber); } std::string QtCodeSnippet::getCode() const @@ -183,13 +175,43 @@ void QtCodeSnippet::clickedTitle() } } +void QtCodeSnippet::clickedFooter() +{ + if (m_footerId > 0) + { + MessageShowScope(m_footerId).dispatch(); + } +} + +QPushButton* QtCodeSnippet::createScopeLine(QBoxLayout* layout) +{ + QHBoxLayout* lineLayout = new QHBoxLayout(); + lineLayout->setMargin(0); + lineLayout->setSpacing(0); + lineLayout->setAlignment(Qt::AlignLeft); + layout->addLayout(lineLayout); + + QPushButton* dots = new QPushButton(this); + dots->setObjectName("dots"); + dots->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac + lineLayout->addWidget(dots); + m_dots.push_back(dots); + + QPushButton* line = new QPushButton(this); + line->setObjectName("scope_name"); + line->minimumSizeHint(); // force font loading + line->setAttribute(Qt::WA_LayoutUsesWidgetRect); // fixes layouting on Mac + line->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + lineLayout->addWidget(line); + + return line; +} + void QtCodeSnippet::updateDots() { - if (!m_dots) + for (QPushButton* dots : m_dots) { - return; + dots->setText(QString::fromStdString(std::string(lineNumberDigits(), '.'))); + dots->setMinimumWidth(m_codeArea->lineNumberAreaWidth()); } - - m_dots->setText(QString::fromStdString(std::string(lineNumberDigits(), '.'))); - m_dots->setMinimumWidth(m_codeArea->lineNumberAreaWidth()); } diff --git a/src/lib_gui/qt/element/QtCodeSnippet.h b/src/lib_gui/qt/element/QtCodeSnippet.h index 84121b51..005e3d06 100644 --- a/src/lib_gui/qt/element/QtCodeSnippet.h +++ b/src/lib_gui/qt/element/QtCodeSnippet.h @@ -10,6 +10,9 @@ #include "qt/element/QtCodeArea.h" +#include "component/view/helper/CodeSnippetParams.h" + +class QBoxLayout; class QPushButton; class QtCodeFile; class TokenLocationFile; @@ -22,14 +25,7 @@ class QtCodeSnippet public: static std::shared_ptr merged(QtCodeSnippet* a, QtCodeSnippet* b, QtCodeFile* file); - QtCodeSnippet( - uint startLineNumber, - const std::string& title, - Id titleId, - const std::string& code, - std::shared_ptr locationFile, - QtCodeFile* file - ); + QtCodeSnippet(const CodeSnippetParams& params, QtCodeFile* file); virtual ~QtCodeSnippet(); QtCodeFile* getFile() const; @@ -46,7 +42,8 @@ public: void setIsActiveFile(bool isActiveFile); - QRectF getFirstActiveLineRect() const; + uint getFirstActiveLineNumber() const; + QRectF getLineRectForLineNumber(uint lineNumber) const; std::string getCode() const; @@ -55,15 +52,22 @@ protected: private slots: void clickedTitle(); + void clickedFooter(); private: + QPushButton* createScopeLine(QBoxLayout* layout); void updateDots(); Id m_titleId; std::string m_titleString; - QPushButton* m_dots; + Id m_footerId; + std::string m_footerString; + + std::vector m_dots; + QPushButton* m_title; + QPushButton* m_footer; std::shared_ptr m_codeArea; }; diff --git a/src/lib_gui/qt/view/QtCodeView.cpp b/src/lib_gui/qt/view/QtCodeView.cpp index a10ceb09..95a8b129 100644 --- a/src/lib_gui/qt/view/QtCodeView.cpp +++ b/src/lib_gui/qt/view/QtCodeView.cpp @@ -127,15 +127,7 @@ void QtCodeView::doShowCodeSnippets(const std::vector& snippe } else { - m_widget->addCodeSnippet( - params.startLineNumber, - params.title, - params.titleId, - params.code, - params.locationFile, - params.refCount, - params.modificationTime - ); + m_widget->addCodeSnippet(params); } } @@ -146,16 +138,7 @@ void QtCodeView::doAddCodeSnippets(const std::vector& snippet { for (const CodeSnippetParams& params : snippets) { - m_widget->addCodeSnippet( - params.startLineNumber, - params.title, - params.titleId, - params.code, - params.locationFile, - params.refCount, - params.modificationTime, - insert - ); + m_widget->addCodeSnippet(params, insert); } setStyleSheet(); // so property "isLast" of QtCodeSnippet is computed correctly @@ -165,7 +148,7 @@ void QtCodeView::doAddCodeSnippets(const std::vector& snippet void QtCodeView::doShowCodeFile(const CodeSnippetParams& params) { - m_widget->addCodeSnippet(1, params.title, 0, params.code, params.locationFile, -1, params.modificationTime); + m_widget->addCodeSnippet(params); } void QtCodeView::doSetFileState(const FilePath filePath, FileState state)