1 | /* $Id: UIApplianceImportEditorWidget.cpp 79032 2019-06-07 07:28:32Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * VBox Qt GUI - UIApplianceImportEditorWidget class implementation.
|
---|
4 | */
|
---|
5 |
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2009-2019 Oracle Corporation
|
---|
8 | *
|
---|
9 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
10 | * available from http://www.virtualbox.org. This file is free software;
|
---|
11 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
12 | * General Public License (GPL) as published by the Free Software
|
---|
13 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
14 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
15 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
16 | */
|
---|
17 |
|
---|
18 | /* Qt includes: */
|
---|
19 | #include <QCheckBox>
|
---|
20 | #include <QGridLayout>
|
---|
21 | #include <QLabel>
|
---|
22 | #include <QTextEdit>
|
---|
23 | #include <QVBoxLayout>
|
---|
24 |
|
---|
25 | /* GUI includes: */
|
---|
26 | #include "QITreeView.h"
|
---|
27 | #include "UIApplianceImportEditorWidget.h"
|
---|
28 | #include "UIFilePathSelector.h"
|
---|
29 | #include "UIMessageCenter.h"
|
---|
30 | #include "UIWizardImportApp.h"
|
---|
31 | #include "VBoxGlobal.h"
|
---|
32 |
|
---|
33 | /* COM includes: */
|
---|
34 | #include "CAppliance.h"
|
---|
35 | #include "CSystemProperties.h"
|
---|
36 |
|
---|
37 |
|
---|
38 | ////////////////////////////////////////////////////////////////////////////////
|
---|
39 | // ImportSortProxyModel
|
---|
40 |
|
---|
41 | class ImportSortProxyModel: public UIApplianceSortProxyModel
|
---|
42 | {
|
---|
43 | public:
|
---|
44 | ImportSortProxyModel(QObject *pParent = NULL)
|
---|
45 | : UIApplianceSortProxyModel(pParent)
|
---|
46 | {
|
---|
47 | m_aFilteredList << KVirtualSystemDescriptionType_License;
|
---|
48 | }
|
---|
49 | };
|
---|
50 |
|
---|
51 | ////////////////////////////////////////////////////////////////////////////////
|
---|
52 | // UIApplianceImportEditorWidget
|
---|
53 |
|
---|
54 | UIApplianceImportEditorWidget::UIApplianceImportEditorWidget(QWidget *pParent)
|
---|
55 | : UIApplianceEditorWidget(pParent)
|
---|
56 | , m_pPathSelectorLabel(0)
|
---|
57 | , m_pPathSelector(0)
|
---|
58 | , m_pImportHDsAsVDI(0)
|
---|
59 | , m_pMACComboBoxLabel(0)
|
---|
60 | , m_pMACComboBox(0)
|
---|
61 | , m_pOptionsLayout(0)
|
---|
62 | , m_pAdditionalOptionsLabel(0)
|
---|
63 | {
|
---|
64 | prepareWidgets();
|
---|
65 | }
|
---|
66 |
|
---|
67 | void UIApplianceImportEditorWidget::prepareWidgets()
|
---|
68 | {
|
---|
69 | /* Create options layout: */
|
---|
70 | m_pOptionsLayout = new QGridLayout;
|
---|
71 | if (m_pOptionsLayout)
|
---|
72 | {
|
---|
73 | m_pOptionsLayout->setColumnStretch(0, 0);
|
---|
74 | m_pOptionsLayout->setColumnStretch(1, 1);
|
---|
75 |
|
---|
76 | /* Create path selector label: */
|
---|
77 | m_pPathSelectorLabel = new QLabel;
|
---|
78 | if (m_pPathSelectorLabel)
|
---|
79 | {
|
---|
80 | m_pPathSelectorLabel->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
|
---|
81 |
|
---|
82 | /* Add into layout: */
|
---|
83 | m_pOptionsLayout->addWidget(m_pPathSelectorLabel, 0, 0);
|
---|
84 | }
|
---|
85 |
|
---|
86 | /* Create path selector editor: */
|
---|
87 | m_pPathSelector = new UIFilePathSelector;
|
---|
88 | if (m_pPathSelector)
|
---|
89 | {
|
---|
90 | m_pPathSelector->setResetEnabled(true);
|
---|
91 | m_pPathSelector->setDefaultPath(vboxGlobal().virtualBox().GetSystemProperties().GetDefaultMachineFolder());
|
---|
92 | m_pPathSelector->setPath(vboxGlobal().virtualBox().GetSystemProperties().GetDefaultMachineFolder());
|
---|
93 | m_pPathSelectorLabel->setBuddy(m_pPathSelector);
|
---|
94 |
|
---|
95 | /* Add into layout: */
|
---|
96 | m_pOptionsLayout->addWidget(m_pPathSelector, 0, 1, 1, 2);
|
---|
97 | }
|
---|
98 |
|
---|
99 | /* Create MAC address policy label: */
|
---|
100 | m_pMACComboBoxLabel = new QLabel;
|
---|
101 | if (m_pMACComboBoxLabel)
|
---|
102 | {
|
---|
103 | m_pMACComboBoxLabel->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
|
---|
104 |
|
---|
105 | /* Add into layout: */
|
---|
106 | m_pOptionsLayout->addWidget(m_pMACComboBoxLabel, 1, 0);
|
---|
107 | }
|
---|
108 |
|
---|
109 | /* Create MAC address policy combo: */
|
---|
110 | m_pMACComboBox = new QComboBox;
|
---|
111 | if (m_pMACComboBox)
|
---|
112 | {
|
---|
113 | m_pMACComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
---|
114 | m_pMACComboBoxLabel->setBuddy(m_pMACComboBox);
|
---|
115 |
|
---|
116 | /* Add into layout: */
|
---|
117 | m_pOptionsLayout->addWidget(m_pMACComboBox, 1, 1, 1, 2);
|
---|
118 | }
|
---|
119 |
|
---|
120 | /* Create additional options label: */
|
---|
121 | m_pAdditionalOptionsLabel = new QLabel;
|
---|
122 | if (m_pAdditionalOptionsLabel)
|
---|
123 | {
|
---|
124 | m_pAdditionalOptionsLabel->setAlignment(Qt::AlignRight | Qt::AlignTrailing | Qt::AlignVCenter);
|
---|
125 |
|
---|
126 | /* Add into layout: */
|
---|
127 | m_pOptionsLayout->addWidget(m_pAdditionalOptionsLabel, 2, 0);
|
---|
128 | }
|
---|
129 |
|
---|
130 | /* Create import HDs as VDIs checkbox: */
|
---|
131 | m_pImportHDsAsVDI = new QCheckBox;
|
---|
132 | {
|
---|
133 | m_pImportHDsAsVDI->setCheckState(Qt::Checked);
|
---|
134 |
|
---|
135 | /* Add into layout: */
|
---|
136 | m_pOptionsLayout->addWidget(m_pImportHDsAsVDI, 2, 1);
|
---|
137 | }
|
---|
138 |
|
---|
139 | /* Add into layout: */
|
---|
140 | m_pLayout->addLayout(m_pOptionsLayout);
|
---|
141 | }
|
---|
142 |
|
---|
143 | /* Populate MAC address import combo: */
|
---|
144 | populateMACAddressImportPolicies();
|
---|
145 | /* And connect signals afterwards: */
|
---|
146 | connect(m_pPathSelector, &UIFilePathSelector::pathChanged,
|
---|
147 | this, &UIApplianceImportEditorWidget::sltHandlePathChanged);
|
---|
148 | connect(m_pMACComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
|
---|
149 | this, &UIApplianceImportEditorWidget::sltHandleMACAddressImportPolicyComboChange);
|
---|
150 |
|
---|
151 | /* Apply language settings: */
|
---|
152 | retranslateUi();
|
---|
153 | }
|
---|
154 |
|
---|
155 | bool UIApplianceImportEditorWidget::setFile(const QString& strFile)
|
---|
156 | {
|
---|
157 | bool fResult = false;
|
---|
158 | if (!strFile.isEmpty())
|
---|
159 | {
|
---|
160 | CProgress progress;
|
---|
161 | CVirtualBox vbox = vboxGlobal().virtualBox();
|
---|
162 | /* Create a appliance object */
|
---|
163 | m_pAppliance = new CAppliance(vbox.CreateAppliance());
|
---|
164 | fResult = m_pAppliance->isOk();
|
---|
165 | if (fResult)
|
---|
166 | {
|
---|
167 | /* Read the appliance */
|
---|
168 | progress = m_pAppliance->Read(strFile);
|
---|
169 | fResult = m_pAppliance->isOk();
|
---|
170 | if (fResult)
|
---|
171 | {
|
---|
172 | /* Show some progress, so the user know whats going on */
|
---|
173 | msgCenter().showModalProgressDialog(progress, tr("Reading Appliance ..."), ":/progress_reading_appliance_90px.png", this);
|
---|
174 | if (!progress.isOk() || progress.GetResultCode() != 0)
|
---|
175 | fResult = false;
|
---|
176 | else
|
---|
177 | {
|
---|
178 | /* Now we have to interpret that stuff */
|
---|
179 | m_pAppliance->Interpret();
|
---|
180 | fResult = m_pAppliance->isOk();
|
---|
181 | if (fResult)
|
---|
182 | {
|
---|
183 | if (m_pModel)
|
---|
184 | delete m_pModel;
|
---|
185 |
|
---|
186 | QVector<CVirtualSystemDescription> vsds = m_pAppliance->GetVirtualSystemDescriptions();
|
---|
187 |
|
---|
188 | m_pModel = new UIApplianceModel(vsds, m_pTreeViewSettings);
|
---|
189 |
|
---|
190 | ImportSortProxyModel *pProxy = new ImportSortProxyModel(this);
|
---|
191 | pProxy->setSourceModel(m_pModel);
|
---|
192 | pProxy->sort(ApplianceViewSection_Description, Qt::DescendingOrder);
|
---|
193 |
|
---|
194 | UIApplianceDelegate *pDelegate = new UIApplianceDelegate(pProxy, this);
|
---|
195 |
|
---|
196 | /* Set our own model */
|
---|
197 | m_pTreeViewSettings->setModel(pProxy);
|
---|
198 | /* Set our own delegate */
|
---|
199 | m_pTreeViewSettings->setItemDelegate(pDelegate);
|
---|
200 | /* For now we hide the original column. This data is displayed as tooltip
|
---|
201 | also. */
|
---|
202 | m_pTreeViewSettings->setColumnHidden(ApplianceViewSection_OriginalValue, true);
|
---|
203 | m_pTreeViewSettings->expandAll();
|
---|
204 | /* Set model root index and make it current: */
|
---|
205 | m_pTreeViewSettings->setRootIndex(pProxy->mapFromSource(m_pModel->root()));
|
---|
206 | m_pTreeViewSettings->setCurrentIndex(pProxy->mapFromSource(m_pModel->root()));
|
---|
207 |
|
---|
208 | /* Check for warnings & if there are one display them. */
|
---|
209 | bool fWarningsEnabled = false;
|
---|
210 | QVector<QString> warnings = m_pAppliance->GetWarnings();
|
---|
211 | if (warnings.size() > 0)
|
---|
212 | {
|
---|
213 | foreach (const QString& text, warnings)
|
---|
214 | m_pTextEditWarning->append("- " + text);
|
---|
215 | fWarningsEnabled = true;
|
---|
216 | }
|
---|
217 | m_pPaneWarning->setVisible(fWarningsEnabled);
|
---|
218 | }
|
---|
219 | }
|
---|
220 | }
|
---|
221 | }
|
---|
222 | if (!fResult)
|
---|
223 | {
|
---|
224 | if (!m_pAppliance->isOk())
|
---|
225 | msgCenter().cannotImportAppliance(*m_pAppliance, this);
|
---|
226 | else if (!progress.isNull() && (!progress.isOk() || progress.GetResultCode() != 0))
|
---|
227 | msgCenter().cannotImportAppliance(progress, m_pAppliance->GetPath(), this);
|
---|
228 | /* Delete the appliance in a case of an error */
|
---|
229 | delete m_pAppliance;
|
---|
230 | m_pAppliance = NULL;
|
---|
231 | }
|
---|
232 | }
|
---|
233 | /* Make sure we initialize model items with correct base folder path: */
|
---|
234 | if (m_pPathSelector)
|
---|
235 | sltHandlePathChanged(m_pPathSelector->path());
|
---|
236 |
|
---|
237 | return fResult;
|
---|
238 | }
|
---|
239 |
|
---|
240 | void UIApplianceImportEditorWidget::prepareImport()
|
---|
241 | {
|
---|
242 | if (m_pAppliance)
|
---|
243 | m_pModel->putBack();
|
---|
244 | }
|
---|
245 |
|
---|
246 | bool UIApplianceImportEditorWidget::import()
|
---|
247 | {
|
---|
248 | if (m_pAppliance)
|
---|
249 | {
|
---|
250 | /* Start the import asynchronously */
|
---|
251 | CProgress progress;
|
---|
252 | QVector<KImportOptions> options;
|
---|
253 | if (m_pMACComboBox)
|
---|
254 | {
|
---|
255 | MACAddressImportPolicy macPolicy = static_cast<MACAddressImportPolicy>(m_pMACComboBox->currentIndex());
|
---|
256 | switch (macPolicy)
|
---|
257 | {
|
---|
258 | case MACAddressImportPolicy_KeepAllMACs:
|
---|
259 | options.append(KImportOptions_KeepAllMACs);
|
---|
260 | break;
|
---|
261 | case MACAddressImportPolicy_KeepNATMACs:
|
---|
262 | options.append(KImportOptions_KeepNATMACs);
|
---|
263 | break;
|
---|
264 | default:
|
---|
265 | break;
|
---|
266 | }
|
---|
267 | }
|
---|
268 |
|
---|
269 | if (m_pImportHDsAsVDI->isChecked())
|
---|
270 | options.append(KImportOptions_ImportToVDI);
|
---|
271 | progress = m_pAppliance->ImportMachines(options);
|
---|
272 | bool fResult = m_pAppliance->isOk();
|
---|
273 | if (fResult)
|
---|
274 | {
|
---|
275 | /* Show some progress, so the user know whats going on */
|
---|
276 | msgCenter().showModalProgressDialog(progress, tr("Importing Appliance ..."), ":/progress_import_90px.png", this);
|
---|
277 | if (progress.GetCanceled())
|
---|
278 | return false;
|
---|
279 | if (!progress.isOk() || progress.GetResultCode() != 0)
|
---|
280 | {
|
---|
281 | msgCenter().cannotImportAppliance(progress, m_pAppliance->GetPath(), this);
|
---|
282 | return false;
|
---|
283 | }
|
---|
284 | else
|
---|
285 | return true;
|
---|
286 | }
|
---|
287 | if (!fResult)
|
---|
288 | msgCenter().cannotImportAppliance(*m_pAppliance, this);
|
---|
289 | }
|
---|
290 | return false;
|
---|
291 | }
|
---|
292 |
|
---|
293 | QList<QPair<QString, QString> > UIApplianceImportEditorWidget::licenseAgreements() const
|
---|
294 | {
|
---|
295 | QList<QPair<QString, QString> > list;
|
---|
296 |
|
---|
297 | CVirtualSystemDescriptionVector vsds = m_pAppliance->GetVirtualSystemDescriptions();
|
---|
298 | for (int i = 0; i < vsds.size(); ++i)
|
---|
299 | {
|
---|
300 | QVector<QString> strLicense;
|
---|
301 | strLicense = vsds[i].GetValuesByType(KVirtualSystemDescriptionType_License,
|
---|
302 | KVirtualSystemDescriptionValueType_Original);
|
---|
303 | if (!strLicense.isEmpty())
|
---|
304 | {
|
---|
305 | QVector<QString> strName;
|
---|
306 | strName = vsds[i].GetValuesByType(KVirtualSystemDescriptionType_Name,
|
---|
307 | KVirtualSystemDescriptionValueType_Auto);
|
---|
308 | list << QPair<QString, QString>(strName.first(), strLicense.first());
|
---|
309 | }
|
---|
310 | }
|
---|
311 |
|
---|
312 | return list;
|
---|
313 | }
|
---|
314 |
|
---|
315 | void UIApplianceImportEditorWidget::retranslateUi()
|
---|
316 | {
|
---|
317 | UIApplianceEditorWidget::retranslateUi();
|
---|
318 | if (m_pPathSelectorLabel)
|
---|
319 | m_pPathSelectorLabel->setText(tr("&Machine Base Folder:"));
|
---|
320 | if (m_pImportHDsAsVDI)
|
---|
321 | {
|
---|
322 | m_pImportHDsAsVDI->setText(tr("&Import hard drives as VDI"));
|
---|
323 | m_pImportHDsAsVDI->setToolTip(tr("When checked, all the hard drives that belong to this appliance will be imported in VDI format."));
|
---|
324 | }
|
---|
325 |
|
---|
326 | /* Translate MAC address policy combo-box: */
|
---|
327 | m_pMACComboBoxLabel->setText(tr("MAC Address &Policy:"));
|
---|
328 | m_pMACComboBox->setItemText(MACAddressImportPolicy_KeepAllMACs,
|
---|
329 | tr("Include all network adapter MAC addresses"));
|
---|
330 | m_pMACComboBox->setItemText(MACAddressImportPolicy_KeepNATMACs,
|
---|
331 | tr("Include only NAT network adapter MAC addresses"));
|
---|
332 | m_pMACComboBox->setItemText(MACAddressImportPolicy_StripAllMACs,
|
---|
333 | tr("Generate new MAC addresses for all network adapters"));
|
---|
334 | m_pMACComboBox->setItemData(MACAddressImportPolicy_KeepAllMACs,
|
---|
335 | tr("Include all network adapter MAC addresses during cloning."), Qt::ToolTipRole);
|
---|
336 | m_pMACComboBox->setItemData(MACAddressImportPolicy_KeepNATMACs,
|
---|
337 | tr("Include only NAT network adapter MAC addresses during cloning."), Qt::ToolTipRole);
|
---|
338 | m_pMACComboBox->setItemData(MACAddressImportPolicy_StripAllMACs,
|
---|
339 | tr("Generate new MAC addresses for all network adapters during cloning."), Qt::ToolTipRole);
|
---|
340 |
|
---|
341 | m_pAdditionalOptionsLabel->setText(tr("Additional Options:"));
|
---|
342 |
|
---|
343 | #if 0 /* this may be needed if contents became dinamical to avoid label jumping */
|
---|
344 | QList<QWidget*> labels;
|
---|
345 | labels << m_pMACComboBoxLabel;
|
---|
346 | labels << m_pAdditionalOptionsLabel;
|
---|
347 |
|
---|
348 | int iMaxWidth = 0;
|
---|
349 | foreach (QWidget *pLabel, labels)
|
---|
350 | iMaxWidth = qMax(iMaxWidth, pLabel->minimumSizeHint().width());
|
---|
351 | m_pOptionsLayout->setColumnMinimumWidth(0, iMaxWidth);
|
---|
352 | #endif /* this may be needed if contents became dinamical to avoid label jumping */
|
---|
353 | }
|
---|
354 |
|
---|
355 | void UIApplianceImportEditorWidget::sltHandlePathChanged(const QString &newPath)
|
---|
356 | {
|
---|
357 | setVirtualSystemBaseFolder(newPath);
|
---|
358 | }
|
---|
359 |
|
---|
360 | void UIApplianceImportEditorWidget::populateMACAddressImportPolicies()
|
---|
361 | {
|
---|
362 | AssertReturnVoid(m_pMACComboBox->count() == 0);
|
---|
363 |
|
---|
364 | /* Apply hardcoded policies list: */
|
---|
365 | for (int i = 0; i < (int)MACAddressImportPolicy_MAX; ++i)
|
---|
366 | {
|
---|
367 | m_pMACComboBox->addItem(QString::number(i));
|
---|
368 | m_pMACComboBox->setItemData(i, i);
|
---|
369 | }
|
---|
370 |
|
---|
371 | /* Set default: */
|
---|
372 | setMACAddressImportPolicy(MACAddressImportPolicy_KeepNATMACs);
|
---|
373 | }
|
---|
374 |
|
---|
375 | void UIApplianceImportEditorWidget::setMACAddressImportPolicy(MACAddressImportPolicy enmMACAddressImportPolicy)
|
---|
376 | {
|
---|
377 | const int iIndex = m_pMACComboBox->findData((int)enmMACAddressImportPolicy);
|
---|
378 | AssertMsg(iIndex != -1, ("Data not found!"));
|
---|
379 | m_pMACComboBox->setCurrentIndex(iIndex);
|
---|
380 | }
|
---|
381 |
|
---|
382 | void UIApplianceImportEditorWidget::sltHandleMACAddressImportPolicyComboChange()
|
---|
383 | {
|
---|
384 | /* Update tool-tip: */
|
---|
385 | updateMACAddressImportPolicyComboToolTip();
|
---|
386 | }
|
---|
387 |
|
---|
388 | void UIApplianceImportEditorWidget::updateMACAddressImportPolicyComboToolTip()
|
---|
389 | {
|
---|
390 | const int iCurrentIndex = m_pMACComboBox->currentIndex();
|
---|
391 | const QString strCurrentToolTip = m_pMACComboBox->itemData(iCurrentIndex, Qt::ToolTipRole).toString();
|
---|
392 | AssertMsg(!strCurrentToolTip.isEmpty(), ("Data not found!"));
|
---|
393 | m_pMACComboBox->setToolTip(strCurrentToolTip);
|
---|
394 | }
|
---|