diff --git a/README.en.md b/README.en.md
index f47a5c8d8..8c6164fb3 100644
--- a/README.en.md
+++ b/README.en.md
@@ -45,6 +45,8 @@ _The **dev** branch is current development branch, build dependencies may change
## Installation
+ *If you install the IDE on Ubuntu by source code, please refer to the [DTK dependent installation](./docs/dtk-install-guide.en.md). After the installation of the dtk environment and the basic qt environment, you can install the IDE through the following source installation method.*
+
1. Make sure you have installed all dependencies.
``` shell
diff --git a/README.md b/README.md
index 5cc510a8c..8360c2b59 100644
--- a/README.md
+++ b/README.md
@@ -45,6 +45,8 @@ _当前的开发分支为**dev**,编译依赖可能会在没有更新本说明
## 安装
+ *如若在Ubuntu上使用源码安装方式安装IDE,请先参考[DTK依赖安装](./docs/dtk-install-guide.md),在DTK环境以及基本qt环境安装完成后,可通过下面源码安装的方式安装本IDE。*
+
1. 确保已经安装所有依赖库。
diff --git a/assets/configures/unioncode.desktop b/assets/configures/unioncode.desktop
index 7af2cb0f6..36ff17137 100644
--- a/assets/configures/unioncode.desktop
+++ b/assets/configures/unioncode.desktop
@@ -10,6 +10,6 @@ MimeType=text/plain;application/x-code-workspace;
Name=Deepin Union Code
Path=/usr/bin
StartupNotify=false
-StartupWMClass=Code
+StartupWMClass=UnionCode
Type=Application
X-Deepin-Vendor=user-custom
diff --git a/assets/translations/zh_CN.ts b/assets/translations/zh_CN.ts
index a20803da3..cdbb567d6 100644
--- a/assets/translations/zh_CN.ts
+++ b/assets/translations/zh_CN.ts
@@ -2668,7 +2668,7 @@ repos path: %0
Clear
- 清扫
+ 清除
diff --git a/docs/dtk-install-guide.en.md b/docs/dtk-install-guide.en.md
new file mode 100644
index 000000000..14b364b34
--- /dev/null
+++ b/docs/dtk-install-guide.en.md
@@ -0,0 +1,61 @@
+## DTK Dependency Installation
+
+For deepin-unioncode, the required dependency libraries include dtkcore, dtkwidget, dtkgui, and qt5integration, and this section describes the installation of these dependencies.
+
+### 1. Source Code Pull
+
+First you need to download the source code of the dtk dependency library in the [deepin github community](https://github.com/linuxdeepin):
+
+[dtkcore](https://github.com/linuxdeepin/dtkcore),[dtkwidget](https://github.com/linuxdeepin/dtkwidget),[dtkgui](https://github.com/linuxdeepin/dtkgui),[qt5integration](https://github.com/linuxdeepin/qt5integration)
+
+The dtkcore might rely on [dtkcommon](https://github.com/linuxdeepin/dtkcommon),qt5integration will depend on the [qt5platform-plugins](https://github.com/linuxdeepin/qt5platform-plugins)
+
+### 2. Environmental Installation
+
+First you need to install the qt environment and execute the following command
+
+```shell
+sudo apt update
+sudo apt install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools qttools5-dev qt5-private-dev
+```
+
+### 3. DTK Installation
+
+After the source code is pulled down, ensure that the required dependencies are properly installed and execute the following command in the directory location where the source code for each dependency library is located
+
+```shell
+sudo apt build-dep .
+```
+
+There are two ways to install dtk dependencies, one is the source code installation, and the second is the build-your-own-package installation. The source installation method is described in the README document of the respective dependent libraries, and will not be repeated here. This section describes how to install using a software package:
+
+In the source root of the respective dependent library, use the following command to package
+
+```shell
+dpkg-buildpackage -us -uc -b -j16
+```
+
+"-j16" Specifies the parameter for multi-core execution, which can be increased or decreased according to the number of processor cores and performance.
+
+The following errors may occur when installing dependent libraries:
+
+![image-20240605152527906](./dtk-install/error1.png)
+
+Cause: The dependent version failed to be properly packaged
+
+The solution:
+
+```shell
+vim debian/rules
+# Find "override_dh_shlibdeps:" in the opened file
+# Add "dh_shlibdeps -- dpkg-shlibdps-params =--ignore-missing-info"
+```
+
+![image-20240605153447864](./dtk-install/solution1.png)
+
+After all dependencies are successfully packaged, you can use the installation package to install the dependencies. After the installation, run commands to check whether the dependencies are successfully installed and whether their versions meet requirements.
+
+```shell
+apt policy libdtkcore5
+# Other dependencies are viewed in the same way
+```
diff --git a/docs/dtk-install-guide.md b/docs/dtk-install-guide.md
new file mode 100644
index 000000000..fec1861da
--- /dev/null
+++ b/docs/dtk-install-guide.md
@@ -0,0 +1,61 @@
+## DTK依赖安装
+
+对于Deepin-IDE,所需要的依赖库包括dtkcore,dtkwidget,dtkgui以及qt5integration,本部分介绍这几个依赖的安装。
+
+### 1. 源码拉取
+
+首先需要在深度的github社区中下载dtk依赖库的源码:
+
+[dtkcore](https://github.com/linuxdeepin/dtkcore),[dtkwidget](https://github.com/linuxdeepin/dtkwidget),[dtkgui](https://github.com/linuxdeepin/dtkgui),[qt5integration](https://github.com/linuxdeepin/qt5integration)
+
+其中,dtkcore可能会依赖[dtkcommon](https://github.com/linuxdeepin/dtkcommon),qt5integration会依赖[qt5platform-plugins](https://github.com/linuxdeepin/qt5platform-plugins)
+
+### 2. 环境安装
+
+首先需要安装qt环境,按照以下命令执行
+
+```shell
+sudo apt update
+sudo apt install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools qttools5-dev qt5-private-dev
+```
+
+### 3. 安装
+
+源码拉下来之后,确保所需依赖都已正确安装,在每个依赖库的源码所在的目录位置执行以下命令
+
+```shell
+sudo apt build-dep .
+```
+
+接下来有两种方式来安装dtk依赖,一种是源码安装方式,第二种是自己构建软件包安装方式。源码安装方式在对应的各自依赖库的README文档中有介绍,这里不再赘述。这里介绍使用软件包安装方式:
+
+在各自依赖库的源码根目录下,使用以下命令打包
+
+```shell
+dpkg-buildpackage -us -uc -b -j16
+```
+
+-j16为多核执行,可根据处理器核数和性能酌情增减。
+
+安装依赖库时可能会出现以下错误:
+
+![image-20240605152527906](./dtk-install/error1.png)
+
+原因:依赖的版本问题导致无法正常打包
+
+解决方法:
+
+```shell
+vim debian/rules
+# 在打开的文件中找到override_dh_shlibdeps:
+# 添加dh_shlibdeps --dpkg-shlibdeps-params=--ignore-missing-info
+```
+
+![image-20240605153447864](./dtk-install/solution1.png)
+
+在所有依赖都成功打包后,可直接使用安装包进行依赖的安装,安装完成后使用命令查看依赖是否安装成功,以及依赖的版本是否满足要求。
+
+```shell
+apt policy libdtkcore5
+# 其他依赖同理
+```
diff --git a/docs/dtk-install/error1.png b/docs/dtk-install/error1.png
new file mode 100644
index 000000000..a0fd086bc
Binary files /dev/null and b/docs/dtk-install/error1.png differ
diff --git a/docs/dtk-install/solution1.png b/docs/dtk-install/solution1.png
new file mode 100644
index 000000000..f27e3416a
Binary files /dev/null and b/docs/dtk-install/solution1.png differ
diff --git a/src/common/find/abstractdocumentfind.h b/src/common/find/abstractdocumentfind.h
index 5bcafbd01..a3af919dd 100644
--- a/src/common/find/abstractdocumentfind.h
+++ b/src/common/find/abstractdocumentfind.h
@@ -18,11 +18,11 @@ class AbstractDocumentFind : public QObject
virtual void findNext(const QString &txt) = 0;
virtual void findPrevious(const QString &txt) = 0;
- virtual void replace(const QString &before, const QString &after) {};
- virtual void replaceFind(const QString &before, const QString &after) {};
- virtual void replaceAll(const QString &before, const QString &after) {};
- virtual void findStringChanged() {};
- virtual bool supportsReplace() const { return true; };
+ virtual void replace(const QString &before, const QString &after) {}
+ virtual void replaceFind(const QString &before, const QString &after) {}
+ virtual void replaceAll(const QString &before, const QString &after) {}
+ virtual void findStringChanged() {}
+ virtual bool supportsReplace() const { return true; }
};
#endif // ABSTRACTDOCUMENTFIND_H
diff --git a/src/common/util/eventdefinitions.h b/src/common/util/eventdefinitions.h
index 9326b4b06..ebfa945ea 100644
--- a/src/common/util/eventdefinitions.h
+++ b/src/common/util/eventdefinitions.h
@@ -20,7 +20,7 @@ OPI_OBJECT(project,
OPI_INTERFACE(openProject, "kitName", "language", "workspace")
OPI_INTERFACE(activeProject, "kitName", "language", "workspace")
// out
- OPI_INTERFACE(activedProject, "projectInfo")
+ OPI_INTERFACE(activatedProject, "projectInfo")
OPI_INTERFACE(deletedProject, "projectInfo")
OPI_INTERFACE(createdProject, "projectInfo")
OPI_INTERFACE(projectUpdated, "projectInfo")
@@ -43,6 +43,7 @@ OPI_OBJECT(editor,
OPI_INTERFACE(back)
OPI_INTERFACE(forward)
OPI_INTERFACE(gotoLine, "fileName", "line")
+ OPI_INTERFACE(gotoPosition, "fileName", "line", "column")
// (AnnotationType)type
OPI_INTERFACE(addAnnotation, "fileName", "title", "content", "line", "type")
diff --git a/src/plugins/builder/mainframe/buildmanager.cpp b/src/plugins/builder/mainframe/buildmanager.cpp
index f51c716f3..e5c4730bf 100644
--- a/src/plugins/builder/mainframe/buildmanager.cpp
+++ b/src/plugins/builder/mainframe/buildmanager.cpp
@@ -395,13 +395,13 @@ void BuildManager::slotResetBuildUI()
uiController.switchContext(tr("&Build"));
}
-void BuildManager::setActivedProjectInfo(const QString &kitName, const QString &workingDir)
+void BuildManager::setActivatedProjectInfo(const QString &kitName, const QString &workingDir)
{
d->activedKitName = kitName;
d->activedWorkingDir = workingDir;
}
-void BuildManager::clearActivedProjectInfo()
+void BuildManager::clearActivatedProjectInfo()
{
d->activedKitName.clear();
d->activedWorkingDir.clear();
diff --git a/src/plugins/builder/mainframe/buildmanager.h b/src/plugins/builder/mainframe/buildmanager.h
index e48277c44..f3e01c514 100644
--- a/src/plugins/builder/mainframe/buildmanager.h
+++ b/src/plugins/builder/mainframe/buildmanager.h
@@ -33,8 +33,8 @@ class BuildManager : public QObject
ProblemOutputPane *getProblemOutputPane() const;
DTK_WIDGET_NAMESPACE::DWidget *getCompileWidget() const;
- void setActivedProjectInfo(const QString &kitName, const QString &workingDir);
- void clearActivedProjectInfo();
+ void setActivatedProjectInfo(const QString &kitName, const QString &workingDir);
+ void clearActivatedProjectInfo();
bool handleCommand(const QList &info, bool isSynchronous);
diff --git a/src/plugins/builder/transceiver/builderreceiver.cpp b/src/plugins/builder/transceiver/builderreceiver.cpp
index 164b93870..76c4245b1 100644
--- a/src/plugins/builder/transceiver/builderreceiver.cpp
+++ b/src/plugins/builder/transceiver/builderreceiver.cpp
@@ -25,18 +25,18 @@ QStringList BuilderReceiver::topics()
void BuilderReceiver::eventProcess(const dpf::Event &event)
{
- if (event.data() == project.activedProject.name) {
- QVariant proInfoVar = event.property(project.activedProject.pKeys[0]);
+ if (event.data() == project.activatedProject.name) {
+ QVariant proInfoVar = event.property(project.activatedProject.pKeys[0]);
dpfservice::ProjectInfo projectInfo = qvariant_cast(proInfoVar);
- BuildManager::instance()->setActivedProjectInfo(projectInfo.kitName(), projectInfo.workspaceFolder());
+ BuildManager::instance()->setActivatedProjectInfo(projectInfo.kitName(), projectInfo.workspaceFolder());
} else if (event.data() == project.createdProject.name) {
QVariant proInfoVar = event.property(project.createdProject.pKeys[0]);
dpfservice::ProjectInfo projectInfo = qvariant_cast(proInfoVar);
- BuildManager::instance()->setActivedProjectInfo(projectInfo.kitName(), projectInfo.workspaceFolder());
+ BuildManager::instance()->setActivatedProjectInfo(projectInfo.kitName(), projectInfo.workspaceFolder());
} else if (event.data() == project.deletedProject.name) {
QVariant proInfoVar = event.property(project.deletedProject.pKeys[0]);
dpfservice::ProjectInfo projectInfo = qvariant_cast(proInfoVar);
- BuildManager::instance()->clearActivedProjectInfo();
+ BuildManager::instance()->clearActivatedProjectInfo();
} else if (event.data() == symbol.parseDone.name) {
bool bSuccess = event.property("success").toBool();
if(!bSuccess) {
diff --git a/src/plugins/codeeditor/codeeditor.cpp b/src/plugins/codeeditor/codeeditor.cpp
index fc00894ec..2b9ca2f42 100644
--- a/src/plugins/codeeditor/codeeditor.cpp
+++ b/src/plugins/codeeditor/codeeditor.cpp
@@ -10,6 +10,7 @@
#include "gui/settings/editorsettingswidget.h"
#include "lexer/lexermanager.h"
#include "utils/editorutils.h"
+#include "status/statusinfomanager.h"
#include "base/abstractmenu.h"
#include "base/abstractaction.h"
@@ -166,6 +167,9 @@ void CodeEditor::initEditorService()
editorService->registerWidget = std::bind(&WorkspaceWidget::registerWidget, workspaceWidget, _1, _2);
editorService->switchWidget = std::bind(&WorkspaceWidget::switchWidget, workspaceWidget, _1);
editorService->switchDefaultWidget = std::bind(&WorkspaceWidget::switchDefaultWidget, workspaceWidget);
+ editorService->openedFiles = std::bind(&WorkspaceWidget::openedFiles, workspaceWidget);
+ editorService->fileText = std::bind(&WorkspaceWidget::fileText, workspaceWidget, _1);
+ editorService->replaceAll = std::bind(&WorkspaceWidget::replaceAll, workspaceWidget, _1, _2, _3, _4, _5);
LexerManager::instance()->init(editorService);
}
@@ -190,6 +194,8 @@ void CodeEditor::initWindowService()
windowService->addAction(MWM_FILE, new AbstractAction(sep));
windowService->addContextWidget(QTabWidget::tr("Search &Results"), new AbstractWidget(CodeLens::instance()), true);
+
+ StatusInfoManager::instance()->init(windowService);
}
}
diff --git a/src/plugins/codeeditor/find/editordocumentfind.cpp b/src/plugins/codeeditor/find/editordocumentfind.cpp
index 8a59e11e4..3735d016a 100644
--- a/src/plugins/codeeditor/find/editordocumentfind.cpp
+++ b/src/plugins/codeeditor/find/editordocumentfind.cpp
@@ -30,7 +30,8 @@ class EditorDocumentFindPrivate
void adjustFindStartPosition(TextEditor *editor);
void dealWithZeroFound(TextEditor *editor);
bool findStep(const QString &text, bool isForward);
- void doReplaceAll(TextEditor *editor, const QString &findText, const QString &replaceText);
+ void doReplaceAll(TextEditor *editor, const QString &findText,
+ const QString &replaceText, bool caseSensitive = false, bool wholeWords = false);
int buildSearchFlags(bool re, bool cs, bool wo, bool wrap, bool forward, FindNextType findNextType, bool posix, bool cxx11);
public:
@@ -115,13 +116,14 @@ bool EditorDocumentFindPrivate::findStep(const QString &text, bool isForward)
return ret;
}
-void EditorDocumentFindPrivate::doReplaceAll(TextEditor *editor, const QString &findText, const QString &replaceText)
+void EditorDocumentFindPrivate::doReplaceAll(TextEditor *editor, const QString &findText,
+ const QString &replaceText, bool caseSensitive, bool wholeWords)
{
int srcPosition = editor->cursorPosition();
int firstDisLineNum = editor->SendScintilla(TextEditor::SCI_GETFIRSTVISIBLELINE);
editor->beginUndoAction();
- int flags = buildSearchFlags(false, false, false, false, true, FINDNEXTTYPE_REPLACENEXT, 0, 0);
+ int flags = buildSearchFlags(false, caseSensitive, wholeWords, false, true, FINDNEXTTYPE_REPLACENEXT, 0, 0);
editor->SendScintilla(TextEditor::SCI_SETSEARCHFLAGS, flags);
FindReplaceInfo findReplaceInfo;
@@ -266,3 +268,16 @@ void EditorDocumentFind::findStringChanged()
{
d->isFindFirst = true;
}
+
+void EditorDocumentFind::replaceAll(TextEditor *editor, const QString &before,
+ const QString &after, bool caseSensitive, bool wholeWords)
+{
+ if (before.isEmpty())
+ return;
+
+ if (!editor || editor->isReadOnly())
+ return;
+
+ d->doReplaceAll(editor, before, after, caseSensitive, wholeWords);
+ d->isFindFirst = true;
+}
diff --git a/src/plugins/codeeditor/find/editordocumentfind.h b/src/plugins/codeeditor/find/editordocumentfind.h
index 5ebf71e7a..ac31937cf 100644
--- a/src/plugins/codeeditor/find/editordocumentfind.h
+++ b/src/plugins/codeeditor/find/editordocumentfind.h
@@ -7,6 +7,7 @@
#include "common/find/abstractdocumentfind.h"
+class TextEditor;
class EditorDocumentFindPrivate;
class EditorDocumentFind : public AbstractDocumentFind
{
@@ -22,8 +23,11 @@ class EditorDocumentFind : public AbstractDocumentFind
virtual void replaceAll(const QString &before, const QString &after) override;
virtual void findStringChanged() override;
+ void replaceAll(TextEditor *editor, const QString &before,
+ const QString &after, bool caseSensitive, bool wholeWords);
+
private:
EditorDocumentFindPrivate *const d;
};
-#endif // EDITORDOCUMENTFIND_H
+#endif // EDITORDOCUMENTFIND_H
diff --git a/src/plugins/codeeditor/gui/private/tabwidget_p.h b/src/plugins/codeeditor/gui/private/tabwidget_p.h
index f772fb0d4..1de89cb41 100644
--- a/src/plugins/codeeditor/gui/private/tabwidget_p.h
+++ b/src/plugins/codeeditor/gui/private/tabwidget_p.h
@@ -8,6 +8,8 @@
#include "gui/tabwidget.h"
#include "gui/tabbar.h"
#include "gui/texteditor.h"
+#include "gui/recent/recentopenwidget.h"
+#include "find/editordocumentfind.h"
#include "common/util/eventdefinitions.h"
@@ -70,6 +72,10 @@ public slots:
PosRecord curPosRecord;
QList prePosRecord;
QList nextPosRecord;
+
+ QVector recentOpenedFiles;
+ RecentOpenWidget *openedWidget { nullptr };
+ EditorDocumentFind *docFind { nullptr };
};
#endif // TABWIDGET_P_H
diff --git a/src/plugins/codeeditor/gui/private/workspacewidget_p.h b/src/plugins/codeeditor/gui/private/workspacewidget_p.h
index dc44f17c9..559e32fee 100644
--- a/src/plugins/codeeditor/gui/private/workspacewidget_p.h
+++ b/src/plugins/codeeditor/gui/private/workspacewidget_p.h
@@ -62,6 +62,7 @@ public slots:
void handleRenameSymbol();
void handleSetModifiedAutoReload(const QString &fileName, bool flag);
void handleSetComment();
+ void handleShowOpenedFiles();
public:
WorkspaceWidget *q;
diff --git a/src/plugins/codeeditor/gui/recent/recentopenlistdelegate.cpp b/src/plugins/codeeditor/gui/recent/recentopenlistdelegate.cpp
new file mode 100644
index 000000000..f444a2155
--- /dev/null
+++ b/src/plugins/codeeditor/gui/recent/recentopenlistdelegate.cpp
@@ -0,0 +1,59 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "recentopenlistdelegate.h"
+
+#include
+
+#include
+#include
+
+DWIDGET_USE_NAMESPACE
+
+RecentOpenListDelegate::RecentOpenListDelegate(QAbstractItemView *parent) :
+ QStyledItemDelegate(parent)
+{
+}
+
+void RecentOpenListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ painter->setRenderHint(QPainter::Antialiasing);
+ painter->save();
+ if (option.widget) {
+ DPalette pl = DGuiApplicationHelper::instance()->applicationPalette();
+ QColor baseColor = pl.color(DPalette::ColorGroup::Active, DPalette::ColorType::ItemBackground);
+ QColor adjustColor = baseColor;
+
+ bool isSelected = (option.state & QStyle::State_Selected) && option.showDecorationSelected;
+
+ if (isSelected) {
+ adjustColor = option.palette.color(DPalette::ColorGroup::Active, QPalette::Highlight);
+ } else if (option.state & QStyle::StateFlag::State_MouseOver) {
+ // hover color
+ adjustColor = DGuiApplicationHelper::adjustColor(baseColor, 0, 0, 0, 0, 0, 0, +10);
+ } else {
+ // alternately background color
+ painter->setOpacity(0);
+ if (index.row() % 2 == 0) {
+ adjustColor = DGuiApplicationHelper::adjustColor(baseColor, 0, 0, 0, 0, 0, 0, +5);
+ painter->setOpacity(1);
+ }
+ }
+
+ // set paint path
+ QPainterPath path;
+ path.addRoundedRect(option.rect, 8, 8);
+ painter->fillPath(path, adjustColor);
+ }
+ painter->restore();
+ QStyledItemDelegate::paint(painter, option, index);
+}
+
+QSize RecentOpenListDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ QSize s;
+ s.setWidth(option.rect.width());
+ s.setHeight(30);
+ return s;
+}
diff --git a/src/plugins/codeeditor/gui/recent/recentopenlistdelegate.h b/src/plugins/codeeditor/gui/recent/recentopenlistdelegate.h
new file mode 100644
index 000000000..b7e4ba0f2
--- /dev/null
+++ b/src/plugins/codeeditor/gui/recent/recentopenlistdelegate.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RECENTOPENLISTDELEGATE_H
+#define RECENTOPENLISTDELEGATE_H
+
+#include
+#include
+
+#include
+#include
+
+class RecentOpenListDelegate : public QStyledItemDelegate
+{
+ Q_OBJECT
+public:
+ explicit RecentOpenListDelegate(QAbstractItemView *parent = nullptr);
+
+protected:
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
+ QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
+};
+
+#endif // RECENTOPENLISTDELEGATE_H
diff --git a/src/plugins/codeeditor/gui/recent/recentopenlistview.cpp b/src/plugins/codeeditor/gui/recent/recentopenlistview.cpp
new file mode 100644
index 000000000..ea03166be
--- /dev/null
+++ b/src/plugins/codeeditor/gui/recent/recentopenlistview.cpp
@@ -0,0 +1,33 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "recentopenlistview.h"
+
+#include
+
+RecentOpenListView::RecentOpenListView(QWidget *parent)
+ : DListView(parent)
+{
+}
+
+RecentOpenListView::~RecentOpenListView()
+{
+}
+
+void RecentOpenListView::keyPressEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Tab) {
+ QModelIndex currentIndex = this->currentIndex();
+ if (currentIndex.isValid()) {
+ QModelIndex nextIndex = model()->index(currentIndex.row() + 1, currentIndex.column(), currentIndex.parent());
+ if (nextIndex.isValid()) {
+ setCurrentIndex(nextIndex);
+ } else {
+ setCurrentIndex(model()->index(0, 0));
+ }
+ }
+ } else {
+ DListView::keyPressEvent(event);
+ }
+}
diff --git a/src/plugins/codeeditor/gui/recent/recentopenlistview.h b/src/plugins/codeeditor/gui/recent/recentopenlistview.h
new file mode 100644
index 000000000..7d82e5db0
--- /dev/null
+++ b/src/plugins/codeeditor/gui/recent/recentopenlistview.h
@@ -0,0 +1,21 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RECENTOPENLISTVIEW_H
+#define RECENTOPENLISTVIEW_H
+
+#include
+
+class RecentOpenListView : public Dtk::Widget::DListView
+{
+ Q_OBJECT
+public:
+ explicit RecentOpenListView(QWidget *parent = nullptr);
+ ~RecentOpenListView();
+
+protected:
+ void keyPressEvent(QKeyEvent *event) override;
+};
+
+#endif // RECENTOPENLISTVIEW_H
diff --git a/src/plugins/codeeditor/gui/recent/recentopenwidget.cpp b/src/plugins/codeeditor/gui/recent/recentopenwidget.cpp
new file mode 100644
index 000000000..acceb3f78
--- /dev/null
+++ b/src/plugins/codeeditor/gui/recent/recentopenwidget.cpp
@@ -0,0 +1,112 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "recentopenwidget.h"
+#include "common/util/customicons.h"
+
+#include
+
+#include
+#include
+#include
+
+DWIDGET_USE_NAMESPACE
+
+RecentOpenWidget::RecentOpenWidget(QWidget *parent)
+ : DFrame(parent)
+{
+ initUI();
+}
+
+RecentOpenWidget::~RecentOpenWidget()
+{
+}
+
+void RecentOpenWidget::keyReleaseEvent(QKeyEvent *event)
+{
+ if (event->key() == Qt::Key_Control) {
+ if (this->listView->selectionModel()->hasSelection()) {
+ this->triggered(listView->selectionModel()->selectedIndexes()[0]);
+ this->close();
+ }
+ }
+ DFrame::keyReleaseEvent(event);
+}
+
+void RecentOpenWidget::initUI()
+{
+ QHBoxLayout *mainLayout = new QHBoxLayout();
+
+ listView = new RecentOpenListView(this);
+ listView->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ listView->setLineWidth(0);
+ listView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ delegate = new RecentOpenListDelegate(listView);
+ listView->setItemDelegate(delegate);
+ listView->setSelectionMode(QAbstractItemView::SingleSelection);
+
+ model = new QStandardItemModel(this);
+ listView->setModel(model);
+
+ connect(listView, &RecentOpenListView::clicked, this, &RecentOpenWidget::triggered);
+
+ mainLayout->addWidget(listView);
+ mainLayout->setContentsMargins(10, 10, 10, 0);
+ this->setLineWidth(0);
+ this->setLayout(mainLayout);
+ this->setMinimumSize(400, 265);
+ DStyle::setFrameRadius(this, 16);
+}
+
+void RecentOpenWidget::setOpenedFiles(const QVector &list)
+{
+ model->clear();
+ QSet fileNamesSet;
+
+ for (const QString &absolutePath : list) {
+ QFileInfo info(absolutePath);
+ QString fileName = info.fileName();
+ QStandardItem *item = new QStandardItem(fileName);
+ item->setData(absolutePath, RecentOpenedUserRole::FilePathRole);
+ item->setIcon(CustomIcons::icon(info));
+ model->appendRow(item);
+ }
+
+ for (int i = 0; i < model->rowCount(); ++i) {
+ QStandardItem *item = model->item(i);
+ QString fileName = item->text();
+ if (fileNamesSet.contains(fileName)) {
+ for (int j = 0; j < model->rowCount(); ++j) {
+ QStandardItem *nextItem = model->item(j);
+ if (nextItem->text() == fileName) {
+ QString dirName = QFileInfo(nextItem->data(RecentOpenedUserRole::FilePathRole).toString()).absolutePath();
+ dirName = dirName.mid(dirName.lastIndexOf('/') + 1);
+ QString newName = dirName + "/" + fileName;
+ nextItem->setText(newName);
+ }
+ }
+ } else {
+ fileNamesSet.insert(fileName);
+ }
+ }
+}
+
+void RecentOpenWidget::setListViewSelection(int num)
+{
+ if (num < 0 || !listView || !listView->model()) {
+ return;
+ }
+
+ int rowCount = listView->model()->rowCount();
+
+ if (num >= rowCount) {
+ return;
+ }
+ listView->setCurrentIndex(listView->model()->index(num, 0));
+}
+
+void RecentOpenWidget::setFocusListView()
+{
+ listView->setFocus();
+}
diff --git a/src/plugins/codeeditor/gui/recent/recentopenwidget.h b/src/plugins/codeeditor/gui/recent/recentopenwidget.h
new file mode 100644
index 000000000..c65d1df08
--- /dev/null
+++ b/src/plugins/codeeditor/gui/recent/recentopenwidget.h
@@ -0,0 +1,44 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RECENTOPENWIDGET_H
+#define RECENTOPENWIDGET_H
+
+#include "recentopenlistview.h"
+#include "recentopenlistdelegate.h"
+
+#include
+
+#include
+#include
+
+class RecentOpenWidget : public Dtk::Widget::DFrame
+{
+ Q_OBJECT
+
+public:
+ enum RecentOpenedUserRole{
+ FilePathRole = Qt::UserRole + 1
+ };
+ explicit RecentOpenWidget(QWidget *parent = nullptr);
+ ~RecentOpenWidget();
+
+ void initUI();
+ void setOpenedFiles(const QVector &list);
+ void setListViewSelection(int index);
+ void setFocusListView();
+
+signals:
+ void triggered(const QModelIndex &index);
+
+protected:
+ void keyReleaseEvent(QKeyEvent *event) override;
+
+private:
+ RecentOpenListView *listView = nullptr;
+ QStandardItemModel *model = nullptr;
+ RecentOpenListDelegate *delegate = nullptr;
+};
+
+#endif // RECENTOPENWIDGET_H
diff --git a/src/plugins/codeeditor/gui/tabbar.cpp b/src/plugins/codeeditor/gui/tabbar.cpp
index bdc93d474..bcf67ec3d 100644
--- a/src/plugins/codeeditor/gui/tabbar.cpp
+++ b/src/plugins/codeeditor/gui/tabbar.cpp
@@ -5,10 +5,10 @@
#include "tabbar.h"
#include "private/tabbar_p.h"
-#include "common/common.h"
-#include "services/editor/editorservice.h"
+#include "common/util/eventdefinitions.h"
#include
+#include
#include
#include
@@ -201,20 +201,25 @@ void TabBar::removeTab(const QString &fileName)
QString text = d->tabBar->tabText(index);
QFileInfo info(fileName);
if (info.exists() && text.length() > 0 && text.at(0) == "*") {
- int ret = QMessageBox::question(this, QMessageBox::tr("Save Changes"),
- QMessageBox::tr("The file has unsaved changes, will save?"),
- QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
- QMessageBox::Cancel);
- if (QMessageBox::Yes != ret && QMessageBox::No != ret) {
- return;
- } else if (QMessageBox::Yes == ret) {
+ DDialog dialog(this);
+ dialog.setWindowTitle(tr("Save Changes"));
+ dialog.setIcon(QIcon::fromTheme("dialog-warning"));
+ dialog.setMessage(tr("The file has unsaved changes, will save?"));
+ dialog.addButton(tr("Save", "button"), true, DDialog::ButtonRecommend);
+ dialog.addButton(tr("Do Not Save", "button"));
+ dialog.addButton(tr("Cancel"), "button");
+
+ int ret = dialog.exec();
+ if (ret == 0) // save
emit saveFileRequested(fileName);
- }
+ else if (ret == 2 || ret == -1) // cancel or close
+ return;
}
emit tabClosed(fileName);
editor.fileClosed(fileName);
d->tabBar->removeTab(index);
+ editor.switchedFile(this->currentFileName());
}
void TabBar::setCloseButtonVisible(bool visible)
diff --git a/src/plugins/codeeditor/gui/tabwidget.cpp b/src/plugins/codeeditor/gui/tabwidget.cpp
index 3e21484d4..132ecbfac 100644
--- a/src/plugins/codeeditor/gui/tabwidget.cpp
+++ b/src/plugins/codeeditor/gui/tabwidget.cpp
@@ -5,10 +5,10 @@
#include "tabwidget.h"
#include "private/tabwidget_p.h"
#include "transceiver/codeeditorreceiver.h"
-#include "find/editordocumentfind.h"
#include "common/common.h"
#include "settings/settingsdefine.h"
#include "base/abstractaction.h"
+#include "recent/recentopenwidget.h"
#include "services/window/windowservice.h"
@@ -124,6 +124,9 @@ void TabWidgetPrivate::initUI()
mainLayout->addWidget(tabBar, 0, Qt::AlignTop);
mainLayout->addLayout(editorLayout);
+ openedWidget = new RecentOpenWidget(q);
+ openedWidget->hide();
+
auto holder = createFindPlaceHolder();
if (holder)
mainLayout->addWidget(holder);
@@ -135,6 +138,7 @@ void TabWidgetPrivate::initConnection()
connect(tabBar, &TabBar::tabClosed, this, &TabWidgetPrivate::onTabClosed);
connect(tabBar, &TabBar::spliterClicked, this, &TabWidgetPrivate::onSpliterClicked);
connect(tabBar, &TabBar::closeRequested, q, &TabWidget::closeRequested);
+ connect(tabBar, &TabBar::saveFileRequested, q, &TabWidget::saveFile);
connect(EditorCallProxy::instance(), &EditorCallProxy::reqAddAnnotation, this, &TabWidgetPrivate::handleAddAnnotation);
connect(EditorCallProxy::instance(), &EditorCallProxy::reqRemoveAnnotation, this, &TabWidgetPrivate::handleRemoveAnnotation);
@@ -151,6 +155,28 @@ void TabWidget::handleSetComment()
editor->commentOperation();
}
+void TabWidget::handleShowOpenedFiles(const int &x, const int &y, const QSize &size)
+{
+ int count = d->tabBar->tabCount();
+ if (count < 2)
+ return;
+
+ d->openedWidget->setWindowFlags(Qt::Popup);
+ QSize popupSize = d->openedWidget->size();
+
+ int posX = (size.width() - popupSize.width()) / 2 + x;
+ int posY = (size.height() - popupSize.height()) / 2 + y;
+
+ d->openedWidget->move(posX, posY);
+ d->openedWidget->setOpenedFiles(d->recentOpenedFiles);
+ d->openedWidget->setListViewSelection(1);
+ connect(d->openedWidget, &RecentOpenWidget::triggered, this, [=](const QModelIndex &index) {
+ d->tabBar->setCurrentIndex(d->tabBar->indexOf(index.data(RecentOpenWidget::RecentOpenedUserRole::FilePathRole).toString()));
+ });
+ d->openedWidget->show();
+ d->openedWidget->setFocusListView();
+}
+
QWidget *TabWidgetPrivate::createSpaceWidget()
{
QWidget *widget = new QWidget(q);
@@ -191,12 +217,12 @@ QWidget *TabWidgetPrivate::createSpaceWidget()
QWidget *TabWidgetPrivate::createFindPlaceHolder()
{
+ docFind = new EditorDocumentFind(q);
auto &ctx = dpfInstance.serviceContext();
WindowService *windowService = ctx.service(WindowService::name());
if (!windowService)
return nullptr;
- auto docFind = new EditorDocumentFind(q);
return windowService->createFindPlaceHolder(q, docFind);
}
@@ -220,6 +246,7 @@ TextEditor *TabWidgetPrivate::createEditor(const QString &fileName)
});
editorMng.insert(fileName, editor);
+ recentOpenedFiles.prepend(fileName);
return editor;
}
@@ -333,6 +360,8 @@ void TabWidgetPrivate::onTabSwitched(const QString &fileName)
return;
editorLayout->setCurrentWidget(editorMng[fileName]);
+ recentOpenedFiles.removeOne(fileName);
+ recentOpenedFiles.prepend(fileName);
changeFocusProxy();
}
@@ -345,6 +374,7 @@ void TabWidgetPrivate::onTabClosed(const QString &fileName)
Inotify::globalInstance()->removePath(fileName);
removePositionRecord(fileName);
editorMng.remove(fileName);
+ recentOpenedFiles.removeOne(fileName);
editorLayout->removeWidget(editor);
changeFocusProxy();
@@ -563,6 +593,24 @@ void TabWidget::setText(const QString &text)
}
}
+QString TabWidget::fileText(const QString &fileName, bool *success)
+{
+ if (auto editor = d->findEditor(fileName)) {
+ if (success) *success = true;
+ return editor->text();
+ }
+
+ if (success) *success = false;
+ return {};
+}
+
+void TabWidget::replaceAll(const QString &fileName, const QString &oldText,
+ const QString &newText, bool caseSensitive, bool wholeWords)
+{
+ if (auto editor = d->findEditor(fileName))
+ d->docFind->replaceAll(editor, oldText, newText, caseSensitive, wholeWords);
+}
+
void TabWidget::saveAll() const
{
for (auto editor : d->editorMng.values())
@@ -872,6 +920,12 @@ void TabWidget::gotoPosition(int line, int column)
editor->gotoPosition(editor->positionFromLineIndex(line, column));
}
+void TabWidget::saveFile(const QString &fileName)
+{
+ if (auto editor = d->findEditor(fileName))
+ editor->save();
+}
+
void TabWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (!event->mimeData()->hasUrls())
diff --git a/src/plugins/codeeditor/gui/tabwidget.h b/src/plugins/codeeditor/gui/tabwidget.h
index 7936a3a01..6565fda98 100644
--- a/src/plugins/codeeditor/gui/tabwidget.h
+++ b/src/plugins/codeeditor/gui/tabwidget.h
@@ -25,6 +25,9 @@ class TabWidget : public QWidget
QStringList modifiedFiles() const;
QStringList openedFiles() const;
void setText(const QString &text);
+ QString fileText(const QString &fileName, bool *success = nullptr);
+ void replaceAll(const QString &fileName, const QString &oldText,
+ const QString &newText, bool caseSensitive, bool wholeWords);
void saveAll() const;
bool saveAs(const QString &from, const QString &to);
void reloadFile(const QString &fileName);
@@ -55,6 +58,7 @@ class TabWidget : public QWidget
void toggleBreakpoint();
void clearAllBreakpoints();
void handleSetComment();
+ void handleShowOpenedFiles(const int &x, const int &y, const QSize &size);
int zoomValue();
void updateZoomValue(int value);
@@ -67,7 +71,8 @@ public slots:
void removeDebugLine();
void gotoLine(int line);
void gotoPosition(int line, int column);
-
+ void saveFile(const QString &fileName);
+
signals:
void closeRequested();
void splitRequested(Qt::Orientation ori, const QString &fileName);
diff --git a/src/plugins/codeeditor/gui/workspacewidget.cpp b/src/plugins/codeeditor/gui/workspacewidget.cpp
index 247dde2fc..5997d1659 100644
--- a/src/plugins/codeeditor/gui/workspacewidget.cpp
+++ b/src/plugins/codeeditor/gui/workspacewidget.cpp
@@ -63,14 +63,23 @@ void WorkspaceWidgetPrivate::initActions()
if (!windowService)
return;
+ // add/del comment
QAction *commentAction = new QAction(tr("Add/Delete Comment"), q);
auto abstractCommentAction = new AbstractAction(commentAction, q);
abstractCommentAction->setShortCutInfo("Editor.addAndRemoveComment",
tr("Add/Remove Comment"), QKeySequence(Qt::Modifier::CTRL | Qt::Key_Slash));
-
windowService->addAction(tr("&Add/Remove Comment"), abstractCommentAction);
connect(commentAction, &QAction::triggered, this, &WorkspaceWidgetPrivate::handleSetComment);
+
+ // show opened files
+ QAction *showOpenedAction = new QAction(tr("Show opened files"), q);
+
+ auto abstractShowOpenedAction = new AbstractAction(showOpenedAction, q);
+ abstractShowOpenedAction->setShortCutInfo("Editor.showOpened",
+ tr("Show opened files"), QKeySequence(Qt::CTRL | Qt::Key_Tab));
+ windowService->addAction(tr("&Show open files"), abstractShowOpenedAction);
+ connect(showOpenedAction, &QAction::triggered, this, &WorkspaceWidgetPrivate::handleShowOpenedFiles);
}
void WorkspaceWidgetPrivate::handleSetComment()
@@ -81,6 +90,14 @@ void WorkspaceWidgetPrivate::handleSetComment()
currentTabWidget()->handleSetComment();
}
+void WorkspaceWidgetPrivate::handleShowOpenedFiles()
+{
+ if (!currentTabWidget())
+ return;
+
+ currentTabWidget()->handleShowOpenedFiles(q->pos().x() - q->mapFromGlobal(q->pos()).x(), q->pos().y() + q->mapToGlobal(q->pos()).y() - 100, q->size());
+}
+
void WorkspaceWidgetPrivate::initConnection()
{
connect(&fileCheckTimer, &QTimer::timeout, this, &WorkspaceWidgetPrivate::checkFileState);
@@ -338,6 +355,11 @@ void WorkspaceWidgetPrivate::onCloseRequested()
tabWidgetList.removeOne(tabWidget);
tabWidget->deleteLater();
+ if (!tabWidgetList.isEmpty()) {
+ tabWidgetList.last()->setFocus();
+ editor.switchedFile(tabWidgetList.last()->currentFile());
+ }
+
if (tabWidgetList.size() == 1)
tabWidgetList.first()->setCloseButtonVisible(false);
}
@@ -497,6 +519,8 @@ void WorkspaceWidgetPrivate::onFocusChanged(QWidget *old, QWidget *now)
return;
focusTabWidget = tabWidget;
+ editor.switchedFile(focusTabWidget->currentFile());
+
}
void WorkspaceWidgetPrivate::onZoomValueChanged()
@@ -708,6 +732,37 @@ void WorkspaceWidget::closeFileEditor(const QString &fileName)
tabWidget->closeFileEditor(fileName);
}
+QStringList WorkspaceWidget::openedFiles() const
+{
+ QStringList files;
+ for (auto tabWidget : d->tabWidgetList)
+ files << tabWidget->openedFiles();
+
+ // Delete duplicates
+ auto tmp = files.toSet();
+ return tmp.toList();
+}
+
+QString WorkspaceWidget::fileText(const QString &fileName) const
+{
+ for (auto tabWidget : d->tabWidgetList) {
+ bool success = false;
+ const auto &text = tabWidget->fileText(fileName, &success);
+ if (success)
+ return text;
+ }
+
+ return {};
+}
+
+void WorkspaceWidget::replaceAll(const QString &fileName, const QString &oldText,
+ const QString &newText, bool caseSensitive, bool wholeWords)
+{
+ for (auto tabWidget : d->tabWidgetList) {
+ tabWidget->replaceAll(fileName, oldText, newText, caseSensitive, wholeWords);
+ }
+}
+
void WorkspaceWidget::registerWidget(const QString &id, AbstractEditWidget *widget)
{
d->registeredWidget.insert(id, widget);
diff --git a/src/plugins/codeeditor/gui/workspacewidget.h b/src/plugins/codeeditor/gui/workspacewidget.h
index ef1c2da5b..29859f501 100644
--- a/src/plugins/codeeditor/gui/workspacewidget.h
+++ b/src/plugins/codeeditor/gui/workspacewidget.h
@@ -33,6 +33,9 @@ class WorkspaceWidget : public QWidget
void reloadFile(const QString &fileName);
void setFileModified(const QString &fileName, bool isModified);
void closeFileEditor(const QString &fileName);
+ QStringList openedFiles() const;
+ QString fileText(const QString &fileName) const;
+ void replaceAll(const QString &fileName, const QString &oldText, const QString &newText, bool caseSensitive, bool wholeWords);
void registerWidget(const QString &id, AbstractEditWidget *widget);
void switchWidget(const QString &id);
diff --git a/src/plugins/codeeditor/lexer/lexermanager.cpp b/src/plugins/codeeditor/lexer/lexermanager.cpp
index 4d533d550..ea8d8a146 100644
--- a/src/plugins/codeeditor/lexer/lexermanager.cpp
+++ b/src/plugins/codeeditor/lexer/lexermanager.cpp
@@ -86,8 +86,6 @@ QsciLexer *LexerManager::defaultSciLexer(const QString &language)
lexer = new QsciLexerPython();
} else if (language.compare("js", Qt::CaseInsensitive) == 0) {
lexer = new QsciLexerJavaScript();
- } else {
- lexer = new QsciLexerCPP();
}
// The `lexer` is structured by `TextEditor`
diff --git a/src/plugins/codeeditor/status/editorlabel.cpp b/src/plugins/codeeditor/status/editorlabel.cpp
new file mode 100644
index 000000000..ba4018297
--- /dev/null
+++ b/src/plugins/codeeditor/status/editorlabel.cpp
@@ -0,0 +1,24 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "editorlabel.h"
+
+#include
+#include
+
+EditorLabel::EditorLabel(QWidget *parent)
+ : QWidget(parent)
+{
+ QHBoxLayout *layout = new QHBoxLayout(this);
+ layout->setContentsMargins(0, 0, 0, 0);
+
+ cursorlabel = new QLabel(this);
+ layout->addWidget(cursorlabel);
+}
+
+void EditorLabel::updateCursor(int line, int column)
+{
+ QString format(tr("Line %1 Column %2"));
+ cursorlabel->setText(format.arg(line + 1).arg(column + 1));
+}
diff --git a/src/plugins/codeeditor/status/editorlabel.h b/src/plugins/codeeditor/status/editorlabel.h
new file mode 100644
index 000000000..bb890e8af
--- /dev/null
+++ b/src/plugins/codeeditor/status/editorlabel.h
@@ -0,0 +1,25 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef EDITORLABEL_H
+#define EDITORLABEL_H
+
+#include
+
+class QLabel;
+
+class EditorLabel : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit EditorLabel(QWidget *parent = nullptr);
+
+public Q_SLOTS:
+ void updateCursor(int line, int column);
+
+private:
+ QLabel *cursorlabel { nullptr };
+};
+
+#endif // EDITORLABEL_H
diff --git a/src/plugins/codeeditor/status/statusinfomanager.cpp b/src/plugins/codeeditor/status/statusinfomanager.cpp
new file mode 100644
index 000000000..00b17b312
--- /dev/null
+++ b/src/plugins/codeeditor/status/statusinfomanager.cpp
@@ -0,0 +1,93 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "statusinfomanager.h"
+#include "editorlabel.h"
+#include "gui/texteditor.h"
+
+#include "services/window/windowservice.h"
+
+#include
+
+using namespace dpfservice;
+
+class StatusInfoManagerPrivate : public QObject
+{
+public:
+ void init(WindowService *winSrv);
+ void initConnect();
+
+ void resetEditor(TextEditor *edit);
+ void updateLabelInfo();
+ void handleFocusChanged(QWidget *old, QWidget *now);
+
+public:
+ TextEditor *currentEditor { nullptr };
+ EditorLabel *editorLabel { nullptr };
+};
+
+void StatusInfoManagerPrivate::init(WindowService *winSrv)
+{
+ editorLabel = new EditorLabel();
+ winSrv->addStatusBarItem(editorLabel);
+}
+
+void StatusInfoManagerPrivate::initConnect()
+{
+ connect(qApp, &QApplication::focusChanged, this, &StatusInfoManagerPrivate::handleFocusChanged);
+}
+
+void StatusInfoManagerPrivate::resetEditor(TextEditor *edit)
+{
+ if (currentEditor == edit)
+ return;
+
+ if (currentEditor)
+ disconnect(currentEditor, &TextEditor::cursorPositionChanged, editorLabel, &EditorLabel::updateCursor);
+
+ currentEditor = edit;
+ connect(currentEditor, &TextEditor::cursorPositionChanged, editorLabel, &EditorLabel::updateCursor);
+ updateLabelInfo();
+}
+
+void StatusInfoManagerPrivate::updateLabelInfo()
+{
+ int line = 0, col = 0;
+ currentEditor->getCursorPosition(&line, &col);
+ editorLabel->updateCursor(line, col);
+}
+
+void StatusInfoManagerPrivate::handleFocusChanged(QWidget *old, QWidget *now)
+{
+ Q_UNUSED(old)
+
+ auto edit = qobject_cast(now);
+ if (!edit)
+ return;
+
+ resetEditor(edit);
+}
+
+StatusInfoManager::StatusInfoManager(QObject *parent)
+ : QObject(parent),
+ d(new StatusInfoManagerPrivate)
+{
+}
+
+StatusInfoManager::~StatusInfoManager()
+{
+ delete d;
+}
+
+StatusInfoManager *StatusInfoManager::instance()
+{
+ static StatusInfoManager ins;
+ return &ins;
+}
+
+void StatusInfoManager::init(WindowService *winSrv)
+{
+ d->init(winSrv);
+ d->initConnect();
+}
diff --git a/src/plugins/codeeditor/status/statusinfomanager.h b/src/plugins/codeeditor/status/statusinfomanager.h
new file mode 100644
index 000000000..a6ff093cd
--- /dev/null
+++ b/src/plugins/codeeditor/status/statusinfomanager.h
@@ -0,0 +1,30 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef STATUSINFOMANAGER_H
+#define STATUSINFOMANAGER_H
+
+#include
+
+namespace dpfservice {
+class WindowService;
+}
+
+class StatusInfoManagerPrivate;
+class StatusInfoManager : public QObject
+{
+ Q_OBJECT
+public:
+ static StatusInfoManager *instance();
+
+ void init(dpfservice::WindowService *winSrv);
+
+private:
+ explicit StatusInfoManager(QObject *parent = nullptr);
+ ~StatusInfoManager();
+
+ StatusInfoManagerPrivate *const d;
+};
+
+#endif // STATUSINFOMANAGER_H
diff --git a/src/plugins/codeeditor/transceiver/codeeditorreceiver.cpp b/src/plugins/codeeditor/transceiver/codeeditorreceiver.cpp
index be501f611..9a9140f81 100644
--- a/src/plugins/codeeditor/transceiver/codeeditorreceiver.cpp
+++ b/src/plugins/codeeditor/transceiver/codeeditorreceiver.cpp
@@ -4,8 +4,6 @@
#include "codeeditorreceiver.h"
-#include "common/common.h"
-#include "services/project/projectservice.h"
#include "services/window/windowelement.h"
#include "mainframe/texteditkeeper.h"
@@ -18,6 +16,7 @@ CodeEditorReceiver::CodeEditorReceiver(QObject *parent)
eventHandleMap.insert(editor.back.name, std::bind(&CodeEditorReceiver::processBackEvent, this, _1));
eventHandleMap.insert(editor.forward.name, std::bind(&CodeEditorReceiver::processForwardEvent, this, _1));
eventHandleMap.insert(editor.gotoLine.name, std::bind(&CodeEditorReceiver::processGotoLineEvent, this, _1));
+ eventHandleMap.insert(editor.gotoPosition.name, std::bind(&CodeEditorReceiver::processGotoPositionEvent, this, _1));
eventHandleMap.insert(editor.addAnnotation.name, std::bind(&CodeEditorReceiver::processAddAnnotationEvent, this, _1));
eventHandleMap.insert(editor.removeAnnotation.name, std::bind(&CodeEditorReceiver::processRemoveAnnotationEvent, this, _1));
eventHandleMap.insert(editor.clearAllAnnotation.name, std::bind(&CodeEditorReceiver::processClearAllAnnotationEvent, this, _1));
@@ -40,7 +39,7 @@ dpf::EventHandler::Type CodeEditorReceiver::type()
QStringList CodeEditorReceiver::topics()
{
- return { editor.topic, actionanalyse.topic, project.topic };
+ return { editor.topic };
}
void CodeEditorReceiver::eventProcess(const dpf::Event &event)
@@ -81,6 +80,14 @@ void CodeEditorReceiver::processGotoLineEvent(const dpf::Event &event)
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 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();
diff --git a/src/plugins/codeeditor/transceiver/codeeditorreceiver.h b/src/plugins/codeeditor/transceiver/codeeditorreceiver.h
index ce4ff0ff7..e99b9048d 100644
--- a/src/plugins/codeeditor/transceiver/codeeditorreceiver.h
+++ b/src/plugins/codeeditor/transceiver/codeeditorreceiver.h
@@ -23,6 +23,7 @@ class CodeEditorReceiver : public dpf::EventHandler, dpf::AutoEventHandlerRegist
void processBackEvent(const dpf::Event &event);
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);
diff --git a/src/plugins/codegeex/widgets/codeeditcomponent.h b/src/plugins/codegeex/widgets/codeeditcomponent.h
index 34deaf130..5f019d2df 100644
--- a/src/plugins/codegeex/widgets/codeeditcomponent.h
+++ b/src/plugins/codegeex/widgets/codeeditcomponent.h
@@ -6,8 +6,8 @@
#define CODEEDITCOMPONENT_H
#include
#include
-#include
-#include
+#include
+#include
#include
#include
diff --git a/src/plugins/collaborators/collaborators.cpp b/src/plugins/collaborators/collaborators.cpp
index 9287d57a9..ae13b4fc1 100644
--- a/src/plugins/collaborators/collaborators.cpp
+++ b/src/plugins/collaborators/collaborators.cpp
@@ -24,28 +24,33 @@ bool Collaborators::start()
if (windowService->addNavigationItem) {
QAction *actionGit = new QAction(MWNA_GIT, this);
actionGit->setIcon(QIcon::fromTheme("git-navigation"));
+
+#ifdef ENABLE_SVN // TODO(Any): svn should not contained in this plugin.
QAction *actionSvn = new QAction(MWNA_SVN, this);
actionSvn->setIcon(QIcon::fromTheme("svn-navigation"));
-
- windowService->addNavigationItem(new AbstractAction(actionGit), Priority::medium);
windowService->addNavigationItem(new AbstractAction(actionSvn), Priority::medium);
+ AbstractWidget *svnMainWidgetImpl = new AbstractWidget(CVSkeeper::instance()->svnMainWidget());
+ windowService->registerWidget(MWNA_SVN, svnMainWidgetImpl);
+ connect(actionSvn, &QAction::triggered, this, [=](){
+ windowService->replaceWidget(MWNA_SVN,
+ Position::FullWindow);
+ windowService->hideStatusBar();
+ }, Qt::DirectConnection);
+#endif
+ windowService->addNavigationItem(new AbstractAction(actionGit), Priority::medium);
+
AbstractWidget *gitMainWidgetImpl = new AbstractWidget(CVSkeeper::instance()->gitMainWidget());
- AbstractWidget *svnMainWidgetImpl = new AbstractWidget(CVSkeeper::instance()->svnMainWidget());
+
windowService->registerWidget(MWNA_GIT, gitMainWidgetImpl);
- windowService->registerWidget(MWNA_SVN, svnMainWidgetImpl);
+
connect(actionGit, &QAction::triggered, this, [=](){
windowService->replaceWidget(MWNA_GIT,
Position::FullWindow);
windowService->hideStatusBar();
}, Qt::DirectConnection);
- connect(actionSvn, &QAction::triggered, this, [=](){
- windowService->replaceWidget(MWNA_SVN,
- Position::FullWindow);
- windowService->hideStatusBar();
- }, Qt::DirectConnection);
}
}
return true;
diff --git a/src/plugins/core/gui/plugindetailsview.cpp b/src/plugins/core/gui/plugindetailsview.cpp
index 13aee90f6..a54b406d7 100644
--- a/src/plugins/core/gui/plugindetailsview.cpp
+++ b/src/plugins/core/gui/plugindetailsview.cpp
@@ -21,6 +21,8 @@
#include
#endif
#include
+#include
+#include
DWIDGET_USE_NAMESPACE
using namespace dpfservice;
@@ -29,33 +31,35 @@ using namespace dpfservice;
class AutoZoomWebEngineView : public QWebEngineView {
public:
explicit AutoZoomWebEngineView(QWidget *parent = nullptr)
- : QWebEngineView(parent) {
- page()->settings()->setAttribute(QWebEngineSettings::ShowScrollBars, false);
- connect(page(), &QWebEnginePage::loadFinished, [this](bool ok) {
- if (ok) {
- page()->runJavaScript("document.body.scrollWidth", [this](const QVariant &widthResult) {
- pageWidth = widthResult.toInt();
- });
- }
- }
- );
- }
+ : QWebEngineView(parent)
+ {
+ page()->settings()->setAttribute(QWebEngineSettings::ShowScrollBars, false);
+ }
protected:
void resizeEvent(QResizeEvent *event) override {
QWebEngineView::resizeEvent(event);
- QSize newSize = event->size();
- qreal zoomFactor = calculateZoomFactor(newSize);
+ int pageWidth = static_cast(QGuiApplication::primaryScreen()->size().width() * webPageWidthScale);
+
+ qreal zoomFactor = calculateZoomFactor(event->size(), pageWidth);
setZoomFactor(zoomFactor);
}
- qreal calculateZoomFactor(const QSize &size) {
+ qreal calculateZoomFactor(const QSize &size, int pageWidth)
+ {
+ if (pageWidth == 0)
+ return 1;
+
qreal zoomFactor = static_cast(size.width()) / pageWidth;
+ if (zoomFactor > 1) {
+ zoomFactor = 1;
+ }
return zoomFactor;
}
+
private:
- int pageWidth = 0;
+ qreal webPageWidthScale = 0.8;
};
#endif
diff --git a/src/plugins/core/gui/workspacewidget.h b/src/plugins/core/gui/workspacewidget.h
index 82643d6f3..00118b22c 100644
--- a/src/plugins/core/gui/workspacewidget.h
+++ b/src/plugins/core/gui/workspacewidget.h
@@ -31,6 +31,7 @@ class WorkspaceWidget : public DWidget
signals:
void expandStateChange(bool canExpand);
+ void autoFocusStateChange(bool autoFocusState);
void workSpaceWidgeSwitched(const QString &title);
private:
diff --git a/src/plugins/core/uicontroller/controller.cpp b/src/plugins/core/uicontroller/controller.cpp
index 2613c508e..f42dfda96 100644
--- a/src/plugins/core/uicontroller/controller.cpp
+++ b/src/plugins/core/uicontroller/controller.cpp
@@ -1012,8 +1012,8 @@ void Controller::showWorkspace()
expandAll->setVisible(d->workspace->getCurrentExpandState());
foldAll->setVisible(d->workspace->getCurrentExpandState());
- d->mainWindow->setDockHeadername(WN_WORKSPACE, d->workspace->getCurrentTitle());
+ d->mainWindow->setDockHeadername(WN_WORKSPACE, d->workspace->getCurrentTitle());
connect(d->workspace, &WorkspaceWidget::expandStateChange, this, [=](bool canExpand){
expandAll->setVisible(canExpand);
foldAll->setVisible(canExpand);
diff --git a/src/plugins/cxx/cmake/project/cmakeasynparse.cpp b/src/plugins/cxx/cmake/project/cmakeasynparse.cpp
index 8c4fa552c..79d2cdbf7 100644
--- a/src/plugins/cxx/cmake/project/cmakeasynparse.cpp
+++ b/src/plugins/cxx/cmake/project/cmakeasynparse.cpp
@@ -169,8 +169,11 @@ QStandardItem *CmakeAsynParse::parseProject(QStandardItem *rootItem, const dpfse
auto cbpParser = TargetsManager::instance()->cbpParser();
// add cmakefile to tree first.
auto cmakeList = cbpParser->getCmakeFileList();
+ QSet cmakeFiles {};
for (auto &cmakeFile : cmakeList) {
QString cmakeFilePath = cmakeFile.get()->getfilePath();
+ if (cmakeFilePath.endsWith("CMakeLists.txt"))
+ cmakeFiles.insert(cmakeFilePath);
QFileInfo cmakeFileInfo(cmakeFilePath);
if (cmakeFileInfo.fileName().toLower() == kProjectFile.toLower()) {
auto cmakeParentItem = rootItem;
@@ -197,7 +200,7 @@ QStandardItem *CmakeAsynParse::parseProject(QStandardItem *rootItem, const dpfse
}
}
- QSet allFiles {};
+ QSet commonFiles {};
const QList &targets = cbpParser->getBuildTargets();
for (auto target : targets) {
if (target.type == kUtility) {
@@ -258,7 +261,7 @@ QStandardItem *CmakeAsynParse::parseProject(QStandardItem *rootItem, const dpfse
if (parentItem)
parentItem->appendRow(srcItem);
- allFiles.insert(src);
+ commonFiles.insert(src);
}
}
@@ -269,7 +272,8 @@ QStandardItem *CmakeAsynParse::parseProject(QStandardItem *rootItem, const dpfse
tempInfo.setRunProgram(activeExecTarget.output);
tempInfo.setRunWorkspaceDir(activeExecTarget.workingDir);
}
- tempInfo.setSourceFiles(allFiles);
+
+ tempInfo.setSourceFiles(commonFiles + cmakeFiles);
tempInfo.setExePrograms(TargetsManager::instance()->getExeTargetNamesList());
tempInfo.setCurrentProgram(TargetsManager::instance()->getActivedTargetByTargetType(TargetType::kActiveExecTarget).name);
ProjectInfo::set(rootItem, tempInfo);
diff --git a/src/plugins/cxx/cmake/project/properties/runCfgWidget/runconfigpane.cpp b/src/plugins/cxx/cmake/project/properties/runCfgWidget/runconfigpane.cpp
index 11757ce71..4eae22779 100644
--- a/src/plugins/cxx/cmake/project/properties/runCfgWidget/runconfigpane.cpp
+++ b/src/plugins/cxx/cmake/project/properties/runCfgWidget/runconfigpane.cpp
@@ -58,7 +58,6 @@ void RunConfigPane::setupUi()
// excutable label ui.
d->excutableLabel = new DLineEdit(mainFrame);
d->excutableLabel->setText(tr("Here is the executable path"));
- d->excutableLabel->lineEdit()->setReadOnly(true);
d->formLayout->addRow(tr("Executable path:"), d->excutableLabel);
d->formLayout->setSpacing(10);
diff --git a/src/plugins/cxx/cmake/project/transceiver/projectcmakereceiver.cpp b/src/plugins/cxx/cmake/project/transceiver/projectcmakereceiver.cpp
index e94c5c59a..a6c95e36e 100644
--- a/src/plugins/cxx/cmake/project/transceiver/projectcmakereceiver.cpp
+++ b/src/plugins/cxx/cmake/project/transceiver/projectcmakereceiver.cpp
@@ -35,8 +35,8 @@ void ProjectCmakeReceiver::eventProcess(const dpf::Event &event)
builderEvent(event);
}
- if (event.data() == project.activedProject.name) {
- QVariant proInfoVar = event.property(project.activedProject.pKeys[0]);
+ if (event.data() == project.activatedProject.name) {
+ QVariant proInfoVar = event.property(project.activatedProject.pKeys[0]);
dpfservice::ProjectInfo projectInfo = qvariant_cast(proInfoVar);
TargetsManager::instance()->readTargets(projectInfo.buildFolder(), projectInfo.workspaceFolder());
}
diff --git a/src/plugins/debugger/dap/dapdebugger.cpp b/src/plugins/debugger/dap/dapdebugger.cpp
index 8b172d54e..e06d490a5 100644
--- a/src/plugins/debugger/dap/dapdebugger.cpp
+++ b/src/plugins/debugger/dap/dapdebugger.cpp
@@ -75,6 +75,7 @@ class DebuggerPrivate
DEBUG::DebugSession *currentSession { nullptr };
dap::integer threadId = 0;
+ QList threads;
StackFrameData currentValidFrame;
/**
@@ -197,12 +198,12 @@ void DAPDebugger::startDebug()
if (d->currentSession == d->remoteSession)
d->currentSession = d->localSession;
- updateRunState(kPreparing);
auto &ctx = dpfInstance.serviceContext();
LanguageService *service = ctx.service(LanguageService::name());
if (service) {
auto generator = service->create(d->activeProjectKitName);
if (generator) {
+ updateRunState(kPreparing);
if (generator->isNeedBuild()) {
d->currentBuildUuid = requestBuild();
} else {
@@ -571,11 +572,19 @@ void DAPDebugger::registerDapHandlers()
Q_UNUSED(event)
qInfo() << "\n--> recv : "
<< "ThreadEvent";
+
+ if (event.reason == "started")
+ d->threads.append(event.threadId);
+
+ if (event.reason == "exited") {
+ d->threads.removeOne(event.threadId);
+ if (d->threads.isEmpty())
+ updateRunState(kNoRun);
+ }
});
// The event indicates that the target has produced some output.
dapSession->registerHandler([&](const OutputEvent &event) {
- Q_UNUSED(event)
qInfo() << "\n--> recv : "
<< "OutputEvent\n"
<< "content : " << event.output.c_str();
@@ -705,17 +714,15 @@ void DAPDebugger::handleEvents(const dpf::Event &event)
}
} else if (event.data() == debugger.prepareDebugProgress.name) {
printOutput(event.property(debugger.prepareDebugProgress.pKeys[0]).toString());
- } else if (event.data() == project.activedProject.name) {
- getActiveProjectInfo() = qvariant_cast(event.property(project.activedProject.pKeys[0]));
- d->activeProjectKitName = getActiveProjectInfo().kitName();
- updateRunState(kNoRun);
- } else if (event.data() == project.createdProject.name) {
- getActiveProjectInfo() = qvariant_cast(event.property(project.createdProject.pKeys[0]));
- d->activeProjectKitName = getActiveProjectInfo().kitName();
- updateRunState(kNoRun);
+ } else if (event.data() == project.activatedProject.name) {
+ d->projectInfo = qvariant_cast(event.property("projectInfo"));
+ d->activeProjectKitName = d->projectInfo.kitName();
} else if (event.data() == project.deletedProject.name) {
- d->activeProjectKitName.clear();
- updateRunState(kNoRun);
+ auto prjInfo = event.property("projectInfo").value();
+ if (d->projectInfo.isSame(prjInfo)) {
+ d->activeProjectKitName.clear();
+ updateRunState(kNoRun);
+ }
} else if (event.data() == editor.switchedFile.name) {
QString filePath = event.property(editor.switchedFile.pKeys[0]).toString();
if (d->currentOpenedFileName != filePath) {
@@ -1143,6 +1150,9 @@ void DAPDebugger::updateWatchingVariables()
void DAPDebugger::exitDebug()
{
+ //abort debugger
+ abortDebug();
+
// Change UI.
editor.removeDebugLine();
d->variablesPane->hide();
diff --git a/src/plugins/debugger/debugmanager.cpp b/src/plugins/debugger/debugmanager.cpp
index 022453967..bc83fa188 100644
--- a/src/plugins/debugger/debugmanager.cpp
+++ b/src/plugins/debugger/debugmanager.cpp
@@ -200,8 +200,8 @@ void DebugManager::handleEvents(const dpf::Event &event)
QString data = event.data().toString();
if (event.data() == debugger.prepareDebugProgress.name) {
// TODO(logan)
- } else if (event.data() == project.activedProject.name) {
- auto projectInfo = qvariant_cast(event.property(project.activedProject.pKeys[0]));
+ } else if (event.data() == project.activatedProject.name) {
+ auto projectInfo = qvariant_cast(event.property(project.activatedProject.pKeys[0]));
activeProjectKitName = projectInfo.kitName();
} else if (event.data() == project.createdProject.name) {
auto projectInfo = qvariant_cast(event.property(project.createdProject.pKeys[0]));
diff --git a/src/plugins/debugger/runner/runner.cpp b/src/plugins/debugger/runner/runner.cpp
index 794fb0ad3..e23257be6 100644
--- a/src/plugins/debugger/runner/runner.cpp
+++ b/src/plugins/debugger/runner/runner.cpp
@@ -131,7 +131,7 @@ void Runner::handleEvents(const dpf::Event &event)
if (d->currentOpenedFilePath == filePath) {
d->currentOpenedFilePath.clear();
}
- } else if (event.data() == project.activedProject.name) {
+ } else if (event.data() == project.activatedProject.name) {
QVariant proInfoVar = event.property("projectInfo");
dpfservice::ProjectInfo projectInfo = qvariant_cast(proInfoVar);
auto programs = projectInfo.exePrograms();
diff --git a/src/plugins/filebrowser/transceiver/filebrowserreceiver.cpp b/src/plugins/filebrowser/transceiver/filebrowserreceiver.cpp
index 3d83fb0d4..c52ac383b 100644
--- a/src/plugins/filebrowser/transceiver/filebrowserreceiver.cpp
+++ b/src/plugins/filebrowser/transceiver/filebrowserreceiver.cpp
@@ -28,14 +28,14 @@ QStringList FileBrowserReceiver::topics()
void FileBrowserReceiver::eventProcess(const dpf::Event &event)
{
- if (event.data() == project.activedProject.name) {
- QVariant proInfoVar = event.property(project.activedProject.pKeys[0]);
+ if (event.data() == project.activatedProject.name) {
+ QVariant proInfoVar = event.property(project.activatedProject.pKeys[0]);
dpfservice::ProjectInfo proInfo = qvariant_cast(proInfoVar);
TreeViewKeeper::instance()->treeView()->setProjectInfo(proInfo);
} else if (event.data() == project.deletedProject.name) {
TreeViewKeeper::instance()->treeView()->setProjectInfo({});
} else if (event.data() == project.createdProject.name) {
- QVariant proInfoVar = event.property(project.activedProject.pKeys[0]);
+ QVariant proInfoVar = event.property(project.activatedProject.pKeys[0]);
dpfservice::ProjectInfo proInfo = qvariant_cast(proInfoVar);
TreeViewKeeper::instance()->treeView()->setProjectInfo(proInfo);
}
diff --git a/src/plugins/find/constants.h b/src/plugins/find/constants.h
index 1fb3d3d64..ec0b7e689 100644
--- a/src/plugins/find/constants.h
+++ b/src/plugins/find/constants.h
@@ -8,33 +8,64 @@
#include
#include
+enum ResultRole {
+ LineRole = Qt::UserRole + 1,
+ ColumnRole,
+ KeywordRole
+};
+
+enum SearchScope {
+ AllProjects = 0,
+ CurrentProject,
+ CurrentFile
+};
+
+enum SearchFlag {
+ SearchNoFlag = 0,
+ SearchCaseSensitive = 1,
+ SearchWholeWord = 1 << 1
+};
+Q_DECLARE_FLAGS(SearchFlags, SearchFlag)
+
+struct BaseParams
+{
+ QStringList baseFileList;
+ QStringList openedFileList;
+ QString keyword;
+};
+
struct SearchParams
{
- QStringList filePathList;
- QString searchText;
- bool sensitiveFlag;
- bool wholeWordsFlag;
- QStringList patternsList;
- QStringList exPatternsList;
- QMap projectInfoMap;
+ BaseParams baseParams;
+ QStringList includeList;
+ QStringList excludeList;
+ SearchFlags flags = SearchNoFlag;
+ SearchScope scope = AllProjects;
};
struct ReplaceParams
{
- QStringList filePathList;
- QString searchText;
+ BaseParams baseParams;
QString replaceText;
+ SearchFlags flags = SearchNoFlag;
};
struct FindItem
{
QString filePathName;
- int lineNumber;
+ int line = -1;
+ int column = -1;
+ QString keyword;
QString context;
+
+ inline bool operator==(const FindItem &other)
+ {
+ return filePathName == other.filePathName && line == other.line
+ && column == other.column;
+ }
};
using FindItemList = QList;
-using ProjectInfo = QMap;
Q_DECLARE_METATYPE(SearchParams)
Q_DECLARE_METATYPE(ReplaceParams)
diff --git a/src/plugins/find/find.qrc b/src/plugins/find/find.qrc
index 4aaeb3f53..a80f448fa 100644
--- a/src/plugins/find/find.qrc
+++ b/src/plugins/find/find.qrc
@@ -1,7 +1,9 @@
-
- texts/search-find_16px.svg
- actions/find_matchComplete_16px.svg
- icons/find_noResults_96px.png
+
+
+ icons/deepin/builtin/icons/find_noResults_96px.png
+ icons/deepin/builtin/texts/find_matchComplete_16px.svg
+ icons/deepin/builtin/texts/search-find_16px.svg
+ icons/deepin/builtin/texts/match_case_16px.svg
diff --git a/src/plugins/find/findplugin.cpp b/src/plugins/find/findplugin.cpp
index 94bccae9b..4b615b9c1 100644
--- a/src/plugins/find/findplugin.cpp
+++ b/src/plugins/find/findplugin.cpp
@@ -5,8 +5,8 @@
#include "findplugin.h"
#include "services/window/windowservice.h"
-#include "findtoolwindow.h"
-#include "searchresultwindow.h"
+#include "gui/findtoolwindow.h"
+#include "gui/searchresultwindow.h"
#include "common/common.h"
#include "base/abstractmenu.h"
#include "base/abstractwidget.h"
diff --git a/src/plugins/find/findtoolwindow.cpp b/src/plugins/find/findtoolwindow.cpp
deleted file mode 100644
index 06ceb9ad5..000000000
--- a/src/plugins/find/findtoolwindow.cpp
+++ /dev/null
@@ -1,431 +0,0 @@
-// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include "findtoolwindow.h"
-#include "searchresultwindow.h"
-#include "transceiver/findreceiver.h"
-#include "util/searcreplacehworker.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-DWIDGET_USE_NAMESPACE
-class FindToolWindowPrivate
-{
- FindToolWindowPrivate() {}
- ~FindToolWindowPrivate();
-
- DStackedWidget *stackedWidget { nullptr };
- SearchResultWindow *searchResultWindow { nullptr };
- QSet allProjectsPathList { nullptr };
- QString currentProjectPath;
- QString currentFilePath;
- QMap projectInfoMap;
- QSharedPointer searchReplaceWorker { nullptr };
- QThread thread;
-
- DComboBox *scopeComboBox { nullptr };
- DLineEdit *searchLineEdit { nullptr };
- DCheckBox *senseCheckBox { nullptr };
- DCheckBox *wholeWordsCheckBox { nullptr };
- DCheckBox *regularCheckBox { nullptr };
- DLineEdit *patternLineEdit { nullptr };
- DLineEdit *expatternLineEdit { nullptr };
- DSuggestButton *senseCheckBtnOn { nullptr };
- DPushButton *senseCheckBtnOff { nullptr };
- DSuggestButton *wholeWordsCheckBtnOn { nullptr };
- DPushButton *wholeWordsCheckBtnOff { nullptr };
-
- bool senseCheckBtnFlag = false;
- bool wholeWordsCheckBtnFlag = false;
- friend class FindToolWindow;
-};
-
-FindToolWindowPrivate::~FindToolWindowPrivate()
-{
- searchReplaceWorker->stop();
- thread.quit();
- thread.wait();
-}
-
-FindToolWindow::FindToolWindow(QWidget *parent)
- : QWidget(parent),
- d(new FindToolWindowPrivate())
-{
- setupUi();
- initWorker();
- connect(FindEventTransmit::instance(), QOverload::of(&FindEventTransmit::sendProjectPath),
- [=](const QString &projectPath, const QString &language) {
- d->currentProjectPath = projectPath;
- d->projectInfoMap.insert(projectPath, language);
- d->allProjectsPathList.insert(projectPath);
- });
-
- connect(FindEventTransmit::instance(), QOverload::of(&FindEventTransmit::sendRemovedProject),
- [=](const QString &projectPath) {
- d->currentProjectPath = "";
- d->allProjectsPathList.remove(projectPath);
- d->projectInfoMap.remove(projectPath);
- });
-
- connect(FindEventTransmit::instance(), QOverload::of(&FindEventTransmit::sendCurrentEditFile),
- [=](const QString &filePath, bool actived) {
- if (actived) {
- d->currentFilePath = filePath;
- } else
- d->currentFilePath = "";
- });
-}
-
-FindToolWindow::~FindToolWindow()
-{
- delete d;
-}
-
-void FindToolWindow::setupUi()
-{
- DFrame *mainPaneFrame = new DFrame(this);
- DStyle::setFrameRadius(mainPaneFrame, 0);
- d->stackedWidget = new DStackedWidget();
- QHBoxLayout *hLayout = new QHBoxLayout();
- hLayout->setContentsMargins(0, 0, 0, 0);
-
- DScrollArea *scrollArea = new DScrollArea(mainPaneFrame);
- scrollArea->setWidgetResizable(true);
- scrollArea->setWidget(d->stackedWidget);
- scrollArea->setLineWidth(0);
-
- mainPaneFrame->setLineWidth(0);
- hLayout->addWidget(mainPaneFrame);
- QHBoxLayout *scrollLayout = new QHBoxLayout();
- scrollLayout->addWidget(scrollArea);
- mainPaneFrame->setLayout(scrollLayout);
-
- QWidget *searchParamWidget = new QWidget();
- QWidget *searchResultWidget = new QWidget();
-
- addSearchParamWidget(searchParamWidget);
- addSearchResultWidget(searchResultWidget);
-
- d->stackedWidget->addWidget(searchParamWidget);
- d->stackedWidget->addWidget(searchResultWidget);
- d->stackedWidget->setCurrentIndex(0);
-
- setLayout(hLayout);
-}
-
-void FindToolWindow::initWorker()
-{
- d->searchReplaceWorker.reset(new SearchReplaceWorker);
- connect(d->searchReplaceWorker.data(), &SearchReplaceWorker::matched, this, &FindToolWindow::handleSearchMatched, Qt::QueuedConnection);
- connect(d->searchReplaceWorker.data(), &SearchReplaceWorker::searchFinished, this, &FindToolWindow::handleSearchFinished, Qt::QueuedConnection);
- connect(d->searchReplaceWorker.data(), &SearchReplaceWorker::replaceFinished, this, &FindToolWindow::handleReplaceFinished, Qt::QueuedConnection);
-
- d->searchReplaceWorker->moveToThread(&d->thread);
- d->thread.start();
-}
-
-void FindToolWindow::addSearchParamWidget(QWidget *parentWidget)
-{
- QFormLayout *formLayout = new QFormLayout();
- parentWidget->setLayout(formLayout);
-
- DLabel *scopeLabel = new DLabel(QLabel::tr("Scope:"));
- d->scopeComboBox = new DComboBox(parentWidget);
- d->scopeComboBox->addItem(tr("All Projects"));
- d->scopeComboBox->addItem(tr("Current Project"));
- d->scopeComboBox->addItem(tr("Current File"));
- d->scopeComboBox->setFixedWidth(369);
-
- DLabel *searchLabel = new DLabel(QLabel::tr("Search for:"));
- QHBoxLayout *hlayout = new QHBoxLayout();
- d->searchLineEdit = new DLineEdit(parentWidget);
- d->searchLineEdit->setFixedWidth(277);
- d->searchLineEdit->setPlaceholderText(tr("thread"));
-
- d->senseCheckBtnOn = new DSuggestButton(parentWidget);
- d->senseCheckBtnOn->setText("Aa");
- d->senseCheckBtnOn->setFixedSize(36, 36);
- d->senseCheckBtnOn->hide();
-
- d->senseCheckBtnOff = new DPushButton(parentWidget);
- d->senseCheckBtnOff->setText("aa");
- d->senseCheckBtnOff->setFixedSize(36, 36);
-
- d->wholeWordsCheckBtnOn = new DSuggestButton(parentWidget);
- d->wholeWordsCheckBtnOn->setIcon(QIcon::fromTheme("find_matchComplete"));
- d->wholeWordsCheckBtnOn->setFixedSize(36, 36);
- d->wholeWordsCheckBtnOn->hide();
-
- d->wholeWordsCheckBtnOff = new DPushButton(parentWidget);
- d->wholeWordsCheckBtnOff->setIcon(QIcon::fromTheme("find_matchComplete"));
- d->wholeWordsCheckBtnOff->setFixedSize(36, 36);
-
- hlayout->addWidget(d->searchLineEdit);
- hlayout->addWidget(d->senseCheckBtnOn);
- hlayout->addWidget(d->senseCheckBtnOff);
- hlayout->addWidget(d->wholeWordsCheckBtnOn);
- hlayout->addWidget(d->wholeWordsCheckBtnOff);
-
- DLabel *patternLabel = new DLabel(QLabel::tr("File pattern:"), parentWidget);
- d->patternLineEdit = new DLineEdit(parentWidget);
- d->patternLineEdit->setPlaceholderText(tr("e.g.*.ts,src/**/include"));
- d->patternLineEdit->setFixedWidth(369);
-
- DLabel *expatternLabel = new DLabel(QLabel::tr("Exclusion pattern:"), parentWidget);
- d->expatternLineEdit = new DLineEdit(parentWidget);
- d->expatternLineEdit->setPlaceholderText(tr("e.g.*.ts,src/**/include"));
- d->expatternLineEdit->setFixedWidth(369);
-
- QHBoxLayout *btnLayout = new QHBoxLayout();
- DPushButton *searchBtn = new DPushButton(QPushButton::tr("Search"), parentWidget);
- searchBtn->setMinimumWidth(120);
- searchBtn->setMaximumWidth(120);
- searchBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
-
- DPushButton *replaceBtn = new DPushButton(QPushButton::tr("Search && Replace"), parentWidget);
- replaceBtn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
- replaceBtn->setMinimumWidth(120);
- replaceBtn->setMaximumWidth(120);
-
- btnLayout->addWidget(searchBtn);
- btnLayout->addWidget(replaceBtn);
- btnLayout->setContentsMargins(213, 0, 0, 0);
-
- connect(searchBtn, &QAbstractButton::clicked, this, &FindToolWindow::search);
- connect(replaceBtn, &QAbstractButton::clicked, this, &FindToolWindow::replace);
-
- connect(d->senseCheckBtnOn, &QPushButton::clicked, this, &FindToolWindow::onSenseCheckBtnClicked);
- connect(d->wholeWordsCheckBtnOn, &QPushButton::clicked, this, &FindToolWindow::onwholeWordsCheckBtnClicked);
- connect(d->senseCheckBtnOff, &QPushButton::clicked, this, &FindToolWindow::onSenseCheckBtnClicked);
- connect(d->wholeWordsCheckBtnOff, &QPushButton::clicked, this, &FindToolWindow::onwholeWordsCheckBtnClicked);
-
- formLayout->setContentsMargins(26, 10, 0, 0);
- formLayout->setSpacing(10);
- formLayout->addRow(scopeLabel, d->scopeComboBox);
- formLayout->addRow(searchLabel, hlayout);
- formLayout->addRow(patternLabel, d->patternLineEdit);
- formLayout->addRow(expatternLabel, d->expatternLineEdit);
- formLayout->addRow(btnLayout);
- formLayout->setAlignment(btnLayout, Qt::AlignLeft);
-}
-
-void FindToolWindow::onSenseCheckBtnClicked()
-{
- d->senseCheckBtnFlag = !d->senseCheckBtnFlag;
- if (d->senseCheckBtnFlag) {
- d->senseCheckBtnOff->hide();
- d->senseCheckBtnOn->show();
- } else {
- d->senseCheckBtnOn->hide();
- d->senseCheckBtnOff->show();
- }
-}
-
-void FindToolWindow::onwholeWordsCheckBtnClicked()
-{
- d->wholeWordsCheckBtnFlag = !d->wholeWordsCheckBtnFlag;
- if (d->wholeWordsCheckBtnFlag) {
- d->wholeWordsCheckBtnOff->hide();
- d->wholeWordsCheckBtnOn->show();
- } else {
- d->wholeWordsCheckBtnOn->hide();
- d->wholeWordsCheckBtnOff->show();
- }
-}
-
-void FindToolWindow::addSearchResultWidget(QWidget *parentWidget)
-{
- QVBoxLayout *vLayout = new QVBoxLayout();
- parentWidget->setLayout(vLayout);
-
- d->searchResultWindow = new SearchResultWindow();
- connect(d->searchResultWindow, &SearchResultWindow::reqBack, this, &FindToolWindow::switchSearchParamWidget);
- connect(d->searchResultWindow, &SearchResultWindow::reqReplace, this, &FindToolWindow::handleReplace);
- vLayout->addWidget(d->searchResultWindow);
-}
-
-void FindToolWindow::search()
-{
- searchText();
- d->searchResultWindow->setRepalceWidgtVisible(false);
-}
-
-void FindToolWindow::createMessageDialog(const QString &message)
-{
- DDialog *messageDialog = new DDialog(this);
- messageDialog->setIcon(QIcon::fromTheme("dialog-warning"));
- messageDialog->setMessage(message);
- messageDialog->insertButton(0, tr("Ok"));
- messageDialog->setAttribute(Qt::WA_DeleteOnClose);
- connect(messageDialog, &DDialog::buttonClicked, [=](int index) {
- if (index == 0) {
- messageDialog->reject();
- }
- });
-
- messageDialog->exec();
-}
-
-bool FindToolWindow::checkSelectedScopeValid()
-{
- int index = d->scopeComboBox->currentIndex();
- switch (index) {
- case 0: {
- if (d->allProjectsPathList.isEmpty()) {
- createMessageDialog(tr("All projects path is empty, please import!"));
- return false;
- }
- break;
- }
- case 1: {
- if (d->currentProjectPath.isEmpty()) {
- createMessageDialog(tr("Current project path is empty, please import!"));
- return false;
- }
- break;
- }
- case 2: {
- if (d->currentFilePath.isEmpty()) {
- createMessageDialog(tr("Current project path is empty, please import!"));
- return false;
- }
- break;
- }
- default: {
- createMessageDialog(tr("Scope is not selected, please select!"));
- return false;
- }
- }
-
- return true;
-}
-
-bool FindToolWindow::getSearchParams(SearchParams *searchParams)
-{
- if (!checkSelectedScopeValid())
- return false;
- QString text = d->searchLineEdit->text();
- if (text.isEmpty()) {
- d->searchLineEdit->showAlertMessage(tr("Search for text is empty, please input!"));
- return false;
- }
-
- QStringList searchPathList;
- int index = d->scopeComboBox->currentIndex();
- switch (index) {
- case 0:
- searchPathList = d->allProjectsPathList.values();
- break;
- case 1:
- searchPathList = QStringList { d->currentProjectPath };
- break;
- case 2:
- searchPathList = QStringList { d->currentFilePath };
- break;
- default:
- break;
- }
-
- searchParams->filePathList = searchPathList;
- searchParams->searchText = text;
- searchParams->sensitiveFlag = d->senseCheckBtnFlag;
- searchParams->wholeWordsFlag = d->wholeWordsCheckBtnFlag;
- searchParams->patternsList = d->patternLineEdit->text().trimmed().split(",", QString::SkipEmptyParts);
- searchParams->exPatternsList = d->expatternLineEdit->text().trimmed().split(",", QString::SkipEmptyParts);
- searchParams->exPatternsList << "*.so" << "*.o";
- searchParams->projectInfoMap = d->projectInfoMap;
-
- return true;
-}
-
-void FindToolWindow::searchText()
-{
- SearchParams params;
- if (!getSearchParams(¶ms)) {
- return;
- }
-
- d->searchResultWindow->showMsg(true, tr("Searching, please wait..."));
- d->searchResultWindow->clear();
- metaObject()->invokeMethod(d->searchReplaceWorker.data(),
- "addSearchTask",
- Qt::QueuedConnection,
- Q_ARG(SearchParams, params));
- d->stackedWidget->setCurrentIndex(1);
-}
-
-void FindToolWindow::replace()
-{
- if (!checkSelectedScopeValid())
- return;
- searchText();
- d->searchResultWindow->setRepalceWidgtVisible(true);
-}
-
-void FindToolWindow::switchSearchParamWidget()
-{
- d->searchReplaceWorker->stop();
- d->stackedWidget->setCurrentIndex(0);
-}
-
-void FindToolWindow::handleSearchMatched()
-{
- const auto &results = d->searchReplaceWorker->getResults();
- if (results.isEmpty())
- return;
-
- d->searchResultWindow->appendResults(results, d->projectInfoMap);
-}
-
-void FindToolWindow::handleSearchFinished()
-{
- d->searchResultWindow->searchFinished();
-}
-
-void FindToolWindow::handleReplace(const QString &text)
-{
- ReplaceParams params;
- params.replaceText = text;
- params.searchText = d->searchLineEdit->text();
- int index = d->scopeComboBox->currentIndex();
- switch (index) {
- case 0:
- params.filePathList = d->allProjectsPathList.values();
- break;
- case 1:
- params.filePathList = QStringList { d->currentProjectPath };
- break;
- case 2:
- params.filePathList = QStringList { d->currentFilePath };
- break;
- default:
- break;
- }
- metaObject()->invokeMethod(d->searchReplaceWorker.data(),
- "addReplaceTask",
- Qt::QueuedConnection,
- Q_ARG(ReplaceParams, params));
-}
-
-void FindToolWindow::handleReplaceFinished(int result)
-{
- d->searchResultWindow->replaceFinished(result == 0);
-}
diff --git a/src/plugins/find/gui/findtoolwindow.cpp b/src/plugins/find/gui/findtoolwindow.cpp
new file mode 100644
index 000000000..a5cae6935
--- /dev/null
+++ b/src/plugins/find/gui/findtoolwindow.cpp
@@ -0,0 +1,405 @@
+// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "findtoolwindow.h"
+#include "searchresultwindow.h"
+#include "util/searcreplacehworker.h"
+
+#include "services/project/projectservice.h"
+#include "services/editor/editorservice.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+using namespace dpfservice;
+DWIDGET_USE_NAMESPACE
+class FindToolWindowPrivate : public QObject
+{
+public:
+ explicit FindToolWindowPrivate(FindToolWindow *qq);
+ ~FindToolWindowPrivate();
+
+ void initUI();
+ void initConnect();
+ void initWorker();
+
+ QWidget *createSearchParamWidget();
+ QWidget *createSearchResultWidget();
+
+ bool checkSelectedScopeValid();
+ bool setBaseParams(BaseParams *params, bool onlyOpened = false);
+ void showMessage(const QString &message);
+
+public:
+ FindToolWindow *q;
+ DStackedWidget *stackedWidget { nullptr };
+ SearchResultWindow *searchResultWindow { nullptr };
+ QSharedPointer searchReplaceWorker { nullptr };
+ QThread thread;
+
+ DPushButton *searchBtn { nullptr };
+ DPushButton *replaceBtn { nullptr };
+ DComboBox *scopeComboBox { nullptr };
+ DLineEdit *searchLineEdit { nullptr };
+ DLineEdit *patternLineEdit { nullptr };
+ DLineEdit *expatternLineEdit { nullptr };
+ DPushButton *caseSensitiveCheckBtn { nullptr };
+ DPushButton *wholeWordsCheckBtn { nullptr };
+
+ friend class FindToolWindow;
+};
+
+FindToolWindowPrivate::FindToolWindowPrivate(FindToolWindow *qq)
+ : q(qq)
+{
+}
+
+FindToolWindowPrivate::~FindToolWindowPrivate()
+{
+ searchReplaceWorker->stop();
+ thread.quit();
+ thread.wait();
+}
+
+void FindToolWindowPrivate::initUI()
+{
+ DFrame *mainPaneFrame = new DFrame(q);
+ DStyle::setFrameRadius(mainPaneFrame, 0);
+ stackedWidget = new DStackedWidget();
+ QHBoxLayout *hLayout = new QHBoxLayout(q);
+ hLayout->setContentsMargins(0, 0, 0, 0);
+
+ DScrollArea *scrollArea = new DScrollArea(mainPaneFrame);
+ scrollArea->setWidgetResizable(true);
+ scrollArea->setWidget(stackedWidget);
+ scrollArea->setLineWidth(0);
+
+ mainPaneFrame->setLineWidth(0);
+ hLayout->addWidget(mainPaneFrame);
+ QHBoxLayout *scrollLayout = new QHBoxLayout();
+ scrollLayout->addWidget(scrollArea);
+ mainPaneFrame->setLayout(scrollLayout);
+
+ stackedWidget->addWidget(createSearchParamWidget());
+ stackedWidget->addWidget(createSearchResultWidget());
+ stackedWidget->setCurrentIndex(0);
+}
+
+void FindToolWindowPrivate::initConnect()
+{
+ connect(searchBtn, &QAbstractButton::clicked, q, &FindToolWindow::search);
+ connect(replaceBtn, &QAbstractButton::clicked, q, &FindToolWindow::replace);
+
+ connect(searchResultWindow, &SearchResultWindow::reqBack, q, &FindToolWindow::switchSearchParamWidget);
+ connect(searchResultWindow, &SearchResultWindow::reqReplace, q, &FindToolWindow::handleReplace);
+}
+
+void FindToolWindowPrivate::initWorker()
+{
+ searchReplaceWorker.reset(new SearchReplaceWorker);
+ connect(searchReplaceWorker.data(), &SearchReplaceWorker::matched, q, &FindToolWindow::handleSearchMatched, Qt::QueuedConnection);
+ connect(searchReplaceWorker.data(), &SearchReplaceWorker::searchFinished, q, &FindToolWindow::handleSearchFinished, Qt::QueuedConnection);
+ connect(searchReplaceWorker.data(), &SearchReplaceWorker::replaceFinished, q, &FindToolWindow::handleReplaceFinished, Qt::QueuedConnection);
+
+ searchReplaceWorker->moveToThread(&thread);
+ thread.start();
+}
+
+QWidget *FindToolWindowPrivate::createSearchParamWidget()
+{
+ QWidget *widget = new QWidget(q);
+ QHBoxLayout *mainLayout = new QHBoxLayout(widget);
+
+ DLabel *scopeLabel = new DLabel(FindToolWindow::tr("Scope:"));
+ scopeComboBox = new DComboBox(q);
+ scopeComboBox->addItem(tr("All Projects"), AllProjects);
+ scopeComboBox->addItem(tr("Current Project"), CurrentProject);
+ scopeComboBox->addItem(tr("Current File"), CurrentFile);
+ scopeComboBox->setFixedWidth(369);
+
+ DLabel *searchLabel = new DLabel(FindToolWindow::tr("Search for:"));
+ QHBoxLayout *hlayout = new QHBoxLayout();
+ searchLineEdit = new DLineEdit(q);
+ searchLineEdit->setFixedWidth(277);
+ searchLineEdit->setPlaceholderText(FindToolWindow::tr("thread"));
+
+ caseSensitiveCheckBtn = new DPushButton(q);
+ caseSensitiveCheckBtn->setToolTip(FindToolWindow::tr("Case sensitive"));
+ caseSensitiveCheckBtn->setIcon(QIcon::fromTheme("match_case"));
+ caseSensitiveCheckBtn->setIconSize({ 16, 16 });
+ caseSensitiveCheckBtn->setCheckable(true);
+
+ wholeWordsCheckBtn = new DPushButton(q);
+ wholeWordsCheckBtn->setToolTip(FindToolWindow::tr("Whole words only"));
+ wholeWordsCheckBtn->setIcon(QIcon::fromTheme("find_matchComplete"));
+ wholeWordsCheckBtn->setIconSize({ 16, 16 });
+ wholeWordsCheckBtn->setCheckable(true);
+
+ hlayout->addWidget(searchLineEdit);
+ hlayout->addWidget(caseSensitiveCheckBtn);
+ hlayout->addWidget(wholeWordsCheckBtn);
+
+ DLabel *patternLabel = new DLabel(FindToolWindow::tr("File pattern:"), q);
+ patternLineEdit = new DLineEdit(q);
+ patternLineEdit->setPlaceholderText(FindToolWindow::tr("e.g.*.ts,src/**/include"));
+ patternLineEdit->setFixedWidth(369);
+
+ DLabel *expatternLabel = new DLabel(FindToolWindow::tr("Exclusion pattern:"), q);
+ expatternLineEdit = new DLineEdit(q);
+ expatternLineEdit->setPlaceholderText(FindToolWindow::tr("e.g.*.ts,src/**/include"));
+ expatternLineEdit->setFixedWidth(369);
+
+ searchBtn = new DPushButton(FindToolWindow::tr("Search", "button"), q);
+ searchBtn->setMinimumWidth(120);
+ replaceBtn = new DPushButton(FindToolWindow::tr("Search && Replace", "button"), q);
+ replaceBtn->setMinimumWidth(120);
+
+ QHBoxLayout *btnLayout = new QHBoxLayout();
+ btnLayout->setContentsMargins(0, 0, 0, 0);
+ btnLayout->addStretch(1);
+ btnLayout->addWidget(searchBtn);
+ btnLayout->addWidget(replaceBtn);
+
+ QFormLayout *formLayout = new QFormLayout(widget);
+ formLayout->setContentsMargins(26, 10, 0, 0);
+ formLayout->setSpacing(10);
+ formLayout->addRow(scopeLabel, scopeComboBox);
+ formLayout->addRow(searchLabel, hlayout);
+ formLayout->addRow(patternLabel, patternLineEdit);
+ formLayout->addRow(expatternLabel, expatternLineEdit);
+ formLayout->addRow(btnLayout);
+ formLayout->setAlignment(btnLayout, Qt::AlignLeft);
+
+ mainLayout->addLayout(formLayout);
+ mainLayout->addStretch(1);
+ return widget;
+}
+
+QWidget *FindToolWindowPrivate::createSearchResultWidget()
+{
+ QWidget *widget = new QWidget(q);
+ QVBoxLayout *vLayout = new QVBoxLayout(widget);
+
+ searchResultWindow = new SearchResultWindow(q);
+ vLayout->addWidget(searchResultWindow);
+
+ return widget;
+}
+
+bool FindToolWindowPrivate::checkSelectedScopeValid()
+{
+ int scope = scopeComboBox->currentData().toInt();
+ switch (scope) {
+ case AllProjects: {
+ auto projectSrv = dpfGetService(ProjectService);
+ const auto &infoList = projectSrv->getAllProjectInfo();
+ if (infoList.isEmpty()) {
+ showMessage(FindToolWindow::tr("All projects path is empty, please import!"));
+ return false;
+ }
+ break;
+ }
+ case CurrentProject: {
+ auto projectSrv = dpfGetService(ProjectService);
+ const auto &info = projectSrv->getActiveProjectInfo();
+ if (info.isEmpty()) {
+ showMessage(FindToolWindow::tr("Current project path is empty, please import!"));
+ return false;
+ }
+ break;
+ }
+ case CurrentFile: {
+ auto editSrv = dpfGetService(EditorService);
+ auto curFile = editSrv->currentFile();
+ if (curFile.isEmpty()) {
+ showMessage(FindToolWindow::tr("No files are currently open, please open!"));
+ return false;
+ }
+ break;
+ }
+ default: {
+ showMessage(FindToolWindow::tr("Scope is not selected, please select!"));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool FindToolWindowPrivate::setBaseParams(BaseParams *params, bool onlyOpened)
+{
+ if (!params)
+ return false;
+
+ params->keyword = searchLineEdit->text();
+ if (params->keyword.isEmpty()) {
+ searchLineEdit->showAlertMessage(tr("Search for text is empty, please input!"));
+ return false;
+ }
+
+ auto projectSrv = dpfGetService(ProjectService);
+ auto editSrv = dpfGetService(EditorService);
+ int scope = scopeComboBox->currentData().toInt();
+ switch (scope) {
+ case AllProjects: {
+ params->openedFileList = editSrv->openedFiles();
+ if (onlyOpened)
+ return true;
+
+ const auto &infoList = projectSrv->getAllProjectInfo();
+ for (const auto &info : infoList) {
+ params->baseFileList.append(info.sourceFiles().toList());
+ }
+ return true;
+ }
+ case CurrentProject: {
+ params->openedFileList = editSrv->openedFiles();
+ if (onlyOpened)
+ return true;
+
+ const auto &info = projectSrv->getActiveProjectInfo();
+ params->baseFileList.append(info.sourceFiles().toList());
+ return true;
+ }
+ case CurrentFile: {
+ auto curFile = editSrv->currentFile();
+ params->openedFileList << curFile;
+ return true;
+ }
+ default: {
+ break;
+ }
+ }
+
+ return false;
+}
+
+void FindToolWindowPrivate::showMessage(const QString &message)
+{
+ DDialog dlg(q);
+ dlg.setIcon(QIcon::fromTheme("dialog-warning"));
+ dlg.setMessage(message);
+ dlg.insertButton(0, FindToolWindow::tr("Ok"));
+
+ dlg.exec();
+}
+
+FindToolWindow::FindToolWindow(QWidget *parent)
+ : QWidget(parent),
+ d(new FindToolWindowPrivate(this))
+{
+ d->initUI();
+ d->initWorker();
+ d->initConnect();
+}
+
+FindToolWindow::~FindToolWindow()
+{
+ delete d;
+}
+
+void FindToolWindow::search()
+{
+ searchText();
+ d->searchResultWindow->setRepalceWidgtVisible(false);
+}
+
+bool FindToolWindow::getSearchParams(SearchParams *searchParams)
+{
+ if (!d->checkSelectedScopeValid())
+ return false;
+
+ if (!d->setBaseParams(&searchParams->baseParams))
+ return false;
+
+ searchParams->scope = static_cast(d->scopeComboBox->currentData().toInt());
+ searchParams->flags |= d->caseSensitiveCheckBtn->isChecked() ? SearchCaseSensitive : SearchNoFlag;
+ searchParams->flags |= d->wholeWordsCheckBtn->isChecked() ? SearchWholeWord : SearchNoFlag;
+ searchParams->includeList = d->patternLineEdit->text().trimmed().split(",", QString::SkipEmptyParts);
+ searchParams->excludeList = d->expatternLineEdit->text().trimmed().split(",", QString::SkipEmptyParts);
+
+ return true;
+}
+
+void FindToolWindow::searchText()
+{
+ SearchParams params;
+ if (!getSearchParams(¶ms)) {
+ return;
+ }
+
+ d->searchResultWindow->showMsg(true, tr("Searching, please wait..."));
+ d->searchResultWindow->clear();
+ metaObject()->invokeMethod(d->searchReplaceWorker.data(),
+ "addSearchTask",
+ Qt::QueuedConnection,
+ Q_ARG(SearchParams, params));
+ d->stackedWidget->setCurrentIndex(1);
+}
+
+void FindToolWindow::replace()
+{
+ if (!d->checkSelectedScopeValid())
+ return;
+
+ searchText();
+ d->searchResultWindow->setRepalceWidgtVisible(true);
+}
+
+void FindToolWindow::switchSearchParamWidget()
+{
+ d->searchReplaceWorker->stop();
+ d->stackedWidget->setCurrentIndex(0);
+}
+
+void FindToolWindow::handleSearchMatched()
+{
+ const auto &results = d->searchReplaceWorker->getResults();
+ if (results.isEmpty())
+ return;
+
+ d->searchResultWindow->appendResults(results);
+}
+
+void FindToolWindow::handleSearchFinished()
+{
+ d->searchResultWindow->searchFinished();
+}
+
+void FindToolWindow::handleReplace(const QString &text)
+{
+ if (!d->checkSelectedScopeValid())
+ return;
+
+ ReplaceParams params;
+ if (!d->setBaseParams(¶ms.baseParams, true))
+ return;
+
+ params.replaceText = text;
+ params.baseParams.baseFileList = d->searchResultWindow->resultFileList();
+ params.flags |= d->caseSensitiveCheckBtn->isChecked() ? SearchCaseSensitive : SearchNoFlag;
+ params.flags |= d->wholeWordsCheckBtn->isChecked() ? SearchWholeWord : SearchNoFlag;
+ metaObject()->invokeMethod(d->searchReplaceWorker.data(),
+ "addReplaceTask",
+ Qt::QueuedConnection,
+ Q_ARG(ReplaceParams, params));
+}
+
+void FindToolWindow::handleReplaceFinished(int result)
+{
+ d->searchResultWindow->replaceFinished(result == 0);
+}
diff --git a/src/plugins/find/findtoolwindow.h b/src/plugins/find/gui/findtoolwindow.h
similarity index 68%
rename from src/plugins/find/findtoolwindow.h
rename to src/plugins/find/gui/findtoolwindow.h
index 90bc2db53..798863c90 100644
--- a/src/plugins/find/findtoolwindow.h
+++ b/src/plugins/find/gui/findtoolwindow.h
@@ -5,7 +5,7 @@
#ifndef FINDTOOLWINDOW_H
#define FINDTOOLWINDOW_H
-#include "searchresultwindow.h"
+#include "constants.h"
#include
@@ -17,27 +17,17 @@ class FindToolWindow : public QWidget
explicit FindToolWindow(QWidget *parent = nullptr);
~FindToolWindow() override;
-signals:
-
private:
- void setupUi();
- void initWorker();
void search();
void searchText();
void replace();
- void addSearchParamWidget(QWidget *parentWidget);
- void addSearchResultWidget(QWidget *parentWidget);
void switchSearchParamWidget();
- bool checkSelectedScopeValid();
bool getSearchParams(SearchParams *searchParams);
- void createMessageDialog(const QString &message);
+ friend class FindToolWindowPrivate;
FindToolWindowPrivate *const d;
private slots:
- void onSenseCheckBtnClicked();
- void onwholeWordsCheckBtnClicked();
-
void handleSearchMatched();
void handleSearchFinished();
void handleReplace(const QString &text);
diff --git a/src/plugins/find/gui/resulttemdelegate.cpp b/src/plugins/find/gui/resulttemdelegate.cpp
new file mode 100644
index 000000000..cb1412631
--- /dev/null
+++ b/src/plugins/find/gui/resulttemdelegate.cpp
@@ -0,0 +1,217 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "resulttemdelegate.h"
+#include "constants.h"
+
+#include
+
+#include
+#include
+
+const int LinePadding = 4;
+const int LineDigits = 6;
+
+DGUI_USE_NAMESPACE
+
+static std::pair lineNumberInfo(const QStyleOptionViewItem &option,
+ const QModelIndex &index)
+{
+ int line = index.data(LineRole).toInt();
+ if (line < 1)
+ return { 0, {} };
+
+ const QString lineText = QString::number(line);
+ const int lineDigits = qMax(LineDigits, lineText.size());
+ const int fontWidth = option.fontMetrics.horizontalAdvance(QString(lineDigits, QLatin1Char('0')));
+ const QStyle *style = option.widget ? option.widget->style() : QApplication::style();
+ return { LinePadding + fontWidth + LinePadding + style->pixelMetric(QStyle::PM_FocusFrameHMargin), lineText };
+}
+
+static QString itemText(const QModelIndex &index)
+{
+ QString text = index.data(Qt::DisplayRole).toString();
+ if (index.model()->hasChildren(index))
+ text += " (" + QString::number(index.model()->rowCount(index)) + ')';
+
+ return text;
+}
+
+ResultItemDelegate::ResultItemDelegate(QObject *parent)
+ : QItemDelegate(parent)
+{
+ tabStr = QString(8, ' ');
+}
+
+void ResultItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ painter->save();
+ const LayoutInfo info = getLayoutInfo(option, index);
+ painter->setFont(info.option.font);
+ QItemDelegate::drawBackground(painter, info.option, index);
+
+ // icon
+ if (!info.icon.isNull())
+ info.icon.paint(painter, info.iconRect, info.option.decorationAlignment);
+
+ // line numbers
+ drawLineNumber(painter, info.option, info.lineNumberRect, index);
+
+ // text
+ drawText(painter, info.option, info.textRect, index);
+ QItemDelegate::drawFocus(painter, info.option, info.option.rect);
+ painter->restore();
+}
+
+QSize ResultItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ return QSize(INT_MAX, 24);
+}
+
+LayoutInfo ResultItemDelegate::getLayoutInfo(const QStyleOptionViewItem &option, const QModelIndex &index) const
+{
+ auto op = option;
+ if (!option.state.testFlag(QStyle::State_HasFocus)) {
+ QColor color;
+ DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::LightType
+ ? color = Qt::black
+ : color = QColor("#c5c8c9");
+ op.palette.setColor(QPalette::Text, color);
+ }
+
+ LayoutInfo info;
+ info.option = setOptions(index, op);
+
+ // icon
+ info.icon = index.data(Qt::DecorationRole).value();
+ if (!info.icon.isNull()) {
+ const QSize size = info.icon.actualSize(QSize(16, 16));
+ info.iconRect = QRect(0, 0, size.width(), size.height());
+ }
+
+ // text
+ info.textRect = info.option.rect.adjusted(0, 0, info.iconRect.width(), 0);
+
+ // do basic layout
+ QRect checkRect;
+ doLayout(info.option, &checkRect, &info.iconRect, &info.textRect, false);
+
+ // adapt for line numbers
+ const int lineNumberWidth = lineNumberInfo(info.option, index).first;
+ info.lineNumberRect = info.textRect;
+ info.lineNumberRect.setWidth(lineNumberWidth);
+ info.textRect.adjust(lineNumberWidth, 0, 0, 0);
+ return info;
+}
+
+int ResultItemDelegate::drawLineNumber(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QModelIndex &index) const
+{
+ const bool isSelected = option.state & QStyle::State_Selected;
+ const std::pair numberInfo = lineNumberInfo(option, index);
+ if (numberInfo.first == 0)
+ return 0;
+
+ QRect lineNumberAreaRect(rect);
+ lineNumberAreaRect.setWidth(numberInfo.first);
+
+ QPalette::ColorGroup cg = QPalette::Normal;
+ if (!(option.state & QStyle::State_Active))
+ cg = QPalette::Inactive;
+ else if (!(option.state & QStyle::State_Enabled))
+ cg = QPalette::Disabled;
+
+ painter->fillRect(lineNumberAreaRect,
+ QBrush(isSelected
+ ? option.palette.brush(cg, QPalette::Highlight)
+ : option.palette.color(cg, QPalette::Base).darker(111)));
+
+ QStyleOptionViewItem opt = option;
+ opt.displayAlignment = Qt::AlignRight | Qt::AlignVCenter;
+ opt.palette.setColor(cg, QPalette::Text, Qt::darkGray);
+
+ const QStyle *style = QApplication::style();
+ const int textMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, nullptr, nullptr) + 1;
+
+ const QRect rowRect = lineNumberAreaRect.adjusted(-textMargin, 0, textMargin - LinePadding, 0);
+ QItemDelegate::drawDisplay(painter, opt, rowRect, numberInfo.second);
+
+ return numberInfo.first;
+}
+
+void ResultItemDelegate::drawText(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QModelIndex &index) const
+{
+ const auto text = itemText(index);
+ const int searchTermStart = index.data(ColumnRole).toInt();
+ const auto searchKeyword = index.data(KeywordRole).toString();
+ int searchTermLength = searchKeyword.length();
+ if (searchTermStart < 0 || searchTermStart >= text.length() || searchTermLength < 1) {
+ QItemDelegate::drawDisplay(painter,
+ option,
+ rect,
+ QString(text).replace(QLatin1Char('\t'), tabStr));
+ return;
+ }
+
+ // clip searchTermLength to end of line
+ searchTermLength = qMin(searchTermLength, text.length() - searchTermStart);
+ const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
+ const QString textBefore = text.left(searchTermStart).replace(QLatin1Char('\t'), tabStr);
+ const QString textHighlight = text.mid(searchTermStart, searchTermLength).replace(QLatin1Char('\t'), tabStr);
+ const QString textAfter = text.mid(searchTermStart + searchTermLength).replace(QLatin1Char('\t'), tabStr);
+ int searchTermStartPixels = option.fontMetrics.horizontalAdvance(textBefore);
+ int searchTermLengthPixels = option.fontMetrics.horizontalAdvance(textHighlight);
+ int textAfterLengthPixels = option.fontMetrics.horizontalAdvance(textAfter);
+
+ // rects
+ QRect beforeHighlightRect(rect);
+ beforeHighlightRect.setRight(beforeHighlightRect.left() + searchTermStartPixels);
+
+ QRect resultHighlightRect(rect);
+ resultHighlightRect.setLeft(beforeHighlightRect.right());
+ resultHighlightRect.setRight(resultHighlightRect.left() + searchTermLengthPixels);
+
+ QRect afterHighlightRect(rect);
+ afterHighlightRect.setLeft(resultHighlightRect.right());
+ afterHighlightRect.setRight(afterHighlightRect.left() + textAfterLengthPixels);
+
+ // paint all highlight backgrounds
+ bool isSelected = option.state & QStyle::State_Selected;
+ QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
+ ? QPalette::Normal
+ : QPalette::Disabled;
+ if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
+ cg = QPalette::Inactive;
+ QStyleOptionViewItem baseOption = option;
+ baseOption.state &= ~QStyle::State_Selected;
+ if (isSelected) {
+ painter->fillRect(beforeHighlightRect.adjusted(textMargin, 0, textMargin, 0),
+ option.palette.brush(cg, QPalette::Highlight));
+ painter->fillRect(afterHighlightRect.adjusted(textMargin, 0, textMargin, 0),
+ option.palette.brush(cg, QPalette::Highlight));
+ }
+
+ QColor highlightBackground("#ffef0b");
+ if (DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::DarkType)
+ highlightBackground = QColor("#8a7f2c");
+ painter->fillRect(resultHighlightRect.adjusted(textMargin, 0, textMargin - 1, 0),
+ QBrush(highlightBackground));
+
+ // Text before the highlighting
+ QColor textColor = baseOption.palette.color(QPalette::Text);
+ QStyleOptionViewItem noHighlightOpt = baseOption;
+ noHighlightOpt.rect = beforeHighlightRect;
+ noHighlightOpt.textElideMode = Qt::ElideNone;
+ if (isSelected)
+ noHighlightOpt.palette.setColor(QPalette::Text, noHighlightOpt.palette.color(cg, QPalette::HighlightedText));
+ QItemDelegate::drawDisplay(painter, noHighlightOpt, beforeHighlightRect, textBefore);
+
+ // Highlight text
+ QStyleOptionViewItem highlightOpt = noHighlightOpt;
+ highlightOpt.palette.setColor(QPalette::Text, textColor);
+ QItemDelegate::drawDisplay(painter, highlightOpt, resultHighlightRect, textHighlight);
+
+ // Text after the Highlight
+ noHighlightOpt.rect = afterHighlightRect;
+ QItemDelegate::drawDisplay(painter, noHighlightOpt, afterHighlightRect, textAfter);
+}
diff --git a/src/plugins/find/gui/resulttemdelegate.h b/src/plugins/find/gui/resulttemdelegate.h
new file mode 100644
index 000000000..e12e0b37a
--- /dev/null
+++ b/src/plugins/find/gui/resulttemdelegate.h
@@ -0,0 +1,37 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RESULTTEMDELEGATE_H
+#define RESULTTEMDELEGATE_H
+
+#include
+
+struct LayoutInfo
+{
+ QRect iconRect;
+ QRect textRect;
+ QRect lineNumberRect;
+ QIcon icon;
+ QStyleOptionViewItem option;
+};
+
+class ResultItemDelegate : public QItemDelegate
+{
+ Q_OBJECT
+public:
+ explicit ResultItemDelegate(QObject *parent = nullptr);
+
+ void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
+ QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override;
+
+private:
+ LayoutInfo getLayoutInfo(const QStyleOptionViewItem &option, const QModelIndex &index) const;
+ int drawLineNumber(QPainter *painter, const QStyleOptionViewItem &option, const QRect &rect, const QModelIndex &index) const;
+ void drawText(QPainter *painter, const QStyleOptionViewItem &option,
+ const QRect &rect, const QModelIndex &index) const;
+
+ QString tabStr;
+};
+
+#endif // RESULTTEMDELEGATE_H
diff --git a/src/plugins/find/gui/searchresulttreeview.cpp b/src/plugins/find/gui/searchresulttreeview.cpp
new file mode 100644
index 000000000..134dc12d8
--- /dev/null
+++ b/src/plugins/find/gui/searchresulttreeview.cpp
@@ -0,0 +1,239 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "searchresulttreeview.h"
+
+#include "common/util/eventdefinitions.h"
+
+#include
+
+DWIDGET_USE_NAMESPACE
+
+SearchResultModel::SearchResultModel(QObject *parent)
+ : QAbstractItemModel(parent)
+{
+}
+
+int SearchResultModel::columnCount(const QModelIndex &parent) const
+{
+ return 1;
+}
+
+QVariant SearchResultModel::data(const QModelIndex &index, int role) const
+{
+ if (auto item = findItem(index))
+ return data(*item, role);
+
+ QString group = findGroup(index);
+ if (!group.isEmpty())
+ return data(group, role);
+
+ return QVariant();
+}
+
+QModelIndex SearchResultModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (column == 0 && parent.isValid()) {
+ QString group = findGroup(parent);
+ if (!group.isEmpty()) {
+ auto items = resultData.value(group);
+ if (row < items.count()) {
+ auto &item = items.at(row);
+ return createIndex(row, 0, const_cast(&item));
+ }
+ }
+ } else if (column == 0 && row < resultData.size()) {
+ return createIndex(row, 0);
+ }
+
+ return QModelIndex();
+}
+
+QModelIndex SearchResultModel::parent(const QModelIndex &child) const
+{
+ if (auto tool = findItem(child)) {
+ int groupIndex = 0;
+ for (const auto &itemsInGroup : resultData) {
+ if (itemsInGroup.contains(*tool))
+ return index(groupIndex, 0);
+ ++groupIndex;
+ }
+ }
+ return QModelIndex();
+}
+
+int SearchResultModel::rowCount(const QModelIndex &parent) const
+{
+ if (!parent.isValid())
+ return resultData.size();
+
+ if (findItem(parent))
+ return 0;
+
+ QString group = findGroup(parent);
+ if (!group.isEmpty())
+ return resultData.value(group).count();
+
+ return 0;
+}
+
+Qt::ItemFlags SearchResultModel::flags(const QModelIndex &index) const
+{
+ return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
+}
+
+void SearchResultModel::clear()
+{
+ beginResetModel();
+ resultData.clear();
+ endResetModel();
+}
+
+FindItem *SearchResultModel::findItem(const QModelIndex &index) const
+{
+ auto item = static_cast(index.internalPointer());
+ return item;
+}
+
+QString SearchResultModel::findGroup(const QModelIndex &index) const
+{
+ if (index.isValid() && !index.parent().isValid() && index.column() == 0 && index.row() >= 0) {
+ const QList &keys = resultData.keys();
+ if (index.row() < keys.count())
+ return keys.at(index.row());
+ }
+
+ return QString();
+}
+
+void SearchResultModel::appendResult(const FindItemList &list)
+{
+ QMap result;
+ for (const auto &item : list) {
+ if (!resultData.contains(item.filePathName)) {
+ if (result.contains(item.filePathName)) {
+ addItem(item.filePathName, result[item.filePathName]);
+ result.clear();
+ }
+ addGroup(item.filePathName);
+ result[item.filePathName].append(item);
+ } else {
+ result[item.filePathName].append(item);
+ }
+ }
+
+ for (auto iter = result.begin(); iter != result.end(); ++iter)
+ addItem(iter.key(), iter.value());
+}
+
+QStringList SearchResultModel::fileList() const
+{
+ return resultData.keys();
+}
+
+void SearchResultModel::addGroup(const QString &group)
+{
+ QList groupList = resultData.keys();
+ groupList.append(group);
+ std::stable_sort(std::begin(groupList), std::end(groupList));
+ int pos = groupList.indexOf(group);
+
+ beginInsertRows(QModelIndex(), pos, pos);
+ resultData.insert(group, FindItemList());
+ endInsertRows();
+}
+
+void SearchResultModel::addItem(const QString &group, const FindItemList &itemList)
+{
+ int pos = resultData.keys().indexOf(group);
+ auto parent = index(pos, 0);
+
+ beginInsertRows(parent, pos, pos + itemList.size());
+ resultData[group].append(itemList);
+ endInsertRows();
+}
+
+QVariant SearchResultModel::data(const FindItem &item, int role) const
+{
+ switch (role) {
+ case Qt::ToolTipRole:
+ case Qt::DisplayRole:
+ return item.context;
+ case LineRole:
+ return item.line;
+ case ColumnRole:
+ return item.column;
+ case KeywordRole:
+ return item.keyword;
+ default:
+ break;
+ }
+
+ return QVariant();
+}
+
+QVariant SearchResultModel::data(const QString &group, int role) const
+{
+ switch (role) {
+ case Qt::ToolTipRole:
+ case Qt::DisplayRole:
+ return group;
+ case Qt::DecorationRole:
+ return DFileIconProvider::globalProvider()->icon(QFileInfo(group));
+ default:
+ break;
+ }
+
+ return QVariant();
+}
+
+class SearchResultTreeViewPrivate
+{
+ SearchResultTreeViewPrivate() {}
+ ~SearchResultTreeViewPrivate();
+
+ SearchResultModel model;
+ friend class SearchResultTreeView;
+};
+
+SearchResultTreeViewPrivate::~SearchResultTreeViewPrivate()
+{
+}
+
+SearchResultTreeView::SearchResultTreeView(QWidget *parent)
+ : DTreeView(parent), d(new SearchResultTreeViewPrivate())
+{
+ setModel(&d->model);
+ auto font = this->font();
+ font.setFamily("Noto Mono");
+ setFont(font);
+
+ connect(this, &DTreeView::doubleClicked, this, [=](const QModelIndex &index) {
+ auto item = d->model.findItem(index);
+ if (!item)
+ return;
+
+ editor.gotoPosition(item->filePathName, item->line, item->column);
+ });
+}
+
+SearchResultTreeView::~SearchResultTreeView()
+{
+ delete d;
+}
+
+void SearchResultTreeView::appendData(const FindItemList &itemList)
+{
+ d->model.appendResult(itemList);
+}
+
+void SearchResultTreeView::clearData()
+{
+ d->model.clear();
+}
+
+QStringList SearchResultTreeView::resultFileList() const
+{
+ return d->model.fileList();
+}
diff --git a/src/plugins/find/gui/searchresulttreeview.h b/src/plugins/find/gui/searchresulttreeview.h
new file mode 100644
index 000000000..6f95f1ae7
--- /dev/null
+++ b/src/plugins/find/gui/searchresulttreeview.h
@@ -0,0 +1,56 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef SEARCHRESULTTREEVIEW_H
+#define SEARCHRESULTTREEVIEW_H
+
+#include "constants.h"
+
+#include
+
+class SearchResultModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ explicit SearchResultModel(QObject *parent = nullptr);
+
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
+ QModelIndex parent(const QModelIndex &child) const override;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+
+ void clear();
+ FindItem *findItem(const QModelIndex &index) const;
+ QString findGroup(const QModelIndex &index) const;
+ void appendResult(const FindItemList &list);
+ QStringList fileList() const;
+
+private:
+ void addGroup(const QString &group);
+ void addItem(const QString &group, const FindItemList &itemList);
+ QVariant data(const FindItem &item, int role = Qt::DisplayRole) const;
+ QVariant data(const QString &group, int role = Qt::DisplayRole) const;
+
+ QMap resultData;
+};
+
+class SearchResultTreeViewPrivate;
+class SearchResultTreeView : public DTK_WIDGET_NAMESPACE::DTreeView
+{
+ Q_OBJECT
+public:
+ explicit SearchResultTreeView(QWidget *parent = nullptr);
+ ~SearchResultTreeView();
+
+ void appendData(const FindItemList &itemList);
+ void clearData();
+ QStringList resultFileList() const;
+
+private:
+ SearchResultTreeViewPrivate *const d;
+};
+
+#endif // SEARCHRESULTTREEVIEW_H
diff --git a/src/plugins/find/searchresultwindow.cpp b/src/plugins/find/gui/searchresultwindow.cpp
similarity index 54%
rename from src/plugins/find/searchresultwindow.cpp
rename to src/plugins/find/gui/searchresultwindow.cpp
index 204e5ab9b..5dfdfde3f 100644
--- a/src/plugins/find/searchresultwindow.cpp
+++ b/src/plugins/find/gui/searchresultwindow.cpp
@@ -3,175 +3,21 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include "searchresultwindow.h"
-#include "common/common.h"
-#include "qobjectdefs.h"
-#include "base/baseitemdelegate.h"
+#include "searchresulttreeview.h"
+#include "resulttemdelegate.h"
#include
#include
#include
#include
-#include
#include
#include
#include
-#include
-#include
#include
-#include
#include
-ItemProxy::ItemProxy(QObject *parent)
- : QObject(parent)
-{
-}
-
-void ItemProxy::setRuningState(bool isRuning)
-{
- this->isRuning = isRuning;
-}
-
-void ItemProxy::addTask(const FindItemList &itemList)
-{
- if (!isRuning)
- return;
-
- QHash>> findItemHash;
- for (const FindItem &findItem : itemList) {
- if (!isRuning)
- return;
-
- QString key = findItem.filePathName;
- auto value = qMakePair(findItem.lineNumber, findItem.context);
- if (findItemHash.contains(key)) {
- QList> valueList = findItemHash.value(key);
- valueList.append(value);
- findItemHash[key] = valueList;
- } else {
- findItemHash.insert(key, { value });
- }
- }
-
- QList viewItemList;
- auto iter = findItemHash.begin();
- for (; iter != findItemHash.end(); ++iter) {
- if (!isRuning) {
- qDeleteAll(viewItemList);
- return;
- }
-
- QList> contentList = iter.value();
- QStandardItem *parentItem = new QStandardItem(iter.key() + " (" + QString::number(contentList.count()) + ")");
- parentItem->setData(iter.key());
- parentItem->setEditable(false);
- viewItemList << parentItem;
- for (const auto &content : contentList) {
- if (!isRuning) {
- qDeleteAll(viewItemList);
- return;
- }
-
- QString title = QString::number(content.first) + " " + content.second;
- QStandardItem *childItem = new QStandardItem(title);
- childItem->setEditable(false);
- int lineNumber = content.first;
- childItem->setData(lineNumber);
- parentItem->appendRow(childItem);
- }
- }
-
- Q_EMIT taskCompleted(viewItemList);
-}
-
-class SearchResultTreeViewPrivate
-{
- SearchResultTreeViewPrivate() {}
- ~SearchResultTreeViewPrivate();
-
- QMap projectInfoMap;
- QThread thread;
- QSharedPointer proxy;
- friend class SearchResultTreeView;
-};
-
-SearchResultTreeViewPrivate::~SearchResultTreeViewPrivate()
-{
- proxy->setRuningState(false);
- thread.quit();
- thread.wait();
-}
-
-SearchResultTreeView::SearchResultTreeView(QWidget *parent)
- : DTreeView(parent), d(new SearchResultTreeViewPrivate())
-{
- QAbstractItemModel *itemModel = new QStandardItemModel(this);
- setModel(itemModel);
-
- QObject::connect(this, &DTreeView::doubleClicked, [=](const QModelIndex &index) {
- if (!index.isValid())
- return;
- if (!index.parent().isValid())
- return;
- QModelIndex parentIndex = index.parent();
- QString filePath = parentIndex.data(Qt::UserRole + 1).toString().trimmed();
- int lineNumber = index.data(Qt::UserRole + 1).toInt();
- qInfo() << filePath << lineNumber;
-
- foreach (QString key, d->projectInfoMap.keys()) {
- if (filePath.contains(key, Qt::CaseInsensitive)) {
- editor.gotoLine(filePath, lineNumber);
- break;
- }
- }
- });
-
- d->proxy.reset(new ItemProxy);
- connect(d->proxy.data(), &ItemProxy::taskCompleted, this, &SearchResultTreeView::appendItems, Qt::QueuedConnection);
-
- d->proxy->moveToThread(&d->thread);
- d->thread.start();
-}
-
-SearchResultTreeView::~SearchResultTreeView()
-{
- delete d;
-}
-
-void SearchResultTreeView::appendData(const FindItemList &itemList, const ProjectInfo &projectInfo)
-{
- d->projectInfoMap = projectInfo;
- d->proxy->setRuningState(true);
- metaObject()->invokeMethod(d->proxy.data(),
- "addTask",
- Qt::QueuedConnection,
- Q_ARG(FindItemList, itemList));
-}
-
-QIcon SearchResultTreeView::icon(const QString &data)
-{
- QFileInfo info(data);
- return iconProvider.icon(info);
-}
-
-void SearchResultTreeView::appendItems(const QList &itemList)
-{
- auto model = qobject_cast(SearchResultTreeView::model());
- if (!model)
- return;
-
- for (auto item : itemList) {
- item->setIcon(icon(item->data().toString()));
- model->appendRow(item);
- }
-}
-
-void SearchResultTreeView::clearData()
-{
- d->proxy->setRuningState(false);
- auto model = qobject_cast(SearchResultTreeView::model());
- model->clear();
-}
+DWIDGET_USE_NAMESPACE
class SearchResultWindowPrivate
{
@@ -197,7 +43,6 @@ SearchResultWindow::SearchResultWindow(QWidget *parent)
setupUi();
qRegisterMetaType("FindItemList");
- qRegisterMetaType("ProjectInfo");
}
SearchResultWindow::~SearchResultWindow()
@@ -244,10 +89,9 @@ void SearchResultWindow::setupUi()
d->treeView = new SearchResultTreeView(this);
d->treeView->setHeaderHidden(true);
d->treeView->setLineWidth(0);
- d->treeView->setItemDelegate(new BaseItemDelegate(this));
+ d->treeView->setItemDelegate(new ResultItemDelegate(this));
QVBoxLayout *vLayout = new QVBoxLayout();
- // vLayout->setAlignment(Qt::AlignTop);
vLayout->setContentsMargins(0, 0, 0, 0);
vLayout->addLayout(hLayout);
vLayout->addWidget(d->treeView, 1);
@@ -274,11 +118,11 @@ void SearchResultWindow::setRepalceWidgtVisible(bool visible)
d->replaceWidget->setVisible(visible);
}
-void SearchResultWindow::appendResults(const FindItemList &itemList, const ProjectInfo &projectInfo)
+void SearchResultWindow::appendResults(const FindItemList &itemList)
{
d->treeView->setVisible(true);
d->iconLabel->setVisible(false);
- d->treeView->appendData(itemList, projectInfo);
+ d->treeView->appendData(itemList);
d->resultCount += itemList.count();
QString msg = tr("%1 matches found.").arg(d->resultCount);
showMsg(true, msg);
@@ -356,3 +200,8 @@ void SearchResultWindow::showMsg(bool succeed, QString msg)
d->resultLabel->setPalette(palette);
d->resultLabel->setText(msg);
}
+
+QStringList SearchResultWindow::resultFileList() const
+{
+ return d->treeView->resultFileList();
+}
diff --git a/src/plugins/find/gui/searchresultwindow.h b/src/plugins/find/gui/searchresultwindow.h
new file mode 100644
index 000000000..aecc4d90f
--- /dev/null
+++ b/src/plugins/find/gui/searchresultwindow.h
@@ -0,0 +1,40 @@
+// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef SEARCHRESULTWINDOW_H
+#define SEARCHRESULTWINDOW_H
+
+#include "constants.h"
+
+#include
+
+class SearchResultWindowPrivate;
+class SearchResultWindow : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit SearchResultWindow(QWidget *parent = nullptr);
+ ~SearchResultWindow();
+
+ void clear();
+ void appendResults(const FindItemList &itemList);
+ void searchFinished();
+ void replaceFinished(bool success);
+ void setRepalceWidgtVisible(bool hide);
+ void showMsg(bool succeed, QString msg);
+ QStringList resultFileList() const;
+
+signals:
+ void reqBack();
+ void reqReplace(const QString &text);
+
+private:
+ void setupUi();
+ void clean();
+ void replace();
+
+ SearchResultWindowPrivate *const d;
+};
+
+#endif // SEARCHRESULTWINDOW_H
diff --git a/src/plugins/find/icons/find_noResults_96px.png b/src/plugins/find/icons/deepin/builtin/icons/find_noResults_96px.png
similarity index 100%
rename from src/plugins/find/icons/find_noResults_96px.png
rename to src/plugins/find/icons/deepin/builtin/icons/find_noResults_96px.png
diff --git a/src/plugins/find/actions/find_matchComplete_16px.svg b/src/plugins/find/icons/deepin/builtin/texts/find_matchComplete_16px.svg
similarity index 100%
rename from src/plugins/find/actions/find_matchComplete_16px.svg
rename to src/plugins/find/icons/deepin/builtin/texts/find_matchComplete_16px.svg
diff --git a/src/plugins/find/icons/deepin/builtin/texts/match_case_16px.svg b/src/plugins/find/icons/deepin/builtin/texts/match_case_16px.svg
new file mode 100644
index 000000000..53bf1172d
--- /dev/null
+++ b/src/plugins/find/icons/deepin/builtin/texts/match_case_16px.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/src/plugins/find/texts/search-find_16px.svg b/src/plugins/find/icons/deepin/builtin/texts/search-find_16px.svg
similarity index 100%
rename from src/plugins/find/texts/search-find_16px.svg
rename to src/plugins/find/icons/deepin/builtin/texts/search-find_16px.svg
diff --git a/src/plugins/find/searchresultwindow.h b/src/plugins/find/searchresultwindow.h
deleted file mode 100644
index e79e70c8d..000000000
--- a/src/plugins/find/searchresultwindow.h
+++ /dev/null
@@ -1,83 +0,0 @@
-// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#ifndef SEARCHRESULTWINDOW_H
-#define SEARCHRESULTWINDOW_H
-
-#include "constants.h"
-
-#include
-#include
-#include
-#include
-
-DWIDGET_USE_NAMESPACE
-
-class ItemProxy : public QObject
-{
- Q_OBJECT
-public:
- explicit ItemProxy(QObject *parent = nullptr);
-
- void setRuningState(bool isRuning);
-
-public Q_SLOTS:
- void addTask(const FindItemList &itemList);
-
-Q_SIGNALS:
- void taskCompleted(const QList &itemList);
-
-private:
- QAtomicInteger isRuning { false };
-};
-
-class SearchResultTreeViewPrivate;
-class SearchResultTreeView : public DTreeView
-{
- Q_OBJECT
- DFileIconProvider iconProvider;
-
-public:
- explicit SearchResultTreeView(QWidget *parent = nullptr);
- ~SearchResultTreeView();
-
- void appendData(const FindItemList &itemList, const ProjectInfo &projectInfo);
- void clearData();
- virtual QIcon icon(const QString &data);
-
-private Q_SLOTS:
- void appendItems(const QList &itemList);
-
-private:
- SearchResultTreeViewPrivate *const d;
-};
-
-class SearchResultWindowPrivate;
-class SearchResultWindow : public DWidget
-{
- Q_OBJECT
-public:
- explicit SearchResultWindow(QWidget *parent = nullptr);
- ~SearchResultWindow();
-
- void clear();
- void appendResults(const FindItemList &itemList, const ProjectInfo &projectInfo);
- void searchFinished();
- void replaceFinished(bool success);
- void setRepalceWidgtVisible(bool hide);
- void showMsg(bool succeed, QString msg);
-
-signals:
- void reqBack();
- void reqReplace(const QString &text);
-
-private:
- void setupUi();
- void clean();
- void replace();
-
- SearchResultWindowPrivate *const d;
-};
-
-#endif // SEARCHRESULTWINDOW_H
diff --git a/src/plugins/find/transceiver/findreceiver.cpp b/src/plugins/find/transceiver/findreceiver.cpp
deleted file mode 100644
index 720dcf692..000000000
--- a/src/plugins/find/transceiver/findreceiver.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#include "findreceiver.h"
-#include "common/common.h"
-#include "services/project/projectservice.h"
-
-FindReceiver::FindReceiver(QObject *parent)
- : dpf::EventHandler(parent)
-{
-
-}
-
-dpf::EventHandler::Type FindReceiver::type()
-{
- return dpf::EventHandler::Type::Sync;
-}
-
-QStringList FindReceiver::topics()
-{
- return { project.topic, editor.topic };
-}
-
-void FindReceiver::eventProcess(const dpf::Event &event)
-{
- if (event.data() == project.activedProject.name) {
- dpfservice::ProjectInfo projectInfo = qvariant_cast(
- event.property(project.activedProject.pKeys[0]));
- QString workspace = projectInfo.workspaceFolder();
- QString language = projectInfo.language();
- emit FindEventTransmit::instance()->sendProjectPath(workspace, language);
- } else if(event.data() == project.openProject.name) {
- dpfservice::ProjectInfo projectInfo = qvariant_cast(
- event.property(project.openProject.pKeys[0]));
- QString workspace = projectInfo.workspaceFolder();
- QString language = projectInfo.language();
- emit FindEventTransmit::instance()->sendProjectPath(workspace, language);
- } else if (event.data() == project.deletedProject.name){
- dpfservice::ProjectInfo projectInfo = qvariant_cast(
- event.property(project.deletedProject.pKeys[0]));
- QString workspace = projectInfo.workspaceFolder();
- emit FindEventTransmit::instance()->sendRemovedProject(workspace);
- } else if (event.data() == editor.fileOpened.name) {
- QString filePath = event.property(editor.fileOpened.pKeys[0]).toString();
- emit FindEventTransmit::instance()->sendCurrentEditFile(filePath, true);
- } else if (event.data() == editor.fileClosed.name) {
- QString filePath = event.property(editor.switchedFile.pKeys[0]).toString();
- emit FindEventTransmit::instance()->sendCurrentEditFile(filePath, false);
- } else if (event.data() == editor.switchedFile.name) {
- QString filePath = event.property(editor.switchedFile.pKeys[0]).toString();
- emit FindEventTransmit::instance()->sendCurrentEditFile(filePath, true);
- }
-}
-
-FindEventTransmit::FindEventTransmit(QObject *parent)
- : QObject(parent)
-{
-}
-
-FindEventTransmit::~FindEventTransmit()
-{
-
-}
-
-FindEventTransmit* FindEventTransmit::instance()
-{
- static FindEventTransmit instance;
- return &instance;
-}
diff --git a/src/plugins/find/transceiver/findreceiver.h b/src/plugins/find/transceiver/findreceiver.h
deleted file mode 100644
index bda8f0f10..000000000
--- a/src/plugins/find/transceiver/findreceiver.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
-//
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-#ifndef FINDRECEIVER_H
-#define FINDRECEIVER_H
-
-#include
-
-class FindReceiver : public dpf::EventHandler, dpf::AutoEventHandlerRegister
-{
- Q_OBJECT
-public:
- explicit FindReceiver(QObject *parent = nullptr);
- static Type type();
- static QStringList topics();
- virtual void eventProcess(const dpf::Event& event) override;
-};
-
-class FindEventTransmit : public QObject
-{
- Q_OBJECT
- Q_DISABLE_COPY(FindEventTransmit)
-public:
- static FindEventTransmit* instance();
-
-signals:
- void sendProjectPath(const QString &projectPath, const QString &language);
- void sendRemovedProject(const QString &projectPath);
- void sendCurrentEditFile(const QString &filePath, bool actived);
-
-private:
- explicit FindEventTransmit(QObject *parent = nullptr);
- virtual ~FindEventTransmit();
-};
-
-
-#endif // FINDRECEIVER_H
diff --git a/src/plugins/find/util/searchplaceworker_p.h b/src/plugins/find/util/searchplaceworker_p.h
new file mode 100644
index 000000000..c5649d3bb
--- /dev/null
+++ b/src/plugins/find/util/searchplaceworker_p.h
@@ -0,0 +1,67 @@
+// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+//
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef SEARCHPLACEWORKER_P_H
+#define SEARCHPLACEWORKER_P_H
+
+#include "searcreplacehworker.h"
+
+#include "services/editor/editorservice.h"
+
+class SearchReplaceWorkerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ enum JobType {
+ SearchJob,
+ ReplaceJob
+ };
+
+ struct Job
+ {
+ JobType type;
+ QString cmd;
+ QString channelData;
+ QString keyword;
+ bool caseSensitive = false;
+ bool wholeWords = false;
+ };
+
+ explicit SearchReplaceWorkerPrivate(SearchReplaceWorker *qq);
+ ~SearchReplaceWorkerPrivate();
+
+ void startAll();
+ void startNextJob();
+
+ void createSearchJob(const SearchParams ¶ms);
+ void createReplaceJob(const ReplaceParams ¶ms);
+ Job buildSearchJob(const QStringList &fileList,
+ const QStringList &includeList,
+ const QStringList &excludeList,
+ const QString &keyword,
+ SearchFlags flags,
+ bool isOpenedFile);
+ Job buildReplaceJob(const QStringList &fileList,
+ const QString &oldText,
+ const QString &newText,
+ SearchFlags flags,
+ bool isOpenedFile);
+
+ void processWorkingFiles(QStringList &baseFiles, QStringList &openedFiles);
+ Q_INVOKABLE void replaceOpenedFile(const QString &fileName, const QString &oldText,
+ const QString &newText, bool caseSensitive, bool wholeWords);
+
+public:
+ SearchReplaceWorker *q;
+
+ dpfservice::EditorService *editSrv { nullptr };
+ QMutex mutex;
+ FindItemList searchResults;
+ QSharedPointer process { nullptr };
+
+ QList jobList;
+ int currentJob = 0;
+};
+
+#endif // SEARCHPLACEWORKER_P_H
diff --git a/src/plugins/find/util/searcreplacehworker.cpp b/src/plugins/find/util/searcreplacehworker.cpp
index baad9351c..6fb0b5bd6 100644
--- a/src/plugins/find/util/searcreplacehworker.cpp
+++ b/src/plugins/find/util/searcreplacehworker.cpp
@@ -3,76 +3,211 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#include "searcreplacehworker.h"
+#include "searchplaceworker_p.h"
+
+#include "common/util/qtcassert.h"
#include
#include
#include
#include
-class SearchReplaceWorkerPrivate
+using namespace dpfservice;
+
+SearchReplaceWorkerPrivate::SearchReplaceWorkerPrivate(SearchReplaceWorker *qq)
+ : q(qq)
{
-public:
- explicit SearchReplaceWorkerPrivate(SearchReplaceWorker *qq);
- ~SearchReplaceWorkerPrivate();
+}
- QString buildCommand(const SearchParams ¶ms);
- QString buildCommand(const ReplaceParams ¶ms);
+SearchReplaceWorkerPrivate::~SearchReplaceWorkerPrivate()
+{
+ q->stop();
+}
-public:
- SearchReplaceWorker *q;
+void SearchReplaceWorkerPrivate::startAll()
+{
+ QTC_ASSERT(!jobList.isEmpty(), return );
+ QTC_ASSERT(!process, return );
- QMutex mutex;
- FindItemList searchResults;
- QAtomicInteger isRuning { false };
- QSharedPointer searchProcess { nullptr };
- QSharedPointer replaceProcess { nullptr };
- QString filePath;
-};
+ currentJob = 0;
+ startNextJob();
+}
-SearchReplaceWorkerPrivate::SearchReplaceWorkerPrivate(SearchReplaceWorker *qq)
- : q(qq)
+void SearchReplaceWorkerPrivate::startNextJob()
{
+ QTC_ASSERT(currentJob < jobList.count(), return );
+
+ Job job = jobList.at(currentJob);
+ process.reset(new QProcess);
+ if (job.type == SearchJob)
+ connect(process.data(), &QProcess::readyReadStandardOutput, q,
+ std::bind(&SearchReplaceWorker::handleReadSearchResult, q, job.keyword, job.caseSensitive, job.wholeWords));
+ connect(process.data(), qOverload(&QProcess::finished),
+ q, std::bind(&SearchReplaceWorker::processDone, q, job.type));
+
+ process->start(job.cmd);
+ if (!job.channelData.isEmpty()) {
+ process->write(job.channelData.toUtf8());
+ process->closeWriteChannel();
+ }
}
-SearchReplaceWorkerPrivate::~SearchReplaceWorkerPrivate()
+void SearchReplaceWorkerPrivate::createSearchJob(const SearchParams ¶ms)
{
- if (searchProcess && searchProcess->state() != QProcess::NotRunning)
- searchProcess->kill();
+ jobList.clear();
+ switch (params.scope) {
+ case AllProjects:
+ case CurrentProject: {
+ auto tmpParams = params;
+ processWorkingFiles(tmpParams.baseParams.baseFileList, tmpParams.baseParams.openedFileList);
+ for (const auto &file : tmpParams.baseParams.openedFileList) {
+ const auto &job = buildSearchJob({ file }, tmpParams.includeList, tmpParams.excludeList,
+ tmpParams.baseParams.keyword, tmpParams.flags, true);
+ if (!job.cmd.isEmpty())
+ jobList << job;
+ }
+
+ const auto &job = buildSearchJob(tmpParams.baseParams.baseFileList, tmpParams.includeList, tmpParams.excludeList,
+ tmpParams.baseParams.keyword, tmpParams.flags, false);
+ if (!job.cmd.isEmpty())
+ jobList << job;
+ } break;
+ case CurrentFile: {
+ const auto &job = buildSearchJob(params.baseParams.openedFileList, params.includeList, params.excludeList,
+ params.baseParams.keyword, params.flags, true);
+ if (!job.cmd.isEmpty())
+ jobList << job;
+ } break;
+ default:
+ break;
+ }
+}
+
+void SearchReplaceWorkerPrivate::createReplaceJob(const ReplaceParams ¶ms)
+{
+ jobList.clear();
+ auto tmpParams = params;
+ processWorkingFiles(tmpParams.baseParams.baseFileList, tmpParams.baseParams.openedFileList);
+ buildReplaceJob(tmpParams.baseParams.openedFileList,
+ tmpParams.baseParams.keyword,
+ tmpParams.replaceText,
+ tmpParams.flags, true);
+
+ const auto &job = buildReplaceJob(tmpParams.baseParams.baseFileList,
+ tmpParams.baseParams.keyword,
+ tmpParams.replaceText,
+ tmpParams.flags, false);
+ if (!job.cmd.isEmpty())
+ jobList << job;
+}
+
+SearchReplaceWorkerPrivate::Job
+SearchReplaceWorkerPrivate::buildSearchJob(const QStringList &fileList,
+ const QStringList &includeList,
+ const QStringList &excludeList,
+ const QString &keyword, SearchFlags flags,
+ bool isOpenedFile)
+{
+ if (fileList.isEmpty())
+ return {};
+
+ Job job;
+ job.type = SearchJob;
+ job.keyword = keyword;
+ QStringList cmd;
+ cmd << "grep -Hn";
+ if (!flags.testFlag(SearchCaseSensitive))
+ cmd << "-i";
+ else
+ job.caseSensitive = true;
+
+ if (flags.testFlag(SearchWholeWord)) {
+ cmd << "-w";
+ job.wholeWords = true;
+ }
+
+ if (!includeList.isEmpty())
+ cmd << "--include=" + includeList.join(" --include=");
+ if (!excludeList.isEmpty())
+ cmd << "--exclude=" + excludeList.join(" --exclude=");
+ cmd << "\"" + keyword + "\"";
+
+ if (isOpenedFile) {
+ if (!editSrv)
+ editSrv = dpfGetService(EditorService);
+ job.channelData = editSrv->fileText(fileList.first());
+ cmd << "--label=" + fileList.first();
+ } else {
+ QString searchPath = fileList.join(' ');
+ cmd << searchPath;
+ }
- if (replaceProcess && replaceProcess->state() != QProcess::NotRunning)
- replaceProcess->kill();
+ job.cmd = cmd.join(' ');
+ return job;
}
-QString SearchReplaceWorkerPrivate::buildCommand(const SearchParams ¶ms)
+SearchReplaceWorkerPrivate::Job
+SearchReplaceWorkerPrivate::buildReplaceJob(const QStringList &fileList,
+ const QString &oldText,
+ const QString &newText,
+ SearchFlags flags,
+ bool isOpenedFile)
{
- filePath = params.filePathList.join(" ");
- QString sensitiveFlag = params.sensitiveFlag ? "" : " -i ";
- QString wholeWordsFlag = params.wholeWordsFlag ? " -w " : "";
- QString patternList;
- if (!params.patternsList.isEmpty())
- patternList = " --include=" + params.patternsList.join(" --include=");
+ if (fileList.isEmpty())
+ return {};
+
+ Job job;
+ job.type = ReplaceJob;
+ if (isOpenedFile) {
+ for (const auto &file : fileList) {
+ QMetaObject::invokeMethod(this, "replaceOpenedFile",
+ Qt::QueuedConnection,
+ Q_ARG(QString, file),
+ Q_ARG(QString, oldText),
+ Q_ARG(QString, newText),
+ Q_ARG(bool, flags.testFlag(SearchCaseSensitive)),
+ Q_ARG(bool, flags.testFlag(SearchWholeWord)));
+ }
+ } else {
+ QStringList cmd;
+ cmd << "sed -i ";
+
+ QString body("s/%1/%2/g");
+ if (flags.testFlag(SearchWholeWord)) {
+ body = body.arg("\\<" + oldText + "\\>", newText);
+ } else {
+ body = body.arg(oldText, newText);
+ }
+
+ if (!flags.testFlag(SearchCaseSensitive))
+ body += "I";
- QString exPatternList(" --exclude-dir=.*");
- if (!params.exPatternsList.isEmpty()) {
- QString format(" --exclude={%1}");
- exPatternList += format.arg(params.exPatternsList.join(','));
+ cmd << "\"" + body + "\""
+ << fileList.join(' ');
+ job.cmd = cmd.join(' ');
}
- QString cmd = QString("grep -rn " + sensitiveFlag + wholeWordsFlag
- + "\"" + params.searchText + "\" "
- + patternList + exPatternList + " " + filePath);
- return cmd;
+ return job;
}
-QString SearchReplaceWorkerPrivate::buildCommand(const ReplaceParams ¶ms)
+void SearchReplaceWorkerPrivate::processWorkingFiles(QStringList &baseFiles, QStringList &openedFiles)
{
- QString filePath = params.filePathList.join(' ');
+ for (int i = 0; i < openedFiles.size();) {
+ if (!baseFiles.contains(openedFiles.at(i))) {
+ openedFiles.removeAt(i);
+ } else {
+ baseFiles.removeOne(openedFiles.at(i));
+ ++i;
+ }
+ }
+}
- //exam: sed -i "s/main/main1/g" `grep -rl "main" /project/test`
- QString cmd = "sed -i \"s/" + params.searchText
- + "/" + params.replaceText + "/g\" `grep -rl \"" + params.searchText
- + "\" " + filePath + "`";
- return cmd;
+void SearchReplaceWorkerPrivate::replaceOpenedFile(const QString &fileName, const QString &oldText,
+ const QString &newText, bool caseSensitive, bool wholeWords)
+{
+ if (!editSrv)
+ editSrv = dpfGetService(EditorService);
+ editSrv->replaceAll(fileName, oldText, newText, caseSensitive, wholeWords);
}
SearchReplaceWorker::SearchReplaceWorker(QObject *parent)
@@ -88,7 +223,11 @@ SearchReplaceWorker::~SearchReplaceWorker()
void SearchReplaceWorker::stop()
{
- d->isRuning = false;
+ if (d->process) {
+ d->process->kill();
+ d->process->waitForFinished();
+ d->process.reset();
+ }
}
FindItemList SearchReplaceWorker::getResults()
@@ -99,66 +238,53 @@ FindItemList SearchReplaceWorker::getResults()
void SearchReplaceWorker::addSearchTask(const SearchParams ¶ms)
{
- d->isRuning = true;
- if (!d->searchProcess)
- d->searchProcess.reset(new QProcess);
-
- connect(d->searchProcess.data(), &QProcess::readyReadStandardOutput,
- this, &SearchReplaceWorker::handleReadSearchResult,
- Qt::UniqueConnection);
- connect(d->searchProcess.data(), qOverload(&QProcess::finished),
- this, &SearchReplaceWorker::searchFinished,
- Qt::UniqueConnection);
+ d->createSearchJob(params);
+ if (d->jobList.isEmpty()) {
+ Q_EMIT searchFinished();
+ return;
+ }
- const auto &cmd = d->buildCommand(params);
- d->searchProcess->start(cmd);
- d->searchProcess->waitForFinished(-1);
- d->isRuning = false;
+ d->startAll();
}
void SearchReplaceWorker::addReplaceTask(const ReplaceParams ¶ms)
{
- d->isRuning = true;
- if (!d->replaceProcess)
- d->replaceProcess.reset(new QProcess);
-
- connect(d->replaceProcess.data(), qOverload(&QProcess::finished),
- this, &SearchReplaceWorker::replaceFinished,
- Qt::UniqueConnection);
-
- const auto &cmd = d->buildCommand(params);
- QStringList options;
- options << "-c" << cmd;
+ d->createReplaceJob(params);
+ if (d->jobList.isEmpty()) {
+ Q_EMIT replaceFinished(0);
+ return;
+ }
- d->replaceProcess->start("/bin/sh", options);
- d->replaceProcess->waitForFinished(-1);
- d->isRuning = false;
+ d->startAll();
}
-void SearchReplaceWorker::handleReadSearchResult()
+void SearchReplaceWorker::handleReadSearchResult(const QString &keyword, bool caseSensitive, bool wholeWords)
{
- if (!d->isRuning) {
- d->searchProcess->terminate();
- return;
- }
-
const auto resultLineRegex = QRegularExpression(R"((.+):([0-9]+):(.+))", QRegularExpression::NoPatternOption);
- while (d->searchProcess->canReadLine()) {
- const auto &line = d->searchProcess->readLine();
- if (!d->isRuning) {
- d->searchProcess->terminate();
- return;
- }
-
+ while (d->process->canReadLine()) {
+ const auto &line = d->process->readLine();
QRegularExpressionMatch regMatch;
if ((regMatch = resultLineRegex.match(line)).hasMatch()) {
- FindItem findItem;
- findItem.filePathName = regMatch.captured(1).trimmed().toStdString().c_str();
- findItem.lineNumber = regMatch.captured(2).trimmed().toInt();
- findItem.context = regMatch.captured(3).trimmed().toStdString().c_str();
+ auto name = regMatch.captured(1);
+ auto line = regMatch.captured(2).toInt();
+ auto context = regMatch.captured(3);
+
+ QString pattern = keyword;
+ if (wholeWords)
+ pattern = "\\b" + keyword + "\\b";
+ QRegularExpression regex(pattern, caseSensitive ? QRegularExpression::NoPatternOption : QRegularExpression::CaseInsensitiveOption);
+ for (int index = context.indexOf(regex); index != -1;) {
+ FindItem findItem;
+ findItem.filePathName = name;
+ findItem.line = line;
+ findItem.keyword = keyword;
+ findItem.context = context;
+ findItem.column = index;
- QMutexLocker lk(&d->mutex);
- d->searchResults.append(findItem);
+ index = context.indexOf(regex, index + keyword.size());
+ QMutexLocker lk(&d->mutex);
+ d->searchResults.append(findItem);
+ }
}
}
@@ -166,3 +292,21 @@ void SearchReplaceWorker::handleReadSearchResult()
if (!d->searchResults.isEmpty())
Q_EMIT matched();
}
+
+void SearchReplaceWorker::processDone(int jobType)
+{
+ ++d->currentJob;
+ const bool success = d->process->exitCode() == 0;
+ if (d->currentJob < d->jobList.count() && success) {
+ d->process.reset();
+ d->startNextJob();
+ return;
+ }
+
+ if (jobType == SearchReplaceWorkerPrivate::SearchJob)
+ Q_EMIT searchFinished();
+ else
+ Q_EMIT replaceFinished(d->process->exitCode());
+
+ d->process.reset();
+}
diff --git a/src/plugins/find/util/searcreplacehworker.h b/src/plugins/find/util/searcreplacehworker.h
index 6acffd105..bec5355be 100644
--- a/src/plugins/find/util/searcreplacehworker.h
+++ b/src/plugins/find/util/searcreplacehworker.h
@@ -18,6 +18,7 @@ class SearchReplaceWorker : public QObject
~SearchReplaceWorker();
void stop();
+
FindItemList getResults();
public Q_SLOTS:
@@ -30,9 +31,11 @@ public Q_SLOTS:
void replaceFinished(int result);
private Q_SLOTS:
- void handleReadSearchResult();
+ void handleReadSearchResult(const QString &keyword, bool caseSensitive, bool wholeWords);
+ void processDone(int jobType);
private:
+ friend class SearchReplaceWorkerPrivate;
SearchReplaceWorkerPrivate *const d;
};
diff --git a/src/plugins/git/client/gitclient.cpp b/src/plugins/git/client/gitclient.cpp
index baca35853..5681e62fb 100644
--- a/src/plugins/git/client/gitclient.cpp
+++ b/src/plugins/git/client/gitclient.cpp
@@ -44,7 +44,7 @@ class GitClientPrivate : public QObject
QString GitClientPrivate::findRepository(const QString &filePath)
{
- if (filePath == "/")
+ if (filePath == "/" || filePath.isEmpty())
return {};
QFileInfo info(filePath);
@@ -275,16 +275,17 @@ bool GitClient::gitDiff(const QString &filePath, bool isProject)
return true;
}
-void GitClient::show(const QString &source, const QString &commitId)
+bool GitClient::show(const QString &source, const QString &commitId)
{
if (!d->canShow(commitId))
- return;
+ return false;
QString repository;
if (!checkRepositoryExist(source, &repository))
- return;
+ return false;
d->show(repository, commitId);
+ return true;
}
QWidget *GitClient::instantBlameWidget() const
diff --git a/src/plugins/git/client/gitclient.h b/src/plugins/git/client/gitclient.h
index 47ed76748..38061dd5d 100644
--- a/src/plugins/git/client/gitclient.h
+++ b/src/plugins/git/client/gitclient.h
@@ -24,7 +24,7 @@ class GitClient : public QObject
bool gitLog(const QString &filePath, bool isProject);
bool blameFile(const QString &filePath);
bool gitDiff(const QString &filePath, bool isProject);
- void show(const QString &source, const QString &commitId);
+ bool show(const QString &source, const QString &commitId);
QWidget *instantBlameWidget() const;
QWidget *gitTabWidget() const;
diff --git a/src/plugins/git/gui/instantblamewidget.cpp b/src/plugins/git/gui/instantblamewidget.cpp
index 538d0a2c3..167ac8bdb 100644
--- a/src/plugins/git/gui/instantblamewidget.cpp
+++ b/src/plugins/git/gui/instantblamewidget.cpp
@@ -65,8 +65,8 @@ void InstantBlameWidget::mousePressEvent(QMouseEvent *event)
if (editSrv) {
auto file = editSrv->currentFile();
auto ret = parserBlameOutput(info.split('\n'));
- GitClient::instance()->show(file, ret.sha1);
- editSrv->switchWidget(GitWindow);
+ if (GitClient::instance()->show(file, ret.sha1))
+ editSrv->switchWidget(GitWindow);
}
QWidget::mousePressEvent(event);
diff --git a/src/plugins/git/transceiver/gitreceiver.cpp b/src/plugins/git/transceiver/gitreceiver.cpp
index 36ca660a3..d2dc58ef7 100644
--- a/src/plugins/git/transceiver/gitreceiver.cpp
+++ b/src/plugins/git/transceiver/gitreceiver.cpp
@@ -17,7 +17,7 @@ GitReceiver::GitReceiver(QObject *parent)
using namespace std::placeholders;
eventHandleMap.insert(editor.switchedFile.name, std::bind(&GitReceiver::handleSwitchedFileEvent, this, _1));
eventHandleMap.insert(editor.contextMenu.name, std::bind(&GitReceiver::handleContextMenuEvent, this, _1));
- eventHandleMap.insert(project.activedProject.name, std::bind(&GitReceiver::handleProjectChangedEvent, this, _1));
+ eventHandleMap.insert(project.activatedProject.name, std::bind(&GitReceiver::handleProjectChangedEvent, this, _1));
eventHandleMap.insert(project.deletedProject.name, std::bind(&GitReceiver::handleProjectChangedEvent, this, _1));
}
diff --git a/src/plugins/project/mainframe/projecttree.cpp b/src/plugins/project/mainframe/projecttree.cpp
index 64b9ba6af..2acf39764 100644
--- a/src/plugins/project/mainframe/projecttree.cpp
+++ b/src/plugins/project/mainframe/projecttree.cpp
@@ -38,6 +38,8 @@ class ProjectTreePrivate
ProjectDelegate *delegate {nullptr};
DDialog *messDialog = nullptr;
QPoint startPos;
+ QString currentFile = "";
+ bool autoFocusState = true;
int itemDepth(const QStandardItem *item)
{
int depth = 0;
@@ -266,6 +268,47 @@ void ProjectTree::expandedProjectAll(const QStandardItem *root)
}
}
+void ProjectTree::selectProjectFile(const QString &file)
+{
+ d->currentFile = file;
+ if (!d->autoFocusState)
+ return;
+ focusCurrentFile();
+}
+
+void ProjectTree::focusCurrentFile()
+{
+ QModelIndex root = d->itemModel->index(0, 0);
+ if (!root.isValid()) {
+ return;
+ }
+ if (d->currentFile.isEmpty()) {
+ clearSelection();
+ return;
+ }
+ QModelIndexList indices = model()->match(root, Qt::ToolTipRole, d->currentFile, 1, Qt::MatchExactly | Qt::MatchRecursive);
+ if (!indices.isEmpty()) {
+ QModelIndex index = indices.first();
+
+ QModelIndex parent = index.parent();
+ while (parent.isValid()) {
+ expand(parent);
+ parent = parent.parent();
+ }
+ setCurrentIndex(index);
+ }
+}
+
+void ProjectTree::setAutoFocusState(bool state)
+{
+ d->autoFocusState = state;
+}
+
+bool ProjectTree::getAutoFocusState() const
+{
+ return d->autoFocusState;
+}
+
QList ProjectTree::getAllProjectInfo()
{
using namespace dpfservice;
diff --git a/src/plugins/project/mainframe/projecttree.h b/src/plugins/project/mainframe/projecttree.h
index 9854d9560..191f26cd5 100644
--- a/src/plugins/project/mainframe/projecttree.h
+++ b/src/plugins/project/mainframe/projecttree.h
@@ -29,6 +29,10 @@ class ProjectTree : public DTreeView
void takeRootItem(QStandardItem *root);
void expandedProjectDepth(const QStandardItem *root, int depth);
void expandedProjectAll(const QStandardItem *root);
+ void selectProjectFile(const QString &file);
+ void setAutoFocusState(bool state);
+ bool getAutoFocusState() const;
+ void focusCurrentFile();
QList getAllProjectInfo();
dpfservice::ProjectInfo getProjectInfo(const QString &kitName, const QString &workspace) const;
dpfservice::ProjectInfo getActiveProjectInfo() const;
diff --git a/src/plugins/project/projectcore.cpp b/src/plugins/project/projectcore.cpp
index b6fcb0613..337b6cca3 100644
--- a/src/plugins/project/projectcore.cpp
+++ b/src/plugins/project/projectcore.cpp
@@ -47,6 +47,32 @@ bool ProjectCore::start()
DToolButton *projectProperty = new DToolButton(ProjectKeeper::instance()->treeView());
projectProperty->setIcon(QIcon::fromTheme("settings"));
projectProperty->setToolTip(tr("Open activted project`s property dialog"));
+
+ DToolButton *autoFocusSwitcher = new DToolButton(ProjectKeeper::instance()->treeView());
+ autoFocusSwitcher->setToolTip(tr("Auto Focus"));
+ autoFocusSwitcher->setIcon(QIcon::fromTheme("focus_auto"));
+ autoFocusSwitcher->setCheckable(true);
+ autoFocusSwitcher->setChecked(true);
+
+ DToolButton *focusFile = new DToolButton(ProjectKeeper::instance()->treeView());
+ focusFile->setToolTip(tr("Focus File"));
+ focusFile->setIcon(QIcon::fromTheme("focus"));
+
+ connect(focusFile, &DToolButton::clicked, this, [](){
+ ProjectKeeper::instance()->treeView()->focusCurrentFile();
+ }, Qt::DirectConnection);
+ focusFile->hide();
+
+ connect(autoFocusSwitcher, &DToolButton::clicked, this, [=](){
+ bool state = ProjectKeeper::instance()->treeView()->getAutoFocusState();
+ ProjectKeeper::instance()->treeView()->setAutoFocusState(!state);
+ if (state) {
+ focusFile->show();
+ } else {
+ focusFile->hide();
+ }
+ }, Qt::DirectConnection);
+
connect(projectProperty, &DToolButton::clicked, this, [=](){
project.openProjectPropertys(ProjectKeeper::instance()->treeView()->getActiveProjectInfo());
}, Qt::DirectConnection);
@@ -57,6 +83,8 @@ bool ProjectCore::start()
else
projectProperty->setEnabled(true);
}, Qt::DirectConnection);
+ windowService->registerToolBtnToWorkspaceWidget(focusFile, MWCWT_PROJECTS);
+ windowService->registerToolBtnToWorkspaceWidget(autoFocusSwitcher, MWCWT_PROJECTS);
windowService->registerToolBtnToWorkspaceWidget(projectProperty, MWCWT_PROJECTS);
}
}
diff --git a/src/plugins/project/resource.qrc b/src/plugins/project/resource.qrc
index 77c43e0a6..2d6d43cc6 100644
--- a/src/plugins/project/resource.qrc
+++ b/src/plugins/project/resource.qrc
@@ -2,5 +2,7 @@
texts/project_16px.svg
texts/settings_16px.svg
+ texts/focus_16px.svg
+ texts/focus_auto_16px.svg
diff --git a/src/plugins/project/texts/focus_16px.svg b/src/plugins/project/texts/focus_16px.svg
new file mode 100644
index 000000000..39335fe42
--- /dev/null
+++ b/src/plugins/project/texts/focus_16px.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/src/plugins/project/texts/focus_auto_16px.svg b/src/plugins/project/texts/focus_auto_16px.svg
new file mode 100644
index 000000000..e309c9500
--- /dev/null
+++ b/src/plugins/project/texts/focus_auto_16px.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/src/plugins/project/transceiver/projectcorereceiver.cpp b/src/plugins/project/transceiver/projectcorereceiver.cpp
index 18fba6917..2a458f865 100644
--- a/src/plugins/project/transceiver/projectcorereceiver.cpp
+++ b/src/plugins/project/transceiver/projectcorereceiver.cpp
@@ -23,7 +23,7 @@ dpf::EventHandler::Type ProjectCoreReceiver::type()
QStringList ProjectCoreReceiver::topics()
{
- return {project.topic, workspace.topic}; //绑定menu 事件
+ return {project.topic, workspace.topic, editor.topic}; //绑定menu 事件
}
void ProjectCoreReceiver::eventProcess(const dpf::Event &event)
@@ -31,9 +31,9 @@ void ProjectCoreReceiver::eventProcess(const dpf::Event &event)
using namespace dpfservice;
if (event.data() == project.activeProject.name) {
auto infos = ProjectKeeper::instance()->treeView()->getAllProjectInfo();
- QString kitName = event.property(project.openProject.pKeys[0]).toString();
- QString language = event.property(project.openProject.pKeys[1]).toString();
- QString workspace = event.property(project.openProject.pKeys[2]).toString();
+ QString kitName = event.property("kitName").toString();
+ QString language = event.property("language").toString();
+ QString workspace = event.property("workspace").toString();
ProjectKeeper::instance()->treeView()->activeProjectInfo(kitName, language, workspace);
} else if (event.data() == project.openProject.name) {
uiController.doSwitch(dpfservice::MWNA_EDIT);
@@ -60,11 +60,13 @@ void ProjectCoreReceiver::eventProcess(const dpf::Event &event)
ProjectKeeper::instance()->treeView()->expandAll();
} else if (event.data() == workspace.foldAll.name) {
ProjectKeeper::instance()->treeView()->collapseAll();
- } else if (event.data() == project.activedProject.name) {
+ } else if (event.data() == project.activatedProject.name) {
QVariant proInfoVar = event.property("projectInfo");
dpfservice::ProjectInfo projectInfo = qvariant_cast(proInfoVar);
emit ProjectProxy::instance()->projectActivated(projectInfo);
+ } else if (event.data() == editor.switchedFile.name) {
+ ProjectKeeper::instance()->treeView()->selectProjectFile(event.property("fileName").toString());
}
}
diff --git a/src/plugins/project/transceiver/sendevents.cpp b/src/plugins/project/transceiver/sendevents.cpp
index 49fb22205..477a29369 100644
--- a/src/plugins/project/transceiver/sendevents.cpp
+++ b/src/plugins/project/transceiver/sendevents.cpp
@@ -8,7 +8,7 @@
void SendEvents::projectActived(const dpfservice::ProjectInfo &info)
{
- project.activedProject(info);
+ project.activatedProject(info);
}
void SendEvents::projectCreated(const dpfservice::ProjectInfo &info)
diff --git a/src/plugins/symbol/transceiver/symbolreceiver.cpp b/src/plugins/symbol/transceiver/symbolreceiver.cpp
index 8e318623e..d5575dee6 100644
--- a/src/plugins/symbol/transceiver/symbolreceiver.cpp
+++ b/src/plugins/symbol/transceiver/symbolreceiver.cpp
@@ -32,8 +32,8 @@ QStringList SymbolReceiver::topics()
void SymbolReceiver::eventProcess(const dpf::Event &event)
{
- if (event.data() == project.activedProject.name) {
- QString projectInfoKey = project.activedProject.pKeys[0];
+ if (event.data() == project.activatedProject.name) {
+ QString projectInfoKey = project.activatedProject.pKeys[0];
dpfservice::ProjectInfo info = qvariant_cast
(event.property(projectInfoKey));
QString workspace = info.workspaceFolder();
diff --git a/src/plugins/valgrind/mainframe/valgrindrunner.cpp b/src/plugins/valgrind/mainframe/valgrindrunner.cpp
index 95527ddcc..d0d979328 100644
--- a/src/plugins/valgrind/mainframe/valgrindrunner.cpp
+++ b/src/plugins/valgrind/mainframe/valgrindrunner.cpp
@@ -24,7 +24,7 @@ class ValgrindRunnerPrivate
QStringList ValgrindArgs;
dpfservice::ProjectInfo projectInfo;
- QString activedProjectKitName;
+ QString activatedProjectKitName;
QString workingDir;
QString currentFilePath;
QString targetPath;
@@ -73,7 +73,7 @@ void ValgrindRunner::initialize()
});
});
- setActionsStatus(d->activedProjectKitName);
+ setActionsStatus(d->activatedProjectKitName);
}
void ValgrindRunner::runValgrind(const QString &type)
@@ -157,13 +157,13 @@ void ValgrindRunner::setActionsStatus(const QString &kitName)
void ValgrindRunner::saveCurrentProjectInfo(const ProjectInfo &projectInfo)
{
d->projectInfo = projectInfo;
- d->activedProjectKitName = d->projectInfo.kitName();
- setActionsStatus(d->activedProjectKitName);
+ d->activatedProjectKitName = d->projectInfo.kitName();
+ setActionsStatus(d->activatedProjectKitName);
}
void ValgrindRunner::removeProjectInfo()
{
- d->activedProjectKitName.clear();
+ d->activatedProjectKitName.clear();
setActionsStatus("");
}
@@ -182,7 +182,7 @@ void ValgrindRunner::runBuilding()
auto &ctx = dpfInstance.serviceContext();
LanguageService *service = ctx.service(LanguageService::name());
if (service) {
- auto generator = service->create(d->activedProjectKitName);
+ auto generator = service->create(d->activatedProjectKitName);
if (generator) {
if (generator->isNeedBuild()) {
generator->build(d->projectInfo.workspaceFolder());
diff --git a/src/plugins/valgrind/transceiver/valgrindreceiver.cpp b/src/plugins/valgrind/transceiver/valgrindreceiver.cpp
index c7a2e7ab9..cf85d45d1 100644
--- a/src/plugins/valgrind/transceiver/valgrindreceiver.cpp
+++ b/src/plugins/valgrind/transceiver/valgrindreceiver.cpp
@@ -30,8 +30,8 @@ QStringList ValgrindReceiver::topics()
void ValgrindReceiver::eventProcess(const dpf::Event &event)
{
- if (event.data() == project.activedProject.name) {
- QVariant proInfoVar = event.property(project.activedProject.pKeys[0]);
+ if (event.data() == project.activatedProject.name) {
+ QVariant proInfoVar = event.property(project.activatedProject.pKeys[0]);
dpfservice::ProjectInfo projectInfo = qvariant_cast(proInfoVar);
QString buildFolder = projectInfo.buildFolder();
ValgrindRunner::instance()->saveCurrentProjectInfo(projectInfo);
diff --git a/src/services/editor/editorservice.h b/src/services/editor/editorservice.h
index 13272f4c9..19411398f 100644
--- a/src/services/editor/editorservice.h
+++ b/src/services/editor/editorservice.h
@@ -41,6 +41,10 @@ class EditorService final : public dpf::PluginService,
DPF_INTERFACE(void, setText, const QString &text);
DPF_INTERFACE(void, setCompletion, const QString &info, const QIcon &icon, const QKeySequence &key);
DPF_INTERFACE(QString, currentFile);
+ DPF_INTERFACE(QStringList, openedFiles);
+ DPF_INTERFACE(QString, fileText, const QString &file);
+ DPF_INTERFACE(void, replaceAll, const QString &file, const QString &oldText,
+ const QString &newText, bool caseSensitive, bool wholeWords);
DPF_INTERFACE(void, registerSciLexerProxy, const QString &language, AbstractLexerProxy *proxy);
DPF_INTERFACE(void, registerWidget, const QString &id, AbstractEditWidget *widget);