diff --git a/src/app/CMakeLists.txt b/src/app/CMakeLists.txt index ba7a0acb..b8ac00a3 100644 --- a/src/app/CMakeLists.txt +++ b/src/app/CMakeLists.txt @@ -1,6 +1,8 @@ add_files( APP_FILES + qt/element/QtCodeFile.cpp + qt/element/QtCodeFile.h qt/element/QtCodeSnippet.cpp qt/element/QtCodeSnippet.h qt/element/QtMainWindow.cpp diff --git a/src/app/qt/element/QtCodeFile.cpp b/src/app/qt/element/QtCodeFile.cpp new file mode 100644 index 00000000..0efb9e8c --- /dev/null +++ b/src/app/qt/element/QtCodeFile.cpp @@ -0,0 +1,41 @@ +#include "qt/element/QtCodeFile.h" + +#include +#include + +#include "qt/element/QtCodeSnippet.h" + +QtCodeFile::QtCodeFile(QtCodeView* parentView, const std::string& fileName, QWidget *parent) + : QWidget(parent) + , m_parentView(parentView) + , m_fileName(fileName) +{ + QVBoxLayout* layout = new QVBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(2); + setLayout(layout); + + QLabel* label = new QLabel(fileName.c_str(), this); + QFontMetrics metrics(label->font()); + + label->setStyleSheet("background-color: #E1E1E1; padding: 3px;"); + label->setFixedWidth(metrics.boundingRect(fileName.c_str()).width() + 12); + layout->addWidget(label); +} + +QtCodeFile::~QtCodeFile() +{ +} + +const std::string& QtCodeFile::getFileName() const +{ + return m_fileName; +} + +void QtCodeFile::addCodeSnippet(const std::string& str, const TokenLocationFile& locationFile, int startLineNumber) +{ + std::shared_ptr snippet = + std::make_shared(m_parentView, str, locationFile, startLineNumber, this); + layout()->addWidget(snippet.get()); + m_snippets.push_back(snippet); +} diff --git a/src/app/qt/element/QtCodeFile.h b/src/app/qt/element/QtCodeFile.h new file mode 100644 index 00000000..5935f7ef --- /dev/null +++ b/src/app/qt/element/QtCodeFile.h @@ -0,0 +1,30 @@ +#ifndef QT_CODE_FILE_H +#define QT_CODE_FILE_H + +#include +#include +#include + +#include + +class QtCodeSnippet; +class QtCodeView; +class TokenLocationFile; + +class QtCodeFile : public QWidget +{ +public: + QtCodeFile(QtCodeView* parentView, const std::string& fileName, QWidget *parent); + virtual ~QtCodeFile(); + + const std::string& getFileName() const; + + void addCodeSnippet(const std::string& str, const TokenLocationFile& locationFile, int startLineNumber); + +private: + QtCodeView* m_parentView; + std::vector > m_snippets; + const std::string m_fileName; +}; + +#endif // QT_CODE_FILE_H diff --git a/src/app/qt/element/QtCodeSnippet.cpp b/src/app/qt/element/QtCodeSnippet.cpp index 5038b533..b5e7bfe4 100644 --- a/src/app/qt/element/QtCodeSnippet.cpp +++ b/src/app/qt/element/QtCodeSnippet.cpp @@ -45,6 +45,7 @@ QtCodeSnippet::QtCodeSnippet( m_lineNumberArea = new LineNumberArea(this); setReadOnly(true); + setFrameStyle(QFrame::NoFrame); QFont font; font.setFamily(ApplicationSettings::getInstance()->getCodeFontName().c_str()); @@ -88,7 +89,7 @@ void QtCodeSnippet::lineNumberAreaPaintEvent(QPaintEvent *event) { QString number = QString::number(blockNumber + m_startLineNumber); painter.setPen(Qt::black); - painter.drawText(0, top, m_lineNumberArea->width() - 1, fontMetrics().height(), Qt::AlignRight, number); + painter.drawText(0, top, m_lineNumberArea->width() - 3, fontMetrics().height(), Qt::AlignRight, number); } block = block.next(); @@ -109,7 +110,7 @@ int QtCodeSnippet::lineNumberAreaWidth() digits++; } - int width = 2 + fontMetrics().width(QLatin1Char('9')) * digits; + int width = fontMetrics().width(QLatin1Char('9')) * digits + 6; return width; } diff --git a/src/app/qt/view/QtCodeView.cpp b/src/app/qt/view/QtCodeView.cpp index 772272e4..c0a22a88 100644 --- a/src/app/qt/view/QtCodeView.cpp +++ b/src/app/qt/view/QtCodeView.cpp @@ -4,9 +4,10 @@ #include #include "data/location/TokenLocationFile.h" -#include "qt/element/QtCodeSnippet.h" +#include "qt/element/QtCodeFile.h" #include "qt/QtWidgetWrapper.h" #include "qt/utility/utilityQt.h" +#include "utility/FileSystem.h" #include "utility/messaging/type/MessageActivateToken.h" QtCodeView::QtCodeView(ViewLayout* viewLayout) @@ -54,15 +55,32 @@ void QtCodeView::activateToken(Id tokenId) const void QtCodeView::doAddCodeSnippet(const std::string& str, const TokenLocationFile& locationFile, int startLineNumber) { - std::shared_ptr snippet = std::make_shared(this, str, locationFile, startLineNumber); + std::string fileName = FileSystem::fileName(locationFile.getFilePath()); + QtCodeFile* file = nullptr; - QWidget* widget = QtWidgetWrapper::getWidgetOfView(this); - widget->layout()->addWidget(snippet.get()); + for (std::shared_ptr filePtr : m_files) + { + if (filePtr->getFileName() == fileName) + { + file = filePtr.get(); + break; + } + } - m_snippets.push_back(snippet); + if (!file) + { + QWidget* widget = QtWidgetWrapper::getWidgetOfView(this); + std::shared_ptr filePtr = std::make_shared(this, fileName, widget); + + m_files.push_back(filePtr); + file = filePtr.get(); + widget->layout()->addWidget(file); + } + + file->addCodeSnippet(str, locationFile, startLineNumber); } void QtCodeView::doClearCodeSnippets() { - m_snippets.clear(); + m_files.clear(); } diff --git a/src/app/qt/view/QtCodeView.h b/src/app/qt/view/QtCodeView.h index ed7723bd..14815092 100644 --- a/src/app/qt/view/QtCodeView.h +++ b/src/app/qt/view/QtCodeView.h @@ -8,7 +8,7 @@ #include "qt/utility/QtThreadedFunctor.h" #include "utility/types.h" -class QtCodeSnippet; +class QtCodeFile; class QtCodeView: public CodeView { @@ -30,7 +30,7 @@ private: void doAddCodeSnippet(const std::string& str, const TokenLocationFile& locationFile, int startLineNumber); void doClearCodeSnippets(); - std::vector > m_snippets; + std::vector > m_files; QtThreadedFunctor m_clearCodeSnippetsFunctor; QtThreadedFunctor m_addCodeSnippetFunctor; diff --git a/src/lib/utility/FileSystem.cpp b/src/lib/utility/FileSystem.cpp index 4ff3e45b..454991d4 100644 --- a/src/lib/utility/FileSystem.cpp +++ b/src/lib/utility/FileSystem.cpp @@ -44,3 +44,7 @@ bool FileSystem::exists(const std::string& path) return boost::filesystem::exists(boost::filesystem::path(path)); } +std::string FileSystem::fileName(const std::string& path) +{ + return boost::filesystem::path(path).filename().generic_string(); +} diff --git a/src/lib/utility/FileSystem.h b/src/lib/utility/FileSystem.h index 94f72037..89b50d51 100644 --- a/src/lib/utility/FileSystem.h +++ b/src/lib/utility/FileSystem.h @@ -11,6 +11,8 @@ public: const std::string& path, const std::vector& extensions ); static bool exists(const std::string& path); + static std::string fileName(const std::string& path); + private: static bool isValidExtension(const std::string& filepath, const std::vector& extensions); }; diff --git a/src/test/FileSystemTestSuite.h b/src/test/FileSystemTestSuite.h index 06a2b427..9907b44f 100644 --- a/src/test/FileSystemTestSuite.h +++ b/src/test/FileSystemTestSuite.h @@ -60,6 +60,12 @@ public: TS_ASSERT(!FileSystem::exists("data/FileSystemTestSuite/blabla.h")); } + void test_filesystem_extracts_filename() + { + TS_ASSERT_EQUALS(FileSystem::fileName("data/FileSystemTestSuite/tictactoe.h"), "tictactoe.h"); + TS_ASSERT_EQUALS(FileSystem::fileName("data/FileSystemTestSuite/Settings/player.h"), "player.h"); + } + private: bool isInVector(const std::vector& files, const std::string filename) {