VirtualBox

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

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

FE/Qt4: disabled internet based OVF export again

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.7 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 /* Type selection is disabled for now */
115 connect (mBtnNext2, SIGNAL (clicked(bool)),
116 mBtnNext3, SLOT (click()));
117 connect (mBtnBack4, SIGNAL (clicked(bool)),
118 mBtnBack3, SLOT (click()));
119
120// bool ok;
121// StorageType type = StorageType (vboxGlobal().virtualBox().GetExtraData (VBoxDefs::GUI_Export_StorageType).toInt(&ok));
122// if (ok)
123// setCurrentStorageType (type);
124}
125
126void VBoxExportApplianceWzd::retranslateUi()
127{
128 /* Translate uic generated strings */
129 Ui::VBoxExportApplianceWzd::retranslateUi (this);
130
131 mDefaultApplianceName = tr("Appliance");
132
133 mExportToFileSystemDesc = tr("Please choose a filename to export the OVF in.");
134 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.");
135 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.");
136
137 switch (currentStorageType())
138 {
139 case Filesystem: mTextTargetOptions->setText (mExportToFileSystemDesc); break;
140 case SunCloud: mTextTargetOptions->setText (mExportToSunCloudDesc); break;
141 case S3: mTextTargetOptions->setText (mExportToS3Desc); break;
142 }
143}
144
145void VBoxExportApplianceWzd::revalidate (QIWidgetValidator *aWval)
146{
147 /* Do individual validations for pages */
148 bool valid = aWval->isOtherValid();
149
150 if (aWval == mWValVMSelector)
151 valid = mVMListWidget->selectedItems().size() > 0;
152
153 if (aWval == mWValFileSelector)
154 {
155 valid = mFileSelector->path().toLower().endsWith (".ovf");
156 if (currentStorageType() == SunCloud)
157 {
158 valid &= !mLeUsername->text().isEmpty() &&
159 !mLePassword->text().isEmpty() &&
160 !mLeBucket->text().isEmpty();
161 }
162 else if (currentStorageType() == S3)
163 {
164 valid &= !mLeUsername->text().isEmpty() &&
165 !mLePassword->text().isEmpty() &&
166 !mLeHostname->text().isEmpty() &&
167 !mLeBucket->text().isEmpty();
168 }
169 }
170
171 aWval->setOtherValid (valid);
172}
173
174void VBoxExportApplianceWzd::enableNext (const QIWidgetValidator *aWval)
175{
176 if (aWval == mWValFileSelector)
177 finishButton()->setEnabled (aWval->isValid());
178 else
179 nextButton (aWval->widget())->setEnabled (aWval->isValid());
180}
181
182void VBoxExportApplianceWzd::accept()
183{
184 CAppliance *appliance = mExportSettingsWgt->appliance();
185 QFileInfo fi (mFileSelector->path());
186 QVector<QString> files;
187 files << fi.fileName();
188 /* We need to know every filename which will be created, so that we can
189 * ask the user for confirmation of overwriting. For that we iterating
190 * over all virtual systems & fetch all descriptions of the type
191 * HardDiskImage. */
192 CVirtualSystemDescriptionVector vsds = appliance->GetVirtualSystemDescriptions();
193 for (int i=0; i < vsds.size(); ++i)
194 {
195 QVector<KVirtualSystemDescriptionType> types;
196 QVector<QString> refs, origValues, configValues, extraConfigValues;
197
198 vsds[i].GetDescriptionByType (KVirtualSystemDescriptionType_HardDiskImage, types, refs, origValues, configValues, extraConfigValues);
199 foreach (const QString &s, origValues)
200 files << QString ("%2").arg (s);
201 }
202 CVFSExplorer explorer = appliance->CreateVFSExplorer(uri());
203 CProgress progress = explorer.Update();
204 bool fResult = explorer.isOk();
205 if (fResult)
206 {
207 /* Show some progress, so the user know whats going on */
208 vboxProblem().showModalProgressDialog (progress, tr ("Checking files ..."), this);
209 if (progress.GetCanceled())
210 return;
211 if (!progress.isOk() || progress.GetResultCode() != 0)
212 {
213 vboxProblem().cannotCheckFiles (progress, this);
214 return;
215 }
216 }
217 QVector<QString> exists = explorer.Exists (files);
218 /* Check if the file exists already, if yes get confirmation for
219 * overwriting from the user. */
220 if (!vboxProblem().askForOverridingFiles (exists, this))
221 return;
222 /* Ok all is confirmed so delete all the files which exists */
223 if (!exists.isEmpty())
224 {
225 CProgress progress1 = explorer.Remove (exists);
226 fResult = explorer.isOk();
227 if (fResult)
228 {
229 /* Show some progress, so the user know whats going on */
230 vboxProblem().showModalProgressDialog (progress1, tr ("Removing files ..."), this);
231 if (progress1.GetCanceled())
232 return;
233 if (!progress1.isOk() || progress1.GetResultCode() != 0)
234 {
235 vboxProblem().cannotRemoveFiles (progress1, this);
236 return;
237 }
238 }
239 }
240 /* Export the VMs, on success we are finished */
241 if (exportVMs (*appliance))
242 {
243// vboxGlobal().virtualBox().SetExtraData (VBoxDefs::GUI_Export_StorageType, QString::number(currentStorageType()));
244// vboxGlobal().virtualBox().SetExtraData (VBoxDefs::GUI_Export_Username, mLeUsername->text());
245// vboxGlobal().virtualBox().SetExtraData (VBoxDefs::GUI_Export_Hostname, mLeHostname->text());
246// vboxGlobal().virtualBox().SetExtraData (VBoxDefs::GUI_Export_Bucket, mLeBucket->text());
247 QIAbstractWizard::accept();
248 }
249}
250
251void VBoxExportApplianceWzd::showNextPage()
252{
253 /* We propose a filename the first time the second page is displayed */
254 if (sender() == mBtnNext1)
255 {
256 prepareSettingsWidget();
257 }
258 else if (sender() == mBtnNext3)
259 {
260 storageTypeChanged();
261 if (mFileSelector->path().isEmpty())
262 {
263 /* Set the default filename */
264 QString name = mDefaultApplianceName;
265 /* If it is one VM only, we use the VM name as file name */
266 if (mVMListWidget->selectedItems().size() == 1)
267 name = mVMListWidget->selectedItems().first()->text();
268
269 name += ".ovf";
270
271 if (currentStorageType() == Filesystem)
272 name = QDir::toNativeSeparators (QString ("%1/%2").arg (vboxGlobal().documentsPath())
273 .arg (name));
274 mFileSelector->setPath (name);
275 mWValFileSelector->revalidate();
276 }
277 mExportSettingsWgt->prepareExport();
278 }
279
280 QIAbstractWizard::showNextPage();
281}
282
283void VBoxExportApplianceWzd::onPageShow()
284{
285 QWidget *page = mPageStack->currentWidget();
286
287 if (page == mTargetOptionsPage)
288 finishButton()->setDefault (true);
289 else
290 nextButton (page)->setDefault (true);
291}
292
293void VBoxExportApplianceWzd::addListViewVMItems (const QString& aSelectName)
294{
295 CVirtualBox vbox = vboxGlobal().virtualBox();
296 CMachineVector vec = vbox.GetMachines();
297 for (CMachineVector::ConstIterator m = vec.begin();
298 m != vec.end(); ++ m)
299 {
300 QPixmap icon;
301 QString name;
302 QString uuid;
303 bool enabled;
304 if (m->GetAccessible())
305 {
306 icon = vboxGlobal().vmGuestOSTypeIcon (m->GetOSTypeId()).scaled (16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
307 name = m->GetName();
308 uuid = m->GetId();
309 enabled = m->GetSessionState() == KSessionState_Closed;
310 }
311 else
312 {
313 QString settingsFile = m->GetSettingsFilePath();
314 QFileInfo fi (settingsFile);
315 name = fi.completeSuffix().toLower() == "xml" ?
316 fi.completeBaseName() : fi.fileName();
317 icon = QPixmap (":/os_other.png").scaled (16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
318 enabled = false;
319 }
320 QListWidgetItem *item = new VMListWidgetItems (icon, name, mVMListWidget);
321 item->setData (Qt::UserRole, uuid);
322 if (!enabled)
323 item->setFlags (0);
324 mVMListWidget->addItem (item);
325 }
326 mVMListWidget->sortItems();
327
328 /* Make sure aSelectName is initial selected in the list */
329 QList<QListWidgetItem *> list = mVMListWidget->findItems (aSelectName, Qt::MatchExactly);
330 if (list.size() > 0)
331 mVMListWidget->setCurrentItem (list.first());
332}
333
334bool VBoxExportApplianceWzd::prepareSettingsWidget()
335{
336 CVirtualBox vbox = vboxGlobal().virtualBox();
337 CAppliance *appliance = mExportSettingsWgt->init();
338 bool fResult = appliance->isOk();
339 if (fResult)
340 {
341 /* Iterate over all selected items */
342 QList<QListWidgetItem *> list = mVMListWidget->selectedItems();
343 foreach (const QListWidgetItem* item, list)
344 {
345 /* The VM uuid can be fetched by the UserRole */
346 QString uuid = item->data (Qt::UserRole).toString();
347 /* Get the machine with the uuid */
348 CMachine m = vbox.GetMachine (uuid);
349 fResult = m.isOk();
350 if (fResult)
351 {
352 /* Add the export description to our appliance object */
353 CVirtualSystemDescription vsd = m.Export (*appliance);
354 fResult = m.isOk();
355 if (!fResult)
356 {
357 vboxProblem().cannotExportAppliance (m, appliance, this);
358 return false;
359 }
360 /* Now add some new fields the user may change */
361 vsd.AddDescription (KVirtualSystemDescriptionType_Product, "", "");
362 vsd.AddDescription (KVirtualSystemDescriptionType_ProductUrl, "", "");
363 vsd.AddDescription (KVirtualSystemDescriptionType_Vendor, "", "");
364 vsd.AddDescription (KVirtualSystemDescriptionType_VendorUrl, "", "");
365 vsd.AddDescription (KVirtualSystemDescriptionType_Version, "", "");
366 vsd.AddDescription (KVirtualSystemDescriptionType_License, "", "");
367 }
368 else
369 break;
370 }
371 /* Make sure the settings widget get the new descriptions */
372 mExportSettingsWgt->populate();
373 }
374 if (!fResult)
375 vboxProblem().cannotExportAppliance (appliance, this);
376 return fResult;
377}
378
379bool VBoxExportApplianceWzd::exportVMs (CAppliance &aAppliance)
380{
381 /* Write the appliance */
382 QString version = mSelectOVF09->isChecked() ? "ovf-0.9" : "ovf-1.0";
383 CProgress progress = aAppliance.Write (version, uri());
384 bool fResult = aAppliance.isOk();
385 if (fResult)
386 {
387 /* Show some progress, so the user know whats going on */
388 vboxProblem().showModalProgressDialog (progress, tr ("Exporting Appliance ..."), this);
389 if (progress.GetCanceled())
390 return false;
391 if (!progress.isOk() || progress.GetResultCode() != 0)
392 {
393 vboxProblem().cannotExportAppliance (progress, &aAppliance, this);
394 return false;
395 }
396 else
397 return true;
398 }
399 if (!fResult)
400 vboxProblem().cannotExportAppliance (&aAppliance, this);
401 return false;
402}
403
404QString VBoxExportApplianceWzd::uri() const
405{
406 if (currentStorageType() == Filesystem)
407 return mFileSelector->path();
408 else if (currentStorageType() == SunCloud)
409 {
410 QString uri ("SunCloud://");
411 if (!mLeUsername->text().isEmpty())
412 uri = QString ("%1%2").arg (uri).arg (mLeUsername->text());
413 if (!mLePassword->text().isEmpty())
414 uri = QString ("%1:%2").arg (uri).arg (mLePassword->text());
415 if (!mLeUsername->text().isEmpty() ||
416 !mLePassword->text().isEmpty())
417 uri = QString ("%1@").arg (uri);
418 uri = QString ("%1%2/%3/%4").arg (uri).arg ("object.storage.network.com").arg (mLeBucket->text()).arg (mFileSelector->path());
419 return uri;
420 }
421 else if (currentStorageType() == S3)
422 {
423 QString uri ("S3://");
424 if (!mLeUsername->text().isEmpty())
425 uri = QString ("%1%2").arg (uri).arg (mLeUsername->text());
426 if (!mLePassword->text().isEmpty())
427 uri = QString ("%1:%2").arg (uri).arg (mLePassword->text());
428 if (!mLeUsername->text().isEmpty() ||
429 !mLePassword->text().isEmpty())
430 uri = QString ("%1@").arg (uri);
431 uri = QString ("%1%2/%3/%4").arg (uri).arg (mLeHostname->text()).arg (mLeBucket->text()).arg (mFileSelector->path());
432 return uri;
433 }
434 return "";
435}
436
437VBoxExportApplianceWzd::StorageType VBoxExportApplianceWzd::currentStorageType() const
438{
439 if (mRBtnLocalFileSystem->isChecked())
440 return Filesystem;
441 else if (mRBtnSunCloud->isChecked())
442 return SunCloud;
443 else
444 return S3;
445}
446
447void VBoxExportApplianceWzd::storageTypeChanged()
448{
449 StorageType type = currentStorageType();
450 switch (type)
451 {
452 case Filesystem:
453 {
454 mTextTargetOptions->setText (mExportToFileSystemDesc);
455 mLblUsername->setVisible (false);
456 mLeUsername->setVisible (false);
457 mLblPassword->setVisible (false);
458 mLePassword->setVisible (false);
459 mLblHostname->setVisible (false);
460 mLeHostname->setVisible (false);
461 mLblBucket->setVisible (false);
462 mLeBucket->setVisible (false);
463 mSelectOVF09->setVisible (true);
464 mFileSelector->setChooserVisible (true);
465 mFileSelector->setFocus();
466 break;
467 };
468 case SunCloud:
469 {
470 mTextTargetOptions->setText (mExportToSunCloudDesc);
471 mLblUsername->setVisible (true);
472 mLeUsername->setVisible (true);
473 mLblPassword->setVisible (true);
474 mLePassword->setVisible (true);
475 mLblHostname->setVisible (false);
476 mLeHostname->setVisible (false);
477 mLblBucket->setVisible (true);
478 mLeBucket->setVisible (true);
479 mSelectOVF09->setVisible (false);
480 mSelectOVF09->setChecked (false);
481 mFileSelector->setChooserVisible (false);
482 mLeUsername->setFocus();
483 break;
484 };
485 case S3:
486 {
487 mTextTargetOptions->setText (mExportToS3Desc);
488 mLblUsername->setVisible (true);
489 mLeUsername->setVisible (true);
490 mLblPassword->setVisible (true);
491 mLePassword->setVisible (true);
492 mLblHostname->setVisible (true);
493 mLeHostname->setVisible (true);
494 mLblBucket->setVisible (true);
495 mLeBucket->setVisible (true);
496 mSelectOVF09->setVisible (true);
497 mFileSelector->setChooserVisible (false);
498 mLeUsername->setFocus();
499 break;
500 };
501 }
502
503 if (!mFileSelector->path().isEmpty())
504 {
505 QFileInfo fi (mFileSelector->path());
506 QString name = fi.fileName();
507 if (type == Filesystem)
508 name = QDir::toNativeSeparators (QString ("%1/%2").arg (vboxGlobal().documentsPath())
509 .arg (name));
510 mFileSelector->setPath (name);
511 }
512}
513
514void VBoxExportApplianceWzd::setCurrentStorageType (VBoxExportApplianceWzd::StorageType aType)
515{
516 switch (aType)
517 {
518 case Filesystem: mRBtnLocalFileSystem->setChecked(true); mRBtnLocalFileSystem->setFocus(); break;
519 case SunCloud: mRBtnSunCloud->setChecked(true); mRBtnSunCloud->setFocus(); break;
520 case S3: mRBtnS3->setChecked(true); mRBtnS3->setFocus(); break;
521 }
522}
523
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