VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/wizards/addcloudvm/UIWizardAddCloudVMPageSource.cpp@ 103551

Last change on this file since 103551 was 101563, checked in by vboxsync, 14 months ago

FE/Qt: bugref:10450: Get rid of Qt5 stuff; This one is about signal connection ambiguity stuff.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.0 KB
Line 
1/* $Id: UIWizardAddCloudVMPageSource.cpp 101563 2023-10-23 23:36:38Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIWizardAddCloudVMPageSource class implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QGridLayout>
30#include <QHeaderView>
31#include <QLabel>
32#include <QListWidget>
33#include <QPushButton>
34#include <QVBoxLayout>
35
36/* GUI includes: */
37#include "QIComboBox.h"
38#include "QIRichTextLabel.h"
39#include "QIToolButton.h"
40#include "UICloudNetworkingStuff.h"
41#include "UIExtraDataManager.h"
42#include "UIIconPool.h"
43#include "UIVirtualBoxEventHandler.h"
44#include "UIVirtualBoxManager.h"
45#include "UIWizardAddCloudVM.h"
46#include "UIWizardAddCloudVMPageSource.h"
47
48/* COM includes: */
49#include "CStringArray.h"
50
51/* Namespaces: */
52using namespace UIWizardAddCloudVMSource;
53
54
55/*********************************************************************************************************************************
56* Namespace UIWizardAddCloudVMSource implementation. *
57*********************************************************************************************************************************/
58
59void UIWizardAddCloudVMSource::populateProviders(QIComboBox *pCombo, UINotificationCenter *pCenter)
60{
61 /* Sanity check: */
62 AssertPtrReturnVoid(pCombo);
63
64 /* Remember current item data to be able to restore it: */
65 QString strOldData;
66 if (pCombo->currentIndex() != -1)
67 strOldData = pCombo->currentData(ProviderData_ShortName).toString();
68 /* Otherwise "OCI" should be the default one: */
69 else
70 strOldData = "OCI";
71
72 /* Block signals while updating: */
73 pCombo->blockSignals(true);
74
75 /* Clear combo initially: */
76 pCombo->clear();
77
78 /* Iterate through existing providers: */
79 foreach (const CCloudProvider &comProvider, listCloudProviders(pCenter))
80 {
81 /* Skip if we have nothing to populate (file missing?): */
82 if (comProvider.isNull())
83 continue;
84 /* Acquire provider name: */
85 QString strProviderName;
86 if (!cloudProviderName(comProvider, strProviderName, pCenter))
87 continue;
88 /* Acquire provider short name: */
89 QString strProviderShortName;
90 if (!cloudProviderShortName(comProvider, strProviderShortName, pCenter))
91 continue;
92
93 /* Compose empty item, fill the data: */
94 pCombo->addItem(QString());
95 pCombo->setItemData(pCombo->count() - 1, strProviderName, ProviderData_Name);
96 pCombo->setItemData(pCombo->count() - 1, strProviderShortName, ProviderData_ShortName);
97 }
98
99 /* Set previous/default item if possible: */
100 int iNewIndex = -1;
101 if ( iNewIndex == -1
102 && !strOldData.isNull())
103 iNewIndex = pCombo->findData(strOldData, ProviderData_ShortName);
104 if ( iNewIndex == -1
105 && pCombo->count() > 0)
106 iNewIndex = 0;
107 if (iNewIndex != -1)
108 pCombo->setCurrentIndex(iNewIndex);
109
110 /* Unblock signals after update: */
111 pCombo->blockSignals(false);
112}
113
114void UIWizardAddCloudVMSource::populateProfiles(QIComboBox *pCombo,
115 UINotificationCenter *pCenter,
116 const QString &strProviderShortName,
117 const QString &strProfileName)
118{
119 /* Sanity check: */
120 AssertPtrReturnVoid(pCombo);
121 /* Acquire provider: */
122 CCloudProvider comProvider = cloudProviderByShortName(strProviderShortName, pCenter);
123 AssertReturnVoid(comProvider.isNotNull());
124
125 /* Remember current item data to be able to restore it: */
126 QString strOldData;
127 if (pCombo->currentIndex() != -1)
128 strOldData = pCombo->currentData(ProfileData_Name).toString();
129 else if (!strProfileName.isEmpty())
130 strOldData = strProfileName;
131
132 /* Block signals while updating: */
133 pCombo->blockSignals(true);
134
135 /* Clear combo initially: */
136 pCombo->clear();
137
138 /* Acquire restricted accounts: */
139 const QStringList restrictedProfiles = gEDataManager->cloudProfileManagerRestrictions();
140
141 /* Iterate through existing profiles: */
142 QStringList allowedProfileNames;
143 QStringList restrictedProfileNames;
144 foreach (const CCloudProfile &comProfile, listCloudProfiles(comProvider, pCenter))
145 {
146 /* Skip if we have nothing to populate (wtf happened?): */
147 if (comProfile.isNull())
148 continue;
149 /* Acquire current profile name: */
150 QString strCurrentProfileName;
151 if (!cloudProfileName(comProfile, strCurrentProfileName, pCenter))
152 continue;
153
154 /* Compose full profile name: */
155 const QString strFullProfileName = QString("/%1/%2").arg(strProviderShortName).arg(strCurrentProfileName);
156 /* Append to appropriate list: */
157 if (restrictedProfiles.contains(strFullProfileName))
158 restrictedProfileNames.append(strCurrentProfileName);
159 else
160 allowedProfileNames.append(strCurrentProfileName);
161 }
162
163 /* Add allowed items: */
164 foreach (const QString &strAllowedProfileName, allowedProfileNames)
165 {
166 /* Compose item, fill it's data: */
167 pCombo->addItem(strAllowedProfileName);
168 pCombo->setItemData(pCombo->count() - 1, strAllowedProfileName, ProfileData_Name);
169 QFont fnt = pCombo->font();
170 fnt.setBold(true);
171 pCombo->setItemData(pCombo->count() - 1, fnt, Qt::FontRole);
172 }
173 /* Add restricted items: */
174 foreach (const QString &strRestrictedProfileName, restrictedProfileNames)
175 {
176 /* Compose item, fill it's data: */
177 pCombo->addItem(strRestrictedProfileName);
178 pCombo->setItemData(pCombo->count() - 1, strRestrictedProfileName, ProfileData_Name);
179 QBrush brsh;
180 brsh.setColor(Qt::gray);
181 pCombo->setItemData(pCombo->count() - 1, brsh, Qt::ForegroundRole);
182 }
183
184 /* Set previous/default item if possible: */
185 int iNewIndex = -1;
186 if ( iNewIndex == -1
187 && !strOldData.isNull())
188 iNewIndex = pCombo->findData(strOldData, ProfileData_Name);
189 if ( iNewIndex == -1
190 && pCombo->count() > 0)
191 iNewIndex = 0;
192 if (iNewIndex != -1)
193 pCombo->setCurrentIndex(iNewIndex);
194
195 /* Unblock signals after update: */
196 pCombo->blockSignals(false);
197}
198
199void UIWizardAddCloudVMSource::populateProfileInstances(QListWidget *pList, UINotificationCenter *pCenter, const CCloudClient &comClient)
200{
201 /* Sanity check: */
202 AssertPtrReturnVoid(pList);
203 AssertReturnVoid(comClient.isNotNull());
204
205 /* Block signals while updating: */
206 pList->blockSignals(true);
207
208 /* Clear list initially: */
209 pList->clear();
210
211 /* Gather instance names and ids: */
212 CStringArray comNames;
213 CStringArray comIDs;
214 if (listCloudSourceInstances(comClient, comNames, comIDs, pCenter))
215 {
216 /* Push acquired names to list rows: */
217 const QVector<QString> names = comNames.GetValues();
218 const QVector<QString> ids = comIDs.GetValues();
219 for (int i = 0; i < names.size(); ++i)
220 {
221 /* Create list item: */
222 QListWidgetItem *pItem = new QListWidgetItem(names.at(i), pList);
223 if (pItem)
224 {
225 pItem->setFlags(pItem->flags() & ~Qt::ItemIsEditable);
226 pItem->setData(Qt::UserRole, ids.at(i));
227 }
228 }
229 }
230
231 /* Choose the 1st one by default if possible: */
232 if (pList->count())
233 pList->setCurrentRow(0);
234
235 /* Unblock signals after update: */
236 pList->blockSignals(false);
237}
238
239void UIWizardAddCloudVMSource::updateComboToolTip(QIComboBox *pCombo)
240{
241 /* Sanity check: */
242 AssertPtrReturnVoid(pCombo);
243
244 const int iCurrentIndex = pCombo->currentIndex();
245 if (iCurrentIndex != -1)
246 {
247 const QString strCurrentToolTip = pCombo->itemData(iCurrentIndex, Qt::ToolTipRole).toString();
248 AssertMsg(!strCurrentToolTip.isEmpty(), ("Tool-tip data not found!\n"));
249 pCombo->setToolTip(strCurrentToolTip);
250 }
251}
252
253QStringList UIWizardAddCloudVMSource::currentListWidgetData(QListWidget *pList)
254{
255 QStringList result;
256 foreach (QListWidgetItem *pItem, pList->selectedItems())
257 result << pItem->data(Qt::UserRole).toString();
258 return result;
259}
260
261
262/*********************************************************************************************************************************
263* Class UIWizardAddCloudVMPageSource implementation. *
264*********************************************************************************************************************************/
265
266UIWizardAddCloudVMPageSource::UIWizardAddCloudVMPageSource()
267 : m_pLabelMain(0)
268 , m_pProviderLayout(0)
269 , m_pProviderLabel(0)
270 , m_pProviderComboBox(0)
271 , m_pLabelDescription(0)
272 , m_pOptionsLayout(0)
273 , m_pProfileLabel(0)
274 , m_pProfileComboBox(0)
275 , m_pProfileToolButton(0)
276 , m_pSourceInstanceLabel(0)
277 , m_pSourceInstanceList(0)
278{
279 /* Prepare main layout: */
280 QVBoxLayout *pLayoutMain = new QVBoxLayout(this);
281 if (pLayoutMain)
282 {
283 /* Prepare main label: */
284 m_pLabelMain = new QIRichTextLabel(this);
285 if (m_pLabelMain)
286 pLayoutMain->addWidget(m_pLabelMain);
287
288 /* Prepare provider layout: */
289 m_pProviderLayout = new QGridLayout;
290 if (m_pProviderLayout)
291 {
292 m_pProviderLayout->setContentsMargins(0, 0, 0, 0);
293 m_pProviderLayout->setColumnStretch(0, 0);
294 m_pProviderLayout->setColumnStretch(1, 1);
295
296 /* Prepare provider label: */
297 m_pProviderLabel = new QLabel(this);
298 if (m_pProviderLabel)
299 m_pProviderLayout->addWidget(m_pProviderLabel, 0, 0, Qt::AlignRight);
300 /* Prepare provider combo-box: */
301 m_pProviderComboBox = new QIComboBox(this);
302 if (m_pProviderComboBox)
303 {
304 m_pProviderLabel->setBuddy(m_pProviderComboBox);
305 m_pProviderLayout->addWidget(m_pProviderComboBox, 0, 1);
306 }
307
308 /* Add into layout: */
309 pLayoutMain->addLayout(m_pProviderLayout);
310 }
311
312 /* Prepare description label: */
313 m_pLabelDescription = new QIRichTextLabel(this);
314 if (m_pLabelDescription)
315 pLayoutMain->addWidget(m_pLabelDescription);
316
317 /* Prepare options layout: */
318 m_pOptionsLayout = new QGridLayout;
319 if (m_pOptionsLayout)
320 {
321 m_pOptionsLayout->setContentsMargins(0, 0, 0, 0);
322 m_pOptionsLayout->setColumnStretch(0, 0);
323 m_pOptionsLayout->setColumnStretch(1, 1);
324 m_pOptionsLayout->setRowStretch(1, 0);
325 m_pOptionsLayout->setRowStretch(2, 1);
326
327 /* Prepare profile label: */
328 m_pProfileLabel = new QLabel(this);
329 if (m_pProfileLabel)
330 m_pOptionsLayout->addWidget(m_pProfileLabel, 0, 0, Qt::AlignRight);
331
332 /* Prepare profile layout: */
333 QHBoxLayout *pProfileLayout = new QHBoxLayout;
334 if (pProfileLayout)
335 {
336 pProfileLayout->setContentsMargins(0, 0, 0, 0);
337 pProfileLayout->setSpacing(1);
338
339 /* Prepare profile combo-box: */
340 m_pProfileComboBox = new QIComboBox(this);
341 if (m_pProfileComboBox)
342 {
343 m_pProfileLabel->setBuddy(m_pProfileComboBox);
344 pProfileLayout->addWidget(m_pProfileComboBox);
345 }
346
347 /* Prepare profile tool-button: */
348 m_pProfileToolButton = new QIToolButton(this);
349 if (m_pProfileToolButton)
350 {
351 m_pProfileToolButton->setIcon(UIIconPool::iconSet(":/cloud_profile_manager_16px.png",
352 ":/cloud_profile_manager_disabled_16px.png"));
353 pProfileLayout->addWidget(m_pProfileToolButton);
354 }
355
356 /* Add into layout: */
357 m_pOptionsLayout->addLayout(pProfileLayout, 0, 1);
358 }
359
360 /* Prepare source instance label: */
361 m_pSourceInstanceLabel = new QLabel(this);
362 if (m_pSourceInstanceLabel)
363 m_pOptionsLayout->addWidget(m_pSourceInstanceLabel, 1, 0, Qt::AlignRight);
364
365 /* Prepare source instances table: */
366 m_pSourceInstanceList = new QListWidget(this);
367 if (m_pSourceInstanceList)
368 {
369 m_pSourceInstanceLabel->setBuddy(m_pSourceInstanceLabel);
370 /* Make source image list fit 50 symbols
371 * horizontally and 8 lines vertically: */
372 const QFontMetrics fm(m_pSourceInstanceList->font());
373#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)
374 const int iFontWidth = fm.horizontalAdvance('x');
375#else
376 const int iFontWidth = fm.width('x');
377#endif
378 const int iTotalWidth = 50 * iFontWidth;
379 const int iFontHeight = fm.height();
380 const int iTotalHeight = 8 * iFontHeight;
381 m_pSourceInstanceList->setMinimumSize(QSize(iTotalWidth, iTotalHeight));
382 /* A bit of look&feel: */
383 m_pSourceInstanceList->setAlternatingRowColors(true);
384 /* Allow to select more than one item to add: */
385 m_pSourceInstanceList->setSelectionMode(QAbstractItemView::ExtendedSelection);
386
387 /* Add into layout: */
388 m_pOptionsLayout->addWidget(m_pSourceInstanceList, 1, 1, 2, 1);
389 }
390
391 /* Add into layout: */
392 pLayoutMain->addLayout(m_pOptionsLayout);
393 }
394 }
395
396 /* Setup connections: */
397 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigCloudProfileRegistered,
398 this, &UIWizardAddCloudVMPageSource::sltHandleProviderComboChange);
399 connect(gVBoxEvents, &UIVirtualBoxEventHandler::sigCloudProfileChanged,
400 this, &UIWizardAddCloudVMPageSource::sltHandleProviderComboChange);
401 connect(m_pProviderComboBox, &QIComboBox::activated,
402 this, &UIWizardAddCloudVMPageSource::sltHandleProviderComboChange);
403 connect(m_pProfileComboBox, &QIComboBox::currentIndexChanged,
404 this, &UIWizardAddCloudVMPageSource::sltHandleProfileComboChange);
405 connect(m_pProfileToolButton, &QIToolButton::clicked,
406 this, &UIWizardAddCloudVMPageSource::sltHandleProfileButtonClick);
407 connect(m_pSourceInstanceList, &QListWidget::itemSelectionChanged,
408 this, &UIWizardAddCloudVMPageSource::sltHandleSourceInstanceChange);
409}
410
411UIWizardAddCloudVM *UIWizardAddCloudVMPageSource::wizard() const
412{
413 return qobject_cast<UIWizardAddCloudVM*>(UINativeWizardPage::wizard());
414}
415
416void UIWizardAddCloudVMPageSource::retranslateUi()
417{
418 /* Translate page: */
419 setTitle(UIWizardAddCloudVM::tr("Source to add from"));
420
421 /* Translate main label: */
422 m_pLabelMain->setText(UIWizardAddCloudVM::tr("Please choose the source to add cloud virtual machine from. This can "
423 "be one of known cloud service providers below."));
424
425 /* Translate provider label: */
426 m_pProviderLabel->setText(UIWizardAddCloudVM::tr("&Source:"));
427 /* Translate received values of Source combo-box.
428 * We are enumerating starting from 0 for simplicity: */
429 for (int i = 0; i < m_pProviderComboBox->count(); ++i)
430 {
431 m_pProviderComboBox->setItemText(i, m_pProviderComboBox->itemData(i, ProviderData_Name).toString());
432 m_pProviderComboBox->setItemData(i, UIWizardAddCloudVM::tr("Add VM from cloud service provider."), Qt::ToolTipRole);
433 }
434
435 /* Translate description label: */
436 m_pLabelDescription->setText(UIWizardAddCloudVM::tr("Please choose one of cloud service profiles you have registered to "
437 "add virtual machine from. Existing instance list will be "
438 "updated. To continue, select at least one instance to add virtual "
439 "machine on the basis of it."));
440
441 /* Translate profile stuff: */
442 m_pProfileLabel->setText(UIWizardAddCloudVM::tr("&Profile:"));
443 m_pProfileToolButton->setToolTip(UIWizardAddCloudVM::tr("Open Cloud Profile Manager..."));
444 m_pSourceInstanceLabel->setText(UIWizardAddCloudVM::tr("&Instances:"));
445
446 /* Adjust label widths: */
447 QList<QWidget*> labels;
448 labels << m_pProviderLabel;
449 labels << m_pProfileLabel;
450 labels << m_pSourceInstanceLabel;
451 int iMaxWidth = 0;
452 foreach (QWidget *pLabel, labels)
453 iMaxWidth = qMax(iMaxWidth, pLabel->minimumSizeHint().width());
454 m_pProviderLayout->setColumnMinimumWidth(0, iMaxWidth);
455 m_pOptionsLayout->setColumnMinimumWidth(0, iMaxWidth);
456
457 /* Update tool-tips: */
458 updateComboToolTip(m_pProviderComboBox);
459}
460
461void UIWizardAddCloudVMPageSource::initializePage()
462{
463 /* Populate providers: */
464 populateProviders(m_pProviderComboBox, wizard()->notificationCenter());
465 /* Translate providers: */
466 retranslateUi();
467 /* Fetch it, asynchronously: */
468 QMetaObject::invokeMethod(this, "sltHandleProviderComboChange", Qt::QueuedConnection);
469 /* Make image list focused by default: */
470 m_pSourceInstanceList->setFocus();
471}
472
473bool UIWizardAddCloudVMPageSource::isComplete() const
474{
475 /* Initial result: */
476 bool fResult = true;
477
478 /* Make sure client is not NULL and
479 * at least one instance is selected: */
480 fResult = wizard()->client().isNotNull()
481 && !wizard()->instanceIds().isEmpty();
482
483 /* Return result: */
484 return fResult;
485}
486
487bool UIWizardAddCloudVMPageSource::validatePage()
488{
489 /* Initial result: */
490 bool fResult = true;
491
492 /* Try to add cloud VMs: */
493 fResult = wizard()->addCloudVMs();
494
495 /* Return result: */
496 return fResult;
497}
498
499void UIWizardAddCloudVMPageSource::sltHandleProviderComboChange()
500{
501 /* Update combo tool-tip: */
502 updateComboToolTip(m_pProviderComboBox);
503
504 /* Update wizard fields: */
505 wizard()->setProviderShortName(m_pProviderComboBox->currentData(ProviderData_ShortName).toString());
506
507 /* Update profiles: */
508 populateProfiles(m_pProfileComboBox, wizard()->notificationCenter(), wizard()->providerShortName(), wizard()->profileName());
509 sltHandleProfileComboChange();
510
511 /* Notify about changes: */
512 emit completeChanged();
513}
514
515void UIWizardAddCloudVMPageSource::sltHandleProfileComboChange()
516{
517 /* Update wizard fields: */
518 wizard()->setProfileName(m_pProfileComboBox->currentData(ProfileData_Name).toString());
519 wizard()->setClient(cloudClientByName(wizard()->providerShortName(), wizard()->profileName(), wizard()->notificationCenter()));
520
521 /* Update profile instances: */
522 wizard()->wizardButton(WizardButtonType_Expert)->setEnabled(false);
523 populateProfileInstances(m_pSourceInstanceList, wizard()->notificationCenter(), wizard()->client());
524 wizard()->wizardButton(WizardButtonType_Expert)->setEnabled(true);
525 sltHandleSourceInstanceChange();
526
527 /* Notify about changes: */
528 emit completeChanged();
529}
530
531void UIWizardAddCloudVMPageSource::sltHandleProfileButtonClick()
532{
533 if (gpManager)
534 gpManager->openCloudProfileManager();
535}
536
537void UIWizardAddCloudVMPageSource::sltHandleSourceInstanceChange()
538{
539 /* Update wizard fields: */
540 wizard()->setInstanceIds(currentListWidgetData(m_pSourceInstanceList));
541
542 /* Notify about changes: */
543 emit completeChanged();
544}
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