1 | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. |
2 | // |
3 | // SPDX-License-Identifier: GPL-3.0-or-later |
4 | |
5 | #include "findtoolwindow.h" |
6 | #include "searchresultwindow.h" |
7 | #include "transceiver/findreceiver.h" |
8 | |
9 | #include <QVBoxLayout> |
10 | #include <QHBoxLayout> |
11 | #include <QLineEdit> |
12 | #include <QLabel> |
13 | #include <QComboBox> |
14 | #include <QCheckBox> |
15 | #include <QPushButton> |
16 | #include <QDebug> |
17 | #include <QStackedWidget> |
18 | #include <QProcess> |
19 | #include <QMessageBox> |
20 | #include <QScrollArea> |
21 | |
22 | #define LABEL_WIDTH (150) |
23 | |
24 | class FindToolWindowPrivate |
25 | { |
26 | FindToolWindowPrivate(){} |
27 | QStackedWidget *stackedWidget{nullptr}; |
28 | SearchResultWindow *searchResultWindow{nullptr}; |
29 | QSet<QString> allProjectsPathList{nullptr}; |
30 | QString currentProjectPath; |
31 | QString currentFilePath; |
32 | QMap<QString, QString> projectInfoMap; |
33 | |
34 | QComboBox *scopeComboBox{nullptr}; |
35 | QLineEdit *searchLineEdit{nullptr}; |
36 | QCheckBox *senseCheckBox{nullptr}; |
37 | QCheckBox *wholeWordsCheckBox{nullptr}; |
38 | QCheckBox *regularCheckBox{nullptr}; |
39 | QLineEdit *patternLineEdit{nullptr}; |
40 | QLineEdit *expatternLineEdit{nullptr}; |
41 | |
42 | friend class FindToolWindow; |
43 | }; |
44 | |
45 | FindToolWindow::FindToolWindow(QWidget *parent) |
46 | : QWidget(parent) |
47 | , d(new FindToolWindowPrivate()) |
48 | { |
49 | setupUi(); |
50 | |
51 | connect(FindEventTransmit::instance(), QOverload<const QString &, const QString &>::of(&FindEventTransmit::sendProjectPath), |
52 | [=](const QString &projectPath, const QString &language){ |
53 | d->currentProjectPath = projectPath; |
54 | d->projectInfoMap.insert(projectPath, language); |
55 | d->allProjectsPathList.insert(projectPath); |
56 | }); |
57 | |
58 | connect(FindEventTransmit::instance(), QOverload<const QString &>::of(&FindEventTransmit::sendRemovedProject), |
59 | [=](const QString &projectPath){ |
60 | d->currentProjectPath = "" ; |
61 | d->allProjectsPathList.remove(projectPath); |
62 | d->projectInfoMap.remove(projectPath); |
63 | }); |
64 | |
65 | connect(FindEventTransmit::instance(), QOverload<const QString &, bool>::of(&FindEventTransmit::sendCurrentEditFile), |
66 | [=](const QString &filePath, bool actived){ |
67 | if (actived) { |
68 | d->currentFilePath = filePath; |
69 | } |
70 | else |
71 | d->currentFilePath = "" ; |
72 | }); |
73 | } |
74 | |
75 | void FindToolWindow::setupUi() |
76 | { |
77 | d->stackedWidget = new QStackedWidget(); |
78 | QVBoxLayout *vLayout = new QVBoxLayout(); |
79 | |
80 | QScrollArea *scrollArea = new QScrollArea(); |
81 | scrollArea->setWidgetResizable(true); |
82 | scrollArea->setWidget(d->stackedWidget); |
83 | vLayout->addWidget(scrollArea); |
84 | |
85 | QWidget *searchParamWidget = new QWidget(); |
86 | QWidget *searchResultWidget = new QWidget(); |
87 | |
88 | addSearchParamWidget(searchParamWidget); |
89 | addSearchResultWidget(searchResultWidget); |
90 | |
91 | d->stackedWidget->addWidget(searchParamWidget); |
92 | d->stackedWidget->addWidget(searchResultWidget); |
93 | |
94 | d->stackedWidget->setCurrentIndex(0); |
95 | |
96 | setLayout(vLayout); |
97 | } |
98 | |
99 | void FindToolWindow::addSearchParamWidget(QWidget *parentWidget) |
100 | { |
101 | QHBoxLayout *hLayout = new QHBoxLayout(); |
102 | parentWidget->setLayout(hLayout); |
103 | |
104 | QWidget *widget = new QWidget(); |
105 | widget->setFixedSize(725, 300); |
106 | hLayout->addWidget(widget, 0, Qt::AlignLeft); |
107 | |
108 | QVBoxLayout *vLayout = new QVBoxLayout(); |
109 | widget->setLayout(vLayout); |
110 | |
111 | QHBoxLayout *scopeLayout = new QHBoxLayout(); |
112 | QLabel *scopeLabel = new QLabel(QLabel::tr("Scope:" )); |
113 | scopeLabel->setAlignment(Qt::AlignRight); |
114 | scopeLabel->setFixedWidth(LABEL_WIDTH); |
115 | d->scopeComboBox = new QComboBox(); |
116 | d->scopeComboBox->addItem(tr("All Projects" )); |
117 | d->scopeComboBox->addItem(tr("Current Project" )); |
118 | d->scopeComboBox->addItem(tr("Current File" )); |
119 | scopeLayout->addWidget(scopeLabel); |
120 | scopeLayout->addWidget(d->scopeComboBox); |
121 | |
122 | QHBoxLayout *searchLayout = new QHBoxLayout(); |
123 | QLabel *searchLabel = new QLabel(QLabel::tr("Search for:" )); |
124 | searchLabel->setAlignment(Qt::AlignRight); |
125 | searchLabel->setFixedWidth(LABEL_WIDTH); |
126 | d->searchLineEdit = new QLineEdit(); |
127 | searchLayout->addWidget(searchLabel); |
128 | searchLayout->addWidget(d->searchLineEdit); |
129 | |
130 | QHBoxLayout *ruleLayout = new QHBoxLayout(); |
131 | d->senseCheckBox = new QCheckBox(QCheckBox::tr("Case sensitive" )); |
132 | d->wholeWordsCheckBox = new QCheckBox(QCheckBox::tr("Whole words only" )); |
133 | d->regularCheckBox = new QCheckBox(QCheckBox::tr("Use regular expressions" )); |
134 | ruleLayout->addStretch(); |
135 | ruleLayout->addWidget(d->senseCheckBox); |
136 | ruleLayout->addWidget(d->wholeWordsCheckBox); |
137 | ruleLayout->addWidget(d->regularCheckBox); |
138 | d->regularCheckBox->setVisible(false); |
139 | |
140 | QHBoxLayout *patternLayout = new QHBoxLayout(); |
141 | QLabel *patternLabel = new QLabel(QLabel::tr("File pattern:" )); |
142 | patternLabel->setAlignment(Qt::AlignRight); |
143 | patternLabel->setFixedWidth(LABEL_WIDTH); |
144 | d->patternLineEdit = new QLineEdit(); |
145 | patternLayout->addWidget(patternLabel); |
146 | patternLayout->addWidget(d->patternLineEdit); |
147 | |
148 | QHBoxLayout *expatternLayout = new QHBoxLayout(); |
149 | QLabel *expatternLabel = new QLabel(QLabel::tr("Exclusion pattern:" )); |
150 | expatternLabel->setAlignment(Qt::AlignRight); |
151 | expatternLabel->setFixedWidth(LABEL_WIDTH); |
152 | d->expatternLineEdit = new QLineEdit(); |
153 | expatternLayout->addWidget(expatternLabel); |
154 | expatternLayout->addWidget(d->expatternLineEdit); |
155 | |
156 | QPushButton *searchBtn = new QPushButton(QPushButton::tr("Search" )); |
157 | QPushButton *replaceBtn = new QPushButton(QPushButton::tr("Search && Replace" )); |
158 | QHBoxLayout *btnLayout = new QHBoxLayout(); |
159 | btnLayout->addStretch(); |
160 | btnLayout->addWidget(searchBtn); |
161 | btnLayout->addWidget(replaceBtn); |
162 | |
163 | connect(searchBtn, &QAbstractButton::clicked, this, &FindToolWindow::search); |
164 | connect(replaceBtn, &QAbstractButton::clicked, this, &FindToolWindow::replace); |
165 | |
166 | vLayout->addLayout(scopeLayout); |
167 | vLayout->addLayout(searchLayout); |
168 | vLayout->addLayout(ruleLayout); |
169 | vLayout->addLayout(patternLayout); |
170 | vLayout->addLayout(expatternLayout); |
171 | vLayout->addLayout(btnLayout); |
172 | } |
173 | |
174 | void FindToolWindow::addSearchResultWidget(QWidget *parentWidget) |
175 | { |
176 | QVBoxLayout *vLayout = new QVBoxLayout(); |
177 | parentWidget->setLayout(vLayout); |
178 | |
179 | d->searchResultWindow = new SearchResultWindow(); |
180 | connect(d->searchResultWindow, &SearchResultWindow::back, this, &FindToolWindow::switchSearchParamWidget); |
181 | vLayout->addWidget(d->searchResultWindow); |
182 | } |
183 | |
184 | void FindToolWindow::search() |
185 | { |
186 | searchText(); |
187 | d->searchResultWindow->setRepalceWidgtVisible(false); |
188 | } |
189 | |
190 | bool FindToolWindow::checkSelectedScopeValid() |
191 | { |
192 | int index = d->scopeComboBox->currentIndex(); |
193 | switch (index) { |
194 | case 0: |
195 | { |
196 | if (d->allProjectsPathList.isEmpty()) { |
197 | QMessageBox::warning(this, tr("Error" ), tr("All projects path is empty, please import!" )); |
198 | return false; |
199 | } |
200 | break; |
201 | } |
202 | case 1: |
203 | { |
204 | if (d->currentProjectPath.isEmpty()) { |
205 | QMessageBox::warning(this, tr("Error" ), tr("Current project path is empty, please import!" )); |
206 | return false; |
207 | } |
208 | break; |
209 | } |
210 | case 2: |
211 | { |
212 | if (d->currentFilePath.isEmpty()) { |
213 | QMessageBox::warning(this, tr("Error" ), tr("Current file path is empty, please import!" )); |
214 | return false; |
215 | } |
216 | break; |
217 | } |
218 | default: |
219 | { |
220 | QMessageBox::warning(this, tr("Error" ), tr("Scope is not selected, please select!" )); |
221 | return false; |
222 | } |
223 | } |
224 | |
225 | return true; |
226 | } |
227 | |
228 | bool FindToolWindow::getSearchParams(SearchParams *searchParams) |
229 | { |
230 | if (!checkSelectedScopeValid()) |
231 | return false; |
232 | |
233 | QString text = d->searchLineEdit->text(); |
234 | if (text.isEmpty()) { |
235 | QMessageBox::warning(this, tr("Error" ), tr("Search for text is empty, please input!" )); |
236 | return false; |
237 | } |
238 | |
239 | QStringList searchPathList; |
240 | int index = d->scopeComboBox->currentIndex(); |
241 | switch (index) { |
242 | case 0: |
243 | searchPathList = d->allProjectsPathList.values(); |
244 | break; |
245 | case 1: |
246 | searchPathList = QStringList{d->currentProjectPath}; |
247 | break; |
248 | case 2: |
249 | searchPathList = QStringList{d->currentFilePath}; |
250 | break; |
251 | default: |
252 | break; |
253 | } |
254 | |
255 | searchParams->filePathList = searchPathList; |
256 | searchParams->searchText = text; |
257 | searchParams->sensitiveFlag = d->senseCheckBox->isChecked(); |
258 | searchParams->wholeWordsFlag = d->wholeWordsCheckBox->isChecked(); |
259 | searchParams->patternsList = d->patternLineEdit->text().trimmed().split("," , QString::SkipEmptyParts); |
260 | searchParams->exPatternsList = d->expatternLineEdit->text().trimmed().split("," , QString::SkipEmptyParts); |
261 | searchParams->projectInfoMap = d->projectInfoMap; |
262 | |
263 | return true; |
264 | } |
265 | |
266 | void FindToolWindow::searchText() |
267 | { |
268 | SearchParams params; |
269 | if (!getSearchParams(¶ms)) { |
270 | return; |
271 | } |
272 | |
273 | d->searchResultWindow->search(¶ms); |
274 | d->stackedWidget->setCurrentIndex(1); |
275 | } |
276 | |
277 | void FindToolWindow::replace() |
278 | { |
279 | if (!checkSelectedScopeValid()) |
280 | return; |
281 | searchText(); |
282 | d->searchResultWindow->setRepalceWidgtVisible(true); |
283 | } |
284 | |
285 | void FindToolWindow::switchSearchParamWidget() |
286 | { |
287 | d->stackedWidget->setCurrentIndex(0); |
288 | } |
289 | |