- enhancement: bookmark view

This commit is contained in:
royqh1979@gmail.com 2021-10-21 17:31:25 +08:00
parent 51b05d73f2
commit e10e173cc9
15 changed files with 988 additions and 373 deletions

View File

@ -7,6 +7,7 @@ Version 0.7.0
- enhancement: set mouse wheel scroll speed in the editor general option tab ( 3 lines by default) - enhancement: set mouse wheel scroll speed in the editor general option tab ( 3 lines by default)
- fix: don't highlight '#' with spaces preceeding it as error - fix: don't highlight '#' with spaces preceeding it as error
- fix: correctly handle integer with 'L' suffix in #if directives ( so <thread> can be correctly parsed ) - fix: correctly handle integer with 'L' suffix in #if directives ( so <thread> can be correctly parsed )
- enhancement: bookmark view
Version 0.6.8 Version 0.6.8
- enhancement: add link to cppreference in the help menu - enhancement: add link to cppreference in the help menu

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1812,32 +1812,30 @@ PBreakpoint BreakpointModel::breakpoint(int index) const
void BreakpointModel::onFileDeleteLines(const QString &filename, int startLine, int count) void BreakpointModel::onFileDeleteLines(const QString &filename, int startLine, int count)
{ {
beginResetModel();
for (int i = mList.count()-1;i>=0;i--){ for (int i = mList.count()-1;i>=0;i--){
PBreakpoint breakpoint = mList[i]; PBreakpoint breakpoint = mList[i];
if (breakpoint->filename == filename if (breakpoint->filename == filename
&& breakpoint->line>=startLine) { && breakpoint->line>=startLine) {
if (breakpoint->line >= startLine+count) { if (breakpoint->line >= startLine+count) {
breakpoint->line -= count; breakpoint->line -= count;
emit dataChanged(createIndex(i,0),createIndex(i,2));
} else { } else {
mList.removeAt(i); removeBreakpoint(i);
} }
} }
} }
endResetModel();
} }
void BreakpointModel::onFileInsertLines(const QString &filename, int startLine, int count) void BreakpointModel::onFileInsertLines(const QString &filename, int startLine, int count)
{ {
beginResetModel();
for (int i = mList.count()-1;i>=0;i--){ for (int i = mList.count()-1;i>=0;i--){
PBreakpoint breakpoint = mList[i]; PBreakpoint breakpoint = mList[i];
if (breakpoint->filename == filename if (breakpoint->filename == filename
&& breakpoint->line>=startLine) { && breakpoint->line>=startLine) {
breakpoint->line+=count; breakpoint->line+=count;
emit dataChanged(createIndex(i,0),createIndex(i,2));
} }
} }
endResetModel();
} }

View File

@ -779,6 +779,9 @@ void Editor::onGutterPaint(QPainter &painter, int aLine, int X, int Y)
} }
return; return;
} }
if (hasBookmark(aLine)) {
painter.drawPixmap(X,Y,*(pIconsManager->bookmark()));
}
} }
} }
@ -1500,7 +1503,9 @@ void Editor::onLinesDeleted(int first, int count)
{ {
pMainWindow->caretList().linesDeleted(this,first,count); pMainWindow->caretList().linesDeleted(this,first,count);
pMainWindow->debugger()->breakpointModel()->onFileDeleteLines(mFilename,first,count); pMainWindow->debugger()->breakpointModel()->onFileDeleteLines(mFilename,first,count);
pMainWindow->bookmarkModel()->onFileDeleteLines(mFilename,first,count);
resetBreakpoints(); resetBreakpoints();
resetBookmarks();
if (!pSettings->editor().syntaxCheckWhenLineChanged()) { if (!pSettings->editor().syntaxCheckWhenLineChanged()) {
//todo: update syntax issues //todo: update syntax issues
} }
@ -1510,7 +1515,9 @@ void Editor::onLinesInserted(int first, int count)
{ {
pMainWindow->caretList().linesInserted(this,first,count); pMainWindow->caretList().linesInserted(this,first,count);
pMainWindow->debugger()->breakpointModel()->onFileInsertLines(mFilename,first,count); pMainWindow->debugger()->breakpointModel()->onFileInsertLines(mFilename,first,count);
pMainWindow->bookmarkModel()->onFileInsertLines(mFilename,first,count);
resetBreakpoints(); resetBreakpoints();
resetBookmarks();
if (!pSettings->editor().syntaxCheckWhenLineChanged()) { if (!pSettings->editor().syntaxCheckWhenLineChanged()) {
//todo: update syntax issues //todo: update syntax issues
} }
@ -1531,6 +1538,12 @@ bool Editor::isBraceChar(QChar ch)
} }
} }
void Editor::resetBookmarks()
{
mBookmarkLines=pMainWindow->bookmarkModel()->bookmarksInFile(mFilename);
invalidate();
}
void Editor::resetBreakpoints() void Editor::resetBreakpoints()
{ {
mBreakpointLines.clear(); mBreakpointLines.clear();
@ -3523,6 +3536,25 @@ bool Editor::hasBreakpoint(int line)
return mBreakpointLines.contains(line); return mBreakpointLines.contains(line);
} }
void Editor::addBookmark(int line, const QString& description)
{
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);
}
bool Editor::hasBookmark(int line)
{
return mBookmarkLines.contains(line);
}
void Editor::removeBreakpointFocus() void Editor::removeBreakpointFocus()
{ {
if (mActiveBreakpointLine!=-1) { if (mActiveBreakpointLine!=-1) {

View File

@ -147,6 +147,9 @@ public:
void toggleBreakpoint(int line); void toggleBreakpoint(int line);
void clearBreakpoints(); void clearBreakpoints();
bool hasBreakpoint(int line); bool hasBreakpoint(int line);
void addBookmark(int line,const QString& description);
void removeBookmark(int line);
bool hasBookmark(int line);
void removeBreakpointFocus(); void removeBreakpointFocus();
void modifyBreakpointProperty(int line); void modifyBreakpointProperty(int line);
void setActiveBreakpointFocus(int Line, bool setFocus=true); void setActiveBreakpointFocus(int Line, bool setFocus=true);
@ -177,6 +180,7 @@ private slots:
private: private:
bool isBraceChar(QChar ch); bool isBraceChar(QChar ch);
void resetBookmarks();
void resetBreakpoints(); void resetBreakpoints();
QChar getCurrentChar(); QChar getCurrentChar();
bool handleSymbolCompletion(QChar key); bool handleSymbolCompletion(QChar key);
@ -242,6 +246,7 @@ private:
int mLineCount; int mLineCount;
int mGutterClickedLine; int mGutterClickedLine;
QSet<int> mBreakpointLines; QSet<int> mBreakpointLines;
QSet<int> mBookmarkLines;
int mActiveBreakpointLine; int mActiveBreakpointLine;
PCppParser mParser; PCppParser mParser;
std::shared_ptr<CodeCompletionPopup> mCompletionPopup; std::shared_ptr<CodeCompletionPopup> mCompletionPopup;

View File

@ -486,5 +486,6 @@
<file>images/classparser/var_private.ico</file> <file>images/classparser/var_private.ico</file>
<file>images/classparser/var_protected.ico</file> <file>images/classparser/var_protected.ico</file>
<file>images/classparser/var_public.ico</file> <file>images/classparser/var_public.ico</file>
<file>images/editor/bookmark.png</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@ -8,6 +8,8 @@ IconsManager::IconsManager(QObject *parent) : QObject(parent)
mSyntaxWarning = std::make_shared<QPixmap>(":/icons/images/editor/syntaxwarning.png"); mSyntaxWarning = std::make_shared<QPixmap>(":/icons/images/editor/syntaxwarning.png");
mBreakpoint = std::make_shared<QPixmap>(":/icons/images/editor/breakpoint.png"); mBreakpoint = std::make_shared<QPixmap>(":/icons/images/editor/breakpoint.png");
mActiveBreakpoint = std::make_shared<QPixmap>(":/icons/images/editor/currentline.png"); mActiveBreakpoint = std::make_shared<QPixmap>(":/icons/images/editor/currentline.png");
mBookmark = std::make_shared<QPixmap>(":/icons/images/editor/bookmark.png");
} }
PIcon IconsManager::syntaxError() const PIcon IconsManager::syntaxError() const
@ -29,3 +31,8 @@ PIcon IconsManager::activeBreakpoint() const
{ {
return mActiveBreakpoint; return mActiveBreakpoint;
} }
const PIcon &IconsManager::bookmark() const
{
return mBookmark;
}

View File

@ -20,12 +20,15 @@ public:
PIcon activeBreakpoint() const; PIcon activeBreakpoint() const;
const PIcon &bookmark() const;
signals: signals:
private: private:
PIcon mSyntaxError; PIcon mSyntaxError;
PIcon mSyntaxWarning; PIcon mSyntaxWarning;
PIcon mBreakpoint; PIcon mBreakpoint;
PIcon mActiveBreakpoint; PIcon mActiveBreakpoint;
PIcon mBookmark;
}; };
extern IconsManager* pIconsManager; extern IconsManager* pIconsManager;

View File

@ -149,6 +149,10 @@ MainWindow::MainWindow(QWidget *parent)
mCodeSnippetManager->load(); mCodeSnippetManager->load();
mToolsManager = std::make_shared<ToolsManager>(); mToolsManager = std::make_shared<ToolsManager>();
mToolsManager->load(); mToolsManager->load();
mBookmarkModel = std::make_shared<BookmarkModel>();
mBookmarkModel->load(includeTrailingPathDelimiter(pSettings->dirs().config())
+DEV_BOOKMARK_FILE);
ui->tableBookmark->setModel(mBookmarkModel.get());
mSearchResultTreeModel = std::make_shared<SearchResultTreeModel>(&mSearchResultModel); mSearchResultTreeModel = std::make_shared<SearchResultTreeModel>(&mSearchResultModel);
mSearchResultListModel = std::make_shared<SearchResultListModel>(&mSearchResultModel); mSearchResultListModel = std::make_shared<SearchResultListModel>(&mSearchResultModel);
mSearchViewDelegate = std::make_shared<SearchResultTreeViewDelegate>(mSearchResultTreeModel); mSearchViewDelegate = std::make_shared<SearchResultTreeViewDelegate>(mSearchResultTreeModel);
@ -267,6 +271,10 @@ void MainWindow::updateEditorActions()
ui->actionClose->setEnabled(false); ui->actionClose->setEnabled(false);
ui->actionClose_All->setEnabled(false); ui->actionClose_All->setEnabled(false);
ui->actionAdd_bookmark->setEnabled(false);
ui->actionRemove_Bookmark->setEnabled(false);
ui->actionModify_Bookmark_Description->setEnabled(false);
} else { } else {
ui->actionAuto_Detect->setEnabled(true); ui->actionAuto_Detect->setEnabled(true);
ui->actionEncode_in_ANSI->setEnabled(true); ui->actionEncode_in_ANSI->setEnabled(true);
@ -302,6 +310,11 @@ void MainWindow::updateEditorActions()
ui->actionClose->setEnabled(true); ui->actionClose->setEnabled(true);
ui->actionClose_All->setEnabled(true); ui->actionClose_All->setEnabled(true);
int line = e->caretY();
ui->actionAdd_bookmark->setEnabled(e->lines()->count()>0 && !e->hasBookmark(line));
ui->actionRemove_Bookmark->setEnabled(e->hasBookmark(line));
ui->actionModify_Bookmark_Description->setEnabled(e->hasBookmark(line));
} }
updateCompileActions(); updateCompileActions();
@ -1478,6 +1491,15 @@ void MainWindow::includeOrSkipDirs(const QStringList &dirs, bool skip)
} }
} }
void MainWindow::onBookmarkContextMenu(const QPoint &pos)
{
QMenu menu(this);
menu.addAction(mBookmark_Remove);
menu.addAction(mBookmark_RemoveAll);
menu.addAction(mBookmark_Modify);
menu.exec(ui->tableBookmark->mapToGlobal(pos));
}
void MainWindow::saveLastOpens() void MainWindow::saveLastOpens()
{ {
QString filename = includeTrailingPathDelimiter(pSettings->dirs().config()) + DEV_LASTOPENS_FILE; QString filename = includeTrailingPathDelimiter(pSettings->dirs().config()) + DEV_LASTOPENS_FILE;
@ -1622,6 +1644,45 @@ void MainWindow::buildContextMenus()
connect(ui->watchView,&QWidget::customContextMenuRequested, connect(ui->watchView,&QWidget::customContextMenuRequested,
this, &MainWindow::onWatchViewContextMenu); this, &MainWindow::onWatchViewContextMenu);
//context menu signal for the bookmark view
ui->tableBookmark->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->tableBookmark,&QWidget::customContextMenuRequested,
this, &MainWindow::onBookmarkContextMenu);
mBookmark_Remove=createActionFor(
tr("Remove"),
ui->tableBookmark);
connect(mBookmark_Remove, &QAction::triggered,
[this]() {
QModelIndex index = ui->tableBookmark->currentIndex();
if (index.isValid()) {
mBookmarkModel->removeBookmarkAt(index.row());
}
});
mBookmark_RemoveAll=createActionFor(
tr("Remove All"),
ui->tableBookmark);
connect(mBookmark_RemoveAll, &QAction::triggered,
[this]() {
mBookmarkModel->clear();
});
mBookmark_Modify=createActionFor(
tr("Modify Description"),
ui->tableBookmark);
connect(mBookmark_Modify, &QAction::triggered,
[this]() {
QModelIndex index = ui->tableBookmark->currentIndex();
if (index.isValid()) {
PBookmark bookmark = mBookmarkModel->bookmark(index.row());
if (bookmark) {
QString desc = QInputDialog::getText(ui->tableBookmark,tr("Bookmark Description"),
tr("Description:"),QLineEdit::Normal,
bookmark->description);
desc = desc.trimmed();
mBookmarkModel->updateDescription(bookmark->filename,bookmark->line,desc);
}
mBookmarkModel->clear();
});
//context menu signal for the watch view //context menu signal for the watch view
ui->debugConsole->setContextMenuPolicy(Qt::CustomContextMenu); ui->debugConsole->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->debugConsole,&QWidget::customContextMenuRequested, connect(ui->debugConsole,&QWidget::customContextMenuRequested,
@ -2271,7 +2332,9 @@ void MainWindow::onEditorContextMenu(const QPoint &pos)
QMenu menu(this); QMenu menu(this);
BufferCoord p; BufferCoord p;
mEditorContextMenuPos = pos; mEditorContextMenuPos = pos;
int line;
if (editor->getPositionOfMouse(p)) { if (editor->getPositionOfMouse(p)) {
line=p.Line;
//mouse on editing area //mouse on editing area
menu.addAction(ui->actionCompile_Run); menu.addAction(ui->actionCompile_Run);
menu.addAction(ui->actionDebug); menu.addAction(ui->actionDebug);
@ -2296,6 +2359,10 @@ void MainWindow::onEditorContextMenu(const QPoint &pos)
menu.addAction(ui->actionToggle_Breakpoint); menu.addAction(ui->actionToggle_Breakpoint);
menu.addAction(ui->actionClear_all_breakpoints); menu.addAction(ui->actionClear_all_breakpoints);
menu.addSeparator(); menu.addSeparator();
menu.addAction(ui->actionAdd_bookmark);
menu.addAction(ui->actionRemove_Bookmark);
menu.addAction(ui->actionModify_Bookmark_Description);
menu.addSeparator();
menu.addAction(ui->actionFile_Properties); menu.addAction(ui->actionFile_Properties);
//these actions needs parser //these actions needs parser
@ -2304,16 +2371,25 @@ void MainWindow::onEditorContextMenu(const QPoint &pos)
ui->actionFind_references->setEnabled(!editor->parser()->parsing()); ui->actionFind_references->setEnabled(!editor->parser()->parsing());
} else { } else {
//mouse on gutter //mouse on gutter
int line;
if (!editor->getLineOfMouse(line)) if (!editor->getLineOfMouse(line))
line=-1; line=-1;
menu.addAction(ui->actionToggle_Breakpoint); menu.addAction(ui->actionToggle_Breakpoint);
menu.addAction(ui->actionBreakpoint_property); menu.addAction(ui->actionBreakpoint_property);
menu.addAction(ui->actionClear_all_breakpoints); menu.addAction(ui->actionClear_all_breakpoints);
ui->actionBreakpoint_property->setEnabled(editor->hasBreakpoint(line)); menu.addSeparator();
menu.addAction(ui->actionAdd_bookmark);
menu.addAction(ui->actionRemove_Bookmark);
menu.addAction(ui->actionModify_Bookmark_Description);
} }
ui->actionBreakpoint_property->setEnabled(editor->hasBreakpoint(line));
ui->actionAdd_bookmark->setEnabled(
line>=0 && editor->lines()->count()>0
&& !editor->hasBreakpoint(line)
);
ui->actionRemove_Bookmark->setEnabled(editor->hasBreakpoint(line));
ui->actionModify_Bookmark_Description->setEnabled(editor->hasBreakpoint(line));
menu.exec(editor->viewport()->mapToGlobal(pos)); menu.exec(editor->viewport()->mapToGlobal(pos));
} }
void MainWindow::onEditorRightTabContextMenu(const QPoint &pos) void MainWindow::onEditorRightTabContextMenu(const QPoint &pos)
@ -2617,6 +2693,8 @@ void MainWindow::closeEvent(QCloseEvent *event) {
settings.setLeftPanelIndex(ui->tabInfos->currentIndex()); settings.setLeftPanelIndex(ui->tabInfos->currentIndex());
settings.setLeftPanelOpenned(mLeftPanelOpenned); settings.setLeftPanelOpenned(mLeftPanelOpenned);
settings.save(); settings.save();
mBookmarkModel->save(includeTrailingPathDelimiter(pSettings->dirs().config())
+DEV_BOOKMARK_FILE);
} }
if (!mShouldRemoveAllSettings && pSettings->editor().autoLoadLastFiles()) { if (!mShouldRemoveAllSettings && pSettings->editor().autoLoadLastFiles()) {
@ -4313,3 +4391,65 @@ void MainWindow::on_actionEGE_Manual_triggered()
QDesktopServices::openUrl(QUrl("https://xege.org/ege-open-source")); QDesktopServices::openUrl(QUrl("https://xege.org/ege-open-source"));
} }
const PBookmarkModel &MainWindow::bookmarkModel() const
{
return mBookmarkModel;
}
void MainWindow::on_actionAdd_bookmark_triggered()
{
Editor* editor = mEditorList->getEditor();
int line;
if (editor && editor->pointToLine(mEditorContextMenuPos,line)) {
if (editor->lines()->count()<=0)
return;
QString desc = QInputDialog::getText(editor,tr("Bookmark Description"),
tr("Description:"),QLineEdit::Normal,
editor->lines()->getString(line-1).trimmed());
desc = desc.trimmed();
editor->addBookmark(line,desc);
}
}
void MainWindow::on_actionRemove_Bookmark_triggered()
{
Editor* editor = mEditorList->getEditor();
int line;
if (editor && editor->pointToLine(mEditorContextMenuPos,line)) {
editor->removeBookmark(line);
}
}
void MainWindow::on_tableBookmark_doubleClicked(const QModelIndex &index)
{
if (!index.isValid())
return;
PBookmark bookmark = mBookmarkModel->bookmark(index.row());
if (bookmark) {
Editor *editor= mEditorList->getEditorByFilename(bookmark->filename);
if (editor) {
editor->setCaretPositionAndActivate(bookmark->line,1);
}
}
}
void MainWindow::on_actionModify_Bookmark_Description_triggered()
{
Editor* editor = mEditorList->getEditor();
int line;
if (editor && editor->pointToLine(mEditorContextMenuPos,line)) {
PBookmark bookmark = mBookmarkModel->bookmark(editor->filename(),line);
if (bookmark) {
QString desc = QInputDialog::getText(editor,tr("Bookmark Description"),
tr("Description:"),QLineEdit::Normal,
bookmark->description);
desc = desc.trimmed();
mBookmarkModel->updateDescription(editor->filename(),line,desc);
}
}
}

View File

@ -16,6 +16,7 @@
#include "todoparser.h" #include "todoparser.h"
#include "toolsmanager.h" #include "toolsmanager.h"
#include "widgets/labelwithmenu.h" #include "widgets/labelwithmenu.h"
#include "widgets/bookmarkmodel.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -137,6 +138,8 @@ public:
bool shouldRemoveAllSettings() const; bool shouldRemoveAllSettings() const;
const PBookmarkModel &bookmarkModel() const;
public slots: public slots:
void onCompileLog(const QString& msg); void onCompileLog(const QString& msg);
void onCompileIssue(PCompileIssue issue); void onCompileIssue(PCompileIssue issue);
@ -194,6 +197,7 @@ private slots:
void onFileChanged(const QString& path); void onFileChanged(const QString& path);
void onWatchViewContextMenu(const QPoint& pos); void onWatchViewContextMenu(const QPoint& pos);
void onBookmarkContextMenu(const QPoint& pos);
void onTableIssuesContextMenu(const QPoint& pos); void onTableIssuesContextMenu(const QPoint& pos);
void onSearchViewContextMenu(const QPoint& pos); void onSearchViewContextMenu(const QPoint& pos);
void onBreakpointsViewContextMenu(const QPoint& pos); void onBreakpointsViewContextMenu(const QPoint& pos);
@ -407,6 +411,14 @@ private slots:
void on_actionEGE_Manual_triggered(); void on_actionEGE_Manual_triggered();
void on_actionAdd_bookmark_triggered();
void on_actionRemove_Bookmark_triggered();
void on_tableBookmark_doubleClicked(const QModelIndex &index);
void on_actionModify_Bookmark_Description_triggered();
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
EditorList *mEditorList; EditorList *mEditorList;
@ -436,6 +448,7 @@ private:
TodoModel mTodoModel; TodoModel mTodoModel;
SearchResultModel mSearchResultModel; SearchResultModel mSearchResultModel;
PBookmarkModel mBookmarkModel;
PSearchResultListModel mSearchResultListModel; PSearchResultListModel mSearchResultListModel;
PSearchResultTreeModel mSearchResultTreeModel; PSearchResultTreeModel mSearchResultTreeModel;
PSearchResultTreeViewDelegate mSearchViewDelegate; PSearchResultTreeViewDelegate mSearchViewDelegate;
@ -497,6 +510,10 @@ private:
QAction * mDebugConsole_Copy; QAction * mDebugConsole_Copy;
QAction * mDebugConsole_Paste; QAction * mDebugConsole_Paste;
QAction * mDebugConsole_SelectAll; QAction * mDebugConsole_SelectAll;
//action for bookmarks
QAction * mBookmark_Remove;
QAction * mBookmark_RemoveAll;
QAction * mBookmark_Modify;
// QWidget interface // QWidget interface
protected: protected:

View File

@ -295,7 +295,7 @@
<enum>QTabWidget::South</enum> <enum>QTabWidget::South</enum>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>4</number> <number>5</number>
</property> </property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
@ -859,6 +859,33 @@
</item> </item>
</layout> </layout>
</widget> </widget>
<widget class="QWidget" name="tabBookmark">
<attribute name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/039-gobook.png</normaloff>:/icons/images/newlook24/039-gobook.png</iconset>
</attribute>
<attribute name="title">
<string>Bookmark</string>
</attribute>
<layout class="QHBoxLayout" name="horizontalLayout_14">
<item>
<widget class="QTableView" name="tableBookmark">
<property name="alternatingRowColors">
<bool>true</bool>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
</widget> </widget>
</widget> </widget>
</item> </item>
@ -956,6 +983,10 @@
<addaction name="actionForward"/> <addaction name="actionForward"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionAdd_bookmark"/>
<addaction name="actionRemove_Bookmark"/>
<addaction name="actionModify_Bookmark_Description"/>
<addaction name="separator"/>
<addaction name="actionReformat_Code"/> <addaction name="actionReformat_Code"/>
</widget> </widget>
<widget class="QMenu" name="menuWindow"> <widget class="QMenu" name="menuWindow">
@ -1885,6 +1916,29 @@
<string>EGE Manual</string> <string>EGE Manual</string>
</property> </property>
</action> </action>
<action name="actionAdd_bookmark">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/003-addbook.png</normaloff>:/icons/images/newlook24/003-addbook.png</iconset>
</property>
<property name="text">
<string>Add Bookmark</string>
</property>
</action>
<action name="actionRemove_Bookmark">
<property name="icon">
<iconset resource="icons.qrc">
<normaloff>:/icons/images/newlook24/064-remsrc.png</normaloff>:/icons/images/newlook24/064-remsrc.png</iconset>
</property>
<property name="text">
<string>Remove Bookmark</string>
</property>
</action>
<action name="actionModify_Bookmark_Description">
<property name="text">
<string>Modify Bookmark Description</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -47,6 +47,7 @@
#define DEV_AUTOLINK_FILE "autolink.json" #define DEV_AUTOLINK_FILE "autolink.json"
#define DEV_SHORTCUT_FILE "shortcuts.json" #define DEV_SHORTCUT_FILE "shortcuts.json"
#define DEV_TOOLS_FILE "tools.json" #define DEV_TOOLS_FILE "tools.json"
#define DEV_BOOKMARK_FILE "bookmarks.json"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
# define PATH_SENSITIVITY Qt::CaseInsensitive # define PATH_SENSITIVITY Qt::CaseInsensitive

View File

@ -1,6 +1,238 @@
#include "bookmarkmodel.h" #include "bookmarkmodel.h"
#include "../systemconsts.h"
BookmarkModel::BookmarkModel(QObject* parent):QAbstractItemModel(parent) #include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QSet>
#include "../utils.h"
BookmarkModel::BookmarkModel(QObject* parent):QAbstractTableModel(parent)
{ {
} }
QSet<int> BookmarkModel::bookmarksInFile(const QString &filename)
{
QSet<int> lines;
foreach (const PBookmark& bookmark, mBookmarks) {
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0) {
lines.insert(bookmark->line);
}
}
return lines;
}
void BookmarkModel::addBookmark(const QString &filename, int line, const QString &description)
{
Q_ASSERT(!isBookmarkExists(filename,line));
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();
}
PBookmark BookmarkModel::bookmark(int i)
{
return mBookmarks[i];
}
PBookmark BookmarkModel::bookmark(const QString &filename, int line)
{
for (int i=0;i<mBookmarks.count();i++) {
PBookmark bookmark = mBookmarks[i];
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0
&& bookmark->line == line) {
return bookmark;
}
}
return PBookmark();
}
bool BookmarkModel::removeBookmark(const QString &filename, int line)
{
for (int i=0;i<mBookmarks.count();i++) {
PBookmark bookmark = mBookmarks[i];
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0
&& bookmark->line == line) {
removeBookmarkAt(i);
return true;
}
}
return false;
}
void BookmarkModel::clear()
{
beginResetModel();
mBookmarks.clear();
endResetModel();
}
bool BookmarkModel::updateDescription(const QString &filename, int line, const QString &description)
{
for (int i=0;i<mBookmarks.count();i++) {
PBookmark bookmark = mBookmarks[i];
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0
&& bookmark->line == line) {
bookmark->description = description;
emit dataChanged(createIndex(i,0),createIndex(i,2));
return true;
}
}
return false;
}
void BookmarkModel::save(const QString &filename)
{
QFile file(filename);
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
QJsonArray array;
foreach (const PBookmark& bookmark, mBookmarks) {
QJsonObject obj;
obj["filename"]=bookmark->filename;
obj["line"]=bookmark->line;
obj["description"]=bookmark->description;
array.append(obj);
}
QJsonDocument doc;
doc.setArray(array);
if (file.write(doc.toJson())<0) {
throw FileError(tr("Save file '%1' failed.")
.arg(filename));
}
} else {
throw FileError(tr("Can't open file '%1' for write.")
.arg(filename));
}
}
void BookmarkModel::load(const QString& filename)
{
clear();
QFile file(filename);
if (!file.exists())
return;
if (file.open(QFile::ReadOnly)) {
QByteArray content = file.readAll();
QJsonParseError error;
QJsonDocument doc(QJsonDocument::fromJson(content,&error));
if (error.error != QJsonParseError::NoError) {
throw FileError(tr("Error in json file '%1':%2 : %3")
.arg(filename)
.arg(error.offset)
.arg(error.errorString()));
}
QJsonArray array = doc.array();
for (int i=0;i<array.count();i++) {
QJsonValue value = array[i];
QJsonObject obj=value.toObject();
addBookmark(obj["filename"].toString(),
obj["line"].toInt(),
obj["description"].toString());
}
} else {
throw FileError(tr("Can't open file '%1' for read.")
.arg(filename));
}
}
void BookmarkModel::onFileDeleteLines(const QString &filename, int startLine, int count)
{
for (int i = mBookmarks.count()-1;i>=0;i--){
PBookmark bookmark = mBookmarks[i];
if (bookmark->filename == filename
&& bookmark->line>=startLine) {
if (bookmark->line >= startLine+count) {
bookmark->line -= count;
emit dataChanged(createIndex(i,0),createIndex(i,2));
} else {
removeBookmarkAt(i);
}
}
}
}
void BookmarkModel::onFileInsertLines(const QString &filename, int startLine, int count)
{
for (int i = mBookmarks.count()-1;i>=0;i--){
PBookmark bookmark = mBookmarks[i];
if (bookmark->filename == filename
&& bookmark->line>=startLine) {
bookmark->line+=count;
emit dataChanged(createIndex(i,0),createIndex(i,2));
}
}
}
void BookmarkModel::removeBookmarkAt(int i)
{
beginRemoveRows(QModelIndex(), i,i);
mBookmarks.removeAt(i);
endRemoveRows();
}
#ifdef QT_DEBUG
bool BookmarkModel::isBookmarkExists(const QString &filename, int line)
{
foreach (const PBookmark& bookmark, mBookmarks) {
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0
&& bookmark->line == line) {
return true;
}
}
return false;
}
int BookmarkModel::rowCount(const QModelIndex &) const
{
return mBookmarks.count();
}
QVariant BookmarkModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
int row = index.row();
PBookmark bookmark = mBookmarks[row];
if (role == Qt::DisplayRole) {
switch(index.column()) {
case 0:
return bookmark->description;
case 1:
return bookmark->line;
case 2:
return bookmark->filename;
}
}
return QVariant();
}
int BookmarkModel::columnCount(const QModelIndex &) const
{
return 3;
}
QVariant BookmarkModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal) {
if (role == Qt::DisplayRole) {
switch(section) {
case 0:
return tr("Description");
case 1:
return tr("Line");
case 2:
return tr("Filename");
}
}
}
return QVariant();
}
#endif

View File

@ -1,13 +1,54 @@
#ifndef BOOKMARKMODEL_H #ifndef BOOKMARKMODEL_H
#define BOOKMARKMODEL_H #define BOOKMARKMODEL_H
#include <QAbstractItemModel> #include <QAbstractTableModel>
#include <memory>
#include <QDebug>
class BookmarkModel : public QAbstractItemModel struct Bookmark {
QString filename;
int line;
QString description;
};
using PBookmark=std::shared_ptr<Bookmark>;
class BookmarkModel : public QAbstractTableModel
{ {
Q_OBJECT Q_OBJECT
public: public:
BookmarkModel(QObject* parent=nullptr); BookmarkModel(QObject* parent=nullptr);
QSet<int> bookmarksInFile(const QString& filename);
void addBookmark(const QString&filename, int line, const QString& description);
PBookmark bookmark(int i);
PBookmark bookmark(const QString&filename, int line);
bool removeBookmark(const QString&filename, int line);
void clear();
bool updateDescription(const QString&filename, int line, const QString& description);
void save(const QString& filename);
void load(const QString& filename);
void removeBookmarkAt(int i);
public slots:
void onFileDeleteLines(const QString& filename, int startLine, int count);
void onFileInsertLines(const QString& filename, int startLine, int count);
private:
#ifdef QT_DEBUG
bool isBookmarkExists(const QString&filename, int line);
#endif
private:
QList<PBookmark> mBookmarks;
// QAbstractItemModel interface
public:
int rowCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role) const override;
int columnCount(const QModelIndex &parent) const override;
// QAbstractItemModel interface
public:
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
}; };
using PBookmarkModel = std::shared_ptr<BookmarkModel>;
#endif // BOOKMARKMODEL_H #endif // BOOKMARKMODEL_H