diff --git a/src/common/util/eventdefinitions.h b/src/common/util/eventdefinitions.h index 7955fa777..fa5a36ba5 100644 --- a/src/common/util/eventdefinitions.h +++ b/src/common/util/eventdefinitions.h @@ -55,9 +55,6 @@ OPI_OBJECT(editor, OPI_INTERFACE(clearAllAnnotation, "title") OPI_INTERFACE(setDebugLine, "fileName", "line") OPI_INTERFACE(removeDebugLine) - OPI_INTERFACE(setLineBackgroundColor, "fileName", "line", "color") - OPI_INTERFACE(resetLineBackgroundColor, "fileName", "line") - OPI_INTERFACE(clearLineBackgroundColor, "fileName") OPI_INTERFACE(setModifiedAutoReload, "fileName", "flag") OPI_INTERFACE(addBreakpoint, "fileName", "line", "enabled") OPI_INTERFACE(removeBreakpoint, "fileName", "line") @@ -74,6 +71,7 @@ OPI_OBJECT(editor, OPI_INTERFACE(breakpointStatusChanged, "fileName", "line", "enabled") OPI_INTERFACE(textChanged) OPI_INTERFACE(cursorPositionChanged, "fileName", "line", "index") + OPI_INTERFACE(selectionChanged, "fileName", "lineFrom", "indexFrom", "lineTo", "indexTo") //right-cliked menu, Related to debugging OPI_INTERFACE(setBreakpointCondition, "fileName", "line") diff --git a/src/plugins/builder/tasks/taskmanager.cpp b/src/plugins/builder/tasks/taskmanager.cpp index 4760d2152..028100529 100644 --- a/src/plugins/builder/tasks/taskmanager.cpp +++ b/src/plugins/builder/tasks/taskmanager.cpp @@ -72,6 +72,6 @@ void TaskManager::triggerDefaultHandler(const QModelIndex &index) return; if (task.file.exists()) { - editor.gotoLine(task.file.toString(), task.movedLine); + editor.gotoLine(task.file.toString(), task.movedLine - 1); } } diff --git a/src/plugins/codeeditor/codeeditor.cpp b/src/plugins/codeeditor/codeeditor.cpp index a3abfef76..598abcc63 100644 --- a/src/plugins/codeeditor/codeeditor.cpp +++ b/src/plugins/codeeditor/codeeditor.cpp @@ -181,6 +181,12 @@ void CodeEditor::initEditorService() editorService->fileText = std::bind(&WorkspaceWidget::fileText, workspaceWidget, _1); editorService->replaceAll = std::bind(&WorkspaceWidget::replaceAll, workspaceWidget, _1, _2, _3, _4, _5); editorService->replaceRange = std::bind(&WorkspaceWidget::replaceRange, workspaceWidget, _1, _2, _3, _4, _5); + editorService->setRangeBackgroundColor = std::bind(&WorkspaceWidget::setRangeBackgroundColor, workspaceWidget, _1, _2, _3, _4); + editorService->clearRangeBackgroundColor = std::bind(&WorkspaceWidget::clearRangeBackgroundColor, workspaceWidget, _1, _2, _3, _4); + editorService->clearAllBackgroundColor = std::bind(&WorkspaceWidget::clearAllBackgroundColor, workspaceWidget, _1, _2); + editorService->showLineWidget = std::bind(&WorkspaceWidget::showLineWidget, workspaceWidget, _1, _2); + editorService->closeLineWidget = std::bind(&WorkspaceWidget::closeLineWidget, workspaceWidget); + editorService->cursorPosition = std::bind(&WorkspaceWidget::cursorPosition, workspaceWidget, _1, _2); LexerManager::instance()->init(editorService); } diff --git a/src/plugins/codeeditor/gui/private/tabwidget_p.h b/src/plugins/codeeditor/gui/private/tabwidget_p.h index c364d9f9a..b6e5edce8 100644 --- a/src/plugins/codeeditor/gui/private/tabwidget_p.h +++ b/src/plugins/codeeditor/gui/private/tabwidget_p.h @@ -56,9 +56,6 @@ public slots: void handleAddAnnotation(const QString &fileName, const QString &title, const QString &content, int line, AnnotationType type); void handleRemoveAnnotation(const QString &fileName, const QString &title); void handleClearAllAnnotation(const QString &title); - void handleSetLineBackgroundColor(const QString &fileName, int line, const QColor &color); - void handleResetLineBackground(const QString &fileName, int line); - void handleClearLineBackground(const QString &fileName); void handleDoRename(const newlsp::WorkspaceEdit &info); void handleOpenFiles(const QList &fileList); diff --git a/src/plugins/codeeditor/gui/private/texteditor_p.cpp b/src/plugins/codeeditor/gui/private/texteditor_p.cpp index fecf23327..58da4e1ce 100644 --- a/src/plugins/codeeditor/gui/private/texteditor_p.cpp +++ b/src/plugins/codeeditor/gui/private/texteditor_p.cpp @@ -55,6 +55,13 @@ void TextEditorPrivate::init() q->SendScintilla(TextEditor::SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR, TextEditor::SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE); + lineWidgetContainer = new QFrame(q, Qt::Tool | Qt::FramelessWindowHint); + lineWidgetContainer->setLayout(new QVBoxLayout); + lineWidgetContainer->setContentsMargins(0, 0, 0, 0); + lineWidgetContainer->installEventFilter(q); + if (mainWindow()) + mainWindow()->installEventFilter(q); + initMargins(); updateColorTheme(); updateSettings(); @@ -69,6 +76,7 @@ void TextEditorPrivate::initConnection() q->cancelTips(); }); + connect(q->verticalScrollBar(), &QScrollBar::valueChanged, this, &TextEditorPrivate::updateLineWidgetPosition); connect(q, &TextEditor::SCN_ZOOM, q, &TextEditor::zoomValueChanged); connect(q, &TextEditor::SCN_DWELLSTART, this, &TextEditorPrivate::onDwellStart); connect(q, &TextEditor::SCN_DWELLEND, this, &TextEditorPrivate::onDwellEnd); @@ -91,13 +99,12 @@ void TextEditorPrivate::initMargins() q->setMarginMarkerMask(SymbolMargin, 1 << Breakpoint | 1 << BreakpointDisabled | 1 << Bookmark | 1 << Runtime - | 1 << RuntimeLineBackground | 1 << CustomLineBackground); + | 1 << RuntimeLineBackground); q->markerDefine(TextEditor::RightTriangle, Bookmark); q->setMarkerBackgroundColor(QColor(Qt::red), Bookmark); q->markerDefine(TextEditor::Background, RuntimeLineBackground); - q->markerDefine(TextEditor::Background, CustomLineBackground); } void TextEditorPrivate::updateColorTheme() @@ -342,8 +349,8 @@ void TextEditorPrivate::showMarginMenu() DebuggerService *debuggerService = ctx.service(DebuggerService::name()); if (debuggerService->getDebugState() == AbstractDebugger::RunState::kStopped) { menu.addSeparator(); - menu.addAction(tr("jump to %1 line").arg(line + 1), q, [this, line] { editor.jumpToLine(fileName, line + 1); }); - menu.addAction(tr("run to %1 line").arg(line + 1), q, [this, line] { editor.runToLine(fileName, line + 1); }); + menu.addAction(tr("jump to %1 line").arg(line + 1), q, [this, line] { editor.jumpToLine(fileName, line); }); + menu.addAction(tr("run to %1 line").arg(line + 1), q, [this, line] { editor.runToLine(fileName, line); }); } // notify other plugin to add action. @@ -440,7 +447,7 @@ QMap TextEditorPrivate::allMarkers() if (mask != 0) markers.insert(line, mask); } - + return markers; } @@ -450,7 +457,7 @@ void TextEditorPrivate::setMarkers(const QMap &maskMap) for (auto iter = maskMap.begin(); iter != maskMap.end(); ++iter) { if (iter.key() >= totalLine) break; - + if (iter.value() & (1 << Breakpoint)) { q->addBreakpoint(iter.key(), true); } else if (iter.value() & (1 << BreakpointDisabled)) { @@ -459,6 +466,66 @@ void TextEditorPrivate::setMarkers(const QMap &maskMap) } } +QWidget *TextEditorPrivate::mainWindow() +{ + static QWidget *mw { nullptr }; + if (mw) + return mw; + + for (auto w : qApp->allWidgets()) { + if (w->objectName() == "MainWindow") { + mw = w; + break; + } + } + + return mw; +} + +void TextEditorPrivate::setContainerWidget(QWidget *widget) +{ + auto layout = lineWidgetContainer->layout(); + while (auto item = layout->takeAt(0)) { + if (QWidget *widget = item->widget()) + widget->setVisible(false); + delete item; + } + + widget->setVisible(true); + lineWidgetContainer->setFocusProxy(widget); + lineWidgetContainer->layout()->addWidget(widget); + lineWidgetContainer->show(); + updateLineWidgetPosition(); +} + +void TextEditorPrivate::updateLineWidgetPosition() +{ + if (!lineWidgetContainer->isVisible() || showAtLine < 0 || showAtLine > q->lines() - 1) + return; + + int pos = q->positionFromLineIndex(showAtLine, 0); + auto point = q->mapToGlobal(q->pointFromPosition(pos)); + auto displayY = point.y() - lineWidgetContainer->height(); + + auto rect = q->rect(); + auto rectTL = q->mapToGlobal(rect.topLeft()); + auto rectBL = q->mapToGlobal(rect.bottomLeft()); + + // NOTE: upate the `lineWidgetContainer` position + // 1.It is displayed above `showAtLine` by default + // 2.The `lineWidgetContainer` does not extend beyond the top and bottom of the editor + // 3.When the `lineWidgetContainer` will block the `showAtLine`, display it below the `showAtLine` + if (displayY < rectTL.y()) { + displayY = point.y() + q->textHeight(showAtLine); + if (displayY < rectTL.y()) + displayY = rectTL.y(); + } else if (displayY > rectBL.y() - lineWidgetContainer->height()) { + displayY = rectBL.y() - lineWidgetContainer->height(); + } + + lineWidgetContainer->move(point.x(), displayY); +} + void TextEditorPrivate::resetThemeColor() { if (q->lexer()) { @@ -505,11 +572,17 @@ void TextEditorPrivate::onModified(int pos, int mtype, const QString &text, int contentsChanged = true; if (isAutoCompletionEnabled && !text.isEmpty()) editor.textChanged(); - + if (added != 0) { int line = 0, index = 0; q->lineIndexFromPosition(pos, &line, &index); - editor.lineChanged(fileName, line + 1, added); + editor.lineChanged(fileName, line, added); + if (lineWidgetContainer->isVisible() && added != 0) { + if (showAtLine > line) { + showAtLine += added; + updateLineWidgetPosition(); + } + } } if (mtype & TextEditor::SC_MOD_INSERTTEXT) { diff --git a/src/plugins/codeeditor/gui/private/texteditor_p.h b/src/plugins/codeeditor/gui/private/texteditor_p.h index fcf14b89f..b8b4144bc 100644 --- a/src/plugins/codeeditor/gui/private/texteditor_p.h +++ b/src/plugins/codeeditor/gui/private/texteditor_p.h @@ -28,8 +28,7 @@ class TextEditorPrivate : public QObject BreakpointDisabled, Bookmark, Runtime, - RuntimeLineBackground, - CustomLineBackground + RuntimeLineBackground }; explicit TextEditorPrivate(TextEditor *qq); @@ -56,6 +55,10 @@ class TextEditorPrivate : public QObject QMap allMarkers(); void setMarkers(const QMap &maskMap); + QWidget *mainWindow(); + void setContainerWidget(QWidget *widget); + void updateLineWidgetPosition(); + public slots: void resetThemeColor(); void onDwellStart(int position, int x, int y); @@ -71,7 +74,7 @@ public slots: int preFirstLineNum { 0 }; int lastCursorPos { 0 }; QMultiHash annotationRecords; - + LanguageClientHandler *languageClient { nullptr }; bool isAutoCompletionEnabled { false }; @@ -83,8 +86,11 @@ public slots: int fontSize { 10 }; CodeCompletionWidget *completionWidget { nullptr }; - QMap commentSettings; + + std::tuple selectionCache { -1, -1, -1, -1 }; + QFrame *lineWidgetContainer { nullptr }; + int showAtLine { 0 }; }; #endif // TEXTEDITOR_P_H diff --git a/src/plugins/codeeditor/gui/tabwidget.cpp b/src/plugins/codeeditor/gui/tabwidget.cpp index c628ad89b..640e6751c 100644 --- a/src/plugins/codeeditor/gui/tabwidget.cpp +++ b/src/plugins/codeeditor/gui/tabwidget.cpp @@ -145,9 +145,6 @@ void TabWidgetPrivate::initConnection() connect(EditorCallProxy::instance(), &EditorCallProxy::reqAddAnnotation, this, &TabWidgetPrivate::handleAddAnnotation); connect(EditorCallProxy::instance(), &EditorCallProxy::reqRemoveAnnotation, this, &TabWidgetPrivate::handleRemoveAnnotation); connect(EditorCallProxy::instance(), &EditorCallProxy::reqClearAllAnnotation, this, &TabWidgetPrivate::handleClearAllAnnotation); - connect(EditorCallProxy::instance(), &EditorCallProxy::reqSetLineBackgroundColor, this, &TabWidgetPrivate::handleSetLineBackgroundColor); - connect(EditorCallProxy::instance(), &EditorCallProxy::reqResetLineBackground, this, &TabWidgetPrivate::handleResetLineBackground); - connect(EditorCallProxy::instance(), &EditorCallProxy::reqClearLineBackground, this, &TabWidgetPrivate::handleClearLineBackground); connect(EditorCallProxy::instance(), &EditorCallProxy::reqDoRename, this, &TabWidgetPrivate::handleDoRename); } @@ -439,24 +436,6 @@ void TabWidgetPrivate::handleClearAllAnnotation(const QString &title) editor->removeAnnotation(title); } -void TabWidgetPrivate::handleSetLineBackgroundColor(const QString &fileName, int line, const QColor &color) -{ - if (auto editor = findEditor(fileName)) - editor->setLineBackgroundColor(line, color); -} - -void TabWidgetPrivate::handleResetLineBackground(const QString &fileName, int line) -{ - if (auto editor = findEditor(fileName)) - editor->resetLineBackgroundColor(line); -} - -void TabWidgetPrivate::handleClearLineBackground(const QString &fileName) -{ - if (auto editor = findEditor(fileName)) - editor->clearLineBackgroundColor(); -} - void TabWidgetPrivate::handleDoRename(const newlsp::WorkspaceEdit &info) { if (info.changes) { @@ -861,6 +840,57 @@ void TabWidget::updateZoomValue(int value) } } +bool TabWidget::setRangeBackgroundColor(const QString &fileName, int startLine, int endLine, const QColor &color, int &marker) +{ + if (auto editor = d->findEditor(fileName)) { + marker = editor->setRangeBackgroundColor(startLine, endLine, color); + return true; + } + + return false; +} + +bool TabWidget::clearRangeBackground(const QString &fileName, int startLine, int endLine, int marker) +{ + if (auto editor = d->findEditor(fileName)) { + editor->clearRangeBackgroundColor(startLine, endLine, marker); + return true; + } + + return false; +} + +bool TabWidget::clearAllBackground(const QString &fileName, int marker) +{ + if (auto editor = d->findEditor(fileName)) { + editor->clearAllBackgroundColor(marker); + return true; + } + + return false; +} + +void TabWidget::showLineWidget(int line, QWidget *widget) +{ + if (auto editor = d->currentTextEditor()) + editor->showLineWidget(line, widget); +} + +void TabWidget::closeLineWidget() +{ + if (auto editor = d->currentTextEditor()) + editor->closeLineWidget(); +} + +void TabWidget::cursorPosition(int *line, int *index) +{ + if (!line || !index) + return; + + if (auto editor = d->currentTextEditor()) + editor->getCursorPosition(line, index); +} + TextEditor *TabWidget::currentEditor() const { return d->currentTextEditor(); diff --git a/src/plugins/codeeditor/gui/tabwidget.h b/src/plugins/codeeditor/gui/tabwidget.h index d6b909659..c1dbece00 100644 --- a/src/plugins/codeeditor/gui/tabwidget.h +++ b/src/plugins/codeeditor/gui/tabwidget.h @@ -65,6 +65,13 @@ class TabWidget : public QWidget int zoomValue(); void updateZoomValue(int value); + bool setRangeBackgroundColor(const QString &fileName, int startLine, int endLine, const QColor &color, int &marker); + bool clearRangeBackground(const QString &fileName, int startLine, int endLine, int marker); + bool clearAllBackground(const QString &fileName, int marker); + void showLineWidget(int line, QWidget *widget); + void closeLineWidget(); + void cursorPosition(int *line, int *index); + TextEditor *currentEditor() const; TextEditor *findEditor(const QString &fileName); diff --git a/src/plugins/codeeditor/gui/texteditor.cpp b/src/plugins/codeeditor/gui/texteditor.cpp index bcba52c4d..6f15ccc71 100644 --- a/src/plugins/codeeditor/gui/texteditor.cpp +++ b/src/plugins/codeeditor/gui/texteditor.cpp @@ -163,7 +163,7 @@ void TextEditor::addBreakpoint(int line, bool enabled) markerAdd(line, TextEditorPrivate::BreakpointDisabled); } - editor.breakpointAdded(d->fileName, line + 1, enabled); + editor.breakpointAdded(d->fileName, line, enabled); } void TextEditor::removeBreakpoint(int line) @@ -173,7 +173,7 @@ void TextEditor::removeBreakpoint(int line) else markerDelete(line, TextEditorPrivate::BreakpointDisabled); - editor.breakpointRemoved(d->fileName, line + 1); + editor.breakpointRemoved(d->fileName, line); } void TextEditor::toggleBreakpoint() @@ -198,12 +198,12 @@ void TextEditor::setBreakpointEnabled(int line, bool enabled) markerDelete(line, TextEditorPrivate::Breakpoint); markerAdd(line, TextEditorPrivate::BreakpointDisabled); } - editor.breakpointStatusChanged(d->fileName, line + 1, enabled); + editor.breakpointStatusChanged(d->fileName, line, enabled); } void TextEditor::setBreakpointCondition(int line) { - editor.setBreakpointCondition(d->fileName, line + 1); + editor.setBreakpointCondition(d->fileName, line); } bool TextEditor::breakpointEnabled(int line) @@ -329,20 +329,36 @@ int TextEditor::cursorPosition() return static_cast(SendScintilla(TextEditor::SCI_GETCURRENTPOS)); } -void TextEditor::setLineBackgroundColor(int line, const QColor &color) +int TextEditor::setRangeBackgroundColor(int startLine, int endLine, const QColor &color) { - markerAdd(line, TextEditorPrivate::CustomLineBackground); - setMarkerBackgroundColor(color, TextEditorPrivate::CustomLineBackground); + startLine = qMax(startLine, 0); + endLine = qMin(endLine, lines() - 1); + if (startLine > endLine) + return -1; + + int marker = markerDefine(Background); + for (; startLine <= endLine; ++startLine) { + markerAdd(startLine, marker); + } + + return marker; } -void TextEditor::resetLineBackgroundColor(int line) +void TextEditor::clearRangeBackgroundColor(int startLine, int endLine, int marker) { - markerDelete(line, TextEditorPrivate::CustomLineBackground); + startLine = qMax(startLine, 0); + endLine = qMin(endLine, lines() - 1); + if (startLine > endLine) + return; + + for (; startLine <= endLine; ++startLine) { + markerDelete(startLine, marker); + } } -void TextEditor::clearLineBackgroundColor() +void TextEditor::clearAllBackgroundColor(int marker) { - markerDeleteAll(TextEditorPrivate::CustomLineBackground); + markerDeleteAll(marker); } void TextEditor::showTips(const QString &tips) @@ -686,6 +702,21 @@ bool TextEditor::isAutomaticInvocationEnabled() const return d->isAutoCompletionEnabled; } +bool TextEditor::showLineWidget(int line, QWidget *widget) +{ + if (line < 0 || line >= lines()) + return false; + + d->showAtLine = line; + d->setContainerWidget(widget); + return true; +} + +void TextEditor::closeLineWidget() +{ + d->lineWidgetContainer->setVisible(false); +} + void TextEditor::onMarginClicked(int margin, int line, Qt::KeyboardModifiers state) { Q_UNUSED(state) @@ -762,6 +793,9 @@ void TextEditor::onCursorPositionChanged(int line, int index) void TextEditor::focusOutEvent(QFocusEvent *event) { + if (!d->lineWidgetContainer->hasFocus()) + d->lineWidgetContainer->setVisible(false); + Q_EMIT focusOut(); Q_EMIT followTypeEnd(); QsciScintilla::focusOutEvent(event); @@ -787,6 +821,33 @@ void TextEditor::mouseMoveEvent(QMouseEvent *event) QsciScintilla::mouseMoveEvent(event); } +void TextEditor::mouseReleaseEvent(QMouseEvent *event) +{ + QsciScintilla::mouseReleaseEvent(event); + + bool selChanged = hasSelectedText(); + if (!selChanged && d->selectionCache != std::make_tuple(-1, -1, -1, -1)) + selChanged = true; + + if (selChanged) { + int lineFrom = -1, indexFrom = -1, lineTo = -1, indexTo = -1; + getSelection(&lineFrom, &indexFrom, &lineTo, &indexTo); + d->selectionCache = std::make_tuple(lineFrom, indexFrom, lineTo, indexTo); + editor.selectionChanged(d->fileName, lineFrom, indexFrom, lineTo, indexTo); + } +} + +bool TextEditor::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == d->lineWidgetContainer && event->type() == QEvent::Resize) { + d->updateLineWidgetPosition(); + } else if (obj == d->mainWindow() && event->type() == QEvent::Move) { + d->updateLineWidgetPosition(); + } + + return QsciScintilla::eventFilter(obj, event); +} + bool TextEditor::event(QEvent *event) { if (!d) diff --git a/src/plugins/codeeditor/gui/texteditor.h b/src/plugins/codeeditor/gui/texteditor.h index f53ea9d08..1cd3cbb50 100644 --- a/src/plugins/codeeditor/gui/texteditor.h +++ b/src/plugins/codeeditor/gui/texteditor.h @@ -66,9 +66,9 @@ class TextEditor : public QsciScintilla void gotoPosition(int pos); int cursorLastPosition(); int cursorPosition(); - void setLineBackgroundColor(int line, const QColor &color); - void resetLineBackgroundColor(int line); - void clearLineBackgroundColor(); + int setRangeBackgroundColor(int startLine, int endLine, const QColor &color); + void clearRangeBackgroundColor(int startLine, int endLine, int marker); + void clearAllBackgroundColor(int marker); void showTips(const QString &tips); void showTips(int pos, const QString &tips); void cancelTips(); @@ -103,6 +103,8 @@ class TextEditor : public QsciScintilla void setAutomaticInvocationEnabled(bool enabled); bool isAutomaticInvocationEnabled() const; + bool showLineWidget(int line, QWidget *widget); + void closeLineWidget(); public slots: void onMarginClicked(int margin, int line, Qt::KeyboardModifiers state); @@ -114,6 +116,8 @@ public slots: virtual void focusOutEvent(QFocusEvent *event) override; virtual void keyPressEvent(QKeyEvent *event) override; virtual void mouseMoveEvent(QMouseEvent *event) override; + virtual void mouseReleaseEvent(QMouseEvent *event) override; + virtual bool eventFilter(QObject *obj, QEvent *event) override; virtual bool event(QEvent *event) override; signals: diff --git a/src/plugins/codeeditor/gui/workspacewidget.cpp b/src/plugins/codeeditor/gui/workspacewidget.cpp index 9049ca8fe..29136488d 100644 --- a/src/plugins/codeeditor/gui/workspacewidget.cpp +++ b/src/plugins/codeeditor/gui/workspacewidget.cpp @@ -1167,6 +1167,12 @@ TabWidget *WorkspaceWidget::currentTabWidget() const return d->currentTabWidget(); } +void WorkspaceWidget::cursorPosition(int *line, int *index) +{ + if (auto tabWidget = d->currentTabWidget()) + tabWidget->cursorPosition(line, index); +} + void WorkspaceWidget::registerWidget(const QString &id, AbstractEditWidget *widget) { d->registeredWidget.insert(id, widget); @@ -1186,6 +1192,45 @@ void WorkspaceWidget::switchDefaultWidget() d->stackWidget->setCurrentIndex(0); } +int WorkspaceWidget::setRangeBackgroundColor(const QString &fileName, int startLine, int endLine, const QColor &color) +{ + int marker = 0; + for (auto tabWidget : d->tabWidgetList) { + if (tabWidget->setRangeBackgroundColor(fileName, startLine, endLine, color, marker)) + break; + } + + return marker; +} + +void WorkspaceWidget::clearRangeBackgroundColor(const QString &fileName, int startLine, int endLine, int marker) +{ + for (auto tabWidget : d->tabWidgetList) { + if (tabWidget->clearRangeBackground(fileName, startLine, endLine, marker)) + break; + } +} + +void WorkspaceWidget::clearAllBackgroundColor(const QString &fileName, int marker) +{ + for (auto tabWidget : d->tabWidgetList) { + if (tabWidget->clearAllBackground(fileName, marker)) + break; + } +} + +void WorkspaceWidget::showLineWidget(int line, QWidget *widget) +{ + if (auto tabWidget = d->currentTabWidget()) + tabWidget->showLineWidget(line, widget); +} + +void WorkspaceWidget::closeLineWidget() +{ + if (auto tabWidget = d->currentTabWidget()) + tabWidget->closeLineWidget(); +} + bool WorkspaceWidget::event(QEvent *event) { if (event->type() == QEvent::WindowActivate) diff --git a/src/plugins/codeeditor/gui/workspacewidget.h b/src/plugins/codeeditor/gui/workspacewidget.h index 76773fbca..f11ab2a30 100644 --- a/src/plugins/codeeditor/gui/workspacewidget.h +++ b/src/plugins/codeeditor/gui/workspacewidget.h @@ -38,11 +38,18 @@ class WorkspaceWidget : public QWidget void replaceAll(const QString &fileName, const QString &oldText, const QString &newText, bool caseSensitive, bool wholeWords); void replaceRange(const QString &fileName, int line, int index, int length, const QString &after); TabWidget *currentTabWidget() const; + void cursorPosition(int *line, int *index); void registerWidget(const QString &id, AbstractEditWidget *widget); void switchWidget(const QString &id); void switchDefaultWidget(); + int setRangeBackgroundColor(const QString &fileName, int startLine, int endLine, const QColor &color); + void clearRangeBackgroundColor(const QString &fileName, int startLine, int endLine, int marker); + void clearAllBackgroundColor(const QString &fileName, int marker); + void showLineWidget(int line, QWidget *widget); + void closeLineWidget(); + protected: bool event(QEvent *event) override; diff --git a/src/plugins/codeeditor/symbol/symbolview.cpp b/src/plugins/codeeditor/symbol/symbolview.cpp index 65532bbc0..dfa3b9012 100644 --- a/src/plugins/codeeditor/symbol/symbolview.cpp +++ b/src/plugins/codeeditor/symbol/symbolview.cpp @@ -109,7 +109,7 @@ void SymbolViewPrivate::handleItemClicked(const QModelIndex &index) return; const auto &range = index.data(SymbolRangeRole).value(); - editor.gotoPosition(path, range.start.line + 1, range.start.character); + editor.gotoPosition(path, range.start.line, range.start.character); } else { if (QFileInfo(path).isDir()) { view->setExpanded(index, !view->isExpanded(index)); diff --git a/src/plugins/codeeditor/transceiver/codeeditorreceiver.cpp b/src/plugins/codeeditor/transceiver/codeeditorreceiver.cpp index 84e809123..fb567689d 100644 --- a/src/plugins/codeeditor/transceiver/codeeditorreceiver.cpp +++ b/src/plugins/codeeditor/transceiver/codeeditorreceiver.cpp @@ -23,9 +23,6 @@ CodeEditorReceiver::CodeEditorReceiver(QObject *parent) eventHandleMap.insert(editor.clearAllAnnotation.name, std::bind(&CodeEditorReceiver::processClearAllAnnotationEvent, this, _1)); eventHandleMap.insert(editor.setDebugLine.name, std::bind(&CodeEditorReceiver::processSetDebugLineEvent, this, _1)); eventHandleMap.insert(editor.removeDebugLine.name, std::bind(&CodeEditorReceiver::processRemoveDebugLineEvent, this, _1)); - eventHandleMap.insert(editor.setLineBackgroundColor.name, std::bind(&CodeEditorReceiver::processSetLineBackgroundColorEvent, this, _1)); - eventHandleMap.insert(editor.resetLineBackgroundColor.name, std::bind(&CodeEditorReceiver::processResetLineBackgroundEvent, this, _1)); - eventHandleMap.insert(editor.clearLineBackgroundColor.name, std::bind(&CodeEditorReceiver::processClearLineBackgroundEvent, this, _1)); eventHandleMap.insert(editor.addBreakpoint.name, std::bind(&CodeEditorReceiver::processAddBreakpointEvent, this, _1)); eventHandleMap.insert(editor.removeBreakpoint.name, std::bind(&CodeEditorReceiver::processRemoveBreakpointEvent, this, _1)); eventHandleMap.insert(editor.setBreakpointEnabled.name, std::bind(&CodeEditorReceiver::processSetBreakpointEnabledEvent, this, _1)); @@ -83,39 +80,18 @@ void CodeEditorReceiver::processForwardEvent(const dpf::Event &event) void CodeEditorReceiver::processGotoLineEvent(const dpf::Event &event) { QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt() - 1; + int line = event.property("line").toInt(); Q_EMIT EditorCallProxy::instance()->reqGotoLine(filePath, line); } void CodeEditorReceiver::processGotoPositionEvent(const dpf::Event &event) { QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt() - 1; + int line = event.property("line").toInt(); int col = event.property("column").toInt(); Q_EMIT EditorCallProxy::instance()->reqGotoPosition(filePath, line, col); } -void CodeEditorReceiver::processSetLineBackgroundColorEvent(const dpf::Event &event) -{ - QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt() - 1; - QColor color = qvariant_cast(event.property("color")); - Q_EMIT EditorCallProxy::instance()->reqSetLineBackgroundColor(filePath, line, color); -} - -void CodeEditorReceiver::processResetLineBackgroundEvent(const dpf::Event &event) -{ - QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt() - 1; - Q_EMIT EditorCallProxy::instance()->reqResetLineBackground(filePath, line); -} - -void CodeEditorReceiver::processClearLineBackgroundEvent(const dpf::Event &event) -{ - QString filePath = event.property("fileName").toString(); - Q_EMIT EditorCallProxy::instance()->reqClearLineBackground(filePath); -} - void CodeEditorReceiver::processSetModifiedAutoReloadEvent(const dpf::Event &event) { QString filePath = event.property("fileName").toString(); @@ -127,7 +103,7 @@ void CodeEditorReceiver::processAddAnnotationEvent(const dpf::Event &event) { QString filePath = event.property("fileName").toString(); QString title = event.property("title").toString(); - int line = event.property("line").toInt() - 1; + int line = event.property("line").toInt(); QString content = event.property("content").toString(); AnnotationType type = qvariant_cast(event.property("type")); Q_EMIT EditorCallProxy::instance()->reqAddAnnotation(filePath, title, content, line, type); @@ -149,7 +125,7 @@ void CodeEditorReceiver::processClearAllAnnotationEvent(const dpf::Event &event) void CodeEditorReceiver::processAddBreakpointEvent(const dpf::Event &event) { QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt() - 1; + int line = event.property("line").toInt(); bool enabled = event.property("enabled").toBool(); Q_EMIT EditorCallProxy::instance()->reqAddBreakpoint(filePath, line, enabled); } @@ -157,14 +133,14 @@ void CodeEditorReceiver::processAddBreakpointEvent(const dpf::Event &event) void CodeEditorReceiver::processRemoveBreakpointEvent(const dpf::Event &event) { QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt() - 1; + int line = event.property("line").toInt(); Q_EMIT EditorCallProxy::instance()->reqRemoveBreakpoint(filePath, line); } void CodeEditorReceiver::processSetBreakpointEnabledEvent(const dpf::Event &event) { QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt() - 1; + int line = event.property("line").toInt(); bool enabled = event.property("enabled").toBool(); Q_EMIT EditorCallProxy::instance()->reqSetBreakpointEnabled(filePath, line, enabled); } @@ -179,7 +155,7 @@ void CodeEditorReceiver::processClearAllBreakpointsEvent(const dpf::Event &event void CodeEditorReceiver::processSetDebugLineEvent(const dpf::Event &event) { QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt() - 1; + int line = event.property("line").toInt(); Q_EMIT EditorCallProxy::instance()->reqSetDebugLine(filePath, line); } diff --git a/src/plugins/codeeditor/transceiver/codeeditorreceiver.h b/src/plugins/codeeditor/transceiver/codeeditorreceiver.h index f36e22a53..37315c21c 100644 --- a/src/plugins/codeeditor/transceiver/codeeditorreceiver.h +++ b/src/plugins/codeeditor/transceiver/codeeditorreceiver.h @@ -25,9 +25,6 @@ class CodeEditorReceiver : public dpf::EventHandler, dpf::AutoEventHandlerRegist void processForwardEvent(const dpf::Event &event); void processGotoLineEvent(const dpf::Event &event); void processGotoPositionEvent(const dpf::Event &event); - void processSetLineBackgroundColorEvent(const dpf::Event &event); - void processResetLineBackgroundEvent(const dpf::Event &event); - void processClearLineBackgroundEvent(const dpf::Event &event); void processSetModifiedAutoReloadEvent(const dpf::Event &event); // annotation @@ -63,9 +60,6 @@ class EditorCallProxy : public QObject void reqForward(); void reqGotoLine(const QString &fileName, int line); void reqGotoPosition(const QString &fileName, int line, int column); - void reqSetLineBackgroundColor(const QString &fileName, int line, const QColor &color); - void reqResetLineBackground(const QString &fileName, int line); - void reqClearLineBackground(const QString &fileName); void reqSetModifiedAutoReload(const QString &fileName, bool flag); void reqDoRename(const newlsp::WorkspaceEdit &info); void reqCloseCurrentEditor(); diff --git a/src/plugins/codeporting/codeportingmanager.cpp b/src/plugins/codeporting/codeportingmanager.cpp index ec861eb7c..ee51cc661 100644 --- a/src/plugins/codeporting/codeportingmanager.cpp +++ b/src/plugins/codeporting/codeportingmanager.cpp @@ -8,6 +8,7 @@ #include "base/abstractwidget.h" #include "services/window/windowservice.h" #include "services/project/projectservice.h" +#include "services/editor/editorservice.h" #include "reportpane.h" #include @@ -84,15 +85,13 @@ void CodePortingManager::slotSelectedChanged(const QString &filePath, const QStr { Q_UNUSED(endLine) - int startLineInEditor = startLine + kLineNumberAdaptation; - int endLineInEditor = endLine + kLineNumberAdaptation; - editor.gotoLine(filePath, startLineInEditor); + editor.gotoLine(filePath, startLine); editor.addAnnotation(filePath, QString("CodePorting"), suggestion, startLine, AnnotationType::NoteAnnotation); QColor backgroundColor(Qt::red); backgroundColor.setAlpha(100); - for (int lineNumber = startLineInEditor; lineNumber <= endLineInEditor; ++lineNumber) { - editor.setLineBackgroundColor(filePath, lineNumber, backgroundColor); - } + + if (auto editSrv = dpfGetService(EditorService)) + editSrv->setRangeBackgroundColor(filePath, startLine, endLine, backgroundColor); } void CodePortingManager::slotAppendOutput(const QString &content, OutputPane::OutputFormat format, OutputPane::AppendMode mode) diff --git a/src/plugins/debugger/dap/dapdebugger.cpp b/src/plugins/debugger/dap/dapdebugger.cpp index cfd0bd54e..d770ae1f9 100644 --- a/src/plugins/debugger/dap/dapdebugger.cpp +++ b/src/plugins/debugger/dap/dapdebugger.cpp @@ -823,7 +823,7 @@ void DAPDebugger::handleEvents(const dpf::Event &event) for (auto index = 0; index < d->breakpointModel.breakpointSize(); index++) { auto bp = d->breakpointModel.BreakpointAt(index); if (bp.filePath == filePath) - editor.addBreakpoint(filePath, bp.lineNumber, bp.enabled); + editor.addBreakpoint(filePath, bp.lineNumber - 1, bp.enabled); } } } else if (event.data() == editor.fileClosed.name) { @@ -833,24 +833,24 @@ void DAPDebugger::handleEvents(const dpf::Event &event) } } else if (event.data() == editor.breakpointAdded.name) { QString filePath = event.property(editor.breakpointAdded.pKeys[0]).toString(); - int line = event.property(editor.breakpointAdded.pKeys[1]).toInt(); + int line = event.property(editor.breakpointAdded.pKeys[1]).toInt() + 1; if (d->bps.contains(filePath) && d->bps.values(filePath).contains(line)) return; d->bps.insert(filePath, line); addBreakpoint(filePath, line); } else if (event.data() == editor.breakpointRemoved.name) { QString filePath = event.property(editor.breakpointRemoved.pKeys[0]).toString(); - int line = event.property(editor.breakpointRemoved.pKeys[1]).toInt(); + int line = event.property(editor.breakpointRemoved.pKeys[1]).toInt() + 1; d->bps.remove(filePath, line); removeBreakpoint(filePath, line); } else if (event.data() == editor.breakpointStatusChanged.name) { QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt(); + int line = event.property("line").toInt() + 1; bool enabled = event.property("enabled").toBool(); switchBreakpointsStatus(filePath, line, enabled); } else if (event.data() == editor.setBreakpointCondition.name) { QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt(); + int line = event.property("line").toInt() + 1; DDialog condition; DLineEdit *edit = new DLineEdit(d->breakpointView); @@ -867,12 +867,12 @@ void DAPDebugger::handleEvents(const dpf::Event &event) } } else if (event.data() == editor.jumpToLine.name) { QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt(); + int line = event.property("line").toInt() + 1; jumpToLine(filePath, line); } else if (event.data() == editor.runToLine.name) { QString filePath = event.property("fileName").toString(); - int line = event.property("line").toInt(); + int line = event.property("line").toInt() + 1; runToLine(filePath, line); } @@ -1055,7 +1055,7 @@ void DAPDebugger::slotBreakpointSelected(const QModelIndex &index) { Q_UNUSED(index); auto curBP = d->breakpointModel.currentBreakpoint(); - editor.gotoLine(curBP.filePath, curBP.lineNumber); + editor.gotoLine(curBP.filePath, curBP.lineNumber - 1); } void DAPDebugger::slotGetChildVariable(const QModelIndex &index) @@ -1568,7 +1568,7 @@ void DAPDebugger::handleUpdateDebugLine() localFile = d->isRemote ? transformRemotePath(curFrame.file) : curFrame.file; if (QFileInfo(localFile).exists()) { - editor.setDebugLine(localFile, curFrame.line); + editor.setDebugLine(localFile, curFrame.line - 1); } else if (!curFrame.address.isEmpty()) { disassemble(curFrame.address); } diff --git a/src/plugins/debugger/interface/breakpointview.cpp b/src/plugins/debugger/interface/breakpointview.cpp index 0ebffdd6d..24ec34abe 100644 --- a/src/plugins/debugger/interface/breakpointview.cpp +++ b/src/plugins/debugger/interface/breakpointview.cpp @@ -108,9 +108,9 @@ void BreakpointView::enableBreakpoints(const QModelIndexList &rows) for (auto row : rows) { auto bp = bpModel->BreakpointAt(row.row()); if (openedFiles.contains(bp.filePath)) - editor.setBreakpointEnabled(bp.filePath, bp.lineNumber, true); + editor.setBreakpointEnabled(bp.filePath, bp.lineNumber - 1, true); else - editor.breakpointStatusChanged(bp.filePath, bp.lineNumber, true); + editor.breakpointStatusChanged(bp.filePath, bp.lineNumber - 1, true); } } @@ -121,9 +121,9 @@ void BreakpointView::disableBreakpoints(const QModelIndexList &rows) for (auto row : rows) { auto bp = bpModel->BreakpointAt(row.row()); if (openedFiles.contains(bp.filePath)) - editor.setBreakpointEnabled(bp.filePath, bp.lineNumber, false); + editor.setBreakpointEnabled(bp.filePath, bp.lineNumber - 1, false); else - editor.breakpointStatusChanged(bp.filePath, bp.lineNumber, false); + editor.breakpointStatusChanged(bp.filePath, bp.lineNumber - 1, false); } } @@ -134,9 +134,9 @@ void BreakpointView::removeBreakpoints(const QModelIndexList &rows) for (auto row : rows) { auto bp = bpModel->BreakpointAt(row.row()); if (openedFiles.contains(bp.filePath)) - editor.removeBreakpoint(bp.filePath, bp.lineNumber); + editor.removeBreakpoint(bp.filePath, bp.lineNumber - 1); else - editor.breakpointRemoved(bp.filePath, bp.lineNumber); + editor.breakpointRemoved(bp.filePath, bp.lineNumber - 1); } } @@ -145,7 +145,7 @@ void BreakpointView::editBreakpointCondition(const QModelIndex &index) BreakpointModel *bpModel = static_cast(model()); auto bp = bpModel->BreakpointAt(index.row()); - editor.setBreakpointCondition(bp.filePath, bp.lineNumber); + editor.setBreakpointCondition(bp.filePath, bp.lineNumber - 1); } void BreakpointView::initHeaderView() diff --git a/src/plugins/find/gui/searchresultwidget.cpp b/src/plugins/find/gui/searchresultwidget.cpp index eff00de54..2f54533ac 100644 --- a/src/plugins/find/gui/searchresultwidget.cpp +++ b/src/plugins/find/gui/searchresultwidget.cpp @@ -82,7 +82,7 @@ void SearchResultWidgetPrivate::openFile(const QModelIndex &index) if (!item) return; - editor.gotoPosition(item->filePathName, item->line, item->column); + editor.gotoPosition(item->filePathName, item->line - 1, item->column); } void SearchResultWidgetPrivate::handleMenuRequested(const QPoint &pos) diff --git a/src/plugins/symbol/mainframe/symbolkeeper.cpp b/src/plugins/symbol/mainframe/symbolkeeper.cpp index 3a578c2fe..71d8b9917 100644 --- a/src/plugins/symbol/mainframe/symbolkeeper.cpp +++ b/src/plugins/symbol/mainframe/symbolkeeper.cpp @@ -56,7 +56,7 @@ void SymbolKeeper::doParse(const SymbolParseArgs &args) void SymbolKeeper::jumpToLine(const QString &filePath, const QString &fileLine) { - editor.gotoLine(filePath, fileLine.toInt()); + editor.gotoLine(filePath, fileLine.toInt() - 1); } void SymbolKeeper::doParseDone(bool result) diff --git a/src/plugins/valgrind/mainframe/xmlstreamreader.cpp b/src/plugins/valgrind/mainframe/xmlstreamreader.cpp index 19f6815b7..d2db53c41 100644 --- a/src/plugins/valgrind/mainframe/xmlstreamreader.cpp +++ b/src/plugins/valgrind/mainframe/xmlstreamreader.cpp @@ -21,7 +21,7 @@ XmlStreamReader::XmlStreamReader(DTreeWidget *tree) if (toolTip.count() > 1) { QString filePath = toolTip.at(0); QString line = toolTip.at(1); - editor.gotoLine(filePath, line.toInt()); + editor.gotoLine(filePath, line.toInt() - 1); } }); } diff --git a/src/services/editor/editorservice.h b/src/services/editor/editorservice.h index 43a13a413..e05b19418 100644 --- a/src/services/editor/editorservice.h +++ b/src/services/editor/editorservice.h @@ -43,6 +43,7 @@ class EditorService final : public dpf::PluginService, DPF_INTERFACE(QString, currentFile); DPF_INTERFACE(QStringList, openedFiles); DPF_INTERFACE(QString, fileText, const QString &file); + DPF_INTERFACE(void, cursorPosition, int *line, int *index); DPF_INTERFACE(void, replaceAll, const QString &file, const QString &oldText, const QString &newText, bool caseSensitive, bool wholeWords); DPF_INTERFACE(void, replaceRange, const QString &file, int line, int index, int length, const QString &after); @@ -51,6 +52,14 @@ class EditorService final : public dpf::PluginService, DPF_INTERFACE(void, registerWidget, const QString &id, AbstractEditWidget *widget); DPF_INTERFACE(void, switchWidget, const QString &id); DPF_INTERFACE(void, switchDefaultWidget); + + // NOTE: Return the `marker` value, + // if the return value is -1, it indicates that the setting failed. + DPF_INTERFACE(int, setRangeBackgroundColor, const QString &file, int startLine, int endLine, const QColor &color); + DPF_INTERFACE(void, clearRangeBackgroundColor, const QString &file, int startLine, int endLine, int marker); + DPF_INTERFACE(void, clearAllBackgroundColor, const QString &file, int marker); + DPF_INTERFACE(void, showLineWidget, int line, QWidget *widget); + DPF_INTERFACE(void, closeLineWidget); }; } // namespace dpfservice