1 | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. |
2 | // |
3 | // SPDX-License-Identifier: GPL-3.0-or-later |
4 | |
5 | #include "reposwidget.h" |
6 | #include "amendswidget.h" |
7 | #include "historyview.h" |
8 | #include "historylogwidget.h" |
9 | #include "historydiffwidget.h" |
10 | #include "historydisplaywidget.h" |
11 | #include "loggindialog.h" |
12 | #include "filesourceview.h" |
13 | #include "filemodifyview.h" |
14 | #include "historydiffview.h" |
15 | |
16 | #include "common/common.h" |
17 | |
18 | #include "FileDiffView.h" |
19 | #include "DiffHelper.h" |
20 | |
21 | #include <QApplication> |
22 | #include <QButtonGroup> |
23 | #include <QDir> |
24 | #include <QLabel> |
25 | #include <QMainWindow> |
26 | #include <QMenu> |
27 | #include <QSet> |
28 | #include <QSplitter> |
29 | #include <QToolBar> |
30 | #include <QToolButton> |
31 | #include <QFileSystemWatcher> |
32 | #include <QDirIterator> |
33 | |
34 | class ReposWidgetPrivate |
35 | { |
36 | friend class ReposWidget; |
37 | QSplitter *splitter{nullptr}; |
38 | // QTimer fileModifyTimer; |
39 | FileSourceView *fileSrcView{nullptr}; |
40 | AmendsWidget *amendsWidget{nullptr}; |
41 | HistoryDisplayWidget *historyWidget{nullptr}; |
42 | QVBoxLayout *vLayout{nullptr}; |
43 | LogginDialog *logginDialog{nullptr}; |
44 | QToolBar *controlBar{nullptr}; |
45 | QButtonGroup *controlGroup{nullptr}; |
46 | QToolButton *refreshButton{nullptr}; |
47 | QToolButton *updateButton{nullptr}; |
48 | QToolButton *optionButton{nullptr}; |
49 | QToolButton *historyButton{nullptr}; |
50 | QFileSystemWatcher *watcher{nullptr}; |
51 | QString reposPath; |
52 | QString name; |
53 | QString passwd; |
54 | HistoryData currHistoryData; |
55 | RevisionFile currRevisonFile; |
56 | bool logginResult = false; |
57 | }; |
58 | |
59 | ReposWidget::ReposWidget(QWidget *parent) |
60 | : QWidget(parent) |
61 | , d(new ReposWidgetPrivate) |
62 | { |
63 | d->vLayout = new QVBoxLayout(); |
64 | d->logginDialog = new LogginDialog(); |
65 | d->vLayout->addWidget(d->logginDialog); |
66 | d->vLayout->setAlignment(d->logginDialog, Qt::AlignCenter); |
67 | setLayout(d->vLayout); |
68 | |
69 | d->splitter = new QSplitter(Qt::Horizontal); |
70 | d->splitter->setHandleWidth(2); |
71 | d->fileSrcView = new FileSourceView(); |
72 | d->fileSrcView->setMinimumWidth(300); |
73 | d->amendsWidget = new AmendsWidget(); |
74 | d->amendsWidget->setMinimumWidth(300); |
75 | d->historyWidget = new HistoryDisplayWidget(); |
76 | d->historyWidget->setMinimumWidth(300); |
77 | |
78 | d->watcher = new QFileSystemWatcher(this); |
79 | |
80 | QObject::connect(d->watcher, &QFileSystemWatcher::directoryChanged, |
81 | [=](const QString &filePath){ |
82 | this->reloadRevisionFiles(); |
83 | }); |
84 | QObject::connect(d->logginDialog, &LogginDialog::logginOk, this, &ReposWidget::doLoggin); |
85 | } |
86 | |
87 | ReposWidget::~ReposWidget() |
88 | { |
89 | if (d) { |
90 | delete d; |
91 | } |
92 | } |
93 | |
94 | QString ReposWidget::getReposPath() const |
95 | { |
96 | return d->reposPath; |
97 | } |
98 | |
99 | void ReposWidget::setReposPath(const QString &path) |
100 | { |
101 | d->reposPath = path; |
102 | |
103 | d->logginDialog->setTitleText(LogginDialog::tr("loggin user from svn\nrepos path: %0" ) |
104 | .arg(d->reposPath)); |
105 | |
106 | QDirIterator dirItera(d->reposPath, QDir::Filter::NoDotAndDotDot|QDir::Dirs|QDir::NoSymLinks); |
107 | while (dirItera.hasNext()) { |
108 | dirItera.next(); |
109 | qInfo() << dirItera.filePath(); |
110 | d->watcher->addPath(dirItera.filePath()); |
111 | } |
112 | d->watcher->addPath(path); |
113 | d->fileSrcView->setRootPath(d->reposPath); |
114 | } |
115 | |
116 | void ReposWidget::loadRevisionFiles() |
117 | { |
118 | if (svnProgram().isEmpty()) { |
119 | return; |
120 | } |
121 | QProcess process; |
122 | process.setProgram(svnProgram()); |
123 | process.setWorkingDirectory(d->reposPath); |
124 | process.setArguments({"status" }); |
125 | process.start(); |
126 | process.waitForStarted(); |
127 | process.waitForFinished(); |
128 | if (process.exitCode() != 0 || process.exitStatus() != QProcess::ExitStatus::NormalExit) { |
129 | ContextDialog::ok(process.readAllStandardError()); |
130 | } |
131 | |
132 | d->amendsWidget->modView()->setUpdatesEnabled(false); |
133 | RevisionFiles files; |
134 | while (process.canReadLine()) { |
135 | QString line = process.readLine(); |
136 | QStringList lineList = line.replace("\n" , "" ).split(" " ); |
137 | QString filePath = d->reposPath + QDir::separator() + *lineList.rbegin(); |
138 | RevisionFile file(*lineList.rbegin(), filePath, lineList.first()); |
139 | d->amendsWidget->modView()->addFile(file); |
140 | files << file; |
141 | } |
142 | d->amendsWidget->modView()->setUpdatesEnabled(true); |
143 | } |
144 | |
145 | void ReposWidget::reloadRevisionFiles() |
146 | { |
147 | if (svnProgram().isEmpty()) { |
148 | return; |
149 | } |
150 | QProcess process; |
151 | process.setProgram(svnProgram()); |
152 | process.setWorkingDirectory(d->reposPath); |
153 | process.setArguments({"status" }); |
154 | process.start(); |
155 | process.waitForStarted(); |
156 | process.waitForFinished(); |
157 | if (process.exitCode() != 0 || process.exitStatus() != QProcess::ExitStatus::NormalExit) { |
158 | ContextDialog::ok(process.readAllStandardError()); |
159 | } |
160 | |
161 | d->amendsWidget->modView()->setUpdatesEnabled(false); |
162 | RevisionFiles newFiles; |
163 | while (process.canReadLine()) { |
164 | QString line = process.readLine(); |
165 | QStringList lineList = line.replace("\n" , "" ).split(" " ); |
166 | QString filePath = d->reposPath + QDir::separator() + *lineList.rbegin(); |
167 | RevisionFile file(*lineList.rbegin(), filePath, lineList.first()); |
168 | newFiles << file; |
169 | } |
170 | |
171 | // to changed added file list |
172 | for(int row = 0; row < d->amendsWidget->modView()->rowCount(); row ++) { |
173 | auto rowFile = d->amendsWidget->modView()->file(row); // row revision file |
174 | if (!newFiles.contains(rowFile)) { |
175 | if (d->amendsWidget->modView()->removeFile(rowFile)) //从界面删除节点 |
176 | row --; |
177 | } |
178 | for (auto newFile : newFiles) { |
179 | if (rowFile == newFile) { // 包含则删除 相同数据 |
180 | newFiles.removeOne(newFile); // 新的文件中删除当前数据 |
181 | break; |
182 | } else if (rowFile.isSameFilePath(newFile) // 路径一致,类型不一致 |
183 | && !rowFile.isSameReviType(newFile)) { |
184 | if (d->amendsWidget->modView()->removeFile(rowFile)) //从界面删除节点 |
185 | row --; |
186 | } |
187 | } |
188 | } |
189 | d->amendsWidget->modView()->addFiles(newFiles); |
190 | d->amendsWidget->modView()->setUpdatesEnabled(true); |
191 | } |
192 | |
193 | void ReposWidget::loadHistory() |
194 | { |
195 | if (svnProgram().isEmpty()) { |
196 | return; |
197 | } |
198 | QProcess process; |
199 | process.setProgram(svnProgram()); |
200 | process.setWorkingDirectory(d->reposPath); |
201 | process.setArguments({"log" , "-v" }); |
202 | process.start(); |
203 | process.waitForStarted(); |
204 | process.waitForFinished(); |
205 | if (process.exitCode() != 0 || process.exitStatus() != QProcess::ExitStatus::NormalExit) { |
206 | ContextDialog::ok(process.readAllStandardError()); |
207 | return; |
208 | } |
209 | |
210 | d->historyWidget->logWidget()->historyView()->setUpdatesEnabled(false); |
211 | HistoryDatas datas; |
212 | QString line = process.readLine(); |
213 | while (process.canReadLine()) { |
214 | if (svnLogSplitStr() == line) { |
215 | HistoryData data; |
216 | // header |
217 | line = process.readLine(); // line 1 |
218 | if (line.count("|" ) == 3) { |
219 | auto list = line.replace("\n" , "" ).split(" | " ); |
220 | if (list.size() == 4) { |
221 | data.revision = list[0]; |
222 | data.user = list[1]; |
223 | data.dateTime = list[2]; |
224 | data.lineCount = list[3]; |
225 | } else { |
226 | qCritical() << "Failed, Unkown error header from svn log -v" ; |
227 | abort(); |
228 | } |
229 | } |
230 | |
231 | // files |
232 | line = process.readLine(); // line 2 |
233 | for (line = process.readLine(); line != "\n" ; line = process.readLine()) { |
234 | while (line.startsWith(" " )) |
235 | line = line.remove(0, 1); |
236 | auto list = line.replace("\n" , "" ).split(" " ); |
237 | RevisionFile rFile; |
238 | if (list.size() == 2) { |
239 | rFile.revisionType = list[0]; |
240 | auto fileNameTemp = list[1]; |
241 | if (fileNameTemp.startsWith("/" )) |
242 | fileNameTemp.remove(0, 1); |
243 | rFile.displayName = fileNameTemp; |
244 | rFile.filePath = d->reposPath + QDir::separator() + fileNameTemp; |
245 | } |
246 | if (rFile.isValid()) { |
247 | data.changedFiles << rFile; |
248 | } else { |
249 | qCritical() << "Failed, Unkown error revision file from svn log -v" ; |
250 | } |
251 | } |
252 | |
253 | // desc |
254 | QString descStr; |
255 | for (line = process.readLine(); |
256 | line != "\n" && line != svnLogSplitStr(); |
257 | line = process.readLine()) { |
258 | descStr += line; |
259 | } |
260 | data.description = descStr; |
261 | descStr.clear(); |
262 | datas << data; |
263 | for (;line != svnLogSplitStr(); line = process.readLine()) { |
264 | |
265 | } |
266 | } |
267 | } |
268 | d->historyWidget->logWidget()->historyView()->setDatas(datas); |
269 | d->historyWidget->logWidget()->historyView()->setUpdatesEnabled(true); |
270 | } |
271 | |
272 | void ReposWidget::reloadHistory() |
273 | { |
274 | if (svnProgram().isEmpty()) { |
275 | return; |
276 | } |
277 | QProcess process; |
278 | process.setProgram(svnProgram()); |
279 | process.setWorkingDirectory(d->reposPath); |
280 | process.setArguments({"log" , "-v" }); |
281 | process.start(); |
282 | process.waitForStarted(); |
283 | process.waitForFinished(); |
284 | if (process.exitCode() != 0 || process.exitStatus() != QProcess::ExitStatus::NormalExit) { |
285 | ContextDialog::ok(process.readAllStandardError()); |
286 | return; |
287 | } |
288 | |
289 | d->historyWidget->logWidget()->historyView()->setUpdatesEnabled(false); |
290 | HistoryDatas datas; |
291 | QString line = process.readLine(); |
292 | while (process.canReadLine()) { |
293 | if (svnLogSplitStr() == line) { |
294 | HistoryData data; |
295 | // header |
296 | line = process.readLine(); // line 1 |
297 | if (line.count("|" ) == 3) { |
298 | auto list = line.replace("\n" , "" ).split(" | " ); |
299 | if (list.size() == 4) { |
300 | data.revision = list[0]; |
301 | data.user = list[1]; |
302 | data.dateTime = list[2]; |
303 | data.lineCount = list[3]; |
304 | } else { |
305 | qCritical() << "Failed, Unkown error header from svn log -v" ; |
306 | abort(); |
307 | } |
308 | } |
309 | |
310 | // files |
311 | line = process.readLine(); // line 2 |
312 | for (line = process.readLine(); line != "\n" ; line = process.readLine()) { |
313 | while (line.startsWith(" " )) |
314 | line = line.remove(0, 1); |
315 | auto list = line.replace("\n" , "" ).split(" " ); |
316 | RevisionFile rFile; |
317 | if (list.size() == 2) { |
318 | rFile.revisionType = list[0]; |
319 | auto fileNameTemp = list[1]; |
320 | if (fileNameTemp.startsWith("/" )) |
321 | fileNameTemp.remove(0, 1); |
322 | rFile.displayName = fileNameTemp; |
323 | rFile.filePath = d->reposPath + QDir::separator() + fileNameTemp; |
324 | } |
325 | if (rFile.isValid()) { |
326 | data.changedFiles << rFile; |
327 | } else { |
328 | qCritical() << "Failed, Unkown error revision file from svn log -v" ; |
329 | } |
330 | } |
331 | |
332 | // desc |
333 | QString descStr; |
334 | for (line = process.readLine(); |
335 | line != "\n" && line != svnLogSplitStr(); |
336 | line = process.readLine()) { |
337 | descStr += line; |
338 | } |
339 | data.description = descStr; |
340 | descStr.clear(); |
341 | if (data == d->historyWidget->logWidget()->historyView()->data(0)) { |
342 | break; |
343 | } |
344 | datas << data; |
345 | for (;line != svnLogSplitStr(); line = process.readLine()) { |
346 | |
347 | } |
348 | } |
349 | } |
350 | d->historyWidget->logWidget()->historyView()->insertTopDatas(datas); |
351 | d->historyWidget->logWidget()->historyView()->setUpdatesEnabled(true); |
352 | } |
353 | |
354 | void ReposWidget::(const RevisionFile &file, const QPoint &pos) |
355 | { |
356 | QMenu ; |
357 | if (file.revisionType == AmendsState_Col1::get()->ADD) { |
358 | QAction *action = menu.addAction("revert" ); |
359 | QObject::connect(action, &QAction::triggered, [=](){ |
360 | this->revert(file.displayName); |
361 | this->reloadRevisionFiles(); |
362 | }); |
363 | } |
364 | if (file.revisionType == AmendsState_Col1::get()->SRC) { |
365 | QAction *action = menu.addAction("add" ); |
366 | QObject::connect(action, &QAction::triggered, [=](){ |
367 | this->add(file.displayName); |
368 | this->reloadRevisionFiles(); |
369 | }); |
370 | } |
371 | menu.exec(pos); |
372 | } |
373 | |
374 | void ReposWidget::historyDataClicked(const QModelIndex &index) |
375 | { |
376 | auto hisView = d->historyWidget->logWidget()->historyView(); |
377 | d->currHistoryData = hisView->data(index.row()); |
378 | } |
379 | |
380 | void ReposWidget::historyFileClicked(const QModelIndex &index) |
381 | { |
382 | auto chaView = d->historyWidget->logWidget()->fileChangedView(); |
383 | d->currRevisonFile = chaView->file(index.row()); |
384 | if (d->currHistoryData.isValid() && d->currRevisonFile.isValid()) { |
385 | doDiffFileAtRevision(); |
386 | } |
387 | } |
388 | |
389 | void ReposWidget::setSrcViewReviFiles(const QString &path) |
390 | { |
391 | qInfo() << path; |
392 | reloadRevisionFiles(); |
393 | d->amendsWidget->modView()->files(); |
394 | } |
395 | |
396 | void ReposWidget::doLoggin() |
397 | { |
398 | // 设置用户名密码缓存 |
399 | setName(d->logginDialog->name()); |
400 | setPasswd(d->logginDialog->passwd()); |
401 | |
402 | // 获取登录结果 |
403 | d->logginResult = testUserLoggin(d->reposPath, d->name, d->passwd); |
404 | |
405 | // 无法登录 直接中断流程 |
406 | if (!d->logginResult) { |
407 | return; |
408 | } |
409 | |
410 | // 设置界面 |
411 | d->vLayout->addWidget(initControlBar(), 0, Qt::AlignHCenter); |
412 | d->vLayout->addWidget(d->splitter); |
413 | d->splitter->addWidget(d->fileSrcView); |
414 | d->splitter->setCollapsible(0, false); |
415 | d->splitter->addWidget(d->amendsWidget); |
416 | d->splitter->setCollapsible(1, false); |
417 | d->splitter->addWidget(d->historyWidget); |
418 | d->splitter->setCollapsible(2, false); |
419 | |
420 | QObject::connect(d->amendsWidget->modView(), |
421 | &FileModifyView::menuRequest, |
422 | this, &ReposWidget::modFileMenu); |
423 | |
424 | // 历史记录操作 |
425 | auto hisView = d->historyWidget->logWidget()->historyView(); |
426 | QObject::connect(hisView, &HistoryView::clicked, |
427 | this, &ReposWidget::historyDataClicked); |
428 | |
429 | auto chaView = d->historyWidget->logWidget()->fileChangedView(); |
430 | QObject::connect(chaView, &FileModifyView::clicked, |
431 | this, &ReposWidget::historyFileClicked); |
432 | |
433 | loadRevisionFiles(); // 创建修订文件 |
434 | loadHistory(); // 添加提交历史 |
435 | |
436 | // 提交信息操作 |
437 | QObject::connect(d->amendsWidget, &AmendsWidget::commitClicked, |
438 | this, &ReposWidget::doAmendsCommit); |
439 | |
440 | QObject::connect(d->amendsWidget, &AmendsWidget::revertAllClicked, |
441 | this, &ReposWidget::doAmendsRevertAll); |
442 | |
443 | // 删除登录界面 |
444 | if (d->logginDialog) |
445 | delete d->logginDialog; |
446 | } |
447 | |
448 | void ReposWidget::doUpdateRepos() |
449 | { |
450 | if (svnProgram().isEmpty()) { |
451 | return; |
452 | } |
453 | QProcess processUpdate; |
454 | processUpdate.setWorkingDirectory(d->reposPath); |
455 | processUpdate.setProgram(svnProgram()); |
456 | processUpdate.setArguments({"update" }); |
457 | processUpdate.start(); |
458 | processUpdate.waitForFinished(); |
459 | if (processUpdate.exitCode() != 0 || processUpdate.exitStatus() != QProcess::ExitStatus::NormalExit) { |
460 | ContextDialog::ok(processUpdate.readAllStandardError()); |
461 | } |
462 | doRefresh(); |
463 | } |
464 | |
465 | void ReposWidget::doRefresh() |
466 | { |
467 | reloadRevisionFiles(); |
468 | reloadHistory(); |
469 | } |
470 | |
471 | void ReposWidget::doAmendsCommit() |
472 | { |
473 | if (svnProgram().isEmpty()) { |
474 | return; |
475 | } |
476 | QProcess processCommit; |
477 | processCommit.setWorkingDirectory(d->reposPath); |
478 | processCommit.setProgram(svnProgram()); |
479 | QString commitDesc = d->amendsWidget->description(); |
480 | processCommit.setArguments({"commit" , "-m" , commitDesc, "--username" , d->name, "--password" , d->passwd}); |
481 | processCommit.start(); |
482 | processCommit.waitForFinished(); |
483 | if (processCommit.exitCode() != 0 || processCommit.exitStatus() != QProcess::ExitStatus::NormalExit) { |
484 | ContextDialog::ok(processCommit.readAllStandardError()); |
485 | } |
486 | reloadRevisionFiles(); |
487 | } |
488 | |
489 | void ReposWidget::doAmendsRevertAll() |
490 | { |
491 | if (svnProgram().isEmpty()) { |
492 | return; |
493 | } |
494 | QProcess process; |
495 | process.setProgram(svnProgram()); |
496 | process.setWorkingDirectory(d->reposPath); |
497 | process.setArguments({"revert" , d->reposPath, "--depth" , "infinity" }); |
498 | process.start(); |
499 | process.waitForFinished(); |
500 | if (process.exitCode() != 0 || process.exitStatus() != QProcess::ExitStatus::NormalExit) { |
501 | ContextDialog::ok(process.readAllStandardError()); |
502 | return; |
503 | } |
504 | qInfo() << process.errorString() << QString::fromUtf8(process.readAll()); |
505 | reloadRevisionFiles(); |
506 | } |
507 | |
508 | void ReposWidget::doDiffFileAtRevision() |
509 | { |
510 | if (svnProgram().isEmpty()) { |
511 | return; |
512 | } |
513 | QProcess process; |
514 | process.setProgram(svnProgram()); |
515 | process.setWorkingDirectory(d->reposPath); |
516 | process.setArguments({"diff" , "--git" , d->currRevisonFile.displayName, "-r" , d->currHistoryData.revision}); |
517 | process.start(); |
518 | process.waitForFinished(); |
519 | if (process.exitCode() != 0 || process.exitStatus() != QProcess::ExitStatus::NormalExit) { |
520 | ContextDialog::ok(process.readAllStandardError()); |
521 | return; |
522 | } |
523 | |
524 | QString text = process.readAll(); |
525 | QPair<QStringList, QVector<ChunkDiffInfo::ChunkInfo>> newFileData; |
526 | QPair<QStringList, QVector<ChunkDiffInfo::ChunkInfo>> oldFileData; |
527 | auto info = DiffHelper::processDiff(text, newFileData, oldFileData); |
528 | |
529 | d->historyWidget->diffWidget()->getOldView()->getDiffView()->loadDiff(oldFileData.first.join('\n'), oldFileData.second); |
530 | d->historyWidget->diffWidget()->getNewView()->getDiffView()->loadDiff(newFileData.first.join('\n'), newFileData.second); |
531 | qInfo() << "jump" ; |
532 | } |
533 | |
534 | bool ReposWidget::testUserLoggin(const QString &reposPath, const QString &name, const QString &passwd) |
535 | { |
536 | if (svnProgram().isEmpty()) { |
537 | return false; |
538 | } |
539 | QProcess process; |
540 | process.setProgram(svnProgram()); |
541 | process.setArguments({"list" , reposPath, "--username" , name, "--password" , passwd}); |
542 | process.start(); |
543 | process.waitForFinished(); |
544 | if (process.exitCode() != 0 || process.exitStatus() != QProcess::ExitStatus::NormalExit) { |
545 | ContextDialog::ok(process.readAllStandardError()); |
546 | return false; |
547 | } |
548 | return true; |
549 | } |
550 | |
551 | QWidget *ReposWidget::initControlBar() |
552 | { |
553 | static int barHeight = 48; |
554 | static int buttonWidth = 40; |
555 | static int buttonHeight = 40; |
556 | d->controlBar = new QToolBar(); |
557 | d->controlBar->setFixedHeight(barHeight); |
558 | d->controlBar->setOrientation(Qt::Orientation::Horizontal); |
559 | d->controlBar->setIconSize({buttonWidth, buttonHeight}); |
560 | |
561 | d->updateButton = new QToolButton(); |
562 | d->updateButton->setFixedSize(buttonWidth, buttonHeight); |
563 | d->updateButton->setIcon(QIcon(":/icons/git_pull" )); |
564 | d->updateButton->setToolTip(QToolButton::tr("update local from remote repos" )); |
565 | QObject::connect(d->updateButton, &QToolButton::clicked, this, &ReposWidget::doUpdateRepos); |
566 | d->controlBar->addWidget(d->updateButton); |
567 | |
568 | d->refreshButton = new QToolButton(); |
569 | d->refreshButton->setFixedSize(buttonWidth, buttonHeight); |
570 | d->refreshButton->setIcon(QIcon(":/icons/refresh" )); |
571 | d->refreshButton->setToolTip(QToolButton::tr("refresh current local to display" )); |
572 | QObject::connect(d->refreshButton, &QToolButton::clicked, this, &ReposWidget::doRefresh); |
573 | d->controlBar->addWidget(d->refreshButton); |
574 | d->controlBar->addSeparator(); |
575 | |
576 | d->optionButton = new QToolButton(); |
577 | d->optionButton->setFixedSize(buttonWidth, buttonHeight); |
578 | d->optionButton->setIcon(QIcon(":/icons/blame" )); |
579 | d->optionButton->setToolTip(QToolButton::tr("show repos operation" )); |
580 | d->optionButton->setCheckable(true); |
581 | d->controlBar->addWidget(d->optionButton); |
582 | |
583 | d->historyButton = new QToolButton(); |
584 | d->historyButton->setFixedSize(buttonWidth, buttonHeight); |
585 | d->historyButton->setIcon(QIcon(":/icons/git_orange" )); |
586 | d->historyButton->setToolTip(QToolButton::tr("show repos history" )); |
587 | d->historyButton->setCheckable(true); |
588 | d->controlBar->addWidget(d->historyButton); |
589 | |
590 | d->controlGroup = new QButtonGroup(d->controlBar); |
591 | d->controlGroup->addButton(d->optionButton); |
592 | d->controlGroup->addButton(d->historyButton); |
593 | |
594 | QObject::connect(d->controlGroup, QOverload<QAbstractButton *, bool> |
595 | ::of(&QButtonGroup::buttonToggled), |
596 | [=](QAbstractButton *button, bool checked){ |
597 | if (button == d->optionButton) { |
598 | if (checked) { |
599 | d->fileSrcView->show(); |
600 | d->amendsWidget->show(); |
601 | } else { |
602 | d->fileSrcView->hide(); |
603 | d->amendsWidget->hide(); |
604 | } |
605 | } |
606 | if (button == d->historyButton) { |
607 | if (checked) { |
608 | d->historyWidget->show(); |
609 | } else { |
610 | d->historyWidget->hide(); |
611 | } |
612 | } |
613 | }); |
614 | |
615 | d->fileSrcView->hide(); |
616 | d->amendsWidget->hide(); |
617 | d->historyWidget->hide(); |
618 | |
619 | d->optionButton->setChecked(true); |
620 | |
621 | return d->controlBar; |
622 | } |
623 | |
624 | bool ReposWidget::add(const QString &display) |
625 | { |
626 | if (svnProgram().isEmpty()) { |
627 | return false; |
628 | } |
629 | QProcess process; |
630 | process.setProgram(svnProgram()); |
631 | process.setWorkingDirectory(d->reposPath); |
632 | process.setArguments({"add" , display}); |
633 | process.start(); |
634 | process.waitForStarted(); |
635 | process.waitForFinished(); |
636 | if (process.exitCode() != 0 || process.exitStatus() != QProcess::ExitStatus::NormalExit) { |
637 | ContextDialog::ok(process.readAllStandardError()); |
638 | return false; |
639 | } |
640 | return true; |
641 | } |
642 | |
643 | bool ReposWidget::revert(const QString &display) |
644 | { |
645 | if (svnProgram().isEmpty()) { |
646 | return false; |
647 | } |
648 | QProcess process; |
649 | process.setProgram(svnProgram()); |
650 | process.setWorkingDirectory(d->reposPath); |
651 | process.setArguments({"revert" , display}); |
652 | process.start(); |
653 | process.waitForStarted(); |
654 | process.waitForFinished(); |
655 | if (process.exitCode() != 0 || process.exitStatus() != QProcess::ExitStatus::NormalExit) { |
656 | ContextDialog::ok(process.readAllStandardError()); |
657 | return false; |
658 | } |
659 | return true; |
660 | } |
661 | |
662 | QString ReposWidget::getName() const |
663 | { |
664 | return d->name; |
665 | } |
666 | |
667 | void ReposWidget::setName(const QString &value) |
668 | { |
669 | d->name = value; |
670 | d->logginDialog->setName(value); |
671 | } |
672 | |
673 | QString ReposWidget::getPasswd() const |
674 | { |
675 | return d->passwd; |
676 | } |
677 | |
678 | void ReposWidget::setPasswd(const QString &value) |
679 | { |
680 | d->passwd = value; |
681 | d->logginDialog->setPasswd(value); |
682 | } |
683 | |
684 | void ReposWidget::setLogginDisplay(const QString &name, const QString &passwd) |
685 | { |
686 | d->logginDialog->setName(name); |
687 | d->logginDialog->setPasswd(passwd); |
688 | } |
689 | |