1 /*
2 * Copyright (C) by Kevin Ottens <kevin.ottens@nextcloud.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 */
14
15 #include "conflictdialog.h"
16 #include "ui_conflictdialog.h"
17
18 #include "conflictsolver.h"
19
20 #include <QDateTime>
21 #include <QDebug>
22 #include <QDesktopServices>
23 #include <QFileInfo>
24 #include <QMimeDatabase>
25 #include <QPushButton>
26 #include <QUrl>
27
28 namespace {
forceHeaderFont(QWidget * widget)29 void forceHeaderFont(QWidget *widget)
30 {
31 auto font = widget->font();
32 font.setPointSizeF(font.pointSizeF() * 1.5);
33 widget->setFont(font);
34 }
35
setBoldFont(QWidget * widget,bool bold)36 void setBoldFont(QWidget *widget, bool bold)
37 {
38 auto font = widget->font();
39 font.setBold(bold);
40 widget->setFont(font);
41 }
42 }
43
44 namespace OCC {
45
ConflictDialog(QWidget * parent)46 ConflictDialog::ConflictDialog(QWidget *parent)
47 : QDialog(parent)
48 , _ui(new Ui::ConflictDialog)
49 , _solver(new ConflictSolver(this))
50 {
51 _ui->setupUi(this);
52 forceHeaderFont(_ui->conflictMessage);
53 _ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
54 _ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Keep selected version"));
55
56 connect(_ui->localVersionRadio, &QCheckBox::toggled, this, &ConflictDialog::updateButtonStates);
57 connect(_ui->localVersionButton, &QToolButton::clicked, this, [=] {
58 QDesktopServices::openUrl(QUrl::fromLocalFile(_solver->localVersionFilename()));
59 });
60
61 connect(_ui->remoteVersionRadio, &QCheckBox::toggled, this, &ConflictDialog::updateButtonStates);
62 connect(_ui->remoteVersionButton, &QToolButton::clicked, this, [=] {
63 QDesktopServices::openUrl(QUrl::fromLocalFile(_solver->remoteVersionFilename()));
64 });
65
66 connect(_solver, &ConflictSolver::localVersionFilenameChanged, this, &ConflictDialog::updateWidgets);
67 connect(_solver, &ConflictSolver::remoteVersionFilenameChanged, this, &ConflictDialog::updateWidgets);
68 }
69
baseFilename() const70 QString ConflictDialog::baseFilename() const
71 {
72 return _baseFilename;
73 }
74
75 ConflictDialog::~ConflictDialog() = default;
76
localVersionFilename() const77 QString ConflictDialog::localVersionFilename() const
78 {
79 return _solver->localVersionFilename();
80 }
81
remoteVersionFilename() const82 QString ConflictDialog::remoteVersionFilename() const
83 {
84 return _solver->remoteVersionFilename();
85 }
86
setBaseFilename(const QString & baseFilename)87 void ConflictDialog::setBaseFilename(const QString &baseFilename)
88 {
89 if (_baseFilename == baseFilename) {
90 return;
91 }
92
93 _baseFilename = baseFilename;
94 _ui->conflictMessage->setText(tr("Conflicting versions of %1.").arg(_baseFilename));
95 }
96
setLocalVersionFilename(const QString & localVersionFilename)97 void ConflictDialog::setLocalVersionFilename(const QString &localVersionFilename)
98 {
99 _solver->setLocalVersionFilename(localVersionFilename);
100 }
101
setRemoteVersionFilename(const QString & remoteVersionFilename)102 void ConflictDialog::setRemoteVersionFilename(const QString &remoteVersionFilename)
103 {
104 _solver->setRemoteVersionFilename(remoteVersionFilename);
105 }
106
accept()107 void ConflictDialog::accept()
108 {
109 const auto isLocalPicked = _ui->localVersionRadio->isChecked();
110 const auto isRemotePicked = _ui->remoteVersionRadio->isChecked();
111
112 Q_ASSERT(isLocalPicked || isRemotePicked);
113 if (!isLocalPicked && !isRemotePicked) {
114 return;
115 }
116
117 const auto solution = isLocalPicked && isRemotePicked ? ConflictSolver::KeepBothVersions
118 : isLocalPicked ? ConflictSolver::KeepLocalVersion
119 : ConflictSolver::KeepRemoteVersion;
120 if (_solver->exec(solution)) {
121 QDialog::accept();
122 }
123 }
124
updateWidgets()125 void ConflictDialog::updateWidgets()
126 {
127 QMimeDatabase mimeDb;
128
129 const auto updateGroup = [this, &mimeDb](const QString &filename, QLabel *linkLabel, const QString &linkText, QLabel *mtimeLabel, QLabel *sizeLabel, QToolButton *button) {
130 const auto fileUrl = QUrl::fromLocalFile(filename).toString();
131 linkLabel->setText(QStringLiteral("<a href='%1'>%2</a>").arg(fileUrl).arg(linkText));
132
133 const auto info = QFileInfo(filename);
134 mtimeLabel->setText(info.lastModified().toString());
135 sizeLabel->setText(locale().formattedDataSize(info.size()));
136
137 const auto mime = mimeDb.mimeTypeForFile(filename);
138 if (QIcon::hasThemeIcon(mime.iconName())) {
139 button->setIcon(QIcon::fromTheme(mime.iconName()));
140 } else {
141 button->setIcon(QIcon(":/qt-project.org/styles/commonstyle/images/file-128.png"));
142 }
143 };
144
145 const auto localVersion = _solver->localVersionFilename();
146 updateGroup(localVersion,
147 _ui->localVersionLink,
148 tr("Open local version"),
149 _ui->localVersionMtime,
150 _ui->localVersionSize,
151 _ui->localVersionButton);
152
153 const auto remoteVersion = _solver->remoteVersionFilename();
154 updateGroup(remoteVersion,
155 _ui->remoteVersionLink,
156 tr("Open server version"),
157 _ui->remoteVersionMtime,
158 _ui->remoteVersionSize,
159 _ui->remoteVersionButton);
160
161 const auto localMtime = QFileInfo(localVersion).lastModified();
162 const auto remoteMtime = QFileInfo(remoteVersion).lastModified();
163
164 setBoldFont(_ui->localVersionMtime, localMtime > remoteMtime);
165 setBoldFont(_ui->remoteVersionMtime, remoteMtime > localMtime);
166 }
167
updateButtonStates()168 void ConflictDialog::updateButtonStates()
169 {
170 const auto isLocalPicked = _ui->localVersionRadio->isChecked();
171 const auto isRemotePicked = _ui->remoteVersionRadio->isChecked();
172 _ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(isLocalPicked || isRemotePicked);
173
174 const auto text = isLocalPicked && isRemotePicked ? tr("Keep both versions")
175 : isLocalPicked ? tr("Keep local version")
176 : isRemotePicked ? tr("Keep server version")
177 : tr("Keep selected version");
178 _ui->buttonBox->button(QDialogButtonBox::Ok)->setText(text);
179 }
180
181 } // namespace OCC
182