1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2010-2011 Ralf Habacker ralf.habacker@freenet.de |
4 | ** |
5 | ** This file is part of the KDE installer for windows |
6 | ** |
7 | ** This library is free software; you can redistribute it and/or |
8 | ** modify it under the terms of the GNU Library General Public |
9 | ** License version 2 as published by the Free Software Foundation. |
10 | ** |
11 | ** This library is distributed in the hope that it will be useful, |
12 | ** but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | ** Library General Public License for more details. |
15 | ** |
16 | ** You should have received a copy of the GNU Library General Public License |
17 | ** along with this library; see the file COPYING.LIB. If not, write to |
18 | ** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | ** Boston, MA 02110-1301, USA. |
20 | ** |
21 | ****************************************************************************/ |
22 | |
23 | #include "installerdialog.h" |
24 | |
25 | #include "../shared/misc.h" |
26 | #include "../shared/debug.h" |
27 | #include "../shared/installercallconfig.h" |
28 | #include "../shared/installerprogress.h" |
29 | #include "../shared/downloader.h" |
30 | #include "../shared/unpacker.h" |
31 | #include "../shared/postprocessing.h" |
32 | |
33 | #include <QCloseEvent> |
34 | #include <QPixmap> |
35 | #include <QTextEdit> |
36 | #include <QTimer> |
37 | |
38 | InstallerDialog::InstallerDialog() |
39 | : okay(":/images/dialog-ok-apply.png" ), next(":/images/go-next.png" ), error(":/images/dialog-cancel.png" ), m_postProcessing(&m_engine, this), m_log(0) |
40 | { |
41 | ui.setupUi(this); |
42 | |
43 | connect(ui.closeButton, SIGNAL(clicked()), this, SLOT(stop())); |
44 | initItems(); |
45 | |
46 | setMessageHandler("single-package-installer" ); |
47 | |
48 | QString setupName; |
49 | |
50 | if (QCoreApplication::arguments().size() > 1) |
51 | setupName = QCoreApplication::arguments().at(1); |
52 | |
53 | InstallerCallConfig config(setupName); |
54 | |
55 | if (config.isValid()) |
56 | { |
57 | InstallerEngine::defaultConfigURL = QString("http://download.kde.org/%1/%2" ).arg(toString(config.releaseType)).arg(config.version); |
58 | InstallerEngine::fallBackURL = QString("http://www.winkde.org/pub/kde/ports/win32/releases/%1/%2" ).arg(toString(config.releaseType)).arg(config.version); |
59 | #ifdef Q_OS_WIN |
60 | QString installRoot = QString("%1/%2-%3-%4-%5%6" ).arg(QLatin1String(qgetenv("ProgramFiles" ))).arg(config.packageName).arg(allCompilers.toString(config.compilerType)).arg(toString(config.releaseType)).arg(config.version).arg(config.hasSDK ? "-sdk" : "" ); |
61 | #else |
62 | QString installRoot = QString("%1/%2-%3-%4-%5%6" ).arg(QLatin1String(qgetenv("HOME" ))).arg(config.packageName).arg(allCompilers.toString(config.compilerType)).arg(toString(config.releaseType)).arg(config.version).arg(config.hasSDK ? "-sdk" : "" ); |
63 | #endif |
64 | addHint("I'm installing into " + installRoot); |
65 | Settings::instance().setInstallDir(installRoot, false); |
66 | m_engine.setRoot(installRoot); |
67 | m_engine.setWithDevelopmentPackages(config.hasSDK); |
68 | m_engine.setCurrentCompiler(config.compilerType); |
69 | ProxySettings ps; |
70 | |
71 | m_postProcessing.setSingleApplicationMode(true); |
72 | m_postProcessing.setPackageName(config.packageName); |
73 | |
74 | QString title = tr("KDE %1 %2 Installer" ).arg(config.packageName).arg(config.hasSDK ? "SDK" : "Application" ); |
75 | setWindowTitle(title); |
76 | ui.topLabel->setText(title); |
77 | |
78 | if (ps.from(ProxySettings::AutoDetect)) |
79 | { |
80 | ps.save(); |
81 | addHint("I'm " + ps.toString()); |
82 | } |
83 | m_packages << config.packageName.toLower()+'-'+allCompilers.toString(config.compilerType); |
84 | |
85 | // @TODO: this is a hack, need to be solved by build requirements in the config file |
86 | if (config.hasSDK && config.packageName.toLower() == "umbrello" ) |
87 | m_packages << "automoc" << "boost" ; |
88 | |
89 | setItem(0); |
90 | QTimer::singleShot(250,this,SLOT(setupEngine())); |
91 | } |
92 | else |
93 | { |
94 | setWindowTitle(tr("KDE Single Application Installer" )); |
95 | ui.topLabel->setText(tr("KDE Single Application Installer" )); |
96 | addHint("I could not find a valid configuration" ); |
97 | } |
98 | } |
99 | |
100 | InstallerDialog::~InstallerDialog() |
101 | { |
102 | delete m_log; |
103 | } |
104 | |
105 | void InstallerDialog::initItems() |
106 | { |
107 | ui.label1->setText("" ); |
108 | ui.label1->setVisible(false); |
109 | ui.textLabel1->setVisible(false); |
110 | ui.label2->setText("" ); |
111 | ui.label2->setVisible(false); |
112 | ui.textLabel2->setVisible(false); |
113 | ui.label3->setText("" ); |
114 | ui.label3->setVisible(false); |
115 | ui.textLabel3->setVisible(false); |
116 | ui.label4->setText("" ); |
117 | ui.label4->setVisible(false); |
118 | ui.textLabel4->setVisible(false); |
119 | ui.label5->setText("" ); |
120 | ui.label5->setVisible(false); |
121 | ui.textLabel5->setVisible(false); |
122 | ui.hintLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); |
123 | ui.logButton->setVisible(false); |
124 | setSubLabelHint("" ); |
125 | connect(ui.logButton, SIGNAL(clicked(bool)), this, SLOT(showLog(bool))); |
126 | } |
127 | |
128 | void InstallerDialog::addHint(const QString &hint) |
129 | { |
130 | ui.hintLabel->setText(ui.hintLabel->text() + "<br>" + hint); |
131 | QCoreApplication::processEvents(); |
132 | } |
133 | |
134 | void InstallerDialog::setSubLabelHint(const QString &hint) |
135 | { |
136 | if (hint.isEmpty()) |
137 | { |
138 | ui.subLabel->setVisible(false); |
139 | } |
140 | else |
141 | { |
142 | ui.subLabel->setVisible(true); |
143 | ui.subLabel->setText(hint); |
144 | } |
145 | QCoreApplication::processEvents(); |
146 | } |
147 | |
148 | void InstallerDialog::showLog(bool checked) |
149 | { |
150 | m_log = new QTextEdit(*log()); |
151 | m_log->showMaximized(); |
152 | } |
153 | |
154 | void InstallerDialog::setItem(int pagenum) |
155 | { |
156 | switch (pagenum) |
157 | { |
158 | case 0: |
159 | ui.label1->setPixmap(next); |
160 | ui.label1->setVisible(true); |
161 | ui.textLabel1->setVisible(true); |
162 | break; |
163 | |
164 | case 1: |
165 | ui.label1->setPixmap(okay); |
166 | ui.label2->setPixmap(next); |
167 | ui.label2->setVisible(true); |
168 | ui.textLabel2->setVisible(true); |
169 | break; |
170 | |
171 | case 2: |
172 | ui.label2->setPixmap(okay); |
173 | ui.label3->setPixmap(next); |
174 | ui.label3->setVisible(true); |
175 | ui.textLabel3->setVisible(true); |
176 | break; |
177 | |
178 | case 3: |
179 | ui.label3->setPixmap(okay); |
180 | ui.label4->setPixmap(next); |
181 | ui.label4->setVisible(true); |
182 | ui.textLabel4->setVisible(true); |
183 | break; |
184 | |
185 | case 4: |
186 | ui.label4->setPixmap(okay); |
187 | ui.label5->setPixmap(next); |
188 | ui.label5->setVisible(true); |
189 | ui.textLabel5->setVisible(true); |
190 | break; |
191 | |
192 | case 5: |
193 | ui.label5->setPixmap(okay); |
194 | break; |
195 | } |
196 | QCoreApplication::processEvents(); |
197 | } |
198 | |
199 | void InstallerDialog::setError(int pagenum) |
200 | { |
201 | switch (pagenum) |
202 | { |
203 | case 0: |
204 | ui.label1->setPixmap(error); |
205 | break; |
206 | |
207 | case 1: |
208 | ui.label2->setPixmap(error); |
209 | break; |
210 | |
211 | case 2: |
212 | ui.label3->setPixmap(error); |
213 | break; |
214 | |
215 | case 3: |
216 | ui.label4->setPixmap(error); |
217 | break; |
218 | |
219 | case 4: |
220 | ui.label5->setPixmap(error); |
221 | break; |
222 | } |
223 | ui.logButton->setVisible(true); |
224 | QCoreApplication::processEvents(); |
225 | } |
226 | |
227 | void InstallerDialog::setupEngine() |
228 | { |
229 | setItem(1); |
230 | |
231 | if (m_engine.init()) |
232 | { |
233 | QStringList urls; |
234 | foreach(Site *site, *m_engine.globalConfig()->sites()) |
235 | { |
236 | const QUrl listURL = site->listURL().isEmpty() ? site->url() : site->listURL(); |
237 | urls << site->name() + " : " + listURL.toString(); |
238 | } |
239 | |
240 | addHint("I'm fetching packages from the following repositories:<br> " + urls.join("<br> " )); |
241 | |
242 | foreach(const QString &package, m_packages) |
243 | { |
244 | Package *p = m_engine.getPackageByName(package); |
245 | if (p) |
246 | { |
247 | m_packagesToInstall.append(p); |
248 | m_engine.setDependencyState(p,m_packagesToInstall); |
249 | } |
250 | else |
251 | { |
252 | addHint(QString(".... could not find package %1" ).arg(package)); |
253 | setError(4); |
254 | } |
255 | } |
256 | // the api should provide a method like |
257 | // m_engine.resolveDependencies(m_packagesToInstall); |
258 | // @TODO: in sdk mode we should download and install all dependencies but not the requested package |
259 | QTimer::singleShot(1,this,SLOT(downloadPackages())); |
260 | } |
261 | else |
262 | { |
263 | addHint(QString(".... initialisation failed" )); |
264 | setError(1); |
265 | } |
266 | } |
267 | |
268 | void InstallerDialog::downloadPackages() |
269 | { |
270 | setItem(2); |
271 | addHint(QString("I will download up to %1 package(s) depending on what has been downloaded earlier" ).arg(m_packagesToInstall.size())); |
272 | m_counter = 10; |
273 | QTimer::singleShot(1,this,SLOT(downloadPackagesStage1())); |
274 | } |
275 | |
276 | void InstallerDialog::downloadPackagesStage1() |
277 | { |
278 | if (m_counter-- > 0) |
279 | { |
280 | setSubLabelHint(QString("%1 seconds left until download starts" ).arg(m_counter+1)); |
281 | QTimer::singleShot(1000,this,SLOT(downloadPackagesStage1())); |
282 | } |
283 | else |
284 | { |
285 | setSubLabelHint("" ); |
286 | QTimer::singleShot(1,this,SLOT(downloadPackagesStage2())); |
287 | } |
288 | } |
289 | |
290 | void InstallerDialog::downloadPackagesStage2() |
291 | { |
292 | setItem(2); |
293 | addHint(QString("I'm downloading package(s)" )); |
294 | if (m_engine.downloadPackages(m_packagesToInstall)) |
295 | QTimer::singleShot(1,this,SLOT(installPackages())); |
296 | else |
297 | { |
298 | addHint(QString(".... download failed" )); |
299 | setError(2); |
300 | } |
301 | } |
302 | |
303 | void InstallerDialog::installPackages() |
304 | { |
305 | setItem(3); |
306 | addHint(QString("I'm installing %1 package(s)" ).arg(m_packagesToInstall.size())); |
307 | if (m_engine.installPackages(m_packagesToInstall)) |
308 | { |
309 | if (m_engine.withDevelopmentPackages()) |
310 | QTimer::singleShot(1,this,SLOT(finished())); |
311 | else |
312 | QTimer::singleShot(1,this,SLOT(postProcessing())); |
313 | } |
314 | else |
315 | { |
316 | addHint(QString(".... installation failed" )); |
317 | setError(3); |
318 | } |
319 | } |
320 | |
321 | void InstallerDialog::postProcessing() |
322 | { |
323 | setItem(4); |
324 | addHint("I'm running tools:" ); |
325 | connect(&m_postProcessing,SIGNAL(finished()),this,SLOT(finished())); |
326 | connect(&m_postProcessing,SIGNAL(commandStarted(const QString &)),this,SLOT(addHint(const QString &))); |
327 | ui.closeButton->setEnabled(false); |
328 | // fetch version from package - it is not sure yet if running a gui app --version returns the version on stdout |
329 | if(m_packagesToInstall.size() <= 0) { |
330 | finished(); |
331 | return; |
332 | } |
333 | |
334 | m_postProcessing.setVersion(m_packagesToInstall[0]->version().toString()); |
335 | m_postProcessing.start(); |
336 | } |
337 | |
338 | void InstallerDialog::finished() |
339 | { |
340 | setItem(5); |
341 | ui.closeButton->setEnabled(true); |
342 | ui.closeButton->setText(tr("Finish" )); |
343 | } |
344 | |
345 | void InstallerDialog::stop() |
346 | { |
347 | close(); |
348 | } |
349 | |
350 | void InstallerDialog::closeEvent(QCloseEvent *e) |
351 | { |
352 | m_postProcessing.stop(); |
353 | if (m_log) |
354 | m_log->hide(); |
355 | e->accept(); |
356 | } |
357 | |
358 | |
359 | |