VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/VBoxExportApplianceWzd.cpp@ 20138

Last change on this file since 20138 was 20138, checked in by vboxsync, 16 years ago

FE/Qt4: little corrections

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.4 KB
Line 
1/** @file
2 *
3 * VBox frontends: Qt4 GUI ("VirtualBox"):
4 * VBoxExportAppliance class implementation
5 */
6
7/*
8 * Copyright (C) 2009 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#include "VBoxExportApplianceWzd.h"
24#include "VBoxGlobal.h"
25#include "QIWidgetValidator.h"
26#include "VBoxProblemReporter.h"
27
28/* Qt includes */
29#include <QDir>
30
31class VMListWidgetItems: public QListWidgetItem
32{
33public:
34 VMListWidgetItems (QPixmap &aIcon, QString &aText, QListWidget *aParent)
35 : QListWidgetItem (aIcon, aText, aParent) {}
36
37 /* Sort like in the VM selector of the main window */
38 bool operator< (const QListWidgetItem &aOther) const
39 {
40 return text().toLower() < aOther.text().toLower();
41 }
42};
43
44////////////////////////////////////////////////////////////////////////////////
45// VBoxExportApplianceWzd
46
47VBoxExportApplianceWzd::VBoxExportApplianceWzd (QWidget *aParent /* = NULL */, const QString& aSelectName /* = QString::null */)
48 : QIWithRetranslateUI<QIAbstractWizard> (aParent)
49{
50 /* Apply UI decorations */
51 Ui::VBoxExportApplianceWzd::setupUi (this);
52
53 /* Initialize wizard hdr */
54 initializeWizardHdr();
55
56 /* Configure the VM selector widget */
57 mVMListWidget->setAlternatingRowColors (true);
58 mVMListWidget->setSelectionMode (QAbstractItemView::ExtendedSelection);
59
60 /* Validator for the VM selector page */
61 mWValVMSelector = new QIWidgetValidator (mVMSelectPage, this);
62 connect (mWValVMSelector, SIGNAL (validityChanged (const QIWidgetValidator *)),
63 this, SLOT (enableNext (const QIWidgetValidator *)));
64 connect (mWValVMSelector, SIGNAL (isValidRequested (QIWidgetValidator *)),
65 this, SLOT (revalidate (QIWidgetValidator *)));
66 connect (mVMListWidget, SIGNAL (itemSelectionChanged()),
67 mWValVMSelector, SLOT (revalidate()));
68
69 /* Fill the VM selector list */
70 addListViewVMItems (aSelectName);
71 mWValVMSelector->revalidate();
72
73 /* Configure the file selector */
74// mFileSelector->setMode (VBoxFilePathSelectorWidget::Mode_File_Save);
75 mFileSelector->setEditable (true);
76 mFileSelector->setButtonPosition (VBoxEmptyFileSelector::RightPosition);
77 mFileSelector->setFileDialogTitle (tr ("Select a file to export into"));
78 mFileSelector->setFileFilters (tr ("Open Virtualization Format (%1)").arg ("*.ovf"));
79 mFileSelector->setDefaultSaveExt ("ovf");
80 setTabOrder (mLeBucket, mFileSelector);
81
82 /* Connect the restore button with the settings widget */
83 connect (mBtnRestore, SIGNAL (clicked()),
84 mExportSettingsWgt, SLOT (restoreDefaults()));
85
86 /* Validator for the file selector page */
87 mWValFileSelector = new QIWidgetValidator (mTargetOptionsPage, this);
88 connect (mWValFileSelector, SIGNAL (validityChanged (const QIWidgetValidator *)),
89 this, SLOT (enableNext (const QIWidgetValidator *)));
90 connect (mWValFileSelector, SIGNAL (isValidRequested (QIWidgetValidator *)),
91 this, SLOT (revalidate (QIWidgetValidator *)));
92 connect (mFileSelector, SIGNAL (pathChanged (const QString &)),
93 mWValFileSelector, SLOT (revalidate()));
94 connect (mLeUsername, SIGNAL (textChanged (const QString &)),
95 mWValFileSelector, SLOT (revalidate()));
96 connect (mLePassword, SIGNAL (textChanged (const QString &)),
97 mWValFileSelector, SLOT (revalidate()));
98 connect (mLeHostname, SIGNAL (textChanged (const QString &)),
99 mWValFileSelector, SLOT (revalidate()));
100 connect (mLeBucket, SIGNAL (textChanged (const QString &)),
101 mWValFileSelector, SLOT (revalidate()));
102
103 mLeUsername->setText (vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_Export_Username));
104 mLeHostname->setText (vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_Export_Hostname));
105 mLeBucket->setText (vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_Export_Bucket));
106
107 mWValFileSelector->revalidate();
108
109 /* Initialize wizard ftr */
110 initializeWizardFtr();
111
112 retranslateUi();
113
114 bool ok;
115 StorageType type = StorageType (vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_Export_StorageType).toInt(&ok));
116 if (ok)
117 setCurrentStorageType (type);
118}
119
120void VBoxExportApplianceWzd::retranslateUi()
121{
122 /* Translate uic generated strings */
123 Ui::VBoxExportApplianceWzd::retranslateUi (this);
124
125 mDefaultApplianceName = tr("Appliance");
126
127 mExportToFileSystemDesc = tr("Please choose a filename to export the OVF in.");
128 mExportToSunCloudDesc = tr("Please complete the additionally fields like the username, password and the bucket. Finally you have to provide a filename for the OVF target.");
129 mExportToS3Desc = tr("Please complete the additionally fields like the username, password, hostname and the bucket. Finally you have to provide a filename for the OVF target.");
130
131 switch (currentStorageType())
132 {
133 case Filesystem: mTextTargetOptions->setText (mExportToFileSystemDesc); break;
134 case SunCloud: mTextTargetOptions->setText (mExportToSunCloudDesc); break;
135 case S3: mTextTargetOptions->setText (mExportToS3Desc); break;
136 }
137}
138
139void VBoxExportApplianceWzd::revalidate (QIWidgetValidator *aWval)
140{
141 /* Do individual validations for pages */
142 bool valid = aWval->isOtherValid();
143
144 if (aWval == mWValVMSelector)
145 valid = mVMListWidget->selectedItems().size() > 0;
146
147 if (aWval == mWValFileSelector)
148 {
149 valid = mFileSelector->path().toLower().endsWith (".ovf");
150 if (currentStorageType() == SunCloud)
151 {
152 valid &= !mLeUsername->text().isEmpty() &&
153 !mLePassword->text().isEmpty() &&
154 !mLeBucket->text().isEmpty();
155 }
156 else if (currentStorageType() == S3)
157 {
158 valid &= !mLeUsername->text().isEmpty() &&
159 !mLePassword->text().isEmpty() &&
160 !mLeHostname->text().isEmpty() &&
161 !mLeBucket->text().isEmpty();
162 }
163 }
164
165 aWval->setOtherValid (valid);
166}
167
168void VBoxExportApplianceWzd::enableNext (const QIWidgetValidator *aWval)
169{
170 if (aWval == mWValFileSelector)
171 finishButton()->setEnabled (aWval->isValid());
172 else
173 nextButton (aWval->widget())->setEnabled (aWval->isValid());
174}
175
176void VBoxExportApplianceWzd::accept()
177{
178 CAppliance *appliance = mExportSettingsWgt->appliance();
179 QFileInfo fi (mFileSelector->path());
180 QVector<QString> files;
181 files << fi.fileName();
182 /* We need to know every filename which will be created, so that we can
183 * ask the user for confirmation of overwriting. For that we iterating
184 * over all virtual systems & fetch all descriptions of the type
185 * HardDiskImage. */
186 CVirtualSystemDescriptionVector vsds = appliance->GetVirtualSystemDescriptions();
187 for (int i=0; i < vsds.size(); ++i)
188 {
189 QVector<KVirtualSystemDescriptionType> types;
190 QVector<QString> refs, origValues, configValues, extraConfigValues;
191
192 vsds[i].GetDescriptionByType (KVirtualSystemDescriptionType_HardDiskImage, types, refs, origValues, configValues, extraConfigValues);
193 foreach (const QString &s, origValues)
194 files << QString ("%2").arg (s);
195 }
196 CVFSExplorer explorer = appliance->CreateVFSExplorer(uri());
197 CProgress progress = explorer.Update();
198 bool fResult = explorer.isOk();
199 if (fResult)
200 {
201 /* Show some progress, so the user know whats going on */
202 vboxProblem().showModalProgressDialog (progress, tr ("Checking files ..."), this);
203 if (progress.GetCanceled())
204 return;
205 if (!progress.isOk() || progress.GetResultCode() != 0)
206 {
207 vboxProblem().cannotCheckFiles (progress, this);
208 return;
209 }
210 }
211 QVector<QString> exists = explorer.Exists (files);
212 /* Check if the file exists already, if yes get confirmation for
213 * overwriting from the user. */
214 if (!vboxProblem().askForOverridingFiles (exists, this))
215 return;
216 /* Ok all is confirmed so delete all the files which exists */
217 if (!exists.isEmpty())
218 {
219 CProgress progress1 = explorer.Remove (exists);
220 fResult = explorer.isOk();
221 if (fResult)
222 {
223 /* Show some progress, so the user know whats going on */
224 vboxProblem().showModalProgressDialog (progress1, tr ("Removing files ..."), this);
225 if (progress1.GetCanceled())
226 return;
227 if (!progress1.isOk() || progress1.GetResultCode() != 0)
228 {
229 vboxProblem().cannotRemoveFiles (progress1, this);
230 return;
231 }
232 }
233 }
234 /* Export the VMs, on success we are finished */
235 if (exportVMs (*appliance))
236 {
237 vboxGlobal().virtualBox().SetExtraData (VBoxDefs::GUI_Export_StorageType, QString::number(currentStorageType()));
238 vboxGlobal().virtualBox().SetExtraData (VBoxDefs::GUI_Export_Username, mLeUsername->text());
239 vboxGlobal().virtualBox().SetExtraData (VBoxDefs::GUI_Export_Hostname, mLeHostname->text());
240 vboxGlobal().virtualBox().SetExtraData (VBoxDefs::GUI_Export_Bucket, mLeBucket->text());
241 QIAbstractWizard::accept();
242 }
243}
244
245void VBoxExportApplianceWzd::showNextPage()
246{
247 /* We propose a filename the first time the second page is displayed */
248 if (sender() == mBtnNext1)
249 {
250 prepareSettingsWidget();
251 }
252 else if (sender() == mBtnNext3)
253 {
254 storageTypeChanged();
255 if (mFileSelector->path().isEmpty())
256 {
257 /* Set the default filename */
258 QString name = mDefaultApplianceName;
259 /* If it is one VM only, we use the VM name as file name */
260 if (mVMListWidget->selectedItems().size() == 1)
261 name = mVMListWidget->selectedItems().first()->text();
262
263 name += ".ovf";
264
265 if (currentStorageType() == Filesystem)
266 name = QDir::toNativeSeparators (QString ("%1/%2").arg (vboxGlobal().documentsPath())
267 .arg (name));
268 mFileSelector->setPath (name);
269 mWValFileSelector->revalidate();
270 }
271 mExportSettingsWgt->prepareExport();
272 }
273
274 QIAbstractWizard::showNextPage();
275}
276
277void VBoxExportApplianceWzd::onPageShow()
278{
279 QWidget *page = mPageStack->currentWidget();
280
281 if (page == mTargetOptionsPage)
282 finishButton()->setDefault (true);
283 else
284 nextButton (page)->setDefault (true);
285}
286
287void VBoxExportApplianceWzd::addListViewVMItems (const QString& aSelectName)
288{
289 CVirtualBox vbox = vboxGlobal().virtualBox();
290 CMachineVector vec = vbox.GetMachines();
291 for (CMachineVector::ConstIterator m = vec.begin();
292 m != vec.end(); ++ m)
293 {
294 QPixmap icon;
295 QString name;
296 QString uuid;
297 bool enabled;
298 if (m->GetAccessible())
299 {
300 icon = vboxGlobal().vmGuestOSTypeIcon (m->GetOSTypeId()).scaled (16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
301 name = m->GetName();
302 uuid = m->GetId();
303 enabled = m->GetSessionState() == KSessionState_Closed;
304 }
305 else
306 {
307 QString settingsFile = m->GetSettingsFilePath();
308 QFileInfo fi (settingsFile);
309 name = fi.completeSuffix().toLower() == "xml" ?
310 fi.completeBaseName() : fi.fileName();
311 icon = QPixmap (":/os_other.png").scaled (16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
312 enabled = false;
313 }
314 QListWidgetItem *item = new VMListWidgetItems (icon, name, mVMListWidget);
315 item->setData (Qt::UserRole, uuid);
316 if (!enabled)
317 item->setFlags (0);
318 mVMListWidget->addItem (item);
319 }
320 mVMListWidget->sortItems();
321
322 /* Make sure aSelectName is initial selected in the list */
323 QList<QListWidgetItem *> list = mVMListWidget->findItems (aSelectName, Qt::MatchExactly);
324 if (list.size() > 0)
325 mVMListWidget->setCurrentItem (list.first());
326}
327
328bool VBoxExportApplianceWzd::prepareSettingsWidget()
329{
330 CVirtualBox vbox = vboxGlobal().virtualBox();
331 CAppliance *appliance = mExportSettingsWgt->init();
332 bool fResult = appliance->isOk();
333 if (fResult)
334 {
335 /* Iterate over all selected items */
336 QList<QListWidgetItem *> list = mVMListWidget->selectedItems();
337 foreach (const QListWidgetItem* item, list)
338 {
339 /* The VM uuid can be fetched by the UserRole */
340 QString uuid = item->data (Qt::UserRole).toString();
341 /* Get the machine with the uuid */
342 CMachine m = vbox.GetMachine (uuid);
343 fResult = m.isOk();
344 if (fResult)
345 {
346 /* Add the export description to our appliance object */
347 CVirtualSystemDescription vsd = m.Export (*appliance);
348 fResult = m.isOk();
349 if (!fResult)
350 {
351 vboxProblem().cannotExportAppliance (m, appliance, this);
352 return false;
353 }
354 /* Now add some new fields the user may change */
355 vsd.AddDescription (KVirtualSystemDescriptionType_Product, "", "");
356 vsd.AddDescription (KVirtualSystemDescriptionType_ProductUrl, "", "");
357 vsd.AddDescription (KVirtualSystemDescriptionType_Vendor, "", "");
358 vsd.AddDescription (KVirtualSystemDescriptionType_VendorUrl, "", "");
359 vsd.AddDescription (KVirtualSystemDescriptionType_Version, "", "");
360 vsd.AddDescription (KVirtualSystemDescriptionType_License, "", "");
361 }
362 else
363 break;
364 }
365 /* Make sure the settings widget get the new descriptions */
366 mExportSettingsWgt->populate();
367 }
368 if (!fResult)
369 vboxProblem().cannotExportAppliance (appliance, this);
370 return fResult;
371}
372
373bool VBoxExportApplianceWzd::exportVMs (CAppliance &aAppliance)
374{
375 /* Write the appliance */
376 QString version = mSelectOVF09->isChecked() ? "ovf-0.9" : "ovf-1.0";
377 CProgress progress = aAppliance.Write (version, uri());
378 bool fResult = aAppliance.isOk();
379 if (fResult)
380 {
381 /* Show some progress, so the user know whats going on */
382 vboxProblem().showModalProgressDialog (progress, tr ("Exporting Appliance ..."), this);
383 if (progress.GetCanceled())
384 return false;
385 if (!progress.isOk() || progress.GetResultCode() != 0)
386 {
387 vboxProblem().cannotExportAppliance (progress, &aAppliance, this);
388 return false;
389 }
390 else
391 return true;
392 }
393 if (!fResult)
394 vboxProblem().cannotExportAppliance (&aAppliance, this);
395 return false;
396}
397
398QString VBoxExportApplianceWzd::uri() const
399{
400 if (currentStorageType() == Filesystem)
401 return mFileSelector->path();
402 else if (currentStorageType() == SunCloud)
403 {
404 QString uri ("SunCloud://");
405 if (!mLeUsername->text().isEmpty())
406 uri = QString ("%1%2").arg (uri).arg (mLeUsername->text());
407 if (!mLePassword->text().isEmpty())
408 uri = QString ("%1:%2").arg (uri).arg (mLePassword->text());
409 if (!mLeUsername->text().isEmpty() ||
410 !mLePassword->text().isEmpty())
411 uri = QString ("%1@").arg (uri);
412 uri = QString ("%1%2/%3/%4").arg (uri).arg ("object.storage.network.com").arg (mLeBucket->text()).arg (mFileSelector->path());
413 return uri;
414 }
415 else if (currentStorageType() == S3)
416 {
417 QString uri ("S3://");
418 if (!mLeUsername->text().isEmpty())
419 uri = QString ("%1%2").arg (uri).arg (mLeUsername->text());
420 if (!mLePassword->text().isEmpty())
421 uri = QString ("%1:%2").arg (uri).arg (mLePassword->text());
422 if (!mLeUsername->text().isEmpty() ||
423 !mLePassword->text().isEmpty())
424 uri = QString ("%1@").arg (uri);
425 uri = QString ("%1%2/%3/%4").arg (uri).arg (mLeHostname->text()).arg (mLeBucket->text()).arg (mFileSelector->path());
426 return uri;
427 }
428 return "";
429}
430
431VBoxExportApplianceWzd::StorageType VBoxExportApplianceWzd::currentStorageType() const
432{
433 if (mRBtnLocalFileSystem->isChecked())
434 return Filesystem;
435 else if (mRBtnSunCloud->isChecked())
436 return SunCloud;
437 else
438 return S3;
439}
440
441void VBoxExportApplianceWzd::storageTypeChanged()
442{
443 StorageType type = currentStorageType();
444 switch (type)
445 {
446 case Filesystem:
447 {
448 mTextTargetOptions->setText (mExportToFileSystemDesc);
449 mLblUsername->setVisible (false);
450 mLeUsername->setVisible (false);
451 mLblPassword->setVisible (false);
452 mLePassword->setVisible (false);
453 mLblHostname->setVisible (false);
454 mLeHostname->setVisible (false);
455 mLblBucket->setVisible (false);
456 mLeBucket->setVisible (false);
457 mSelectOVF09->setVisible (true);
458 mFileSelector->setChooserVisible (true);
459 mFileSelector->setFocus();
460 break;
461 };
462 case SunCloud:
463 {
464 mTextTargetOptions->setText (mExportToSunCloudDesc);
465 mLblUsername->setVisible (true);
466 mLeUsername->setVisible (true);
467 mLblPassword->setVisible (true);
468 mLePassword->setVisible (true);
469 mLblHostname->setVisible (false);
470 mLeHostname->setVisible (false);
471 mLblBucket->setVisible (true);
472 mLeBucket->setVisible (true);
473 mSelectOVF09->setVisible (false);
474 mSelectOVF09->setChecked (false);
475 mFileSelector->setChooserVisible (false);
476 mLeUsername->setFocus();
477 break;
478 };
479 case S3:
480 {
481 mTextTargetOptions->setText (mExportToS3Desc);
482 mLblUsername->setVisible (true);
483 mLeUsername->setVisible (true);
484 mLblPassword->setVisible (true);
485 mLePassword->setVisible (true);
486 mLblHostname->setVisible (true);
487 mLeHostname->setVisible (true);
488 mLblBucket->setVisible (true);
489 mLeBucket->setVisible (true);
490 mSelectOVF09->setVisible (true);
491 mFileSelector->setChooserVisible (false);
492 mLeUsername->setFocus();
493 break;
494 };
495 }
496
497 if (!mFileSelector->path().isEmpty())
498 {
499 QFileInfo fi (mFileSelector->path());
500 QString name = fi.fileName();
501 if (type == Filesystem)
502 name = QDir::toNativeSeparators (QString ("%1/%2").arg (vboxGlobal().documentsPath())
503 .arg (name));
504 mFileSelector->setPath (name);
505 }
506}
507
508void VBoxExportApplianceWzd::setCurrentStorageType (VBoxExportApplianceWzd::StorageType aType)
509{
510 switch (aType)
511 {
512 case Filesystem: mRBtnLocalFileSystem->setChecked(true); mRBtnLocalFileSystem->setFocus(); break;
513 case SunCloud: mRBtnSunCloud->setChecked(true); mRBtnSunCloud->setFocus(); break;
514 case S3: mRBtnS3->setChecked(true); mRBtnS3->setFocus(); break;
515 }
516}
517
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette