1 | /* $Id: UIDownloader.cpp 30356 2010-06-22 08:42:22Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | *
|
---|
4 | * VBox frontends: Qt GUI ("VirtualBox"):
|
---|
5 | * UIDownloader class implementation
|
---|
6 | */
|
---|
7 |
|
---|
8 | /*
|
---|
9 | * Copyright (C) 2006-2010 Oracle Corporation
|
---|
10 | *
|
---|
11 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
12 | * available from http://www.virtualbox.org. This file is free software;
|
---|
13 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
14 | * General Public License (GPL) as published by the Free Software
|
---|
15 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
16 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
17 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
18 | */
|
---|
19 |
|
---|
20 | /* Local includes */
|
---|
21 | #include "UIDownloader.h"
|
---|
22 | #include "QIHttp.h"
|
---|
23 | #include "VBoxGlobal.h"
|
---|
24 | #include "VBoxProblemReporter.h"
|
---|
25 | #include "UISpecialControls.h"
|
---|
26 |
|
---|
27 | /* Global includes */
|
---|
28 | #include <QFile>
|
---|
29 | #include <QProgressBar>
|
---|
30 |
|
---|
31 | UIMiniProcessWidget::UIMiniProcessWidget(QWidget *pParent /* = 0 */)
|
---|
32 | : QWidget(pParent)
|
---|
33 | , m_pProgressBar(new QProgressBar(this))
|
---|
34 | , m_pCancelButton(new UIMiniCancelButton(this))
|
---|
35 | {
|
---|
36 | /* Progress Bar setup */
|
---|
37 | m_pProgressBar->setFixedWidth(100);
|
---|
38 | m_pProgressBar->setFormat("%p%");
|
---|
39 | m_pProgressBar->setValue(0);
|
---|
40 |
|
---|
41 | /* Cancel Button setup */
|
---|
42 | m_pCancelButton->setFocusPolicy(Qt::NoFocus);
|
---|
43 | m_pCancelButton->removeBorder();
|
---|
44 | connect(m_pCancelButton, SIGNAL(clicked()),
|
---|
45 | this, SIGNAL(sigCancel()));
|
---|
46 |
|
---|
47 | setContentsMargins(0, 0, 0, 0);
|
---|
48 | setFixedHeight(16);
|
---|
49 |
|
---|
50 | /* Layout setup */
|
---|
51 | QHBoxLayout *pMainLayout = new QHBoxLayout(this);
|
---|
52 | VBoxGlobal::setLayoutMargin(pMainLayout, 0);
|
---|
53 |
|
---|
54 | #ifdef Q_WS_MAC
|
---|
55 | pMainLayout->setSpacing(2);
|
---|
56 | m_pProgressBar->setFixedHeight(14);
|
---|
57 | m_pCancelButton->setFixedHeight(11);
|
---|
58 | pMainLayout->addWidget(m_pProgressBar, 0, Qt::AlignTop);
|
---|
59 | pMainLayout->addWidget(m_pCancelButton, 0, Qt::AlignBottom);
|
---|
60 | #else /* Q_WS_MAC */
|
---|
61 | pMainLayout->setSpacing(0);
|
---|
62 | pMainLayout->addWidget(m_pProgressBar, 0, Qt::AlignCenter);
|
---|
63 | pMainLayout->addWidget(m_pCancelButton, 0, Qt::AlignCenter);
|
---|
64 | #endif /* !Q_WS_MAC */
|
---|
65 |
|
---|
66 | pMainLayout->addStretch(1);
|
---|
67 |
|
---|
68 | }
|
---|
69 |
|
---|
70 | void UIMiniProcessWidget::setCancelButtonText(const QString &strText)
|
---|
71 | {
|
---|
72 | m_pCancelButton->setText(strText);
|
---|
73 | }
|
---|
74 |
|
---|
75 | QString UIMiniProcessWidget::cancelButtonText() const
|
---|
76 | {
|
---|
77 | return m_pCancelButton->text();
|
---|
78 | }
|
---|
79 |
|
---|
80 | void UIMiniProcessWidget::setCancelButtonToolTip(const QString &strText)
|
---|
81 | {
|
---|
82 | m_pCancelButton->setToolTip(strText);
|
---|
83 | }
|
---|
84 |
|
---|
85 | QString UIMiniProcessWidget::cancelButtonToolTip() const
|
---|
86 | {
|
---|
87 | return m_pCancelButton->toolTip();
|
---|
88 | }
|
---|
89 |
|
---|
90 | void UIMiniProcessWidget::setProgressBarToolTip(const QString &strText)
|
---|
91 | {
|
---|
92 | m_pProgressBar->setToolTip(strText);
|
---|
93 | }
|
---|
94 |
|
---|
95 | QString UIMiniProcessWidget::progressBarToolTip() const
|
---|
96 | {
|
---|
97 | return m_pProgressBar->toolTip();
|
---|
98 | }
|
---|
99 |
|
---|
100 | void UIMiniProcessWidget::setSource(const QString &strSource)
|
---|
101 | {
|
---|
102 | m_strSource = strSource;
|
---|
103 | }
|
---|
104 |
|
---|
105 | QString UIMiniProcessWidget::source() const
|
---|
106 | {
|
---|
107 | return m_strSource;
|
---|
108 | }
|
---|
109 |
|
---|
110 | void UIMiniProcessWidget::sltProcess(int cDone, int cTotal)
|
---|
111 | {
|
---|
112 | m_pProgressBar->setMaximum(cTotal);
|
---|
113 | m_pProgressBar->setValue(cDone);
|
---|
114 | }
|
---|
115 |
|
---|
116 | UIDownloader::UIDownloader()
|
---|
117 | : m_pHttp(0)
|
---|
118 | {
|
---|
119 | }
|
---|
120 |
|
---|
121 | void UIDownloader::setSource(const QString &strSource)
|
---|
122 | {
|
---|
123 | m_source = strSource;
|
---|
124 | }
|
---|
125 |
|
---|
126 | QString UIDownloader::source() const
|
---|
127 | {
|
---|
128 | return m_source.toString();
|
---|
129 | }
|
---|
130 |
|
---|
131 | void UIDownloader::setTarget(const QString &strTarget)
|
---|
132 | {
|
---|
133 | m_strTarget = strTarget;
|
---|
134 | }
|
---|
135 |
|
---|
136 | QString UIDownloader::target() const
|
---|
137 | {
|
---|
138 | return m_strTarget;
|
---|
139 | }
|
---|
140 |
|
---|
141 | void UIDownloader::startDownload()
|
---|
142 | {
|
---|
143 | /* By default we are not using acknowledging step, so
|
---|
144 | * making downloading immediately */
|
---|
145 | downloadStart();
|
---|
146 | }
|
---|
147 |
|
---|
148 | /* This function is used to start acknowledging mechanism:
|
---|
149 | * checking file presence & size */
|
---|
150 | void UIDownloader::acknowledgeStart()
|
---|
151 | {
|
---|
152 | delete m_pHttp;
|
---|
153 | m_pHttp = new QIHttp(this, m_source.host());
|
---|
154 | connect(m_pHttp, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
|
---|
155 | this, SLOT(acknowledgeProcess(const QHttpResponseHeader &)));
|
---|
156 | connect(m_pHttp, SIGNAL(allIsDone(bool)),
|
---|
157 | this, SLOT(acknowledgeFinished(bool)));
|
---|
158 | m_pHttp->get(m_source.toEncoded());
|
---|
159 | }
|
---|
160 |
|
---|
161 | /* This function is used to store content length */
|
---|
162 | void UIDownloader::acknowledgeProcess(const QHttpResponseHeader & /* response */)
|
---|
163 | {
|
---|
164 | /* Abort connection as we already got all we need */
|
---|
165 | m_pHttp->abortAll();
|
---|
166 | }
|
---|
167 |
|
---|
168 | /* This function is used to ask the user about if he really want
|
---|
169 | * to download file of proposed size if no error present or
|
---|
170 | * abort download progress if error is present */
|
---|
171 | void UIDownloader::acknowledgeFinished(bool /* fError */)
|
---|
172 | {
|
---|
173 | m_pHttp->disconnect(this);
|
---|
174 |
|
---|
175 | switch (m_pHttp->errorCode())
|
---|
176 | {
|
---|
177 | case QIHttp::NoError: /* full packet comes before aborting */
|
---|
178 | case QIHttp::Aborted: /* part of packet comes before aborting */
|
---|
179 | {
|
---|
180 | /* Ask the user if he wish to download it */
|
---|
181 | if (confirmDownload())
|
---|
182 | QTimer::singleShot(0, this, SLOT(downloadStart()));
|
---|
183 | else
|
---|
184 | QTimer::singleShot(0, this, SLOT(suicide()));
|
---|
185 | break;
|
---|
186 | }
|
---|
187 | case QIHttp::MovedPermanentlyError:
|
---|
188 | case QIHttp::MovedTemporarilyError:
|
---|
189 | {
|
---|
190 | /* Restart downloading at new location */
|
---|
191 | m_source = m_pHttp->lastResponse().value("location");
|
---|
192 | QTimer::singleShot(0, this, SLOT(acknowledgeStart()));
|
---|
193 | break;
|
---|
194 | }
|
---|
195 | default:
|
---|
196 | {
|
---|
197 | /* Show error happens during acknowledging */
|
---|
198 | abortDownload(m_pHttp->errorString());
|
---|
199 | break;
|
---|
200 | }
|
---|
201 | }
|
---|
202 | }
|
---|
203 |
|
---|
204 | /* This function is used to start downloading mechanism:
|
---|
205 | * downloading and saving the target */
|
---|
206 | void UIDownloader::downloadStart()
|
---|
207 | {
|
---|
208 | delete m_pHttp;
|
---|
209 | m_pHttp = new QIHttp(this, m_source.host());
|
---|
210 | connect(m_pHttp, SIGNAL(dataReadProgress (int, int)),
|
---|
211 | this, SLOT (downloadProcess(int, int)));
|
---|
212 | connect(m_pHttp, SIGNAL(allIsDone(bool)),
|
---|
213 | this, SLOT(downloadFinished(bool)));
|
---|
214 | m_pHttp->get(m_source.toEncoded());
|
---|
215 | }
|
---|
216 |
|
---|
217 | /* this function is used to observe the downloading progress through
|
---|
218 | * changing the corresponding qprogressbar value */
|
---|
219 | void UIDownloader::downloadProcess(int cDone, int cTotal)
|
---|
220 | {
|
---|
221 | emit sigDownloadProcess(cDone, cTotal);
|
---|
222 | }
|
---|
223 |
|
---|
224 | /* This function is used to handle the 'downloading finished' issue
|
---|
225 | * through saving the downloaded into the file if there in no error or
|
---|
226 | * notifying the user about error happens */
|
---|
227 | void UIDownloader::downloadFinished(bool fError)
|
---|
228 | {
|
---|
229 | m_pHttp->disconnect(this);
|
---|
230 |
|
---|
231 | if (fError)
|
---|
232 | {
|
---|
233 | /* Show information about error happens */
|
---|
234 | if (m_pHttp->errorCode() == QIHttp::Aborted)
|
---|
235 | abortDownload(tr("The download process has been canceled by the user."));
|
---|
236 | else
|
---|
237 | abortDownload(m_pHttp->errorString());
|
---|
238 | }
|
---|
239 | else
|
---|
240 | {
|
---|
241 | /* Trying to serialize the incoming buffer into the target, this is the
|
---|
242 | * default behavior which have to be reimplemented in sub-class */
|
---|
243 | QFile file(m_strTarget);
|
---|
244 | if (file.open(QIODevice::WriteOnly))
|
---|
245 | {
|
---|
246 | file.write(m_pHttp->readAll());
|
---|
247 | file.close();
|
---|
248 | }
|
---|
249 | QTimer::singleShot(0, this, SLOT(suicide()));
|
---|
250 | }
|
---|
251 | }
|
---|
252 |
|
---|
253 | /* This slot is used to process cancel-button clicking */
|
---|
254 | void UIDownloader::cancelDownloading()
|
---|
255 | {
|
---|
256 | QTimer::singleShot(0, this, SLOT(suicide()));
|
---|
257 | }
|
---|
258 |
|
---|
259 | /* This function is used to abort download by showing aborting reason
|
---|
260 | * and calling the downloader's delete function */
|
---|
261 | void UIDownloader::abortDownload(const QString &strError)
|
---|
262 | {
|
---|
263 | warnAboutError(strError);
|
---|
264 | QTimer::singleShot(0, this, SLOT(suicide()));
|
---|
265 | }
|
---|
266 |
|
---|
267 | /* This function is used to delete the downloader widget itself,
|
---|
268 | * should be reimplemented to enhance necessary functionality in sub-class */
|
---|
269 | void UIDownloader::suicide()
|
---|
270 | {
|
---|
271 | delete this;
|
---|
272 | }
|
---|
273 |
|
---|