- enhancement: save project's bookmark in it's own bookmark file
- enhancement: project and non-project files use different bookmark view (auto switch when switch editors) - enhancement: auto merge when save bookmarks.
This commit is contained in:
parent
f67628863f
commit
975d90c8f1
4
NEWS.md
4
NEWS.md
|
@ -9,7 +9,9 @@ Red Panda C++ Version 1.5
|
|||
- change: don't show syntax check messages in the tools output panel (to reduce longtime memory usage)
|
||||
- fix: minor memory leaks when set itemmodels
|
||||
- fix: thread for parsing doesn't correctly released when parsing finished ( so and the parser)
|
||||
|
||||
- enhancement: save project's bookmark in it's own bookmark file
|
||||
- enhancement: project and non-project files use different bookmark view (auto switch when switch editors)
|
||||
- enhancement: auto merge when save bookmarks.
|
||||
|
||||
Red Panda C++ Version 1.4
|
||||
|
||||
|
|
|
@ -1292,6 +1292,7 @@ void Editor::showEvent(QShowEvent */*event*/)
|
|||
reparse();
|
||||
}
|
||||
|
||||
pMainWindow->bookmarkModel()->setIsForProject(inProject());
|
||||
// if (pSettings->codeCompletion().clearWhenEditorHidden()
|
||||
// && !inProject()) {
|
||||
// reparse();
|
||||
|
@ -1696,7 +1697,7 @@ void Editor::onLinesDeleted(int first, int count)
|
|||
{
|
||||
pMainWindow->caretList().linesDeleted(this,first,count);
|
||||
pMainWindow->debugger()->breakpointModel()->onFileDeleteLines(mFilename,first,count);
|
||||
pMainWindow->bookmarkModel()->onFileDeleteLines(mFilename,first,count);
|
||||
pMainWindow->bookmarkModel()->onFileDeleteLines(mFilename,first,count, inProject());
|
||||
resetBreakpoints();
|
||||
resetBookmarks();
|
||||
if (!pSettings->editor().syntaxCheckWhenLineChanged()) {
|
||||
|
@ -1708,7 +1709,7 @@ void Editor::onLinesInserted(int first, int count)
|
|||
{
|
||||
pMainWindow->caretList().linesInserted(this,first,count);
|
||||
pMainWindow->debugger()->breakpointModel()->onFileInsertLines(mFilename,first,count);
|
||||
pMainWindow->bookmarkModel()->onFileInsertLines(mFilename,first,count);
|
||||
pMainWindow->bookmarkModel()->onFileInsertLines(mFilename,first,count, inProject());
|
||||
resetBreakpoints();
|
||||
resetBookmarks();
|
||||
if (!pSettings->editor().syntaxCheckWhenLineChanged()) {
|
||||
|
@ -1747,7 +1748,7 @@ bool Editor::shouldOpenInReadonly()
|
|||
|
||||
void Editor::resetBookmarks()
|
||||
{
|
||||
mBookmarkLines=pMainWindow->bookmarkModel()->bookmarksInFile(mFilename);
|
||||
mBookmarkLines=pMainWindow->bookmarkModel()->bookmarksInFile(mFilename,inProject());
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
@ -4407,17 +4408,15 @@ bool Editor::hasBreakpoint(int line)
|
|||
return mBreakpointLines.contains(line);
|
||||
}
|
||||
|
||||
void Editor::addBookmark(int line, const QString& description)
|
||||
void Editor::addBookmark(int line)
|
||||
{
|
||||
mBookmarkLines.insert(line);
|
||||
pMainWindow->bookmarkModel()->addBookmark(mFilename,line,description);
|
||||
invalidateGutterLine(line);
|
||||
}
|
||||
|
||||
void Editor::removeBookmark(int line)
|
||||
{
|
||||
mBookmarkLines.remove(line);
|
||||
pMainWindow->bookmarkModel()->removeBookmark(mFilename,line);
|
||||
invalidateGutterLine(line);
|
||||
}
|
||||
|
||||
|
@ -4429,7 +4428,6 @@ bool Editor::hasBookmark(int line)
|
|||
void Editor::clearBookmarks()
|
||||
{
|
||||
mBookmarkLines.clear();
|
||||
pMainWindow->bookmarkModel()->removeBookmarks(mFilename);
|
||||
invalidateGutter();
|
||||
}
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ public:
|
|||
void toggleBreakpoint(int line);
|
||||
void clearBreakpoints();
|
||||
bool hasBreakpoint(int line);
|
||||
void addBookmark(int line,const QString& description);
|
||||
void addBookmark(int line);
|
||||
void removeBookmark(int line);
|
||||
bool hasBookmark(int line);
|
||||
void clearBookmarks();
|
||||
|
@ -224,6 +224,7 @@ public:
|
|||
QString getWordForCompletionSearch(const QSynedit::BufferCoord& pos,bool permitTilde);
|
||||
QStringList getExpressionAtPosition(
|
||||
const QSynedit::BufferCoord& pos);
|
||||
void resetBookmarks();
|
||||
|
||||
const PCppParser &parser();
|
||||
|
||||
|
@ -242,7 +243,6 @@ private slots:
|
|||
private:
|
||||
bool isBraceChar(QChar ch);
|
||||
bool shouldOpenInReadonly();
|
||||
void resetBookmarks();
|
||||
QChar getCurrentChar();
|
||||
bool handleSymbolCompletion(QChar key);
|
||||
bool handleParentheseCompletion();
|
||||
|
|
|
@ -281,7 +281,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
}
|
||||
mBookmarkModel = std::make_shared<BookmarkModel>();
|
||||
try {
|
||||
mBookmarkModel->load(includeTrailingPathDelimiter(pSettings->dirs().config())
|
||||
mBookmarkModel->loadBookmarks(includeTrailingPathDelimiter(pSettings->dirs().config())
|
||||
+DEV_BOOKMARK_FILE);
|
||||
} catch (FileError &e) {
|
||||
QMessageBox::warning(nullptr,
|
||||
|
@ -407,6 +407,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
updateShortcuts();
|
||||
updateTools();
|
||||
updateEditorSettings();
|
||||
//updateEditorBookmarks();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
|
@ -449,6 +450,14 @@ void MainWindow::updateEditorSettings()
|
|||
mEditorList->applySettings();
|
||||
}
|
||||
|
||||
void MainWindow::updateEditorBookmarks()
|
||||
{
|
||||
for (int i=0;i<mEditorList->pageCount();i++) {
|
||||
Editor * e=(*mEditorList)[i];
|
||||
e->resetBookmarks();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::updateEditorActions()
|
||||
{
|
||||
Editor* e = mEditorList->getEditor();
|
||||
|
@ -1281,45 +1290,50 @@ void MainWindow::openProject(const QString &filename, bool openFiles)
|
|||
|
||||
// Only update class browser once
|
||||
mClassBrowserModel.beginUpdate();
|
||||
{
|
||||
auto action = finally([this]{
|
||||
mClassBrowserModel.endUpdate();
|
||||
});
|
||||
mProject = Project::load(filename,mEditorList,&mFileSystemWatcher);
|
||||
updateProjectView();
|
||||
ui->projectView->expand(
|
||||
mProjectProxyModel->mapFromSource(
|
||||
mProject->model()->rootIndex()));
|
||||
pSettings->history().removeProject(filename);
|
||||
mProject = Project::load(filename,mEditorList,&mFileSystemWatcher);
|
||||
updateProjectView();
|
||||
ui->projectView->expand(
|
||||
mProjectProxyModel->mapFromSource(
|
||||
mProject->model()->rootIndex()));
|
||||
pSettings->history().removeProject(filename);
|
||||
|
||||
// // if project manager isn't open then open it
|
||||
// if not devData.ShowLeftPages then
|
||||
// actProjectManager.Execute;
|
||||
//checkForDllProfiling();
|
||||
// // if project manager isn't open then open it
|
||||
// if not devData.ShowLeftPages then
|
||||
// actProjectManager.Execute;
|
||||
//checkForDllProfiling();
|
||||
|
||||
//parse the project
|
||||
// UpdateClassBrowsing;
|
||||
//parse the project
|
||||
// UpdateClassBrowsing;
|
||||
|
||||
scanActiveProject(true);
|
||||
if (openFiles) {
|
||||
PProjectUnit unit = mProject->doAutoOpen();
|
||||
setProjectViewCurrentUnit(unit);
|
||||
}
|
||||
scanActiveProject(true);
|
||||
|
||||
//update editor's inproject flag
|
||||
foreach (PProjectUnit unit, mProject->unitList()) {
|
||||
Editor* e = mEditorList->getOpenedEditorByFilename(unit->fileName());
|
||||
mProject->associateEditorToUnit(e,unit);
|
||||
}
|
||||
mBookmarkModel->setIsForProject(true);
|
||||
mBookmarkModel->loadProjectBookmarks(
|
||||
changeFileExt(mProject->filename(), PROJECT_BOOKMARKS_EXT),
|
||||
mProject->directory());
|
||||
|
||||
Editor * e = mEditorList->getEditor();
|
||||
if (e) {
|
||||
checkSyntaxInBack(e);
|
||||
}
|
||||
updateAppTitle();
|
||||
updateCompilerSet();
|
||||
updateClassBrowserForEditor(e);
|
||||
if (openFiles) {
|
||||
PProjectUnit unit = mProject->doAutoOpen();
|
||||
setProjectViewCurrentUnit(unit);
|
||||
}
|
||||
|
||||
//update editor's inproject flag
|
||||
foreach (PProjectUnit unit, mProject->unitList()) {
|
||||
Editor* e = mEditorList->getOpenedEditorByFilename(unit->fileName());
|
||||
mProject->associateEditorToUnit(e,unit);
|
||||
if (e)
|
||||
e->resetBookmarks();
|
||||
}
|
||||
|
||||
Editor * e = mEditorList->getEditor();
|
||||
if (e) {
|
||||
checkSyntaxInBack(e);
|
||||
}
|
||||
updateAppTitle();
|
||||
updateCompilerSet();
|
||||
updateClassBrowserForEditor(e);
|
||||
mClassBrowserModel.endUpdate();
|
||||
|
||||
//updateForEncodingInfo();
|
||||
}
|
||||
|
||||
|
@ -2294,8 +2308,10 @@ void MainWindow::loadLastOpens()
|
|||
focusedEditor = editor;
|
||||
pSettings->history().removeFile(editorFilename);
|
||||
}
|
||||
if (mProject && mEditorList->pageCount()==0)
|
||||
if (mProject && mEditorList->pageCount()==0) {
|
||||
mProject->doAutoOpen();
|
||||
updateEditorBookmarks();
|
||||
}
|
||||
if (count>0) {
|
||||
updateEditorActions();
|
||||
//updateForEncodingInfo();
|
||||
|
@ -3759,21 +3775,21 @@ void MainWindow::onBookmarkRemove()
|
|||
PBookmark bookmark = mBookmarkModel->bookmark(index.row());
|
||||
if (bookmark) {
|
||||
Editor * editor = mEditorList->getOpenedEditorByFilename(bookmark->filename);
|
||||
if (editor) {
|
||||
if (editor && editor->inProject() == mBookmarkModel->isForProject()) {
|
||||
editor->removeBookmark(bookmark->line);
|
||||
} else {
|
||||
mBookmarkModel->removeBookmarkAt(index.row());
|
||||
}
|
||||
mBookmarkModel->removeBookmarkAt(index.row());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onBookmarkRemoveAll()
|
||||
{
|
||||
mBookmarkModel->clear();
|
||||
mBookmarkModel->clear(mBookmarkModel->isForProject());
|
||||
for (int i=0;i<mEditorList->pageCount();i++) {
|
||||
Editor * editor = (*mEditorList)[i];
|
||||
editor->clearBookmarks();
|
||||
if (editor->inProject() == mBookmarkModel->isForProject())
|
||||
editor->clearBookmarks();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4305,33 +4321,31 @@ void MainWindow::closeProject(bool refreshEditor)
|
|||
} else
|
||||
mProject->saveLayout(); // always save layout, but not when SaveAll has been called
|
||||
|
||||
mBookmarkModel->saveProjectBookmarks(
|
||||
changeFileExt(mProject->filename(), PROJECT_BOOKMARKS_EXT),
|
||||
mProject->directory());
|
||||
|
||||
mClassBrowserModel.beginUpdate();
|
||||
{
|
||||
auto action2 = finally([this]{
|
||||
mClassBrowserModel.endUpdate();
|
||||
});
|
||||
// Remember it
|
||||
pSettings->history().addToOpenedProjects(mProject->filename());
|
||||
// Remember it
|
||||
pSettings->history().addToOpenedProjects(mProject->filename());
|
||||
|
||||
mEditorList->beginUpdate();
|
||||
{
|
||||
auto action3 = finally([this]{
|
||||
mEditorList->endUpdate();
|
||||
});
|
||||
mProject.reset();
|
||||
mEditorList->beginUpdate();
|
||||
mProject.reset();
|
||||
|
||||
if (!mQuitting && refreshEditor) {
|
||||
//reset Class browsing
|
||||
ui->tabExplorer->setCurrentWidget(ui->tabStructure);
|
||||
Editor * e = mEditorList->getEditor();
|
||||
updateClassBrowserForEditor(e);
|
||||
} else {
|
||||
mClassBrowserModel.setParser(nullptr);
|
||||
mClassBrowserModel.setCurrentFile("");
|
||||
}
|
||||
}
|
||||
if (!mQuitting && refreshEditor) {
|
||||
//reset Class browsing
|
||||
ui->tabExplorer->setCurrentWidget(ui->tabStructure);
|
||||
Editor * e = mEditorList->getEditor();
|
||||
updateClassBrowserForEditor(e);
|
||||
} else {
|
||||
mClassBrowserModel.setParser(nullptr);
|
||||
mClassBrowserModel.setCurrentFile("");
|
||||
}
|
||||
mEditorList->endUpdate();
|
||||
mClassBrowserModel.endUpdate();
|
||||
|
||||
if (!mQuitting) {
|
||||
mBookmarkModel->setIsForProject(false);
|
||||
// Clear error browser
|
||||
clearIssues();
|
||||
updateProjectView();
|
||||
|
@ -4540,7 +4554,7 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
|||
pSettings->environment().setDefaultOpenFolder(QDir::currentPath());
|
||||
pSettings->environment().save();
|
||||
try {
|
||||
mBookmarkModel->save(includeTrailingPathDelimiter(pSettings->dirs().config())
|
||||
mBookmarkModel->saveBookmarks(includeTrailingPathDelimiter(pSettings->dirs().config())
|
||||
+DEV_BOOKMARK_FILE);
|
||||
} catch (FileError& e) {
|
||||
QMessageBox::warning(nullptr,
|
||||
|
@ -4672,8 +4686,8 @@ void MainWindow::on_actionSave_triggered()
|
|||
if (editor != NULL) {
|
||||
try {
|
||||
editor->save();
|
||||
if (editor->inProject() && (mProject))
|
||||
mProject->saveAll();
|
||||
// if (editor->inProject() && (mProject))
|
||||
// mProject->saveAll();
|
||||
} catch(FileError e) {
|
||||
QMessageBox::critical(editor,tr("Error"),e.reason());
|
||||
}
|
||||
|
@ -6942,7 +6956,8 @@ void MainWindow::on_actionAdd_bookmark_triggered()
|
|||
tr("Description:"),QLineEdit::Normal,
|
||||
editor->document()->getString(line-1).trimmed());
|
||||
desc = desc.trimmed();
|
||||
editor->addBookmark(line,desc);
|
||||
editor->addBookmark(line);
|
||||
mBookmarkModel->addBookmark(editor->filename(),line,desc,editor->inProject());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6953,6 +6968,7 @@ void MainWindow::on_actionRemove_Bookmark_triggered()
|
|||
int line;
|
||||
if (editor && editor->pointToLine(mEditorContextMenuPos,line)) {
|
||||
editor->removeBookmark(line);
|
||||
mBookmarkModel->removeBookmark(editor->filename(),line,editor->inProject());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@ public:
|
|||
void updateForStatusbarModeInfo(bool clear=false);
|
||||
void updateStatusbarMessage(const QString& s);
|
||||
void updateEditorSettings();
|
||||
void updateEditorBookmarks();
|
||||
void updateEditorActions();
|
||||
void updateProjectActions();
|
||||
void updateCompileActions();
|
||||
|
|
|
@ -895,7 +895,7 @@
|
|||
<enum>QTabWidget::South</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
|
@ -1512,6 +1512,9 @@
|
|||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
|
|
|
@ -70,6 +70,7 @@
|
|||
#endif
|
||||
|
||||
#define DEV_PROJECT_EXT "dev"
|
||||
#define PROJECT_BOOKMARKS_EXT "bookmarks"
|
||||
#define RC_EXT "rc"
|
||||
#define RES_EXT "res"
|
||||
#define H_EXT "h"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "bookmarkmodel.h"
|
||||
#include "../systemconsts.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonArray>
|
||||
|
@ -26,15 +27,21 @@
|
|||
#include <QSet>
|
||||
#include "../utils.h"
|
||||
|
||||
BookmarkModel::BookmarkModel(QObject* parent):QAbstractTableModel(parent)
|
||||
BookmarkModel::BookmarkModel(QObject* parent):QAbstractTableModel(parent),
|
||||
mIsForProject(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QSet<int> BookmarkModel::bookmarksInFile(const QString &filename)
|
||||
QSet<int> BookmarkModel::bookmarksInFile(const QString &filename, bool forProject)
|
||||
{
|
||||
QSet<int> lines;
|
||||
foreach (const PBookmark& bookmark, mBookmarks) {
|
||||
QList<PBookmark> bookmarks;
|
||||
if (forProject)
|
||||
bookmarks = mProjectBookmarks;
|
||||
else
|
||||
bookmarks = mBookmarks;
|
||||
foreach (const PBookmark& bookmark, bookmarks) {
|
||||
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0) {
|
||||
lines.insert(bookmark->line);
|
||||
}
|
||||
|
@ -42,27 +49,48 @@ QSet<int> BookmarkModel::bookmarksInFile(const QString &filename)
|
|||
return lines;
|
||||
}
|
||||
|
||||
void BookmarkModel::addBookmark(const QString &filename, int line, const QString &description)
|
||||
void BookmarkModel::addBookmark(const QString &filename, int line, const QString &description, bool forProject)
|
||||
{
|
||||
Q_ASSERT(!isBookmarkExists(filename,line));
|
||||
Q_ASSERT(!isBookmarkExists(filename,line,forProject));
|
||||
PBookmark bookmark = std::make_shared<Bookmark>();
|
||||
bookmark->filename = filename;
|
||||
bookmark->line = line;
|
||||
bookmark->description = description;
|
||||
beginInsertRows(QModelIndex(),mBookmarks.count(),mBookmarks.count());
|
||||
mBookmarks.append(bookmark);
|
||||
endInsertRows();
|
||||
bookmark->timestamp = QDateTime::currentMSecsSinceEpoch();
|
||||
if (forProject) {
|
||||
if (forProject==mIsForProject)
|
||||
beginInsertRows(QModelIndex(),mProjectBookmarks.count(),mProjectBookmarks.count());
|
||||
mProjectBookmarks.append(bookmark);
|
||||
} else {
|
||||
if (forProject==mIsForProject)
|
||||
beginInsertRows(QModelIndex(),mBookmarks.count(),mBookmarks.count());
|
||||
mBookmarks.append(bookmark);
|
||||
}
|
||||
if (forProject==mIsForProject)
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
PBookmark BookmarkModel::bookmark(int i, bool forProject)
|
||||
{
|
||||
if (forProject)
|
||||
return mProjectBookmarks[i];
|
||||
else
|
||||
return mBookmarks[i];
|
||||
}
|
||||
|
||||
PBookmark BookmarkModel::bookmark(int i)
|
||||
{
|
||||
return mBookmarks[i];
|
||||
return bookmark(i,isForProject());
|
||||
}
|
||||
|
||||
PBookmark BookmarkModel::bookmark(const QString &filename, int line)
|
||||
PBookmark BookmarkModel::bookmark(const QString &filename, int line, bool forProject)
|
||||
{
|
||||
for (int i=0;i<mBookmarks.count();i++) {
|
||||
PBookmark bookmark = mBookmarks[i];
|
||||
QList<PBookmark> bookmarks;
|
||||
if (forProject)
|
||||
bookmarks = mProjectBookmarks;
|
||||
else
|
||||
bookmarks = mBookmarks;
|
||||
foreach (PBookmark bookmark, bookmarks) {
|
||||
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0
|
||||
&& bookmark->line == line) {
|
||||
return bookmark;
|
||||
|
@ -71,40 +99,65 @@ PBookmark BookmarkModel::bookmark(const QString &filename, int line)
|
|||
return PBookmark();
|
||||
}
|
||||
|
||||
bool BookmarkModel::removeBookmark(const QString &filename, int line)
|
||||
PBookmark BookmarkModel::bookmark(const QString &filename, int line)
|
||||
{
|
||||
for (int i=0;i<mBookmarks.count();i++) {
|
||||
PBookmark bookmark = mBookmarks[i];
|
||||
return bookmark(filename,line,isForProject());
|
||||
}
|
||||
|
||||
bool BookmarkModel::removeBookmark(const QString &filename, int line, bool forProject)
|
||||
{
|
||||
QList<PBookmark> bookmarks;
|
||||
if (forProject)
|
||||
bookmarks = mProjectBookmarks;
|
||||
else
|
||||
bookmarks = mBookmarks;
|
||||
for (int i=0;i<bookmarks.count();i++) {
|
||||
PBookmark bookmark = bookmarks[i];
|
||||
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0
|
||||
&& bookmark->line == line) {
|
||||
removeBookmarkAt(i);
|
||||
removeBookmarkAt(i, forProject);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void BookmarkModel::removeBookmarks(const QString &filename)
|
||||
void BookmarkModel::removeBookmarks(const QString &filename, bool forProject)
|
||||
{
|
||||
for (int i=mBookmarks.count()-1;i>=0;i--) {
|
||||
PBookmark bookmark = mBookmarks[i];
|
||||
QList<PBookmark> bookmarks;
|
||||
if (forProject)
|
||||
bookmarks = mProjectBookmarks;
|
||||
else
|
||||
bookmarks = mBookmarks;
|
||||
for (int i=bookmarks.count()-1;i>=0;i--) {
|
||||
PBookmark bookmark = bookmarks[i];
|
||||
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0) {
|
||||
removeBookmarkAt(i);
|
||||
removeBookmarkAt(i, forProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BookmarkModel::clear()
|
||||
void BookmarkModel::clear(bool forProject)
|
||||
{
|
||||
beginResetModel();
|
||||
mBookmarks.clear();
|
||||
endResetModel();
|
||||
if (forProject==mIsForProject)
|
||||
beginResetModel();
|
||||
if (forProject)
|
||||
mProjectBookmarks.clear();
|
||||
else
|
||||
mBookmarks.clear();
|
||||
if (forProject==mIsForProject)
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
bool BookmarkModel::updateDescription(const QString &filename, int line, const QString &description)
|
||||
bool BookmarkModel::updateDescription(const QString &filename, int line, const QString &description, bool forProject)
|
||||
{
|
||||
for (int i=0;i<mBookmarks.count();i++) {
|
||||
PBookmark bookmark = mBookmarks[i];
|
||||
QList<PBookmark> bookmarks;
|
||||
if (forProject)
|
||||
bookmarks = mProjectBookmarks;
|
||||
else
|
||||
bookmarks = mBookmarks;
|
||||
for (int i=0;i<bookmarks.count();i++) {
|
||||
PBookmark bookmark = bookmarks[i];
|
||||
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0
|
||||
&& bookmark->line == line) {
|
||||
bookmark->description = description;
|
||||
|
@ -115,16 +168,90 @@ bool BookmarkModel::updateDescription(const QString &filename, int line, const Q
|
|||
return false;
|
||||
}
|
||||
|
||||
void BookmarkModel::save(const QString &filename)
|
||||
bool BookmarkModel::updateDescription(const QString &filename, int line, const QString &description)
|
||||
{
|
||||
return updateDescription(filename,line,description,mIsForProject);
|
||||
}
|
||||
|
||||
void BookmarkModel::saveBookmarks(const QString &filename)
|
||||
{
|
||||
save(filename,QString());
|
||||
}
|
||||
|
||||
void BookmarkModel::loadBookmarks(const QString &filename)
|
||||
{
|
||||
if (!mIsForProject)
|
||||
beginResetModel();
|
||||
mBookmarks = load(filename,0,&mLastLoadBookmarksTimestamp);
|
||||
if (!mIsForProject)
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void BookmarkModel::save(const QString &filename, const QString& projectFolder)
|
||||
{
|
||||
bool forProject = !projectFolder.isEmpty();
|
||||
qint64 t,fileTimestamp;
|
||||
QList<PBookmark> bookmarks;
|
||||
if (forProject) {
|
||||
t=mLastLoadProjectBookmarksTimestamp;
|
||||
foreach (const PBookmark& bookmark, mProjectBookmarks) {
|
||||
PBookmark newBookmark=std::make_shared<Bookmark>();
|
||||
newBookmark->description = bookmark->description;
|
||||
newBookmark->filename = extractRelativePath(projectFolder, bookmark->filename);
|
||||
newBookmark->line = bookmark->line;
|
||||
newBookmark->timestamp = bookmark->timestamp;
|
||||
bookmarks.append(newBookmark);
|
||||
}
|
||||
} else {
|
||||
t=mLastLoadBookmarksTimestamp;
|
||||
bookmarks = mBookmarks;
|
||||
}
|
||||
QList<PBookmark> fileBookmarks=load(filename, t,&fileTimestamp);
|
||||
QFile file(filename);
|
||||
int saveOrderCount=0;
|
||||
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
|
||||
QHash<QString,PBookmark> compareHash;
|
||||
QList<PBookmark> saveBookmarks;
|
||||
foreach (const PBookmark& bookmark, bookmarks) {
|
||||
QString key = QString("%1-%2").arg(bookmark->filename).arg(bookmark->line);
|
||||
bookmark->saveOrder=saveOrderCount++;
|
||||
compareHash.insert(key,bookmark);
|
||||
}
|
||||
foreach (const PBookmark& bookmark, fileBookmarks) {
|
||||
QString key = QString("%1-%2").arg(bookmark->filename).arg(bookmark->line);
|
||||
bookmark->saveOrder=saveOrderCount++;
|
||||
if (!compareHash.contains(key))
|
||||
compareHash.insert(key,bookmark);
|
||||
else {
|
||||
PBookmark pTemp=compareHash.value(key);
|
||||
if (pTemp->timestamp<=bookmark->timestamp)
|
||||
compareHash.insert(key,bookmark);
|
||||
}
|
||||
compareHash.insert(key,bookmark);
|
||||
}
|
||||
QList<PBookmark> saveList;
|
||||
foreach (const PBookmark& bookmark, compareHash) {
|
||||
saveList.append(bookmark);
|
||||
}
|
||||
std::sort(saveList.begin(),saveList.end(), [](PBookmark b1,PBookmark b2) {
|
||||
return b1->saveOrder - b2->saveOrder;
|
||||
});
|
||||
|
||||
if (forProject) {
|
||||
mProjectBookmarks=saveList;
|
||||
mLastLoadProjectBookmarksTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||
} else {
|
||||
mBookmarks=saveList;
|
||||
mLastLoadBookmarksTimestamp = QDateTime::currentMSecsSinceEpoch();
|
||||
}
|
||||
|
||||
QJsonArray array;
|
||||
foreach (const PBookmark& bookmark, mBookmarks) {
|
||||
foreach (const PBookmark& bookmark, saveList) {
|
||||
QJsonObject obj;
|
||||
obj["filename"]=bookmark->filename;
|
||||
obj["line"]=bookmark->line;
|
||||
obj["description"]=bookmark->description;
|
||||
obj["timestamp"]=QString("%1").arg(bookmark->timestamp);
|
||||
array.append(obj);
|
||||
}
|
||||
QJsonDocument doc;
|
||||
|
@ -139,12 +266,18 @@ void BookmarkModel::save(const QString &filename)
|
|||
}
|
||||
}
|
||||
|
||||
void BookmarkModel::load(const QString& filename)
|
||||
QList<PBookmark> BookmarkModel::load(const QString& filename, qint64 criteriaTimestamp, qint64* pFileTimestamp)
|
||||
{
|
||||
clear();
|
||||
//clear(forProject);
|
||||
QList<PBookmark> bookmarks;
|
||||
QFileInfo fileInfo(filename);
|
||||
qint64 timestamp=fileInfo.fileTime(QFile::FileModificationTime).toMSecsSinceEpoch();
|
||||
*pFileTimestamp=timestamp;
|
||||
if (timestamp<=criteriaTimestamp)
|
||||
return bookmarks;
|
||||
QFile file(filename);
|
||||
if (!file.exists())
|
||||
return;
|
||||
return bookmarks;
|
||||
if (file.open(QFile::ReadOnly)) {
|
||||
QByteArray content = file.readAll();
|
||||
QJsonParseError error;
|
||||
|
@ -156,58 +289,111 @@ void BookmarkModel::load(const QString& filename)
|
|||
.arg(error.errorString()));
|
||||
}
|
||||
QJsonArray array = doc.array();
|
||||
qint64 bookmarkTimestamp;
|
||||
bool ok;
|
||||
for (int i=0;i<array.count();i++) {
|
||||
QJsonValue value = array[i];
|
||||
QJsonObject obj=value.toObject();
|
||||
addBookmark( QFileInfo(obj["filename"].toString()).absoluteFilePath(),
|
||||
obj["line"].toInt(),
|
||||
obj["description"].toString());
|
||||
|
||||
bookmarkTimestamp = obj["timestamp"].toString().toULongLong(&ok);
|
||||
if (ok && bookmarkTimestamp>criteriaTimestamp) {
|
||||
PBookmark bookmark = std::make_shared<Bookmark>();
|
||||
bookmark->filename = obj["filename"].toString();
|
||||
bookmark->line = obj["line"].toInt();
|
||||
bookmark->description = obj["description"].toString();
|
||||
bookmark->timestamp=obj["timestamp"].toString().toULongLong();
|
||||
bookmarks.append(bookmark);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw FileError(tr("Can't open file '%1' for read.")
|
||||
.arg(filename));
|
||||
}
|
||||
return bookmarks;
|
||||
}
|
||||
|
||||
void BookmarkModel::onFileDeleteLines(const QString &filename, int startLine, int count)
|
||||
void BookmarkModel::saveProjectBookmarks(const QString &filename, const QString& projectFolder)
|
||||
{
|
||||
for (int i = mBookmarks.count()-1;i>=0;i--){
|
||||
PBookmark bookmark = mBookmarks[i];
|
||||
save(filename,projectFolder);
|
||||
}
|
||||
|
||||
void BookmarkModel::loadProjectBookmarks(const QString &filename, const QString& projectFolder)
|
||||
{
|
||||
if (mIsForProject)
|
||||
beginResetModel();
|
||||
mProjectBookmarks = load(filename,0,&mLastLoadProjectBookmarksTimestamp);
|
||||
QDir folder(projectFolder);
|
||||
foreach (PBookmark bookmark, mProjectBookmarks) {
|
||||
bookmark->filename=folder.absoluteFilePath(bookmark->filename);
|
||||
}
|
||||
if (mIsForProject)
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
void BookmarkModel::onFileDeleteLines(const QString &filename, int startLine, int count, bool forProject)
|
||||
{
|
||||
QList<PBookmark> bookmarks;
|
||||
if (forProject)
|
||||
bookmarks = mProjectBookmarks;
|
||||
else
|
||||
bookmarks = mBookmarks;
|
||||
for (int i = bookmarks.count()-1;i>=0;i--){
|
||||
PBookmark bookmark = bookmarks[i];
|
||||
if (bookmark->filename == filename
|
||||
&& bookmark->line>=startLine) {
|
||||
if (bookmark->line >= startLine+count) {
|
||||
bookmark->line -= count;
|
||||
emit dataChanged(createIndex(i,0),createIndex(i,2));
|
||||
if (forProject == mIsForProject)
|
||||
emit dataChanged(createIndex(i,0),createIndex(i,2));
|
||||
} else {
|
||||
removeBookmarkAt(i);
|
||||
removeBookmarkAt(i,forProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BookmarkModel::onFileInsertLines(const QString &filename, int startLine, int count)
|
||||
void BookmarkModel::onFileInsertLines(const QString &filename, int startLine, int count, bool forProject)
|
||||
{
|
||||
for (int i = mBookmarks.count()-1;i>=0;i--){
|
||||
PBookmark bookmark = mBookmarks[i];
|
||||
QList<PBookmark> bookmarks;
|
||||
if (forProject)
|
||||
bookmarks = mProjectBookmarks;
|
||||
else
|
||||
bookmarks = mBookmarks;
|
||||
for (int i = bookmarks.count()-1;i>=0;i--){
|
||||
PBookmark bookmark = bookmarks[i];
|
||||
if (bookmark->filename == filename
|
||||
&& bookmark->line>=startLine) {
|
||||
bookmark->line+=count;
|
||||
emit dataChanged(createIndex(i,0),createIndex(i,2));
|
||||
if (forProject == mIsForProject)
|
||||
emit dataChanged(createIndex(i,0),createIndex(i,2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BookmarkModel::removeBookmarkAt(int i)
|
||||
void BookmarkModel::removeBookmarkAt(int i, bool forProject)
|
||||
{
|
||||
beginRemoveRows(QModelIndex(), i,i);
|
||||
mBookmarks.removeAt(i);
|
||||
endRemoveRows();
|
||||
if (forProject == mIsForProject)
|
||||
beginRemoveRows(QModelIndex(), i,i);
|
||||
if (forProject)
|
||||
mProjectBookmarks.removeAt(i);
|
||||
else
|
||||
mBookmarks.removeAt(i);
|
||||
if (forProject == mIsForProject)
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
bool BookmarkModel::isBookmarkExists(const QString &filename, int line)
|
||||
void BookmarkModel::removeBookmarkAt(int i)
|
||||
{
|
||||
foreach (const PBookmark& bookmark, mBookmarks) {
|
||||
return removeBookmarkAt(i,isForProject());
|
||||
}
|
||||
|
||||
bool BookmarkModel::isBookmarkExists(const QString &filename, int line, bool forProject)
|
||||
{
|
||||
QList<PBookmark> bookmarks;
|
||||
if (forProject)
|
||||
bookmarks = mProjectBookmarks;
|
||||
else
|
||||
bookmarks = mBookmarks;
|
||||
foreach (const PBookmark& bookmark, bookmarks) {
|
||||
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0
|
||||
&& bookmark->line == line) {
|
||||
return true;
|
||||
|
@ -216,9 +402,77 @@ bool BookmarkModel::isBookmarkExists(const QString &filename, int line)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool BookmarkModel::isForProject() const
|
||||
{
|
||||
return mIsForProject;
|
||||
}
|
||||
|
||||
void BookmarkModel::setIsForProject(bool newIsForProject)
|
||||
{
|
||||
if (newIsForProject!=mIsForProject) {
|
||||
mIsForProject = newIsForProject;
|
||||
beginResetModel();
|
||||
endResetModel();
|
||||
}
|
||||
}
|
||||
|
||||
void BookmarkModel::sort(int column, Qt::SortOrder order)
|
||||
{
|
||||
switch(column) {
|
||||
case 0:
|
||||
if (order == Qt::SortOrder::AscendingOrder) {
|
||||
auto sorter=[](PBookmark b1,PBookmark b2) {
|
||||
return QString::compare(b1->description,b2->description);
|
||||
};
|
||||
std::sort(mBookmarks.begin(),mBookmarks.end(),sorter);
|
||||
std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter);
|
||||
} else {
|
||||
auto sorter=[](PBookmark b1,PBookmark b2) {
|
||||
return QString::compare(b2->description,b1->description);
|
||||
};
|
||||
std::sort(mBookmarks.begin(),mBookmarks.end(),sorter);
|
||||
std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (order == Qt::SortOrder::AscendingOrder) {
|
||||
auto sorter=[](PBookmark b1,PBookmark b2) {
|
||||
return QString::compare(b1->filename,b2->filename);
|
||||
};
|
||||
std::sort(mBookmarks.begin(),mBookmarks.end(),sorter);
|
||||
std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter);
|
||||
} else {
|
||||
auto sorter=[](PBookmark b1,PBookmark b2) {
|
||||
return QString::compare(b2->filename,b1->filename);
|
||||
};
|
||||
std::sort(mBookmarks.begin(),mBookmarks.end(),sorter);
|
||||
std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (order == Qt::SortOrder::AscendingOrder) {
|
||||
auto sorter=[](PBookmark b1,PBookmark b2) {
|
||||
return b1->line-b2->line;
|
||||
};
|
||||
std::sort(mBookmarks.begin(),mBookmarks.end(),sorter);
|
||||
std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter);
|
||||
} else {
|
||||
auto sorter=[](PBookmark b1,PBookmark b2) {
|
||||
return b2->line-b1->line;
|
||||
};
|
||||
std::sort(mBookmarks.begin(),mBookmarks.end(),sorter);
|
||||
std::sort(mProjectBookmarks.begin(),mProjectBookmarks.end(),sorter);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int BookmarkModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return mBookmarks.count();
|
||||
if (mIsForProject)
|
||||
return mProjectBookmarks.count();
|
||||
else
|
||||
return mBookmarks.count();
|
||||
}
|
||||
|
||||
QVariant BookmarkModel::data(const QModelIndex &index, int role) const
|
||||
|
@ -226,7 +480,11 @@ QVariant BookmarkModel::data(const QModelIndex &index, int role) const
|
|||
if (!index.isValid())
|
||||
return QVariant();
|
||||
int row = index.row();
|
||||
PBookmark bookmark = mBookmarks[row];
|
||||
PBookmark bookmark;
|
||||
if (mIsForProject)
|
||||
bookmark = mProjectBookmarks[row];
|
||||
else
|
||||
bookmark = mBookmarks[row];
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch(index.column()) {
|
||||
case 0:
|
||||
|
|
|
@ -25,6 +25,8 @@ struct Bookmark {
|
|||
QString filename;
|
||||
int line;
|
||||
QString description;
|
||||
qint64 timestamp;
|
||||
int saveOrder;
|
||||
};
|
||||
|
||||
using PBookmark=std::shared_ptr<Bookmark>;
|
||||
|
@ -34,25 +36,37 @@ class BookmarkModel : public QAbstractTableModel
|
|||
Q_OBJECT
|
||||
public:
|
||||
BookmarkModel(QObject* parent=nullptr);
|
||||
QSet<int> bookmarksInFile(const QString& filename);
|
||||
void addBookmark(const QString&filename, int line, const QString& description);
|
||||
QSet<int> bookmarksInFile(const QString& filename, bool forProject);
|
||||
void addBookmark(const QString&filename, int line, const QString& description, bool forProject);
|
||||
PBookmark bookmark(int i, bool forProject);
|
||||
PBookmark bookmark(int i);
|
||||
PBookmark bookmark(const QString&filename, int line, bool forProject);
|
||||
PBookmark bookmark(const QString&filename, int line);
|
||||
bool removeBookmark(const QString&filename, int line);
|
||||
void removeBookmarks(const QString& filename);
|
||||
void clear();
|
||||
bool removeBookmark(const QString&filename, int line, bool forProject);
|
||||
void removeBookmarks(const QString& filename, bool forProject);
|
||||
void clear(bool forProject);
|
||||
bool updateDescription(const QString&filename, int line, const QString& description, bool forProject);
|
||||
bool updateDescription(const QString&filename, int line, const QString& description);
|
||||
void save(const QString& filename);
|
||||
void load(const QString& filename);
|
||||
void saveBookmarks(const QString& filename);
|
||||
void loadBookmarks(const QString& filename);
|
||||
void saveProjectBookmarks(const QString& filename, const QString& projectFolder);
|
||||
void loadProjectBookmarks(const QString& filename, const QString& projectFolder);
|
||||
void removeBookmarkAt(int i, bool forProject);
|
||||
void removeBookmarkAt(int i);
|
||||
public slots:
|
||||
void onFileDeleteLines(const QString& filename, int startLine, int count);
|
||||
void onFileInsertLines(const QString& filename, int startLine, int count);
|
||||
void onFileDeleteLines(const QString& filename, int startLine, int count, bool forProject);
|
||||
void onFileInsertLines(const QString& filename, int startLine, int count, bool forProject);
|
||||
private:
|
||||
bool isBookmarkExists(const QString&filename, int line);
|
||||
bool isBookmarkExists(const QString&filename, int line, bool forProject);
|
||||
void save(const QString& filename, const QString& projectFolder);
|
||||
QList<PBookmark> load(const QString& filename, qint64 criteriaTimestamp, qint64* pFileTimestamp);
|
||||
|
||||
private:
|
||||
QList<PBookmark> mBookmarks;
|
||||
QList<PBookmark> mProjectBookmarks;
|
||||
qint64 mLastLoadBookmarksTimestamp;
|
||||
qint64 mLastLoadProjectBookmarksTimestamp;
|
||||
bool mIsForProject;
|
||||
|
||||
// QAbstractItemModel interface
|
||||
public:
|
||||
|
@ -63,6 +77,12 @@ public:
|
|||
// QAbstractItemModel interface
|
||||
public:
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
bool isForProject() const;
|
||||
void setIsForProject(bool newIsForProject);
|
||||
|
||||
// QAbstractItemModel interface
|
||||
public:
|
||||
void sort(int column, Qt::SortOrder order) override;
|
||||
};
|
||||
|
||||
using PBookmarkModel = std::shared_ptr<BookmarkModel>;
|
||||
|
|
Loading…
Reference in New Issue