- enhancement: autosave/load bookmarks

- enhancement: autosave/load breakpoints
 - enhancement: autosave/load watches
This commit is contained in:
royqh1979 2021-10-21 19:33:11 +08:00
parent e10e173cc9
commit 3e442b0860
22 changed files with 689 additions and 373 deletions

View File

@ -8,6 +8,9 @@ Version 0.7.0
- 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 )
- enhancement: bookmark view
- enhancement: autosave/load bookmarks
- enhancement: autosave/load breakpoints
- enhancement: autosave/load watches
Version 0.6.8
- 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

@ -12,6 +12,9 @@
#include <QPlainTextEdit>
#include <QDebug>
#include <QDir>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
Debugger::Debugger(QObject *parent) : QObject(parent)
{
@ -149,6 +152,7 @@ void Debugger::addBreakpoint(int line, const QString &filename)
bp->line = line;
bp->filename = filename;
bp->condition = "";
bp->enabled = true;
mBreakpointModel->addBreakpoint(bp);
if (mExecuting) {
sendBreakpointCommand(bp);
@ -1810,6 +1814,65 @@ PBreakpoint BreakpointModel::breakpoint(int index) const
return mList[index];
}
void BreakpointModel::save(const QString &filename)
{
QFile file(filename);
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
QJsonArray array;
foreach (const PBreakpoint& breakpoint, mList) {
QJsonObject obj;
obj["filename"]=breakpoint->filename;
obj["line"]=breakpoint->line;
obj["condition"]=breakpoint->condition;
obj["enabled"]=breakpoint->enabled;
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 BreakpointModel::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();
PBreakpoint breakpoint = std::make_shared<Breakpoint>();
breakpoint->filename = obj["filename"].toString();
breakpoint->line = obj["line"].toInt();
breakpoint->condition = obj["condition"].toString();
breakpoint->enabled = obj["enabled"].toBool();
addBreakpoint(breakpoint);
}
} else {
throw FileError(tr("Can't open file '%1' for read.")
.arg(filename));
}
}
void BreakpointModel::onFileDeleteLines(const QString &filename, int startLine, int count)
{
for (int i = mList.count()-1;i>=0;i--){
@ -2135,6 +2198,63 @@ void WatchModel::notifyUpdated(PWatchVar var)
emit dataChanged(createIndex(row,0,var.get()),createIndex(row,0,var.get()));
}
void WatchModel::save(const QString &filename)
{
QFile file(filename);
if (file.open(QFile::WriteOnly | QFile::Truncate)) {
QJsonArray array;
foreach (const PWatchVar& watchVar, mWatchVars) {
QJsonObject obj;
obj["name"]=watchVar->name;
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 WatchModel::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();
PWatchVar var = std::make_shared<WatchVar>();
var->parent= nullptr;
var->name = obj["name"].toString();
var->value = tr("Execute to evaluate");
var->gdbIndex = -1;
addWatchVar(var);
}
} else {
throw FileError(tr("Can't open file '%1' for read.")
.arg(filename));
}
}
QVariant WatchModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {

View File

@ -63,6 +63,7 @@ struct Breakpoint {
int line;
QString filename;
QString condition;
bool enabled;
};
using PBreakpoint = std::shared_ptr<Breakpoint>;
@ -112,6 +113,8 @@ public:
PBreakpoint setBreakPointCondition(int index, const QString& condition);
const QList<PBreakpoint>& breakpoints() const;
PBreakpoint breakpoint(int index) const;
void save(const QString& filename);
void load(const QString& filename);
public slots:
void onFileDeleteLines(const QString& filename, int startLine, int count);
void onFileInsertLines(const QString& filename, int startLine, int count);
@ -160,6 +163,8 @@ public:
void beginUpdate();
void endUpdate();
void notifyUpdated(PWatchVar var);
void save(const QString& filename);
void load(const QString& filename);
private:
QList<PWatchVar> mWatchVars;
int mUpdateCount;

View File

@ -151,6 +151,9 @@ Editor::Editor(QWidget *parent, const QString& filename,
setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, &QWidget::customContextMenuRequested,
pMainWindow, &MainWindow::onEditorContextMenu);
resetBookmarks();
resetBreakpoints();
}
Editor::~Editor() {
@ -3555,6 +3558,13 @@ bool Editor::hasBookmark(int line)
return mBookmarkLines.contains(line);
}
void Editor::clearBookmarks()
{
mBookmarkLines.clear();
pMainWindow->bookmarkModel()->removeBookmarks(mFilename);
invalidateGutter();
}
void Editor::removeBreakpointFocus()
{
if (mActiveBreakpointLine!=-1) {

View File

@ -150,6 +150,7 @@ public:
void addBookmark(int line,const QString& description);
void removeBookmark(int line);
bool hasBookmark(int line);
void clearBookmarks();
void removeBreakpointFocus();
void modifyBreakpointProperty(int line);
void setActiveBreakpointFocus(int Line, bool setFocus=true);

View File

@ -90,6 +90,11 @@ MainWindow::MainWindow(QWidget *parent)
ui->tblStackTrace->setModel(mDebugger->backtraceModel());
ui->watchView->setModel(mDebugger->watchModel());
mDebugger->breakpointModel()->load(includeTrailingPathDelimiter(pSettings->dirs().config())
+DEV_BREAKPOINTS_FILE);
mDebugger->watchModel()->load(includeTrailingPathDelimiter(pSettings->dirs().config())
+DEV_WATCH_FILE);
// ui->actionIndent->setShortcut(Qt::Key_Tab);
// ui->actionUnIndent->setShortcut(Qt::Key_Tab | Qt::ShiftModifier);
@ -1655,8 +1660,16 @@ void MainWindow::buildContextMenus()
[this]() {
QModelIndex index = ui->tableBookmark->currentIndex();
if (index.isValid()) {
PBookmark bookmark = mBookmarkModel->bookmark(index.row());
if (bookmark) {
Editor * editor = mEditorList->getOpenedEditorByFilename(bookmark->filename);
if (editor) {
editor->removeBookmark(bookmark->line);
} else {
mBookmarkModel->removeBookmarkAt(index.row());
}
}
}
});
mBookmark_RemoveAll=createActionFor(
tr("Remove All"),
@ -1664,6 +1677,10 @@ void MainWindow::buildContextMenus()
connect(mBookmark_RemoveAll, &QAction::triggered,
[this]() {
mBookmarkModel->clear();
for (int i=0;i<mEditorList->pageCount();i++) {
Editor * editor = (*mEditorList)[i];
editor->clearBookmarks();
}
});
mBookmark_Modify=createActionFor(
tr("Modify Description"),
@ -1680,7 +1697,7 @@ void MainWindow::buildContextMenus()
desc = desc.trimmed();
mBookmarkModel->updateDescription(bookmark->filename,bookmark->line,desc);
}
mBookmarkModel->clear();
}
});
//context menu signal for the watch view
@ -2695,6 +2712,19 @@ void MainWindow::closeEvent(QCloseEvent *event) {
settings.save();
mBookmarkModel->save(includeTrailingPathDelimiter(pSettings->dirs().config())
+DEV_BOOKMARK_FILE);
if (pSettings->debugger().autosaveBreakpoints())
mDebugger->breakpointModel()->save(includeTrailingPathDelimiter(pSettings->dirs().config())
+DEV_BREAKPOINTS_FILE);
else
removeFile(includeTrailingPathDelimiter(pSettings->dirs().config())
+DEV_BREAKPOINTS_FILE);
if (pSettings->debugger().autosaveWatches())
mDebugger->watchModel()->save(includeTrailingPathDelimiter(pSettings->dirs().config())
+DEV_WATCH_FILE);
else
removeFile(includeTrailingPathDelimiter(pSettings->dirs().config())
+DEV_WATCH_FILE);
}
if (!mShouldRemoveAllSettings && pSettings->editor().autoLoadLastFiles()) {

View File

@ -3518,7 +3518,7 @@ SynEditorOptions SynEdit::getOptions() const
void SynEdit::setOptions(const SynEditorOptions &Value)
{
if (Value != mOptions) {
bool bSetDrag = mOptions.testFlag(eoDropFiles) != Value.testFlag(eoDropFiles);
//bool bSetDrag = mOptions.testFlag(eoDropFiles) != Value.testFlag(eoDropFiles);
//if (!mOptions.testFlag(eoScrollPastEol))
setLeftChar(mLeftChar);
//if (!mOptions.testFlag(eoScrollPastEof))
@ -3795,6 +3795,8 @@ void SynEdit::doUndoItem()
Item->changeStr(),
Item->changeSelMode());
break;
default:
break;
}
}
}
@ -4013,6 +4015,8 @@ void SynEdit::doRedoItem()
Item->changeEndPos(), Item->changeStr(), Item->changeSelMode());
break;
}
default:
break;
}
}
}
@ -5099,6 +5103,8 @@ void SynEdit::ExecuteCommand(SynEditorCommand Command, QChar AChar, void *pData)
case SynEditorCommand::ecToggleComment:
doToggleComment();
break;
default:
break;
}
// procedure ForceCaretX(aCaretX: integer);
@ -5461,6 +5467,8 @@ bool SynEdit::event(QEvent *event)
updateMouseCursor();
break;
}
default:
break;
}
return QAbstractScrollArea::event(event);
}
@ -5498,8 +5506,8 @@ void SynEdit::mousePressEvent(QMouseEvent *event)
bool bWasSel = false;
bool bStartDrag = false;
mMouseMoved = false;
BufferCoord TmpBegin = mBlockBegin;
BufferCoord TmpEnd = mBlockEnd;
// BufferCoord TmpBegin = mBlockBegin;
// BufferCoord TmpEnd = mBlockEnd;
Qt::MouseButton button = event->button();
int X=event->pos().x();
int Y=event->pos().y();

View File

@ -85,7 +85,7 @@ QString SynHTMLExporter::MakeValidName(const QString &Name)
return Result;
}
bool SynHTMLExporter::StyleNameCallback(PSynHighlighter Highlighter, PSynHighlighterAttribute Attri, const QString& UniqueAttriName, QList<void *> params)
bool SynHTMLExporter::StyleNameCallback(PSynHighlighter /*Highlighter*/, PSynHighlighterAttribute Attri, const QString& UniqueAttriName, QList<void *> params)
{
PSynHighlighterAttribute& AttriToFind = *static_cast<PSynHighlighterAttribute*>(params[0]);
QString& StyleName = *static_cast<QString *>(params[1]);

View File

@ -2831,6 +2831,26 @@ void Settings::Debugger::setSkipCustomLibraries(bool newSkipCustomLibraries)
mSkipCustomLibraries = newSkipCustomLibraries;
}
bool Settings::Debugger::autosaveWatches() const
{
return mAutosaveWatches;
}
void Settings::Debugger::setAutosaveWatches(bool newAutosaveWatches)
{
mAutosaveWatches = newAutosaveWatches;
}
bool Settings::Debugger::autosaveBreakpoints() const
{
return mAutosaveBreakpoints;
}
void Settings::Debugger::setAutosaveBreakpoints(bool newAutosaveBreakpoints)
{
mAutosaveBreakpoints = newAutosaveBreakpoints;
}
bool Settings::Debugger::useIntelStyle() const
{
return mUseIntelStyle;
@ -2873,6 +2893,8 @@ void Settings::Debugger::doSave()
saveValue("skip_system_lib", mSkipSystemLibraries);
saveValue("skip_project_lib", mSkipProjectLibraries);
saveValue("skip_custom_lib", mSkipCustomLibraries);
saveValue("autosave_breakpoints",mAutosaveBreakpoints);
saveValue("autosave_watches",mAutosaveWatches);
}
@ -2888,6 +2910,8 @@ void Settings::Debugger::doLoad()
mSkipSystemLibraries = boolValue("skip_system_lib",true);
mSkipProjectLibraries = boolValue("skip_project_lib",true);
mSkipCustomLibraries = boolValue("skip_custom_lib",false);
mAutosaveBreakpoints = boolValue("autosave_breakpoints",true);
mAutosaveWatches = boolValue("autosave_watches",true);
}
Settings::History::History(Settings *settings):_Base(settings, SETTING_HISTORY)

View File

@ -844,6 +844,12 @@ public:
bool skipCustomLibraries() const;
void setSkipCustomLibraries(bool newSkipCustomLibraries);
bool autosaveBreakpoints() const;
void setAutosaveBreakpoints(bool newAutosaveBreakpoints);
bool autosaveWatches() const;
void setAutosaveWatches(bool newAutosaveWatches);
private:
bool mShowCommandLog;
bool mShowAnnotations;
@ -855,6 +861,8 @@ public:
bool mSkipSystemLibraries;
bool mSkipProjectLibraries;
bool mSkipCustomLibraries;
bool mAutosaveBreakpoints;
bool mAutosaveWatches;
// _Base interface
protected:

View File

@ -31,6 +31,8 @@ void DebugGeneralWidget::doLoad()
ui->chkSkipSystemLib->setChecked(pSettings->debugger().skipSystemLibraries());
ui->chkSkipProjectLib->setChecked(pSettings->debugger().skipProjectLibraries());
ui->chkSkipCustomLib->setChecked(pSettings->debugger().skipCustomLibraries());
ui->chkAutosaveBreakpoints->setChecked(pSettings->debugger().autosaveBreakpoints());
ui->chkAutosaveWatches->setChecked(pSettings->debugger().autosaveWatches());
}
void DebugGeneralWidget::doSave()
@ -45,6 +47,8 @@ void DebugGeneralWidget::doSave()
pSettings->debugger().setSkipSystemLibraries(ui->chkSkipSystemLib->isChecked());
pSettings->debugger().setSkipProjectLibraries(ui->chkSkipProjectLib->isChecked());
pSettings->debugger().setSkipCustomLibraries(ui->chkSkipCustomLib->isChecked());
pSettings->debugger().setAutosaveBreakpoints(ui->chkAutosaveBreakpoints->isChecked());
pSettings->debugger().setAutosaveWatches(ui->chkAutosaveWatches->isChecked());
pSettings->debugger().save();
pMainWindow->updateDebuggerSettings();
}

View File

@ -159,6 +159,29 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Autosave</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QCheckBox" name="chkAutosaveBreakpoints">
<property name="text">
<string>Autosave breakpoints</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="chkAutosaveWatches">
<property name="text">
<string>Autosave watches</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">

View File

@ -38,7 +38,7 @@ void ExecutorGeneralWidget::doSave()
pSettings->executor().save();
}
void ExecutorGeneralWidget::on_btnBrowse_triggered(QAction *arg1)
void ExecutorGeneralWidget::on_btnBrowse_clicked()
{
QString filename = QFileDialog::getOpenFileName(
this,

View File

@ -24,7 +24,7 @@ protected:
void doLoad() override;
void doSave() override;
private slots:
void on_btnBrowse_triggered(QAction *arg1);
void on_btnBrowse_clicked();
};
#endif // EXECUTORGENERALWIDGET_H

View File

@ -48,6 +48,8 @@
#define DEV_SHORTCUT_FILE "shortcuts.json"
#define DEV_TOOLS_FILE "tools.json"
#define DEV_BOOKMARK_FILE "bookmarks.json"
#define DEV_BREAKPOINTS_FILE "breakpoints.json"
#define DEV_WATCH_FILE "watch.json"
#ifdef Q_OS_WIN
# define PATH_SENSITIVITY Qt::CaseInsensitive

View File

@ -829,3 +829,9 @@ void StringToFile(const QString &str, const QString &fileName)
stream<<str;
}
}
bool removeFile(const QString &filename)
{
QFile file(filename);
return file.remove();
}

View File

@ -128,6 +128,7 @@ bool isNonPrintableAsciiChar(char ch);
bool fileExists(const QString& file);
bool fileExists(const QString& dir, const QString& fileName);
bool directoryExists(const QString& file);
bool removeFile(const QString& filename);
QString includeTrailingPathDelimiter(const QString& path);
QString excludeTrailingPathDelimiter(const QString& path);
FileType getFileType(const QString& filename);

View File

@ -67,6 +67,16 @@ bool BookmarkModel::removeBookmark(const QString &filename, int line)
return false;
}
void BookmarkModel::removeBookmarks(const QString &filename)
{
for (int i=mBookmarks.count()-1;i>=0;i--) {
PBookmark bookmark = mBookmarks[i];
if (bookmark->filename.compare(filename, PATH_SENSITIVITY) == 0) {
removeBookmarkAt(i);
}
}
}
void BookmarkModel::clear()
{
beginResetModel();

View File

@ -23,6 +23,7 @@ public:
PBookmark bookmark(int i);
PBookmark bookmark(const QString&filename, int line);
bool removeBookmark(const QString&filename, int line);
void removeBookmarks(const QString& filename);
void clear();
bool updateDescription(const QString&filename, int line, const QString& description);
void save(const QString& filename);

View File

@ -444,13 +444,13 @@ void QConsole::contentsLayouted()
updateScrollbars();
}
void QConsole::contentsRowsAdded(int rowCount)
void QConsole::contentsRowsAdded(int )
{
ensureCaretVisible();
updateScrollbars();
}
void QConsole::contentsLastRowsRemoved(int rowCount)
void QConsole::contentsLastRowsRemoved(int )
{
ensureCaretVisible();
updateScrollbars();
@ -466,7 +466,6 @@ void QConsole::scrollTimerHandler()
{
QPoint iMousePos;
int X, Y;
iMousePos = QCursor::pos();
iMousePos = mapFromGlobal(iMousePos);
@ -834,7 +833,7 @@ bool QConsole::caretInSelection()
{
if (!hasSelection())
return false;
LineChar selBegin = selectionBegin();
//LineChar selBegin = selectionBegin();
LineChar selEnd = selectionEnd();
QString lastline = mContents.getLastLine();
int editBeginChar = lastline.length() - mCurrentEditableLine.length();
@ -930,6 +929,8 @@ bool QConsole::event(QEvent *event)
mInactiveSelectionBackground = palette().color(QPalette::Inactive,QPalette::Highlight);
mInactiveSelectionForeground = palette().color(QPalette::Inactive,QPalette::HighlightedText);
break;
default:
break;
}
return QAbstractScrollArea::event(event);
}
@ -940,8 +941,7 @@ void QConsole::resizeEvent(QResizeEvent *)
std::shared_ptr<QImage> image = std::make_shared<QImage>(clientWidth(),clientHeight(),
QImage::Format_ARGB32);
if (mContentImage) {
QRect newRect = image->rect().intersected(mContentImage->rect());
//QRect newRect = image->rect().intersected(mContentImage->rect());
QPainter painter(image.get());
painter.fillRect(viewport()->rect(),mBackground);
// painter.drawImage(newRect,*mContentImage);