1 #include <cstdio>
2 #include <QtGlobal>
3 
4 #if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
5 #include <QtWidgets>
6 #else
7 #include <QtGui>
8 #endif
9 #include <QTimer>
10 #include <QPixmap>
11 #include <QFile>
12 #include <QFileInfo>
13 #include <QCoreApplication>
14 
15 #include "seafile-applet.h"
16 #include "utils/utils.h"
17 #include "configurator.h"
18 #include "settings-mgr.h"
19 #include "api/requests.h"
20 #include "api/api-error.h"
21 #include "rpc/rpc-client.h"
22 #include "rpc/local-repo.h"
23 #include "rpc/clone-task.h"
24 
25 #include "init-vdrive-dialog.h"
26 
27 namespace {
28 
29 const int kCheckDownloadInterval = 2000;
30 
31 } // namespace
32 
33 
InitVirtualDriveDialog(const Account & account,QWidget * parent)34 InitVirtualDriveDialog::InitVirtualDriveDialog(const Account& account, QWidget *parent)
35     : QDialog(parent),
36       account_(account)
37 {
38     setupUi(this);
39     mLogo->setPixmap(QPixmap(":/images/seafile-32.png"));
40     setWindowTitle(tr("Download Default Library"));
41     setWindowIcon(QIcon(":/images/seafile.png"));
42     setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
43 
44     mStatusText->setText(
45         tr("%1 organizes files by libraries.\nDo you like to download your "
46            "default library?").arg(getBrand()));
47     setStatusIcon(":/images/download-48.png");
48 
49     create_default_repo_req_ = NULL;
50     download_default_repo_req_ = NULL;
51 
52     check_download_timer_ = NULL;
53     connect(mYesBtn, SIGNAL(clicked()), this, SLOT(start()));
54     connect(mNoBtn, SIGNAL(clicked()), this, SLOT(onCancel()));
55 
56     mRunInBackgroundBtn->setVisible(false);
57     mFinishBtn->setVisible(false);
58     mOpenBtn->setVisible(false);
59 }
60 
start()61 void InitVirtualDriveDialog::start()
62 {
63     // mYesBtn->setEnabled(false);
64     // mNoBtn->setEnabled(false);
65     mYesBtn->setVisible(false);
66     mNoBtn->setVisible(false);
67     getDefaultRepo();
68 }
69 
onCancel()70 void InitVirtualDriveDialog::onCancel()
71 {
72     reject();
73 }
74 
getDefaultRepo()75 void InitVirtualDriveDialog::getDefaultRepo()
76 {
77     setStatusText(tr("Checking your default library..."));
78     get_default_repo_req_ = new GetDefaultRepoRequest(account_);
79 
80     connect(get_default_repo_req_, SIGNAL(success(bool, const QString&)),
81             this, SLOT(onGetDefaultRepoSuccess(bool, const QString&)));
82 
83     connect(get_default_repo_req_, SIGNAL(failed(const ApiError&)),
84             this, SLOT(onGetDefaultRepoFailure(const ApiError&)));
85 
86     get_default_repo_req_->send();
87 }
88 
createDefaultRepo()89 void InitVirtualDriveDialog::createDefaultRepo()
90 {
91     setStatusText(tr("Creating the default library..."));
92     create_default_repo_req_ = new CreateDefaultRepoRequest(account_);
93 
94     connect(create_default_repo_req_, SIGNAL(success(const QString&)),
95             this, SLOT(onCreateDefaultRepoSuccess(const QString&)));
96 
97     connect(create_default_repo_req_, SIGNAL(failed(const ApiError&)),
98             this, SLOT(onCreateDefaultRepoFailure(const ApiError&)));
99 
100     create_default_repo_req_->send();
101 }
102 
startDownload(const QString & repo_id)103 void InitVirtualDriveDialog::startDownload(const QString& repo_id)
104 {
105     default_repo_id_ = repo_id;
106 
107     LocalRepo repo;
108 
109     seafApplet->rpcClient()->getLocalRepo(repo_id, &repo);
110     if (repo.isValid()) {
111         // This repo is already here
112         qDebug("The default library has already been downloaded");
113         default_repo_path_ = repo.worktree;
114         finish();
115         return;
116     }
117 
118     download_default_repo_req_ = new DownloadRepoRequest(account_, repo_id, false);
119 
120     connect(download_default_repo_req_, SIGNAL(success(const RepoDownloadInfo&)),
121             this, SLOT(onDownloadRepoSuccess(const RepoDownloadInfo&)));
122 
123     connect(download_default_repo_req_, SIGNAL(failed(const ApiError&)),
124             this, SLOT(onDownloadRepoFailure(const ApiError&)));
125 
126     download_default_repo_req_->send();
127 }
128 
onGetDefaultRepoSuccess(bool exists,const QString & repo_id)129 void InitVirtualDriveDialog::onGetDefaultRepoSuccess(bool exists, const QString& repo_id)
130 {
131     if (!exists) {
132         createDefaultRepo();
133     } else {
134         startDownload(repo_id);
135     }
136 }
137 
onGetDefaultRepoFailure(const ApiError & error)138 void InitVirtualDriveDialog::onGetDefaultRepoFailure(const ApiError& error)
139 {
140     if (error.type() == ApiError::HTTP_ERROR && error.httpErrorCode() == 404) {
141         fail(tr("Failed to create default library:\n\n"
142                 "The server version must be 2.1 or higher to support this."));
143     } else {
144         fail(tr("Failed to get default library:\n%1").arg(error.toString()));
145     }
146 }
147 
148 
onCreateDefaultRepoSuccess(const QString & repo_id)149 void InitVirtualDriveDialog::onCreateDefaultRepoSuccess(const QString& repo_id)
150 {
151     startDownload(repo_id);
152 }
153 
onCreateDefaultRepoFailure(const ApiError & error)154 void InitVirtualDriveDialog::onCreateDefaultRepoFailure(const ApiError& error)
155 {
156     if (error.type() == ApiError::HTTP_ERROR && error.httpErrorCode() == 404) {
157         fail(tr("Failed to create default library:\n\n"
158                 "The server version must be 2.1 or higher to support this."));
159     } else {
160         fail(tr("Failed to create default library:\n%1").arg(error.toString()));
161     }
162 }
163 
onDownloadRepoSuccess(const RepoDownloadInfo & info)164 void InitVirtualDriveDialog::onDownloadRepoSuccess(const RepoDownloadInfo& info)
165 {
166     int ret;
167     QString worktree = seafApplet->configurator()->worktreeDir();
168     QString error;
169 
170     ret = seafApplet->rpcClient()->downloadRepo(info.repo_id,
171                                                 info.repo_version, info.repo_name,
172                                                 worktree, info.token,
173                                                 QString(), info.magic,
174                                                 info.email, info.random_key,
175                                                 info.enc_version, info.more_info,
176                                                 &error);
177 
178     if (ret < 0) {
179         fail(tr("Failed to download default library:\n %1").arg(error));
180     } else {
181         check_download_timer_ = new QTimer(this);
182         connect(check_download_timer_, SIGNAL(timeout()), this, SLOT(checkDownloadProgress()));
183         check_download_timer_->start(kCheckDownloadInterval);
184 
185         setStatusText(tr("Downloading default library..."));
186 
187         mRunInBackgroundBtn->setVisible(true);
188         connect(mRunInBackgroundBtn, SIGNAL(clicked()), this, SLOT(hide()));
189     }
190 }
191 
onDownloadRepoFailure(const ApiError & error)192 void InitVirtualDriveDialog::onDownloadRepoFailure(const ApiError& error)
193 {
194     fail(tr("Failed to download default library:\n%1").arg(error.toString()));
195 }
196 
openVirtualDisk()197 void InitVirtualDriveDialog::openVirtualDisk()
198 {
199     QDesktopServices::openUrl(QUrl::fromLocalFile(default_repo_path_));
200     accept();
201 }
202 
finish()203 void InitVirtualDriveDialog::finish()
204 {
205     QString msg = tr("The default library has been downloaded.\n"
206                      "You can click the \"Open\" button to view it.");
207     setStatusText(msg);
208     setStatusIcon(":/images/sync/done@2x.png");
209 
210     mFinishBtn->setVisible(true);
211     mOpenBtn->setVisible(true);
212 
213     connect(mFinishBtn, SIGNAL(clicked()), this, SLOT(accept()));
214     connect(mOpenBtn, SIGNAL(clicked()), this, SLOT(openVirtualDisk()));
215 }
216 
fail(const QString & reason)217 void InitVirtualDriveDialog::fail(const QString& reason)
218 {
219     ensureVisible();
220 
221     setStatusText(reason);
222     mFinishBtn->setVisible(true);
223     connect(mFinishBtn, SIGNAL(clicked()), this, SLOT(reject()));
224 }
225 
checkDownloadProgress()226 void InitVirtualDriveDialog::checkDownloadProgress()
227 {
228     // First check for error
229     std::vector<CloneTask> tasks;
230     if (seafApplet->rpcClient()->getCloneTasks(&tasks) < 0) {
231         return;
232     }
233 
234     CloneTask task;
235     for (size_t i = 0; i < tasks.size(); i++) {
236         if (tasks[i].repo_id == default_repo_id_) {
237             task = tasks[i];
238             break;
239         }
240     }
241 
242     if (!task.isValid()) {
243         return;
244     }
245 
246     if (task.state != "done" && task.state != "error") {
247         return;
248     }
249 
250     check_download_timer_->stop();
251 
252     mRunInBackgroundBtn->setVisible(false);
253     ensureVisible();
254 
255     if (task.state == "error") {
256         fail(tr("Error when downloading the default library: %1").arg(task.error_str));
257         return;
258     }
259 
260     // Download is finished.
261     LocalRepo repo;
262     seafApplet->rpcClient()->getLocalRepo(default_repo_id_, &repo);
263     default_repo_path_ = repo.worktree;
264     finish();
265 }
266 
267 
setStatusText(const QString & status)268 void InitVirtualDriveDialog::setStatusText(const QString& status)
269 {
270     mStatusText->setText(status);
271 }
272 
setStatusIcon(const QString & path)273 void InitVirtualDriveDialog::setStatusIcon(const QString& path)
274 {
275     mStatusIcon->setPixmap(QPixmap(path));
276 }
277 
ensureVisible()278 void InitVirtualDriveDialog::ensureVisible()
279 {
280     show();
281     raise();
282     activateWindow();
283 }
284