diff --git a/src/app/qt/element/QtCodeFile.cpp b/src/app/qt/element/QtCodeFile.cpp index 629b9499..9a76e873 100644 --- a/src/app/qt/element/QtCodeFile.cpp +++ b/src/app/qt/element/QtCodeFile.cpp @@ -8,6 +8,7 @@ QtCodeFile::QtCodeFile(const std::string& fileName, QWidget *parent) : QWidget(parent) , m_fileName(fileName) + , m_showMaximizeButton(true) { setObjectName("code_file"); @@ -42,6 +43,12 @@ void QtCodeFile::addCodeSnippet( ){ std::shared_ptr snippet( new QtCodeSnippet(startLineNumber, code, locationFile, activeTokenIds, this)); + + if (m_showMaximizeButton) + { + snippet->addMaximizeButton(); + } + layout()->addWidget(snippet.get()); m_snippets.push_back(snippet); @@ -56,3 +63,16 @@ void QtCodeFile::addCodeSnippet( snippet->updateLineNumberAreaWidthForDigits(maxDigits); } } + +void QtCodeFile::setActiveTokenIds(const std::vector& activeTokenIds) +{ + for (std::shared_ptr snippet : m_snippets) + { + snippet->setActiveTokenIds(activeTokenIds); + } +} + +void QtCodeFile::setShowMaximizeButton(bool show) +{ + m_showMaximizeButton = show; +} diff --git a/src/app/qt/element/QtCodeFile.h b/src/app/qt/element/QtCodeFile.h index 9f9c6a39..6502301c 100644 --- a/src/app/qt/element/QtCodeFile.h +++ b/src/app/qt/element/QtCodeFile.h @@ -27,9 +27,13 @@ public: const std::vector& activeTokenIds ); + void setActiveTokenIds(const std::vector& activeTokenIds); + void setShowMaximizeButton(bool show); + private: std::vector > m_snippets; const std::string m_fileName; + bool m_showMaximizeButton; }; #endif // QT_CODE_FILE_H diff --git a/src/app/qt/element/QtCodeFileList.cpp b/src/app/qt/element/QtCodeFileList.cpp index 9ce10ccc..c442c4cc 100644 --- a/src/app/qt/element/QtCodeFileList.cpp +++ b/src/app/qt/element/QtCodeFileList.cpp @@ -8,6 +8,7 @@ QtCodeFileList::QtCodeFileList(QWidget* parent) : QScrollArea(parent) + , m_showMaximizeButton(true) { m_frame = std::make_shared(this); @@ -52,6 +53,8 @@ void QtCodeFileList::addCodeSnippet( file = filePtr.get(); m_frame->layout()->addWidget(file); + + file->setShowMaximizeButton(m_showMaximizeButton); } file->addCodeSnippet(startLineNumber, code, locationFile, activeTokenIds); @@ -61,3 +64,16 @@ void QtCodeFileList::clearCodeSnippets() { m_files.clear(); } + +void QtCodeFileList::setActiveTokenIds(const std::vector& activeTokenIds) +{ + for (std::shared_ptr file: m_files) + { + file->setActiveTokenIds(activeTokenIds); + } +} + +void QtCodeFileList::setShowMaximizeButton(bool show) +{ + m_showMaximizeButton = show; +} diff --git a/src/app/qt/element/QtCodeFileList.h b/src/app/qt/element/QtCodeFileList.h index 18334f65..7ad3f718 100644 --- a/src/app/qt/element/QtCodeFileList.h +++ b/src/app/qt/element/QtCodeFileList.h @@ -29,9 +29,14 @@ public: void clearCodeSnippets(); + void setActiveTokenIds(const std::vector& activeTokenIds); + void setShowMaximizeButton(bool show); + private: std::shared_ptr m_frame; std::vector > m_files; + + bool m_showMaximizeButton; }; #endif // QT_CODE_FILE_LIST diff --git a/src/app/qt/element/QtCodeSnippet.cpp b/src/app/qt/element/QtCodeSnippet.cpp index f9fb1140..d2b2b1bd 100644 --- a/src/app/qt/element/QtCodeSnippet.cpp +++ b/src/app/qt/element/QtCodeSnippet.cpp @@ -8,7 +8,6 @@ #include "ApplicationSettings.h" #include "data/location/TokenLocation.h" #include "data/location/TokenLocationFile.h" -#include "data/location/TokenLocationLine.h" #include "qt/utility/QtHighLighter.h" #include "utility/messaging/type/MessageActivateToken.h" #include "utility/messaging/type/MessageShowFile.h" @@ -43,20 +42,20 @@ QtCodeSnippet::QtCodeSnippet( QWidget *parent ) : QPlainTextEdit(parent) + , m_maximizeButton(nullptr) , m_startLineNumber(startLineNumber) + , m_filePath(locationFile.getFilePath()) , m_activeTokenIds(activeTokenIds) , m_digits(0) - , m_filePath(locationFile.getFilePath()) { setObjectName("code_snippet"); - m_lineNumberArea = new LineNumberArea(this); - setReadOnly(true); setFrameStyle(QFrame::NoFrame); setSizePolicy(sizePolicy().horizontalPolicy(), QSizePolicy::Fixed); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setLineWrapMode(QPlainTextEdit::NoWrap); + m_lineNumberArea = new LineNumberArea(this); m_highlighter = new QtHighlighter(document()); std::string displayCode = code; @@ -66,8 +65,31 @@ QtCodeSnippet::QtCodeSnippet( } setPlainText(QString::fromUtf8(displayCode.c_str())); - annotateText(locationFile); + createAnnotations(locationFile); + annotateText(); + m_digits = lineNumberDigits(); + updateLineNumberAreaWidth(0); + + connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); + connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int))); + connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(clickedTokenLocation())); + connect(this, SIGNAL(selectionChanged()), this, SLOT(clearSelection())); +} + +QtCodeSnippet::~QtCodeSnippet() +{ +} + +QSize QtCodeSnippet::sizeHint() const +{ + int width = 480; + int height = (document()->size().height() + 0.7f) * fontMetrics().lineSpacing(); + return QSize(width, height); +} + +void QtCodeSnippet::addMaximizeButton() +{ QHBoxLayout* layout = new QHBoxLayout(); layout->setMargin(0); layout->setSpacing(0); @@ -79,26 +101,8 @@ QtCodeSnippet::QtCodeSnippet( m_maximizeButton->setEnabled(false); layout->addWidget(m_maximizeButton); layout->setAlignment(m_maximizeButton, Qt::AlignRight); + connect(m_maximizeButton, SIGNAL(clicked()), this, SLOT(clickedMaximizeButton())); - - connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int))); - connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int))); - connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(clickedTokenLocation())); - connect(this, SIGNAL(selectionChanged()), this, SLOT(clearSelection())); - - m_digits = lineNumberDigits(); - updateLineNumberAreaWidth(0); -} - -QtCodeSnippet::~QtCodeSnippet() -{ -} - -QSize QtCodeSnippet::sizeHint() const -{ - int width = lineNumberAreaWidth(); - int height = (document()->size().height() + 0.7f) * fontMetrics().lineSpacing(); - return QSize(width, height); } void QtCodeSnippet::lineNumberAreaPaintEvent(QPaintEvent *event) @@ -150,66 +154,10 @@ void QtCodeSnippet::updateLineNumberAreaWidthForDigits(int digits) updateLineNumberAreaWidth(0); } -void QtCodeSnippet::annotateText(const TokenLocationFile& locationFile) +void QtCodeSnippet::setActiveTokenIds(const std::vector& activeTokenIds) { - QList extraSelections; - - locationFile.forEachTokenLocation( - [&](TokenLocation* location) - { - if (location->isEndTokenLocation() && location->getStartTokenLocation()) - { - return; - } - - Annotation annotation; - if (location->isStartTokenLocation()) - { - annotation.start = toTextEditPosition(location->getLineNumber(), location->getColumnNumber() - 1); - } - else - { - annotation.start = startTextEditPosition(); - } - - TokenLocation* endLocation = location->getEndTokenLocation(); - if (endLocation) - { - annotation.end = toTextEditPosition(endLocation->getLineNumber(), endLocation->getColumnNumber()); - } - else - { - annotation.end = endTextEditPosition(); - } - - annotation.tokenId = location->getTokenId(); - m_annotations.push_back(annotation); - - Colori color; - const std::vector& ids = m_activeTokenIds; - bool isActive = std::find(ids.begin(), ids.end(), location->getTokenId()) != ids.end(); - if (isActive) - { - color = ApplicationSettings::getInstance()->getCodeActiveLinkColor(); - } - else - { - color = ApplicationSettings::getInstance()->getCodeLinkColor(); - } - - QTextEdit::ExtraSelection selection; - selection.format.setBackground(QColor(color.r, color.g, color.b, color.a)); - - selection.cursor = textCursor(); - selection.cursor.clearSelection(); - selection.cursor.setPosition(annotation.start); - selection.cursor.setPosition(annotation.end, QTextCursor::KeepAnchor); - - extraSelections.append(selection); - } - ); - - setExtraSelections(extraSelections); + m_activeTokenIds = activeTokenIds; + annotateText(); } void QtCodeSnippet::resizeEvent(QResizeEvent *e) @@ -230,12 +178,26 @@ void QtCodeSnippet::showEvent(QShowEvent* event) void QtCodeSnippet::enterEvent(QEvent* event) { - m_maximizeButton->setEnabled(true); + if (m_maximizeButton) + { + m_maximizeButton->setEnabled(true); + } } void QtCodeSnippet::leaveEvent(QEvent* event) { - m_maximizeButton->setEnabled(false); + if (m_maximizeButton) + { + m_maximizeButton->setEnabled(false); + } +} + +void QtCodeSnippet::mouseDoubleClickEvent(QMouseEvent* event) +{ + if (m_maximizeButton) + { + clickedMaximizeButton(); + } } void QtCodeSnippet::updateLineNumberAreaWidth(int /* newBlockCount */) @@ -287,7 +249,9 @@ void QtCodeSnippet::clickedTokenLocation() void QtCodeSnippet::clickedMaximizeButton() { - MessageShowFile(m_filePath, m_startLineNumber, m_activeTokenIds).dispatch(); + MessageShowFile( + m_filePath, m_startLineNumber, m_startLineNumber + document()->blockCount() - 1, m_activeTokenIds + ).dispatch(); } void QtCodeSnippet::clearSelection() @@ -297,6 +261,75 @@ void QtCodeSnippet::clearSelection() setTextCursor(cursor); } +void QtCodeSnippet::createAnnotations(const TokenLocationFile& locationFile) +{ + locationFile.forEachTokenLocation( + [&](TokenLocation* location) + { + if (location->isEndTokenLocation() && location->getStartTokenLocation()) + { + return; + } + + Annotation annotation; + if (location->isStartTokenLocation()) + { + annotation.start = toTextEditPosition(location->getLineNumber(), location->getColumnNumber() - 1); + } + else + { + annotation.start = startTextEditPosition(); + } + + TokenLocation* endLocation = location->getEndTokenLocation(); + if (endLocation) + { + annotation.end = toTextEditPosition(endLocation->getLineNumber(), endLocation->getColumnNumber()); + } + else + { + annotation.end = endTextEditPosition(); + } + + annotation.tokenId = location->getTokenId(); + m_annotations.push_back(annotation); + } + ); +} + +void QtCodeSnippet::annotateText() +{ + Colori color; + const std::vector& ids = m_activeTokenIds; + QList extraSelections; + + for (const Annotation& annotation: m_annotations) + { + bool isActive = std::find(ids.begin(), ids.end(), annotation.tokenId) != ids.end(); + + if (isActive) + { + color = ApplicationSettings::getInstance()->getCodeActiveLinkColor(); + } + else + { + color = ApplicationSettings::getInstance()->getCodeLinkColor(); + } + + QTextEdit::ExtraSelection selection; + selection.format.setBackground(QColor(color.r, color.g, color.b, color.a)); + + selection.cursor = textCursor(); + selection.cursor.clearSelection(); + selection.cursor.setPosition(annotation.start); + selection.cursor.setPosition(annotation.end, QTextCursor::KeepAnchor); + + extraSelections.append(selection); + } + + setExtraSelections(extraSelections); +} + int QtCodeSnippet::toTextEditPosition(int lineNumber, int columnNumber) const { lineNumber -= m_startLineNumber - 1; diff --git a/src/app/qt/element/QtCodeSnippet.h b/src/app/qt/element/QtCodeSnippet.h index a3adc386..92abef6b 100644 --- a/src/app/qt/element/QtCodeSnippet.h +++ b/src/app/qt/element/QtCodeSnippet.h @@ -46,18 +46,21 @@ public: QSize sizeHint() const; + void addMaximizeButton(); + void lineNumberAreaPaintEvent(QPaintEvent *event); int lineNumberDigits() const; int lineNumberAreaWidth() const; void updateLineNumberAreaWidthForDigits(int digits); - void annotateText(const TokenLocationFile& locationFile); + void setActiveTokenIds(const std::vector& activeTokenIds); protected: virtual void resizeEvent(QResizeEvent *event); virtual void showEvent(QShowEvent* event); virtual void enterEvent(QEvent* event); virtual void leaveEvent(QEvent* event); + virtual void mouseDoubleClickEvent(QMouseEvent* event); private slots: void updateLineNumberAreaWidth(int newBlockCount); @@ -74,21 +77,25 @@ private: Id tokenId; }; + void createAnnotations(const TokenLocationFile& locationFile); + void annotateText(); + int toTextEditPosition(int lineNumber, int columnNumber) const; int startTextEditPosition() const; int endTextEditPosition() const; + QWidget* m_lineNumberArea; QtHighlighter* m_highlighter; - QWidget* m_lineNumberArea; QPushButton* m_maximizeButton; + bool m_showMaximizeButton; const int m_startLineNumber; - const std::vector m_activeTokenIds; + const std::string m_filePath; + std::vector m_activeTokenIds; + std::vector m_annotations; int m_digits; - - const std::string m_filePath; }; #endif // QT_CODE_SNIPPET_H diff --git a/src/app/qt/view/QtCodeView.cpp b/src/app/qt/view/QtCodeView.cpp index 1654de53..edfedbf7 100644 --- a/src/app/qt/view/QtCodeView.cpp +++ b/src/app/qt/view/QtCodeView.cpp @@ -1,7 +1,10 @@ #include "qt/view/QtCodeView.h" +#include + #include "qt/element/QtCodeFileList.h" #include "qt/view/QtViewWidgetWrapper.h" +#include "utility/FileSystem.h" #include "utility/text/TextAccess.h" QtCodeView::QtCodeView(ViewLayout* viewLayout) @@ -11,6 +14,7 @@ QtCodeView::QtCodeView(ViewLayout* viewLayout) , m_showCodeFileFunctor(std::bind(&QtCodeView::doShowCodeFile, this, std::placeholders::_1)) , m_addCodeSnippetFunctor(std::bind(&QtCodeView::doAddCodeSnippet, this, std::placeholders::_1)) { + m_widget = createQtCodeFileList(); } QtCodeView::~QtCodeView() @@ -19,9 +23,7 @@ QtCodeView::~QtCodeView() void QtCodeView::createWidgetWrapper() { - setWidgetWrapper(std::make_shared( - std::shared_ptr(createQtCodeFileList()) - )); + setWidgetWrapper(std::make_shared(m_widget)); } void QtCodeView::initView() @@ -50,39 +52,69 @@ void QtCodeView::clearCodeSnippets() void QtCodeView::doRefreshView() { - setStyleSheet(getQtCodeFileList()); + setStyleSheet(m_widget.get()); + + clearClosedWindows(); + for (std::shared_ptr window: m_windows) + { + setStyleSheet(window.get()); + } } void QtCodeView::doShowCodeFile(const CodeSnippetParams& params) { - QtCodeFileList* list = createQtCodeFileList(); - list->addCodeSnippet(1, params.code, params.locationFile, params.activeTokenIds); - list->show(); + std::shared_ptr ptr = createQtCodeFileList(); + m_windows.push_back(ptr); + + ptr->setShowMaximizeButton(false); + ptr->addCodeSnippet(1, params.code, params.locationFile, params.activeTokenIds); + + ptr->setWindowTitle(FileSystem::fileName(params.locationFile.getFilePath()).c_str()); + ptr->show(); + + float percent = float(params.startLineNumber + params.endLineNumber) / float(params.lineCount) / 2; + float min = ptr->verticalScrollBar()->minimum(); + float max = ptr->verticalScrollBar()->maximum(); + + ptr->verticalScrollBar()->setValue(min + (max - min) * percent); } void QtCodeView::doAddCodeSnippet(const CodeSnippetParams& params) { - getQtCodeFileList()->addCodeSnippet(params.startLineNumber, params.code, params.locationFile, params.activeTokenIds); + m_widget->addCodeSnippet(params.startLineNumber, params.code, params.locationFile, params.activeTokenIds); + + clearClosedWindows(); + for (std::shared_ptr window: m_windows) + { + window->setActiveTokenIds(params.activeTokenIds); + } } void QtCodeView::doClearCodeSnippets() { - getQtCodeFileList()->clearCodeSnippets(); + m_widget->clearCodeSnippets(); } -QtCodeFileList* QtCodeView::getQtCodeFileList() const +std::shared_ptr QtCodeView::createQtCodeFileList() const { - return dynamic_cast(QtViewWidgetWrapper::getWidgetOfView(this)); -} - -QtCodeFileList* QtCodeView::createQtCodeFileList() const -{ - QtCodeFileList* list = new QtCodeFileList(); - setStyleSheet(list); - return list; + std::shared_ptr ptr = std::make_shared(); + setStyleSheet(ptr.get()); + return ptr; } void QtCodeView::setStyleSheet(QWidget* widget) const { widget->setStyleSheet(TextAccess::createFromFile("data/gui/code_view/code_view.css")->getText().c_str()); } + +void QtCodeView::clearClosedWindows() +{ + for (size_t i = 0; i < m_windows.size(); i++) + { + if (!m_windows[i]->isVisible()) + { + m_windows.erase(m_windows.begin() + i); + i--; + } + } +} diff --git a/src/app/qt/view/QtCodeView.h b/src/app/qt/view/QtCodeView.h index b25a7f44..6870bde3 100644 --- a/src/app/qt/view/QtCodeView.h +++ b/src/app/qt/view/QtCodeView.h @@ -34,15 +34,19 @@ private: void doAddCodeSnippet(const CodeSnippetParams& params); void doClearCodeSnippets(); - QtCodeFileList* getQtCodeFileList() const; - QtCodeFileList* createQtCodeFileList() const; + std::shared_ptr createQtCodeFileList() const; void setStyleSheet(QWidget* widget) const; + void clearClosedWindows(); + QtThreadedFunctor<> m_refreshViewFunctor; QtThreadedFunctor<> m_clearCodeSnippetsFunctor; QtThreadedFunctor m_showCodeFileFunctor; QtThreadedFunctor m_addCodeSnippetFunctor; + + std::shared_ptr m_widget; + std::vector> m_windows; }; # endif // QT_CODE_VIEW_H diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index caaad846..d7e901e6 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -70,10 +70,12 @@ void CodeController::handleMessage(MessageRefresh* message) void CodeController::handleMessage(MessageShowFile* message) { CodeView::CodeSnippetParams params; - params.startLineNumber = message->lineNumber; + params.startLineNumber = message->startLineNumber; + params.endLineNumber = message->endLineNumber; params.activeTokenIds = message->activeTokenIds; std::shared_ptr textAccess = TextAccess::createFromFile(message->filePath); + params.lineCount = textAccess->getLineCount(); params.code = textAccess->getText(); params.locationFile = m_locationAccess->getTokenLocationsForFile(message->filePath); diff --git a/src/lib/component/view/CodeView.h b/src/lib/component/view/CodeView.h index 5689c617..b0f83a73 100644 --- a/src/lib/component/view/CodeView.h +++ b/src/lib/component/view/CodeView.h @@ -15,6 +15,9 @@ public: CodeSnippetParams(); int startLineNumber; + int endLineNumber; + uint lineCount; + std::string code; TokenLocationFile locationFile; std::vector activeTokenIds; diff --git a/src/lib/utility/messaging/type/MessageShowFile.h b/src/lib/utility/messaging/type/MessageShowFile.h index 8edee258..f87bbb65 100644 --- a/src/lib/utility/messaging/type/MessageShowFile.h +++ b/src/lib/utility/messaging/type/MessageShowFile.h @@ -7,9 +7,12 @@ class MessageShowFile: public Message { public: - MessageShowFile(const std::string& filePath, uint lineNumber, const std::vector& activeTokenIds) + MessageShowFile( + const std::string& filePath, uint startLineNumber, uint endLineNumber, const std::vector& activeTokenIds + ) : filePath(filePath) - , lineNumber(lineNumber) + , startLineNumber(startLineNumber) + , endLineNumber(endLineNumber) , activeTokenIds(activeTokenIds) { } @@ -20,7 +23,8 @@ public: } const std::string filePath; - const uint lineNumber; + const uint startLineNumber; + const uint endLineNumber; const std::vector activeTokenIds; };