diff --git a/bin/app/data/gui/code_view/images/pattern.png b/bin/app/data/gui/code_view/images/pattern.png new file mode 100644 index 00000000..2f424187 Binary files /dev/null and b/bin/app/data/gui/code_view/images/pattern.png differ diff --git a/src/app/qt/element/QtCodeFile.cpp b/src/app/qt/element/QtCodeFile.cpp index ea5863bb..83b0416d 100644 --- a/src/app/qt/element/QtCodeFile.cpp +++ b/src/app/qt/element/QtCodeFile.cpp @@ -4,6 +4,8 @@ #include #include +#include "utility/file/FileSystem.h" +#include "utility/logging/logging.h" #include "utility/messaging/type/MessageActivateFile.h" #include "utility/messaging/type/MessageShowFile.h" #include "utility/messaging/type/MessageShowSnippets.h" @@ -19,6 +21,7 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeFileList* parent) : QFrame(parent) , m_parent(parent) , m_filePath(filePath) + , m_updateTitleBarFunctor(std::bind(&QtCodeFile::doUpdateTitleBar, this)) { setObjectName("code_file"); @@ -28,15 +31,15 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeFileList* parent) layout->setAlignment(Qt::AlignTop); setLayout(layout); - QPushButton* titleWidget = new QPushButton(this); - titleWidget->setObjectName("title_widget"); - layout->addWidget(titleWidget); + m_titleBar = new QPushButton(this); + m_titleBar->setObjectName("title_widget"); + layout->addWidget(m_titleBar); QHBoxLayout* titleLayout = new QHBoxLayout(); titleLayout->setMargin(0); titleLayout->setSpacing(0); titleLayout->setAlignment(Qt::AlignLeft); - titleWidget->setLayout(titleLayout); + m_titleBar->setLayout(titleLayout); m_title = new QPushButton(filePath.fileName().c_str(), this); m_title->setObjectName("title_label"); @@ -54,7 +57,7 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeFileList* parent) titleLayout->addWidget(m_title); - titleWidget->setMinimumHeight(m_title->height() + 4); + m_titleBar->setMinimumHeight(m_title->height() + 4); m_referenceCount = new QLabel(this); m_referenceCount->setObjectName("references_label"); @@ -85,7 +88,7 @@ QtCodeFile::QtCodeFile(const FilePath& filePath, QtCodeFileList* parent) m_snippetButton->setEnabled(false); m_maximizeButton->setEnabled(false); - connect(titleWidget, SIGNAL(clicked()), this, SLOT(clickedTitleBar())); + connect(m_titleBar, SIGNAL(clicked()), this, SLOT(clickedTitleBar())); connect(m_title, SIGNAL(clicked()), this, SLOT(clickedTitle())); connect(m_minimizeButton, SIGNAL(clicked()), this, SLOT(clickedMinimizeButton())); connect(m_snippetButton, SIGNAL(clicked()), this, SLOT(clickedSnippetButton())); @@ -105,6 +108,12 @@ QtCodeFile::~QtCodeFile() { } +void QtCodeFile::setModificationTime(TimePoint modificationTime) +{ + m_modificationTime = modificationTime; + updateTitleBar(); +} + const FilePath& QtCodeFile::getFilePath() const { return m_filePath; @@ -386,6 +395,11 @@ void QtCodeFile::clickedMaximizeButton() m_minimizePlaceholder->hide(); } +void QtCodeFile::handleMessage(MessageWindowFocus* message) +{ + updateTitleBar(); +} + void QtCodeFile::updateSnippets() { int maxDigits = 1; @@ -420,3 +434,22 @@ void QtCodeFile::updateRefCount(int refCount) m_referenceCount->hide(); } } + +void QtCodeFile::updateTitleBar() +{ + m_updateTitleBarFunctor(); +} + +void QtCodeFile::doUpdateTitleBar() +{ + // cannot use m_filePath.exists() here since it is only checked when FilePath is constructed. + if ((!FileSystem::exists(m_filePath.str())) || + (FileSystem::getLastWriteTime(m_filePath) > m_modificationTime)) + { + m_title->setStyleSheet("background-image: url(data/gui/code_view/images/pattern.png);"); + } + else + { + m_title->setStyleSheet(""); + } +} diff --git a/src/app/qt/element/QtCodeFile.h b/src/app/qt/element/QtCodeFile.h index 7a938c65..bde81574 100644 --- a/src/app/qt/element/QtCodeFile.h +++ b/src/app/qt/element/QtCodeFile.h @@ -8,7 +8,11 @@ #include #include "utility/file/FilePath.h" +#include "utility/TimePoint.h" #include "utility/types.h" +#include "utility/messaging/MessageListener.h" +#include "utility/messaging/type/MessageWindowFocus.h" +#include "qt/utility/QtThreadedFunctor.h" class QLabel; class QPushButton; @@ -19,6 +23,7 @@ class TokenLocationFile; class QtCodeFile : public QFrame + , MessageListener { Q_OBJECT @@ -26,6 +31,8 @@ public: QtCodeFile(const FilePath& filePath, QtCodeFileList* parent); virtual ~QtCodeFile(); + void setModificationTime(TimePoint modificationTime); + const FilePath& getFilePath() const; std::string getFileName() const; Id getFocusedTokenId() const; @@ -67,11 +74,18 @@ private slots: void clickedMaximizeButton(); private: + virtual void handleMessage(MessageWindowFocus* message); + void updateSnippets(); void updateRefCount(int refCount); + void updateTitleBar(); + void doUpdateTitleBar(); + + QtThreadedFunctor<> m_updateTitleBarFunctor; QtCodeFileList* m_parent; + QPushButton* m_titleBar; QPushButton* m_title; QLabel* m_referenceCount; @@ -85,6 +99,7 @@ private: QWidget* m_minimizePlaceholder; const FilePath m_filePath; + TimePoint m_modificationTime; std::shared_ptr m_locationFile; }; diff --git a/src/app/qt/element/QtCodeFileList.cpp b/src/app/qt/element/QtCodeFileList.cpp index 13c49fd2..9f191603 100644 --- a/src/app/qt/element/QtCodeFileList.cpp +++ b/src/app/qt/element/QtCodeFileList.cpp @@ -47,6 +47,7 @@ void QtCodeFileList::addCodeSnippet( const std::string& code, std::shared_ptr locationFile, int refCount, + TimePoint modificationTime, bool insert ){ QtCodeFile* file = getFile(locationFile); @@ -60,12 +61,14 @@ void QtCodeFileList::addCodeSnippet( { file->addCodeSnippet(startLineNumber, title, titleId, code, locationFile, refCount); } + file->setModificationTime(modificationTime); } -void QtCodeFileList::addFile(std::shared_ptr locationFile, int refCount) +void QtCodeFileList::addFile(std::shared_ptr locationFile, int refCount, TimePoint modificationTime) { QtCodeFile* file = getFile(locationFile); file->setLocationFile(locationFile, refCount); + file->setModificationTime(modificationTime); } void QtCodeFileList::clearCodeSnippets() diff --git a/src/app/qt/element/QtCodeFileList.h b/src/app/qt/element/QtCodeFileList.h index 8025c313..9a369026 100644 --- a/src/app/qt/element/QtCodeFileList.h +++ b/src/app/qt/element/QtCodeFileList.h @@ -7,6 +7,7 @@ #include #include +#include "utility/TimePoint.h" #include "utility/types.h" class QtCodeFile; @@ -33,10 +34,11 @@ public: const std::string& code, std::shared_ptr locationFile, int refCount, + TimePoint modificationTime, bool insert = false ); - void addFile(std::shared_ptr locationFile, int refCount); + void addFile(std::shared_ptr locationFile, int refCount, TimePoint modificationTime); void clearCodeSnippets(); diff --git a/src/app/qt/view/QtCodeView.cpp b/src/app/qt/view/QtCodeView.cpp index 0cd87b97..fec7f032 100644 --- a/src/app/qt/view/QtCodeView.cpp +++ b/src/app/qt/view/QtCodeView.cpp @@ -96,7 +96,7 @@ void QtCodeView::doShowCodeSnippets(const std::vector& snippe { if (params.isCollapsed) { - m_widget->addFile(params.locationFile, params.refCount); + m_widget->addFile(params.locationFile, params.refCount, params.modificationTime); } else { @@ -106,7 +106,8 @@ void QtCodeView::doShowCodeSnippets(const std::vector& snippe params.titleId, params.code, params.locationFile, - params.refCount + params.refCount, + params.modificationTime ); } } @@ -116,15 +117,16 @@ void QtCodeView::doShowCodeSnippets(const std::vector& snippe void QtCodeView::doAddCodeSnippets(const std::vector& snippets) { - for (const CodeSnippetParams& snippet : snippets) + for (const CodeSnippetParams& params : snippets) { m_widget->addCodeSnippet( - snippet.startLineNumber, - snippet.title, - snippet.titleId, - snippet.code, - snippet.locationFile, - snippet.refCount, + params.startLineNumber, + params.title, + params.titleId, + params.code, + params.locationFile, + params.refCount, + params.modificationTime, true ); } @@ -134,7 +136,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); + m_widget->addCodeSnippet(1, params.title, 0, params.code, params.locationFile, -1, params.modificationTime); } void QtCodeView::doShowFirstActiveSnippet() diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 0c8bac6f..1f0320fc 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -302,6 +302,8 @@ add_files( utility/ConfigManager.cpp utility/ConfigManager.h utility/Property.h + utility/TimePoint.cpp + utility/TimePoint.h utility/types.h utility/utility.cpp utility/utility.h diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index d2c995a1..d5d262d9 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -121,6 +121,7 @@ void CodeController::handleMessage(MessageShowFile* message) std::shared_ptr textAccess = m_storageAccess->getFileContent(message->filePath); params.code = textAccess->getText(); + params.modificationTime = m_storageAccess->getFileModificationTime(message->filePath); params.locationFile = m_storageAccess->getTokenLocationsForFile(message->filePath.str()); getView()->showCodeFile(params); @@ -194,6 +195,7 @@ std::vector CodeController::getSnippetsForActiveTok CodeView::CodeSnippetParams params; params.locationFile = file; params.refCount = file->getUnscopedStartTokenLocationCount(); + params.modificationTime = m_storageAccess->getFileModificationTime(file->getFilePath()); params.isCollapsed = true; snippets.push_back(params); @@ -259,6 +261,8 @@ std::vector CodeController::getSnippetsForFile(std: params.refCount = file->getUnscopedStartTokenLocationCount(); params.startLineNumber = std::max(1, range.start.row - (range.start.strong ? 0 : snippetExpandRange)); params.endLineNumber = std::min(textAccess->getLineCount(), range.end.row + (range.end.strong ? 0 : snippetExpandRange)); + params.modificationTime = m_storageAccess->getFileModificationTime(file->getFilePath()); + std::shared_ptr tempFile = m_storageAccess->getTokenLocationsForLinesInFile(file->getFilePath().str(), params.startLineNumber, params.endLineNumber); diff --git a/src/lib/component/view/CodeView.h b/src/lib/component/view/CodeView.h index 17d0eb44..413342ca 100644 --- a/src/lib/component/view/CodeView.h +++ b/src/lib/component/view/CodeView.h @@ -5,6 +5,7 @@ #include "component/view/View.h" #include "data/location/TokenLocationFile.h" +#include "utility/TimePoint.h" #include "utility/types.h" class CodeController; @@ -26,6 +27,7 @@ public: std::string code; Id titleId; + TimePoint modificationTime; std::shared_ptr locationFile; diff --git a/src/lib/data/Storage.cpp b/src/lib/data/Storage.cpp index 94eba30f..1aa3cdd4 100644 --- a/src/lib/data/Storage.cpp +++ b/src/lib/data/Storage.cpp @@ -5,6 +5,7 @@ #include "utility/file/FileSystem.h" #include "utility/logging/logging.h" +#include "utility/TimePoint.h" #include "utility/utility.h" #include "utility/utilityString.h" @@ -1219,6 +1220,11 @@ std::shared_ptr Storage::getFileContent(const FilePath& filePath) co return m_sqliteStorage.getFileContentByPath(filePath.str()); } +TimePoint Storage::getFileModificationTime(const FilePath& filePath) const +{ + return TimePoint(m_sqliteStorage.getFileByPath(filePath.str()).modificationTime); +} + Id Storage::addNodeHierarchy(Node::NodeType nodeType, NameHierarchy nameHierarchy, bool defined, bool distinct) { std::vector nameIds = addNameHierarchyElements(nameHierarchy); diff --git a/src/lib/data/Storage.h b/src/lib/data/Storage.h index abd16a8d..c59b24f3 100644 --- a/src/lib/data/Storage.h +++ b/src/lib/data/Storage.h @@ -161,8 +161,7 @@ public: virtual std::shared_ptr getTokenLocationOfParentScope(const TokenLocation* child) const; virtual std::shared_ptr getFileContent(const FilePath& filePath) const; - - + virtual TimePoint getFileModificationTime(const FilePath& filePath) const; private: Id addNodeHierarchy(Node::NodeType nodeType, NameHierarchy nameHierarchy, bool defined, bool distinct = false); diff --git a/src/lib/data/access/StorageAccess.h b/src/lib/data/access/StorageAccess.h index 2047ca77..8463879c 100644 --- a/src/lib/data/access/StorageAccess.h +++ b/src/lib/data/access/StorageAccess.h @@ -17,6 +17,7 @@ class TextAccess; class TokenLocation; class TokenLocationCollection; class TokenLocationFile; +class TimePoint; class StorageAccess { @@ -56,6 +57,7 @@ public: virtual std::shared_ptr getTokenLocationOfParentScope(const TokenLocation* child) const = 0; virtual std::shared_ptr getFileContent(const FilePath& filePath) const = 0; + virtual TimePoint getFileModificationTime(const FilePath& filePath) const = 0; }; #endif // STORAGE_ACCESS_H diff --git a/src/lib/data/access/StorageAccessProxy.cpp b/src/lib/data/access/StorageAccessProxy.cpp index 6cd5218e..de5b5f01 100644 --- a/src/lib/data/access/StorageAccessProxy.cpp +++ b/src/lib/data/access/StorageAccessProxy.cpp @@ -6,6 +6,7 @@ #include "utility/logging/logging.h" #include "utility/file/FileInfo.h" +#include "utility/TimePoint.h" StorageAccessProxy::StorageAccessProxy() : m_subject(nullptr) @@ -243,3 +244,13 @@ std::shared_ptr StorageAccessProxy::getFileContent(const FilePath& f return nullptr; } + +TimePoint StorageAccessProxy::getFileModificationTime(const FilePath& filePath) const +{ + if (hasSubject()) + { + return m_subject->getFileModificationTime(filePath); + } + + return TimePoint(boost::posix_time::not_a_date_time); +} diff --git a/src/lib/data/access/StorageAccessProxy.h b/src/lib/data/access/StorageAccessProxy.h index 24b892fd..4b434afb 100644 --- a/src/lib/data/access/StorageAccessProxy.h +++ b/src/lib/data/access/StorageAccessProxy.h @@ -47,6 +47,7 @@ public: virtual std::shared_ptr getTokenLocationOfParentScope(const TokenLocation* child) const; virtual std::shared_ptr getFileContent(const FilePath& filePath) const; + virtual TimePoint getFileModificationTime(const FilePath& filePath) const; private: StorageAccess* m_subject; diff --git a/src/lib/utility/TimePoint.cpp b/src/lib/utility/TimePoint.cpp new file mode 100644 index 00000000..9d7e37aa --- /dev/null +++ b/src/lib/utility/TimePoint.cpp @@ -0,0 +1,21 @@ +#include "TimePoint.h" + +TimePoint::TimePoint() + : m_time(boost::posix_time::not_a_date_time) +{ +} + +TimePoint::TimePoint(boost::posix_time::ptime t) + : m_time(t) +{ +} + +//TimePoint::TimePoint(time_t t) +//{ +// needs an implementation +//} + +TimePoint::TimePoint(std::string s) +{ + m_time = boost::posix_time::time_from_string(s); +} diff --git a/src/lib/utility/TimePoint.h b/src/lib/utility/TimePoint.h new file mode 100644 index 00000000..53086a6c --- /dev/null +++ b/src/lib/utility/TimePoint.h @@ -0,0 +1,25 @@ +#ifndef TIME_POINT_H +#define TIME_POINT_H + +#include "boost/date_time/posix_time/posix_time.hpp" + +class TimePoint +{ +public: + TimePoint(); + TimePoint(boost::posix_time::ptime t); + //TimePoint(time_t t); + TimePoint(std::string s); + + inline bool operator==(const TimePoint& rhs){ return m_time == rhs.m_time; } + inline bool operator!=(const TimePoint& rhs){ return m_time != rhs.m_time; } + inline bool operator<(const TimePoint& rhs){ return m_time < rhs.m_time; } + inline bool operator>(const TimePoint& rhs){ return m_time > rhs.m_time; } + inline bool operator<=(const TimePoint& rhs){ return m_time <= rhs.m_time; } + inline bool operator>=(const TimePoint& rhs){ return m_time >= rhs.m_time; } + +private: + boost::posix_time::ptime m_time; +}; + +#endif // TIME_POINT_H diff --git a/src/lib/utility/file/FileSystem.cpp b/src/lib/utility/file/FileSystem.cpp index e3c07d79..a75b5d71 100644 --- a/src/lib/utility/file/FileSystem.cpp +++ b/src/lib/utility/file/FileSystem.cpp @@ -94,6 +94,17 @@ std::vector FileSystem::getFileInfosFromPaths( return files; } +TimePoint FileSystem::getLastWriteTime(const FilePath& filePath) +{ + boost::posix_time::ptime lastWriteTime; + if (FileSystem::exists(filePath.str())) + { + std::time_t t = boost::filesystem::last_write_time(filePath.path()); + lastWriteTime = boost::posix_time::from_time_t(t); + } + return TimePoint(lastWriteTime); +} + std::string FileSystem::getTimeStringNow() // TODO: move to utility { return boost::posix_time::to_iso_string(boost::posix_time::second_clock::universal_time()); diff --git a/src/lib/utility/file/FileSystem.h b/src/lib/utility/file/FileSystem.h index 8df7936f..79eebb5a 100644 --- a/src/lib/utility/file/FileSystem.h +++ b/src/lib/utility/file/FileSystem.h @@ -5,6 +5,7 @@ #include #include "utility/file/FileInfo.h" +#include "utility/TimePoint.h" class FileSystem { @@ -19,6 +20,7 @@ public: static std::vector getFileInfosFromPaths( const std::vector& paths, const std::vector& fileExtensions); + static TimePoint getLastWriteTime(const FilePath& filePath); static std::string getTimeStringNow(); static std::vector getSubDirectories(const FilePath& path);