[26709] | 1 | /* $Id: UIAddDiskEncryptionPasswordDialog.cpp 100347 2023-07-03 13:09:08Z vboxsync $ */
|
---|
[382] | 2 | /** @file
|
---|
[54733] | 3 | * VBox Qt GUI - UIAddDiskEncryptionPasswordDialog class implementation.
|
---|
[382] | 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[98103] | 7 | * Copyright (C) 2006-2023 Oracle and/or its affiliates.
|
---|
[382] | 8 | *
|
---|
[96407] | 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
|
---|
[382] | 26 | */
|
---|
| 27 |
|
---|
[41587] | 28 | /* Qt includes: */
|
---|
[76606] | 29 | #include <QAbstractTableModel>
|
---|
| 30 | #include <QHeaderView>
|
---|
| 31 | #include <QItemEditorFactory>
|
---|
| 32 | #include <QLabel>
|
---|
| 33 | #include <QLineEdit>
|
---|
| 34 | #include <QPushButton>
|
---|
| 35 | #include <QStandardItemEditorCreator>
|
---|
| 36 | #include <QTableView>
|
---|
| 37 | #include <QVBoxLayout>
|
---|
[19817] | 38 |
|
---|
[41587] | 39 | /* GUI includes: */
|
---|
[76606] | 40 | #include "QIDialogButtonBox.h"
|
---|
| 41 | #include "QIStyledItemDelegate.h"
|
---|
| 42 | #include "QIWithRetranslateUI.h"
|
---|
[79365] | 43 | #include "UICommon.h"
|
---|
[76606] | 44 | #include "UIAddDiskEncryptionPasswordDialog.h"
|
---|
| 45 | #include "UIIconPool.h"
|
---|
| 46 | #include "UIMedium.h"
|
---|
[91029] | 47 | #include "UINotificationCenter.h"
|
---|
[382] | 48 |
|
---|
[54733] | 49 | /* Other VBox includes: */
|
---|
[76606] | 50 | #include <iprt/assert.h>
|
---|
[52730] | 51 |
|
---|
| 52 |
|
---|
[54733] | 53 | /** UIEncryptionDataTable field indexes. */
|
---|
| 54 | enum UIEncryptionDataTableSection
|
---|
[54731] | 55 | {
|
---|
[54733] | 56 | UIEncryptionDataTableSection_Id,
|
---|
| 57 | UIEncryptionDataTableSection_Password,
|
---|
| 58 | UIEncryptionDataTableSection_Max
|
---|
[54731] | 59 | };
|
---|
| 60 |
|
---|
[74878] | 61 | template<class T>
|
---|
| 62 | static QStringList toStringList(const QList<T> &list)
|
---|
| 63 | {
|
---|
| 64 | QStringList l;
|
---|
| 65 | foreach(const T &t, list)
|
---|
| 66 | l << t.toString();
|
---|
| 67 | return l;
|
---|
| 68 | }
|
---|
[72038] | 69 |
|
---|
| 70 | /** QLineEdit extension used as
|
---|
[54733] | 71 | * the embedded password editor for the UIEncryptionDataTable. */
|
---|
| 72 | class UIPasswordEditor : public QLineEdit
|
---|
[54731] | 73 | {
|
---|
| 74 | Q_OBJECT;
|
---|
[54733] | 75 |
|
---|
| 76 | /** Holds the current password of the editor. */
|
---|
[54731] | 77 | Q_PROPERTY(QString password READ password WRITE setPassword USER true);
|
---|
| 78 |
|
---|
| 79 | signals:
|
---|
| 80 |
|
---|
[54733] | 81 | /** Notifies listeners about data should be committed. */
|
---|
[54731] | 82 | void sigCommitData(QWidget *pThis);
|
---|
| 83 |
|
---|
[55135] | 84 | /** Notifies listeners about Enter/Return key triggering. */
|
---|
| 85 | void sigEnterKeyTriggered();
|
---|
| 86 |
|
---|
[54731] | 87 | public:
|
---|
| 88 |
|
---|
[72038] | 89 | /** Constructs password editor passing @a pParent to the base-class. */
|
---|
[54733] | 90 | UIPasswordEditor(QWidget *pParent);
|
---|
[54731] | 91 |
|
---|
[72038] | 92 | protected:
|
---|
| 93 |
|
---|
| 94 | /** Handles key-press @a pEvent. */
|
---|
[93990] | 95 | virtual void keyPressEvent(QKeyEvent *pEvent) RT_OVERRIDE;
|
---|
[72038] | 96 |
|
---|
[54733] | 97 | private slots:
|
---|
[54731] | 98 |
|
---|
[56953] | 99 | /** Commits data to the listeners. */
|
---|
| 100 | void sltCommitData() { emit sigCommitData(this); }
|
---|
[54731] | 101 |
|
---|
| 102 | private:
|
---|
| 103 |
|
---|
[72038] | 104 | /** Prepares all. */
|
---|
[54733] | 105 | void prepare();
|
---|
[54731] | 106 |
|
---|
[54733] | 107 | /** Property: Returns the current password of the editor. */
|
---|
[54731] | 108 | QString password() const { return QLineEdit::text(); }
|
---|
[54733] | 109 | /** Property: Defines the current @a strPassword of the editor. */
|
---|
[54731] | 110 | void setPassword(const QString &strPassword) { QLineEdit::setText(strPassword); }
|
---|
| 111 | };
|
---|
| 112 |
|
---|
[72038] | 113 |
|
---|
| 114 | /** QAbstractTableModel extension used as
|
---|
[54733] | 115 | * the data representation model for the UIEncryptionDataTable. */
|
---|
[54731] | 116 | class UIEncryptionDataModel : public QAbstractTableModel
|
---|
| 117 | {
|
---|
| 118 | Q_OBJECT;
|
---|
| 119 |
|
---|
| 120 | public:
|
---|
| 121 |
|
---|
[72038] | 122 | /** Constructs model passing @a pParent to the base-class.
|
---|
[73926] | 123 | * @param encryptedMedia Brings the lists of medium ids (values) encrypted with passwords with ids (keys). */
|
---|
| 124 | UIEncryptionDataModel(QObject *pParent, const EncryptedMediumMap &encryptedMedia);
|
---|
[54731] | 125 |
|
---|
[54733] | 126 | /** Returns the shallow copy of the encryption password map instance. */
|
---|
[55015] | 127 | EncryptionPasswordMap encryptionPasswords() const { return m_encryptionPasswords; }
|
---|
[54731] | 128 |
|
---|
[54733] | 129 | /** Returns the row count, taking optional @a parent instead of root if necessary. */
|
---|
| 130 | virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
---|
| 131 | /** Returns the column count, taking optional @a parent instead of root if necessary. */
|
---|
| 132 | virtual int columnCount(const QModelIndex &parent = QModelIndex()) const;
|
---|
| 133 |
|
---|
[54731] | 134 | /** Returns the @a index flags. */
|
---|
[54733] | 135 | virtual Qt::ItemFlags flags(const QModelIndex &index) const;
|
---|
[54731] | 136 |
|
---|
[54733] | 137 | /** Returns the header data for the @a iSection, @a orientation and @a iRole. */
|
---|
| 138 | virtual QVariant headerData(int iSection, Qt::Orientation orientation, int iRole) const;
|
---|
[54731] | 139 |
|
---|
[54733] | 140 | /** Returns the @a index data for the @a iRole. */
|
---|
| 141 | virtual QVariant data(const QModelIndex &index, int iRole = Qt::DisplayRole) const;
|
---|
| 142 | /** Defines the @a index data for the @a iRole as @a value. */
|
---|
| 143 | virtual bool setData(const QModelIndex &index, const QVariant &value, int iRole = Qt::EditRole);
|
---|
[54731] | 144 |
|
---|
| 145 | private:
|
---|
| 146 |
|
---|
[72038] | 147 | /** Prepares all. */
|
---|
[54733] | 148 | void prepare();
|
---|
[54731] | 149 |
|
---|
| 150 | /** Holds the encrypted medium map reference. */
|
---|
[73926] | 151 | const EncryptedMediumMap &m_encryptedMedia;
|
---|
[54731] | 152 |
|
---|
[54733] | 153 | /** Holds the encryption password map instance. */
|
---|
[72038] | 154 | EncryptionPasswordMap m_encryptionPasswords;
|
---|
[54731] | 155 | };
|
---|
| 156 |
|
---|
[72038] | 157 |
|
---|
| 158 | /** QTableView extension used to
|
---|
[54733] | 159 | * allow the UIAddDiskEncryptionPasswordDialog to enter
|
---|
| 160 | * disk encryption passwords for particular password ids. */
|
---|
[54731] | 161 | class UIEncryptionDataTable : public QTableView
|
---|
| 162 | {
|
---|
| 163 | Q_OBJECT;
|
---|
| 164 |
|
---|
[55016] | 165 | signals:
|
---|
| 166 |
|
---|
[55135] | 167 | /** Notifies listeners about editor's Enter/Return key triggering. */
|
---|
| 168 | void sigEditorEnterKeyTriggered();
|
---|
| 169 |
|
---|
[54731] | 170 | public:
|
---|
| 171 |
|
---|
[72038] | 172 | /** Constructs table.
|
---|
[73926] | 173 | * @param encryptedMedia Brings the lists of medium ids (values) encrypted with passwords with ids (keys). */
|
---|
| 174 | UIEncryptionDataTable(const EncryptedMediumMap &encryptedMedia);
|
---|
[92328] | 175 | /** Destructs table. */
|
---|
[93990] | 176 | virtual ~UIEncryptionDataTable() RT_OVERRIDE;
|
---|
[54731] | 177 |
|
---|
[54733] | 178 | /** Returns the shallow copy of the encryption password map
|
---|
| 179 | * acquired from the UIEncryptionDataModel instance. */
|
---|
[55015] | 180 | EncryptionPasswordMap encryptionPasswords() const;
|
---|
[54731] | 181 |
|
---|
[55038] | 182 | /** Initiates the editor for the first index available. */
|
---|
| 183 | void editFirstIndex();
|
---|
| 184 |
|
---|
[54731] | 185 | private:
|
---|
| 186 |
|
---|
[72038] | 187 | /** Prepares all. */
|
---|
[54733] | 188 | void prepare();
|
---|
[92328] | 189 | /** Cleanups all. */
|
---|
| 190 | void cleanup();
|
---|
[54731] | 191 |
|
---|
| 192 | /** Holds the encrypted medium map reference. */
|
---|
[73926] | 193 | const EncryptedMediumMap &m_encryptedMedia;
|
---|
[54731] | 194 |
|
---|
[54733] | 195 | /** Holds the encryption-data model instance. */
|
---|
[54731] | 196 | UIEncryptionDataModel *m_pModelEncryptionData;
|
---|
[92328] | 197 |
|
---|
| 198 | /** Holds the item editor factory instance. */
|
---|
| 199 | QItemEditorFactory *m_pItemEditorFactory;
|
---|
[54731] | 200 | };
|
---|
| 201 |
|
---|
[72038] | 202 |
|
---|
| 203 | /*********************************************************************************************************************************
|
---|
| 204 | * Class UIPasswordEditor implementation. *
|
---|
| 205 | *********************************************************************************************************************************/
|
---|
| 206 |
|
---|
[54733] | 207 | UIPasswordEditor::UIPasswordEditor(QWidget *pParent)
|
---|
| 208 | : QLineEdit(pParent)
|
---|
[54731] | 209 | {
|
---|
[54733] | 210 | /* Prepare: */
|
---|
| 211 | prepare();
|
---|
[49013] | 212 | }
|
---|
| 213 |
|
---|
[55135] | 214 | void UIPasswordEditor::keyPressEvent(QKeyEvent *pEvent)
|
---|
| 215 | {
|
---|
| 216 | /* Call to base-class: */
|
---|
| 217 | QLineEdit::keyPressEvent(pEvent);
|
---|
| 218 |
|
---|
| 219 | /* Broadcast Enter/Return key press: */
|
---|
| 220 | switch (pEvent->key())
|
---|
| 221 | {
|
---|
| 222 | case Qt::Key_Enter:
|
---|
| 223 | case Qt::Key_Return:
|
---|
| 224 | emit sigEnterKeyTriggered();
|
---|
[56954] | 225 | pEvent->accept();
|
---|
[55135] | 226 | break;
|
---|
| 227 | default:
|
---|
| 228 | break;
|
---|
| 229 | }
|
---|
| 230 | }
|
---|
| 231 |
|
---|
[72038] | 232 | void UIPasswordEditor::prepare()
|
---|
| 233 | {
|
---|
[79798] | 234 | /* Make sure QIStyledDelegate aware of us: */
|
---|
| 235 | setProperty("has_sigCommitData", true);
|
---|
| 236 | setProperty("has_sigEnterKeyTriggered", true);
|
---|
[72038] | 237 | /* Set echo mode: */
|
---|
| 238 | setEchoMode(QLineEdit::Password);
|
---|
| 239 | /* Listen for the text changes: */
|
---|
| 240 | connect(this, &UIPasswordEditor::textChanged,
|
---|
| 241 | this, &UIPasswordEditor::sltCommitData);
|
---|
| 242 | }
|
---|
| 243 |
|
---|
| 244 |
|
---|
| 245 | /*********************************************************************************************************************************
|
---|
| 246 | * Class UIEncryptionDataModel implementation. *
|
---|
| 247 | *********************************************************************************************************************************/
|
---|
| 248 |
|
---|
[73926] | 249 | UIEncryptionDataModel::UIEncryptionDataModel(QObject *pParent, const EncryptedMediumMap &encryptedMedia)
|
---|
[54733] | 250 | : QAbstractTableModel(pParent)
|
---|
[73926] | 251 | , m_encryptedMedia(encryptedMedia)
|
---|
[27310] | 252 | {
|
---|
[54733] | 253 | /* Prepare: */
|
---|
| 254 | prepare();
|
---|
[53046] | 255 | }
|
---|
[27621] | 256 |
|
---|
[54733] | 257 | int UIEncryptionDataModel::rowCount(const QModelIndex &parent /* = QModelIndex() */) const
|
---|
[53046] | 258 | {
|
---|
[54733] | 259 | Q_UNUSED(parent);
|
---|
| 260 | return m_encryptionPasswords.size();
|
---|
[27310] | 261 | }
|
---|
| 262 |
|
---|
[54733] | 263 | int UIEncryptionDataModel::columnCount(const QModelIndex &parent /* = QModelIndex() */) const
|
---|
[45213] | 264 | {
|
---|
[54733] | 265 | Q_UNUSED(parent);
|
---|
| 266 | return UIEncryptionDataTableSection_Max;
|
---|
[45213] | 267 | }
|
---|
| 268 |
|
---|
[54733] | 269 | Qt::ItemFlags UIEncryptionDataModel::flags(const QModelIndex &index) const
|
---|
[45213] | 270 | {
|
---|
[54733] | 271 | /* Check index validness: */
|
---|
| 272 | if (!index.isValid())
|
---|
| 273 | return Qt::NoItemFlags;
|
---|
| 274 | /* Depending on column index: */
|
---|
| 275 | switch (index.column())
|
---|
[45213] | 276 | {
|
---|
[54733] | 277 | case UIEncryptionDataTableSection_Id: return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
---|
| 278 | case UIEncryptionDataTableSection_Password: return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
|
---|
| 279 | default: break;
|
---|
[45213] | 280 | }
|
---|
[54733] | 281 | /* No flags by default: */
|
---|
| 282 | return Qt::NoItemFlags;
|
---|
[45213] | 283 | }
|
---|
| 284 |
|
---|
[54733] | 285 | QVariant UIEncryptionDataModel::headerData(int iSection, Qt::Orientation orientation, int iRole) const
|
---|
[45213] | 286 | {
|
---|
[54733] | 287 | /* Check argument validness: */
|
---|
| 288 | if (iRole != Qt::DisplayRole || orientation != Qt::Horizontal)
|
---|
| 289 | return QVariant();
|
---|
| 290 | /* Depending on column index: */
|
---|
| 291 | switch (iSection)
|
---|
[45213] | 292 | {
|
---|
[56105] | 293 | case UIEncryptionDataTableSection_Id: return UIAddDiskEncryptionPasswordDialog::tr("ID", "password table field");
|
---|
| 294 | case UIEncryptionDataTableSection_Password: return UIAddDiskEncryptionPasswordDialog::tr("Password", "password table field");
|
---|
[54733] | 295 | default: break;
|
---|
[45213] | 296 | }
|
---|
[54733] | 297 | /* Null value by default: */
|
---|
| 298 | return QVariant();
|
---|
[45213] | 299 | }
|
---|
| 300 |
|
---|
[54733] | 301 | QVariant UIEncryptionDataModel::data(const QModelIndex &index, int iRole /* = Qt::DisplayRole */) const
|
---|
[53047] | 302 | {
|
---|
[56953] | 303 | /* Check argument validness: */
|
---|
[54733] | 304 | if (!index.isValid())
|
---|
| 305 | return QVariant();
|
---|
| 306 | /* Depending on role: */
|
---|
| 307 | switch (iRole)
|
---|
[53047] | 308 | {
|
---|
[54733] | 309 | case Qt::DisplayRole:
|
---|
[53049] | 310 | {
|
---|
[54733] | 311 | /* Depending on column index: */
|
---|
| 312 | switch (index.column())
|
---|
[53047] | 313 | {
|
---|
[54733] | 314 | case UIEncryptionDataTableSection_Id:
|
---|
| 315 | return m_encryptionPasswords.keys().at(index.row());
|
---|
| 316 | case UIEncryptionDataTableSection_Password:
|
---|
| 317 | return QString().fill('*', m_encryptionPasswords.value(m_encryptionPasswords.keys().at(index.row())).size());
|
---|
| 318 | default:
|
---|
| 319 | return QVariant();
|
---|
[53047] | 320 | }
|
---|
[54733] | 321 | break;
|
---|
[53047] | 322 | }
|
---|
[54733] | 323 | case Qt::EditRole:
|
---|
[33492] | 324 | {
|
---|
[54733] | 325 | /* Depending on column index: */
|
---|
| 326 | switch (index.column())
|
---|
[34254] | 327 | {
|
---|
[54733] | 328 | case UIEncryptionDataTableSection_Password:
|
---|
| 329 | return m_encryptionPasswords.value(m_encryptionPasswords.keys().at(index.row()));
|
---|
| 330 | default:
|
---|
| 331 | return QVariant();
|
---|
[34254] | 332 | }
|
---|
[54733] | 333 | break;
|
---|
[33492] | 334 | }
|
---|
[54756] | 335 | case Qt::ToolTipRole:
|
---|
| 336 | {
|
---|
| 337 | /* We are generating tool-tip here and not in retranslateUi() because of the tricky plural form handling,
|
---|
| 338 | * but be quiet, it's safe enough because the tool-tip being re-acquired every time on mouse-hovering. */
|
---|
[74878] | 339 | const QList<QUuid> encryptedMedia = m_encryptedMedia.values(m_encryptionPasswords.keys().at(index.row()));
|
---|
[56180] | 340 | return UIAddDiskEncryptionPasswordDialog::tr("<nobr>Used by the following %n hard disk(s):</nobr><br>%1",
|
---|
[56105] | 341 | "This text is never used with n == 0. "
|
---|
| 342 | "Feel free to drop the %n where possible, "
|
---|
| 343 | "we only included it because of problems with Qt Linguist "
|
---|
| 344 | "(but the user can see how many hard drives are in the tool-tip "
|
---|
| 345 | "and doesn't need to be told).",
|
---|
[73926] | 346 | encryptedMedia.size())
|
---|
[74878] | 347 | .arg(toStringList(encryptedMedia).join("<br>"));
|
---|
[54756] | 348 | }
|
---|
[54733] | 349 | default:
|
---|
[51811] | 350 | break;
|
---|
| 351 | }
|
---|
[54733] | 352 | /* Null value by default: */
|
---|
| 353 | return QVariant();
|
---|
[27374] | 354 | }
|
---|
| 355 |
|
---|
[54733] | 356 | bool UIEncryptionDataModel::setData(const QModelIndex &index, const QVariant &value, int iRole /* = Qt::EditRole */)
|
---|
[26890] | 357 | {
|
---|
[54733] | 358 | /* Check argument validness: */
|
---|
[56953] | 359 | if (!index.isValid() || iRole != Qt::EditRole)
|
---|
[54733] | 360 | return false;
|
---|
| 361 | /* Depending on column index: */
|
---|
| 362 | switch (index.column())
|
---|
[30525] | 363 | {
|
---|
[55015] | 364 | case UIEncryptionDataTableSection_Password:
|
---|
| 365 | {
|
---|
| 366 | /* Update password: */
|
---|
| 367 | const int iRow = index.row();
|
---|
| 368 | const QString strPassword = value.toString();
|
---|
| 369 | const QString strKey = m_encryptionPasswords.keys().at(iRow);
|
---|
| 370 | m_encryptionPasswords[strKey] = strPassword;
|
---|
| 371 | break;
|
---|
| 372 | }
|
---|
| 373 | default:
|
---|
| 374 | break;
|
---|
[30525] | 375 | }
|
---|
[54733] | 376 | /* Nothing to set by default: */
|
---|
| 377 | return false;
|
---|
[26890] | 378 | }
|
---|
| 379 |
|
---|
[54733] | 380 | void UIEncryptionDataModel::prepare()
|
---|
[52472] | 381 | {
|
---|
[56953] | 382 | /* Populate the map of passwords and statuses: */
|
---|
[73926] | 383 | foreach (const QString &strPasswordId, m_encryptedMedia.keys())
|
---|
[54733] | 384 | m_encryptionPasswords.insert(strPasswordId, QString());
|
---|
[52472] | 385 | }
|
---|
| 386 |
|
---|
[72038] | 387 |
|
---|
| 388 | /*********************************************************************************************************************************
|
---|
| 389 | * Class UIEncryptionDataTable implementation. *
|
---|
| 390 | *********************************************************************************************************************************/
|
---|
| 391 |
|
---|
[73926] | 392 | UIEncryptionDataTable::UIEncryptionDataTable(const EncryptedMediumMap &encryptedMedia)
|
---|
| 393 | : m_encryptedMedia(encryptedMedia)
|
---|
[54733] | 394 | , m_pModelEncryptionData(0)
|
---|
[92328] | 395 | , m_pItemEditorFactory(0)
|
---|
[382] | 396 | {
|
---|
[54733] | 397 | prepare();
|
---|
[30677] | 398 | }
|
---|
[26815] | 399 |
|
---|
[92328] | 400 | UIEncryptionDataTable::~UIEncryptionDataTable()
|
---|
| 401 | {
|
---|
| 402 | cleanup();
|
---|
| 403 | }
|
---|
| 404 |
|
---|
[55015] | 405 | EncryptionPasswordMap UIEncryptionDataTable::encryptionPasswords() const
|
---|
[30677] | 406 | {
|
---|
[55015] | 407 | AssertPtrReturn(m_pModelEncryptionData, EncryptionPasswordMap());
|
---|
[54733] | 408 | return m_pModelEncryptionData->encryptionPasswords();
|
---|
[30677] | 409 | }
|
---|
[26815] | 410 |
|
---|
[55038] | 411 | void UIEncryptionDataTable::editFirstIndex()
|
---|
| 412 | {
|
---|
| 413 | AssertPtrReturnVoid(m_pModelEncryptionData);
|
---|
| 414 | /* Compose the password field index of the first available table record: */
|
---|
| 415 | const QModelIndex index = m_pModelEncryptionData->index(0, UIEncryptionDataTableSection_Password);
|
---|
| 416 | /* Navigate table to the corresponding index: */
|
---|
| 417 | setCurrentIndex(index);
|
---|
| 418 | /* Compose the fake mouse-event which will trigger the embedded editor: */
|
---|
| 419 | QMouseEvent event(QEvent::MouseButtonPress, QPoint(), Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
|
---|
| 420 | /* Initiate the embedded editor for the corresponding index: */
|
---|
| 421 | edit(index, QAbstractItemView::SelectedClicked, &event);
|
---|
| 422 | }
|
---|
| 423 |
|
---|
[54733] | 424 | void UIEncryptionDataTable::prepare()
|
---|
[30677] | 425 | {
|
---|
[54733] | 426 | /* Create encryption-data model: */
|
---|
[73926] | 427 | m_pModelEncryptionData = new UIEncryptionDataModel(this, m_encryptedMedia);
|
---|
[72038] | 428 | if (m_pModelEncryptionData)
|
---|
[30677] | 429 | {
|
---|
[54733] | 430 | /* Assign configured model to table: */
|
---|
| 431 | setModel(m_pModelEncryptionData);
|
---|
[30677] | 432 | }
|
---|
[1285] | 433 |
|
---|
[54733] | 434 | /* Create item delegate: */
|
---|
| 435 | QIStyledItemDelegate *pStyledItemDelegate = new QIStyledItemDelegate(this);
|
---|
[72038] | 436 | if (pStyledItemDelegate)
|
---|
[30677] | 437 | {
|
---|
[92328] | 438 | /* Create new item editor factory: */
|
---|
| 439 | m_pItemEditorFactory = new QItemEditorFactory;
|
---|
| 440 | if (m_pItemEditorFactory)
|
---|
[49121] | 441 | {
|
---|
[92328] | 442 | /* Register UIPasswordEditor as the QString editor: */
|
---|
[54733] | 443 | QStandardItemEditorCreator<UIPasswordEditor> *pQStringItemEditorCreator = new QStandardItemEditorCreator<UIPasswordEditor>();
|
---|
[72038] | 444 | if (pQStringItemEditorCreator)
|
---|
[100347] | 445 | m_pItemEditorFactory->registerEditor(QMetaType::QString, pQStringItemEditorCreator);
|
---|
[72038] | 446 |
|
---|
[54733] | 447 | /* Assign configured item editor factory to table delegate: */
|
---|
[92328] | 448 | pStyledItemDelegate->setItemEditorFactory(m_pItemEditorFactory);
|
---|
[49121] | 449 | }
|
---|
[72038] | 450 |
|
---|
[54733] | 451 | /* Assign configured item delegate to table: */
|
---|
| 452 | delete itemDelegate();
|
---|
| 453 | setItemDelegate(pStyledItemDelegate);
|
---|
[72038] | 454 |
|
---|
[55135] | 455 | /* Configure item delegate: */
|
---|
[64162] | 456 | pStyledItemDelegate->setWatchForEditorDataCommits(true);
|
---|
[55135] | 457 | pStyledItemDelegate->setWatchForEditorEnterKeyTriggering(true);
|
---|
[72038] | 458 | connect(pStyledItemDelegate, &QIStyledItemDelegate::sigEditorEnterKeyTriggered,
|
---|
| 459 | this, &UIEncryptionDataTable::sigEditorEnterKeyTriggered);
|
---|
[49121] | 460 | }
|
---|
| 461 |
|
---|
[54733] | 462 | /* Configure table: */
|
---|
| 463 | setTabKeyNavigation(false);
|
---|
| 464 | setContextMenuPolicy(Qt::CustomContextMenu);
|
---|
| 465 | setSelectionBehavior(QAbstractItemView::SelectRows);
|
---|
| 466 | setSelectionMode(QAbstractItemView::SingleSelection);
|
---|
| 467 | setEditTriggers(QAbstractItemView::CurrentChanged | QAbstractItemView::SelectedClicked);
|
---|
[49121] | 468 |
|
---|
[54733] | 469 | /* Configure headers: */
|
---|
| 470 | verticalHeader()->hide();
|
---|
| 471 | verticalHeader()->setDefaultSectionSize((int)(verticalHeader()->minimumSectionSize() * 1.33));
|
---|
| 472 | horizontalHeader()->setStretchLastSection(false);
|
---|
[58856] | 473 | horizontalHeader()->setSectionResizeMode(UIEncryptionDataTableSection_Id, QHeaderView::Interactive);
|
---|
| 474 | horizontalHeader()->setSectionResizeMode(UIEncryptionDataTableSection_Password, QHeaderView::Stretch);
|
---|
[49025] | 475 | }
|
---|
| 476 |
|
---|
[92328] | 477 | void UIEncryptionDataTable::cleanup()
|
---|
| 478 | {
|
---|
| 479 | /* Cleanup item editor factory: */
|
---|
| 480 | delete m_pItemEditorFactory;
|
---|
| 481 | m_pItemEditorFactory = 0;
|
---|
| 482 | }
|
---|
[72038] | 483 |
|
---|
[92328] | 484 |
|
---|
[72038] | 485 | /*********************************************************************************************************************************
|
---|
| 486 | * Class UIAddDiskEncryptionPasswordDialog implementation. *
|
---|
| 487 | *********************************************************************************************************************************/
|
---|
| 488 |
|
---|
[54754] | 489 | UIAddDiskEncryptionPasswordDialog::UIAddDiskEncryptionPasswordDialog(QWidget *pParent,
|
---|
| 490 | const QString &strMachineName,
|
---|
[73926] | 491 | const EncryptedMediumMap &encryptedMedia)
|
---|
[54733] | 492 | : QIWithRetranslateUI<QDialog>(pParent)
|
---|
[54754] | 493 | , m_strMachineName(strMachineName)
|
---|
[73926] | 494 | , m_encryptedMedia(encryptedMedia)
|
---|
[54733] | 495 | , m_pLabelDescription(0)
|
---|
| 496 | , m_pTableEncryptionData(0)
|
---|
[55016] | 497 | , m_pButtonBox(0)
|
---|
[49013] | 498 | {
|
---|
[54733] | 499 | /* Prepare: */
|
---|
| 500 | prepare();
|
---|
[72038] | 501 | /* Apply language settings: */
|
---|
[54733] | 502 | retranslateUi();
|
---|
[49013] | 503 | }
|
---|
| 504 |
|
---|
[55015] | 505 | EncryptionPasswordMap UIAddDiskEncryptionPasswordDialog::encryptionPasswords() const
|
---|
[52275] | 506 | {
|
---|
[55015] | 507 | AssertPtrReturn(m_pTableEncryptionData, EncryptionPasswordMap());
|
---|
[54733] | 508 | return m_pTableEncryptionData->encryptionPasswords();
|
---|
[52275] | 509 | }
|
---|
| 510 |
|
---|
[72038] | 511 | void UIAddDiskEncryptionPasswordDialog::retranslateUi()
|
---|
| 512 | {
|
---|
| 513 | /* Translate the dialog title: */
|
---|
| 514 | setWindowTitle(tr("%1 - Disk Encryption").arg(m_strMachineName));
|
---|
| 515 |
|
---|
| 516 | /* Translate the description label: */
|
---|
| 517 | AssertPtrReturnVoid(m_pLabelDescription);
|
---|
| 518 | m_pLabelDescription->setText(tr("This virtual machine is password protected. "
|
---|
| 519 | "Please enter the %n encryption password(s) below.",
|
---|
| 520 | "This text is never used with n == 0. "
|
---|
| 521 | "Feel free to drop the %n where possible, "
|
---|
| 522 | "we only included it because of problems with Qt Linguist "
|
---|
| 523 | "(but the user can see how many passwords are in the list "
|
---|
| 524 | "and doesn't need to be told).",
|
---|
[73926] | 525 | m_encryptedMedia.uniqueKeys().size()));
|
---|
[72038] | 526 | }
|
---|
| 527 |
|
---|
[56953] | 528 | void UIAddDiskEncryptionPasswordDialog::accept()
|
---|
[55135] | 529 | {
|
---|
[56953] | 530 | /* Validate passwords status: */
|
---|
[73926] | 531 | foreach (const QString &strPasswordId, m_encryptedMedia.uniqueKeys())
|
---|
[56953] | 532 | {
|
---|
[74878] | 533 | const QUuid uMediumId = m_encryptedMedia.values(strPasswordId).first();
|
---|
[56953] | 534 | const QString strPassword = m_pTableEncryptionData->encryptionPasswords().value(strPasswordId);
|
---|
[74878] | 535 | if (!isPasswordValid(uMediumId, strPassword))
|
---|
[56954] | 536 | {
|
---|
[91029] | 537 | UINotificationMessage::warnAboutInvalidEncryptionPassword(strPasswordId);
|
---|
[56954] | 538 | AssertPtrReturnVoid(m_pTableEncryptionData);
|
---|
| 539 | m_pTableEncryptionData->setFocus();
|
---|
| 540 | m_pTableEncryptionData->editFirstIndex();
|
---|
| 541 | return;
|
---|
| 542 | }
|
---|
[56953] | 543 | }
|
---|
| 544 | /* Call to base-class: */
|
---|
| 545 | QIWithRetranslateUI<QDialog>::accept();
|
---|
[55135] | 546 | }
|
---|
| 547 |
|
---|
[54733] | 548 | void UIAddDiskEncryptionPasswordDialog::prepare()
|
---|
[30677] | 549 | {
|
---|
[54935] | 550 | /* Configure self: */
|
---|
| 551 | setWindowModality(Qt::WindowModal);
|
---|
| 552 |
|
---|
[54733] | 553 | /* Create main-layout: */
|
---|
| 554 | QVBoxLayout *pMainLayout = new QVBoxLayout(this);
|
---|
[72038] | 555 | if (pMainLayout)
|
---|
[30677] | 556 | {
|
---|
[54733] | 557 | /* Create input-layout: */
|
---|
| 558 | QVBoxLayout *pInputLayout = new QVBoxLayout;
|
---|
[72038] | 559 | if (pInputLayout)
|
---|
[54305] | 560 | {
|
---|
[54733] | 561 | /* Create description label: */
|
---|
[54754] | 562 | m_pLabelDescription = new QLabel;
|
---|
[72038] | 563 | if (m_pLabelDescription)
|
---|
[52998] | 564 | {
|
---|
[54733] | 565 | /* Add label into layout: */
|
---|
| 566 | pInputLayout->addWidget(m_pLabelDescription);
|
---|
[52998] | 567 | }
|
---|
[72038] | 568 |
|
---|
[54733] | 569 | /* Create encryption-data table: */
|
---|
[73926] | 570 | m_pTableEncryptionData = new UIEncryptionDataTable(m_encryptedMedia);
|
---|
[72038] | 571 | if (m_pTableEncryptionData)
|
---|
[52132] | 572 | {
|
---|
[55016] | 573 | /* Configure encryption-data table: */
|
---|
[72038] | 574 | connect(m_pTableEncryptionData, &UIEncryptionDataTable::sigEditorEnterKeyTriggered,
|
---|
| 575 | this, &UIAddDiskEncryptionPasswordDialog::sltEditorEnterKeyTriggered);
|
---|
[55038] | 576 | m_pTableEncryptionData->setFocus();
|
---|
| 577 | m_pTableEncryptionData->editFirstIndex();
|
---|
[54733] | 578 | /* Add label into layout: */
|
---|
| 579 | pInputLayout->addWidget(m_pTableEncryptionData);
|
---|
[52132] | 580 | }
|
---|
[72038] | 581 |
|
---|
[54733] | 582 | /* Add layout into parent: */
|
---|
| 583 | pMainLayout->addLayout(pInputLayout);
|
---|
[52132] | 584 | }
|
---|
[72038] | 585 |
|
---|
[54733] | 586 | /* Create button-box: */
|
---|
[55016] | 587 | m_pButtonBox = new QIDialogButtonBox;
|
---|
[72038] | 588 | if (m_pButtonBox)
|
---|
[52998] | 589 | {
|
---|
[54733] | 590 | /* Configure button-box: */
|
---|
[55016] | 591 | m_pButtonBox->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
---|
[72038] | 592 | connect(m_pButtonBox, &QIDialogButtonBox::accepted, this, &UIAddDiskEncryptionPasswordDialog::accept);
|
---|
| 593 | connect(m_pButtonBox, &QIDialogButtonBox::rejected, this, &UIAddDiskEncryptionPasswordDialog::reject);
|
---|
| 594 |
|
---|
[54733] | 595 | /* Add button-box into layout: */
|
---|
[55016] | 596 | pMainLayout->addWidget(m_pButtonBox);
|
---|
[52998] | 597 | }
|
---|
[52999] | 598 | }
|
---|
[52132] | 599 | }
|
---|
| 600 |
|
---|
[56953] | 601 | /* static */
|
---|
[74942] | 602 | bool UIAddDiskEncryptionPasswordDialog::isPasswordValid(const QUuid &uMediumId, const QString strPassword)
|
---|
[55016] | 603 | {
|
---|
[56953] | 604 | /* Look for the medium with passed ID: */
|
---|
[79365] | 605 | const UIMedium uimedium = uiCommon().medium(uMediumId);
|
---|
[56953] | 606 | if (!uimedium.isNull())
|
---|
| 607 | {
|
---|
| 608 | /* Check wrapped medium for validity: */
|
---|
| 609 | const CMedium medium = uimedium.medium();
|
---|
| 610 | if (!medium.isNull())
|
---|
| 611 | {
|
---|
| 612 | /* Check whether the password is suitable for that medium: */
|
---|
| 613 | medium.CheckEncryptionPassword(strPassword);
|
---|
| 614 | return medium.isOk();
|
---|
| 615 | }
|
---|
| 616 | }
|
---|
| 617 | /* False by default: */
|
---|
| 618 | return false;
|
---|
[55016] | 619 | }
|
---|
| 620 |
|
---|
[72038] | 621 |
|
---|
[54733] | 622 | #include "UIAddDiskEncryptionPasswordDialog.moc"
|
---|