1 | /* $Id: UIMedium.cpp 48089 2013-08-27 16:00:23Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | *
|
---|
4 | * VBox frontends: Qt GUI ("VirtualBox"):
|
---|
5 | * UIMedium class implementation
|
---|
6 | */
|
---|
7 |
|
---|
8 | /*
|
---|
9 | * Copyright (C) 2009-2013 Oracle Corporation
|
---|
10 | *
|
---|
11 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
12 | * available from http://www.virtualbox.org. This file is free software;
|
---|
13 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
14 | * General Public License (GPL) as published by the Free Software
|
---|
15 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
16 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
17 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
18 | */
|
---|
19 |
|
---|
20 | #ifdef VBOX_WITH_PRECOMPILED_HEADERS
|
---|
21 | # include "precomp.h"
|
---|
22 | #else /* !VBOX_WITH_PRECOMPILED_HEADERS */
|
---|
23 |
|
---|
24 | /* Qt includes: */
|
---|
25 | #include <QDir>
|
---|
26 |
|
---|
27 | /* GUI includes: */
|
---|
28 | #include "UIMedium.h"
|
---|
29 | #include "VBoxGlobal.h"
|
---|
30 | #include "UIMessageCenter.h"
|
---|
31 | #include "UIConverter.h"
|
---|
32 |
|
---|
33 | /* COM includes: */
|
---|
34 | #include "CMachine.h"
|
---|
35 | #include "CSnapshot.h"
|
---|
36 |
|
---|
37 | #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
|
---|
38 |
|
---|
39 | QString UIMedium::m_sstrTable = QString("<table>%1</table>");
|
---|
40 | QString UIMedium::m_sstrRow = QString("<tr><td>%1</td></tr>");
|
---|
41 |
|
---|
42 | UIMedium& UIMedium::operator=(const UIMedium &other)
|
---|
43 | {
|
---|
44 | m_medium = other.medium();
|
---|
45 | m_type = other.type();
|
---|
46 | m_state = other.state();
|
---|
47 | m_strLastAccessError = other.lastAccessError();
|
---|
48 | m_result = other.result();
|
---|
49 |
|
---|
50 | m_strId = other.id();
|
---|
51 | m_strName = other.name();
|
---|
52 | m_strLocation = other.location();
|
---|
53 |
|
---|
54 | m_strSize = other.size();
|
---|
55 | m_strLogicalSize = other.logicalSize();
|
---|
56 |
|
---|
57 | m_strHardDiskFormat = other.hardDiskFormat();
|
---|
58 | m_strHardDiskType = other.hardDiskType();
|
---|
59 |
|
---|
60 | m_strStorageDetails = other.storageDetails();
|
---|
61 |
|
---|
62 | m_strUsage = other.usage();
|
---|
63 | m_strToolTip = other.tip();
|
---|
64 |
|
---|
65 | m_fHidden = other.m_fHidden;
|
---|
66 | m_fAttachedToHiddenMachinesOnly = other.m_fAttachedToHiddenMachinesOnly;
|
---|
67 | m_fReadOnly = other.isReadOnly();
|
---|
68 | m_fUsedInSnapshots = other.isUsedInSnapshots();
|
---|
69 | m_fHostDrive = other.isHostDrive();
|
---|
70 |
|
---|
71 | m_curStateMachineIds = other.curStateMachineIds();
|
---|
72 |
|
---|
73 | m_pParent = other.parent();
|
---|
74 |
|
---|
75 | m_noDiffs = other.cache();
|
---|
76 |
|
---|
77 | return *this;
|
---|
78 | }
|
---|
79 |
|
---|
80 | /**
|
---|
81 | * Queries the medium state. Call this and then read the state field instead
|
---|
82 | * of calling GetState() on medium directly as it will properly handle the
|
---|
83 | * situation when GetState() itself fails by setting state to Inaccessible
|
---|
84 | * and memorizing the error info describing why GetState() failed.
|
---|
85 | *
|
---|
86 | * As the last step, this method calls #refresh() to refresh all precomposed
|
---|
87 | * strings.
|
---|
88 | *
|
---|
89 | * @note This method blocks for the duration of the state check. Since this
|
---|
90 | * check may take quite a while (e.g. for a medium located on a
|
---|
91 | * network share), the calling thread must not be the UI thread. You
|
---|
92 | * have been warned.
|
---|
93 | */
|
---|
94 | void UIMedium::blockAndQueryState()
|
---|
95 | {
|
---|
96 | if (m_medium.isNull())
|
---|
97 | return;
|
---|
98 |
|
---|
99 | m_state = m_medium.RefreshState();
|
---|
100 |
|
---|
101 | /* Save the result to distinguish between
|
---|
102 | * inaccessible and e.g. uninitialized objects: */
|
---|
103 | m_result = COMResult(m_medium);
|
---|
104 | if (!m_result.isOk())
|
---|
105 | {
|
---|
106 | m_state = KMediumState_Inaccessible;
|
---|
107 | m_strLastAccessError = QString();
|
---|
108 | }
|
---|
109 | else
|
---|
110 | m_strLastAccessError = m_medium.GetLastAccessError();
|
---|
111 |
|
---|
112 | refresh();
|
---|
113 | }
|
---|
114 |
|
---|
115 | /**
|
---|
116 | * Refreshes the precomposed strings containing such media parameters as
|
---|
117 | * location, size by querying the respective data from the associated
|
---|
118 | * media object.
|
---|
119 | *
|
---|
120 | * Note that some string such as #size() are meaningless if the media state is
|
---|
121 | * KMediumState_NotCreated (i.e. the medium has not yet been checked for
|
---|
122 | * accessibility).
|
---|
123 | */
|
---|
124 | void UIMedium::refresh()
|
---|
125 | {
|
---|
126 | /* Flags are 'false' by default: */
|
---|
127 | m_fHidden = false;
|
---|
128 | m_fAttachedToHiddenMachinesOnly = false;
|
---|
129 | m_fReadOnly = false;
|
---|
130 | m_fUsedInSnapshots = false;
|
---|
131 | m_fHostDrive = false;
|
---|
132 |
|
---|
133 | /* Detect basic parameters */
|
---|
134 | m_strId = m_medium.isNull() ? QUuid().toString().remove ('{').remove ('}') : m_medium.GetId();
|
---|
135 |
|
---|
136 | m_fHostDrive = m_medium.isNull() ? false : m_medium.GetHostDrive();
|
---|
137 |
|
---|
138 | if (m_medium.isNull())
|
---|
139 | m_strName = VBoxGlobal::tr("Empty", "medium");
|
---|
140 | else if (!m_fHostDrive)
|
---|
141 | m_strName = m_medium.GetName();
|
---|
142 | else if (m_medium.GetDescription().isEmpty())
|
---|
143 | m_strName = VBoxGlobal::tr("Host Drive '%1'", "medium").arg(QDir::toNativeSeparators(m_medium.GetLocation()));
|
---|
144 | else
|
---|
145 | m_strName = VBoxGlobal::tr("Host Drive %1 (%2)", "medium").arg(m_medium.GetDescription(), m_medium.GetName());
|
---|
146 |
|
---|
147 | m_strLocation = m_medium.isNull() || m_fHostDrive ? QString("--") :
|
---|
148 | QDir::toNativeSeparators(m_medium.GetLocation());
|
---|
149 |
|
---|
150 | QString tmp;
|
---|
151 | if (!m_medium.isNull())
|
---|
152 | tmp = m_medium.GetProperty("Special/GUI/Hints");
|
---|
153 | if (!tmp.isEmpty())
|
---|
154 | {
|
---|
155 | QStringList tmpList(tmp.split(','));
|
---|
156 | if (tmpList.contains("Hide", Qt::CaseInsensitive))
|
---|
157 | m_fHidden = true;
|
---|
158 | }
|
---|
159 |
|
---|
160 | if (m_type == UIMediumType_HardDisk)
|
---|
161 | {
|
---|
162 | m_strHardDiskFormat = m_medium.GetFormat();
|
---|
163 | m_strHardDiskType = vboxGlobal().mediumTypeString(m_medium);
|
---|
164 |
|
---|
165 | QVector<KMediumVariant> mediumVariants = m_medium.GetVariant();
|
---|
166 | qlonglong mediumVariant = 0;
|
---|
167 | for (int i = 0; i < mediumVariants.size(); ++i)
|
---|
168 | mediumVariant |= mediumVariants[i];
|
---|
169 |
|
---|
170 | m_strStorageDetails = gpConverter->toString((KMediumVariant)mediumVariant);
|
---|
171 | m_fReadOnly = m_medium.GetReadOnly();
|
---|
172 |
|
---|
173 | /* Adjust the parent if its possible: */
|
---|
174 | CMedium parentMedium = m_medium.GetParent();
|
---|
175 | Assert(!parentMedium.isNull() || m_pParent == NULL);
|
---|
176 |
|
---|
177 | if (!parentMedium.isNull() && (m_pParent == NULL || m_pParent->m_medium != parentMedium))
|
---|
178 | {
|
---|
179 | /* Search for the parent (might be there): */
|
---|
180 | const VBoxMediaList &list = vboxGlobal().currentMediaList();
|
---|
181 | for (VBoxMediaList::const_iterator it = list.begin(); it != list.end(); ++it)
|
---|
182 | {
|
---|
183 | if ((*it).m_type != UIMediumType_HardDisk)
|
---|
184 | break;
|
---|
185 |
|
---|
186 | if ((*it).m_medium == parentMedium)
|
---|
187 | {
|
---|
188 | m_pParent = unconst(&*it);
|
---|
189 | break;
|
---|
190 | }
|
---|
191 | }
|
---|
192 | }
|
---|
193 | }
|
---|
194 | else
|
---|
195 | {
|
---|
196 | m_strHardDiskFormat = QString();
|
---|
197 | m_strHardDiskType = QString();
|
---|
198 | m_fReadOnly = false;
|
---|
199 | }
|
---|
200 |
|
---|
201 | /* Detect sizes */
|
---|
202 | if (m_state != KMediumState_Inaccessible && m_state != KMediumState_NotCreated && !m_fHostDrive)
|
---|
203 | {
|
---|
204 | m_strSize = vboxGlobal().formatSize(m_medium.GetSize());
|
---|
205 | if (m_type == UIMediumType_HardDisk)
|
---|
206 | m_strLogicalSize = vboxGlobal().formatSize(m_medium.GetLogicalSize());
|
---|
207 | else
|
---|
208 | m_strLogicalSize = m_strSize;
|
---|
209 | }
|
---|
210 | else
|
---|
211 | {
|
---|
212 | m_strSize = m_strLogicalSize = QString("--");
|
---|
213 | }
|
---|
214 |
|
---|
215 | /* Detect usage */
|
---|
216 | m_strUsage = QString();
|
---|
217 | if (!m_medium.isNull())
|
---|
218 | {
|
---|
219 | m_curStateMachineIds.clear();
|
---|
220 | QVector <QString> machineIds = m_medium.GetMachineIds();
|
---|
221 | if (machineIds.size() > 0)
|
---|
222 | {
|
---|
223 | /* We assume this flag is 'true' if at least one machine present: */
|
---|
224 | m_fAttachedToHiddenMachinesOnly = true;
|
---|
225 |
|
---|
226 | QString strUsage;
|
---|
227 |
|
---|
228 | CVirtualBox vbox = vboxGlobal().virtualBox();
|
---|
229 |
|
---|
230 | for (QVector <QString>::ConstIterator it = machineIds.begin(); it != machineIds.end(); ++it)
|
---|
231 | {
|
---|
232 | CMachine machine = vbox.FindMachine(*it);
|
---|
233 |
|
---|
234 | /* UIMedium object can wrap newly created CMedium object which belongs to
|
---|
235 | * not yet registered machine, like while creating VM clone.
|
---|
236 | * We can skip such a machines in usage string.
|
---|
237 | * CVirtualBox::FindMachine() will return null machine for such case. */
|
---|
238 | if (machine.isNull())
|
---|
239 | {
|
---|
240 | /* We can't decide for that medium yet,
|
---|
241 | * assume this flag is 'false' for now: */
|
---|
242 | m_fAttachedToHiddenMachinesOnly = false;
|
---|
243 | continue;
|
---|
244 | }
|
---|
245 |
|
---|
246 | /* Finally, we are checking if current machine overrides this flag: */
|
---|
247 | if (m_fAttachedToHiddenMachinesOnly && vboxGlobal().shouldWeShowMachine(machine))
|
---|
248 | m_fAttachedToHiddenMachinesOnly = false;
|
---|
249 |
|
---|
250 | QString strName = machine.GetName();
|
---|
251 | QString strSnapshots;
|
---|
252 |
|
---|
253 | QVector <QString> snapIds = m_medium.GetSnapshotIds(*it);
|
---|
254 | for (QVector <QString>::ConstIterator jt = snapIds.begin(); jt != snapIds.end(); ++jt)
|
---|
255 | {
|
---|
256 | if (*jt == *it)
|
---|
257 | {
|
---|
258 | /* The medium is attached to the machine in the current
|
---|
259 | * state, we don't distinguish this for now by always
|
---|
260 | * giving the VM name in front of snapshot names. */
|
---|
261 | m_curStateMachineIds.push_back(*jt);
|
---|
262 | continue;
|
---|
263 | }
|
---|
264 |
|
---|
265 | CSnapshot snapshot = machine.FindSnapshot(*jt);
|
---|
266 | if (!snapshot.isNull()) // can be NULL while takeSnaphot is in progress
|
---|
267 | {
|
---|
268 | if (!strSnapshots.isNull())
|
---|
269 | strSnapshots += ", ";
|
---|
270 | strSnapshots += snapshot.GetName();
|
---|
271 | }
|
---|
272 | }
|
---|
273 |
|
---|
274 | if (!strUsage.isNull())
|
---|
275 | strUsage += ", ";
|
---|
276 |
|
---|
277 | strUsage += strName;
|
---|
278 |
|
---|
279 | if (!strSnapshots.isNull())
|
---|
280 | {
|
---|
281 | strUsage += QString(" (%2)").arg(strSnapshots);
|
---|
282 | m_fUsedInSnapshots = true;
|
---|
283 | }
|
---|
284 | else
|
---|
285 | m_fUsedInSnapshots = false;
|
---|
286 | }
|
---|
287 |
|
---|
288 | if (!strUsage.isEmpty())
|
---|
289 | m_strUsage = strUsage;
|
---|
290 | }
|
---|
291 | }
|
---|
292 |
|
---|
293 | /* Compose the tooltip */
|
---|
294 | if (!m_medium.isNull())
|
---|
295 | {
|
---|
296 | m_strToolTip = m_sstrRow.arg(QString("<p style=white-space:pre><b>%1</b></p>").arg(m_fHostDrive ? m_strName : m_strLocation));
|
---|
297 |
|
---|
298 | if (m_type == UIMediumType_HardDisk)
|
---|
299 | {
|
---|
300 | m_strToolTip += m_sstrRow.arg(VBoxGlobal::tr("<p style=white-space:pre>Type (Format): %1 (%2)</p>", "medium")
|
---|
301 | .arg(m_strHardDiskType).arg(m_strHardDiskFormat));
|
---|
302 | }
|
---|
303 |
|
---|
304 | m_strToolTip += m_sstrRow.arg(VBoxGlobal::tr("<p>Attached to: %1</p>", "image")
|
---|
305 | .arg(m_strUsage.isNull() ? VBoxGlobal::tr("<i>Not Attached</i>", "image") : m_strUsage));
|
---|
306 |
|
---|
307 | switch (m_state)
|
---|
308 | {
|
---|
309 | case KMediumState_NotCreated:
|
---|
310 | {
|
---|
311 | m_strToolTip += m_sstrRow.arg(VBoxGlobal::tr("<i>Checking accessibility...</i>", "medium"));
|
---|
312 | break;
|
---|
313 | }
|
---|
314 | case KMediumState_Inaccessible:
|
---|
315 | {
|
---|
316 | if (m_result.isOk())
|
---|
317 | {
|
---|
318 | /* Not Accessible */
|
---|
319 | m_strToolTip += m_sstrRow.arg("<hr>") + m_sstrRow.arg(VBoxGlobal::highlight(m_strLastAccessError, true /* aToolTip */));
|
---|
320 | }
|
---|
321 | else
|
---|
322 | {
|
---|
323 | /* Accessibility check (eg GetState()) itself failed: */
|
---|
324 | m_strToolTip += m_sstrRow.arg("<hr>") + m_sstrRow.arg(VBoxGlobal::tr("Failed to check media accessibility.", "medium")) +
|
---|
325 | m_sstrRow.arg(UIMessageCenter::formatErrorInfo(m_result) + ".");
|
---|
326 | }
|
---|
327 | break;
|
---|
328 | }
|
---|
329 | default:
|
---|
330 | break;
|
---|
331 | }
|
---|
332 | }
|
---|
333 |
|
---|
334 | /* Reset m_noDiffs */
|
---|
335 | m_noDiffs.isSet = false;
|
---|
336 | }
|
---|
337 |
|
---|
338 | /**
|
---|
339 | * Returns a root medium of this medium. For non-hard disk media, this is always
|
---|
340 | * this medium itself.
|
---|
341 | */
|
---|
342 | UIMedium &UIMedium::root() const
|
---|
343 | {
|
---|
344 | UIMedium *pRoot = unconst(this);
|
---|
345 | while (pRoot->m_pParent != NULL)
|
---|
346 | pRoot = pRoot->m_pParent;
|
---|
347 |
|
---|
348 | return *pRoot;
|
---|
349 | }
|
---|
350 |
|
---|
351 | /**
|
---|
352 | * Returns generated tooltip for this medium.
|
---|
353 | *
|
---|
354 | * In "don't show diffs" mode (where the attributes of the base hard disk are
|
---|
355 | * shown instead of the attributes of the differencing hard disk), extra
|
---|
356 | * information will be added to the tooltip to give the user a hint that the
|
---|
357 | * medium is actually a differencing hard disk.
|
---|
358 | *
|
---|
359 | * @param fNoDiffs @c true to enable user-friendly "don't show diffs" mode.
|
---|
360 | * @param fCheckRO @c true to perform the #readOnly() check and add a notice
|
---|
361 | * accordingly.
|
---|
362 | */
|
---|
363 | QString UIMedium::toolTip (bool fNoDiffs /* = false */, bool fCheckRO /* = false */, bool fNullAllowed /* = false */) const
|
---|
364 | {
|
---|
365 | QString strTip;
|
---|
366 |
|
---|
367 | if (m_medium.isNull())
|
---|
368 | {
|
---|
369 | strTip = fNullAllowed ? m_sstrRow.arg(VBoxGlobal::tr("<b>No medium selected</b>", "medium")) +
|
---|
370 | m_sstrRow.arg(VBoxGlobal::tr("You can also change this while the machine is running.")) :
|
---|
371 | m_sstrRow.arg(VBoxGlobal::tr("<b>No media available</b>", "medium")) +
|
---|
372 | m_sstrRow.arg(VBoxGlobal::tr("You can create media images using the virtual media manager."));
|
---|
373 | }
|
---|
374 | else
|
---|
375 | {
|
---|
376 | unconst(this)->checkNoDiffs(fNoDiffs);
|
---|
377 |
|
---|
378 | strTip = fNoDiffs ? m_noDiffs.toolTip : m_strToolTip;
|
---|
379 |
|
---|
380 | if (fCheckRO && m_fReadOnly)
|
---|
381 | strTip += m_sstrRow.arg("<hr>") +
|
---|
382 | m_sstrRow.arg(VBoxGlobal::tr("Attaching this hard disk will be performed indirectly using "
|
---|
383 | "a newly created differencing hard disk.", "medium"));
|
---|
384 | }
|
---|
385 |
|
---|
386 | return m_sstrTable.arg(strTip);
|
---|
387 | }
|
---|
388 |
|
---|
389 | /**
|
---|
390 | * Returns an icon corresponding to the media state. Distinguishes between
|
---|
391 | * the Inaccessible state and the situation when querying the state itself
|
---|
392 | * failed.
|
---|
393 | *
|
---|
394 | * In "don't show diffs" mode (where the attributes of the base hard disk are
|
---|
395 | * shown instead of the attributes of the differencing hard disk), the most
|
---|
396 | * worst media state on the given hard disk chain will be used to select the
|
---|
397 | * media icon.
|
---|
398 | *
|
---|
399 | * @param fNoDiffs @c true to enable user-friendly "don't show diffs" mode.
|
---|
400 | * @param fCheckRO @c true to perform the #readOnly() check and change the icon
|
---|
401 | * accordingly.
|
---|
402 | */
|
---|
403 | QPixmap UIMedium::icon(bool fNoDiffs /* = false */, bool fCheckRO /* = false */) const
|
---|
404 | {
|
---|
405 | QPixmap pixmap;
|
---|
406 |
|
---|
407 | if (state(fNoDiffs) == KMediumState_Inaccessible)
|
---|
408 | pixmap = result(fNoDiffs).isOk() ? vboxGlobal().warningIcon() : vboxGlobal().errorIcon();
|
---|
409 |
|
---|
410 | if (fCheckRO && m_fReadOnly)
|
---|
411 | pixmap = VBoxGlobal::joinPixmaps(pixmap, QPixmap(":/hd_new_16px.png"));
|
---|
412 |
|
---|
413 | return pixmap;
|
---|
414 | }
|
---|
415 |
|
---|
416 | /**
|
---|
417 | * Returns the details of this medium as a single-line string
|
---|
418 | *
|
---|
419 | * For hard disks, the details include the location, type and the logical size
|
---|
420 | * of the hard disk. Note that if @a fNoDiffs is @c true, these properties are
|
---|
421 | * queried on the root hard disk of the given hard disk because the primary
|
---|
422 | * purpose of the returned string is to be human readable (so that seeing a
|
---|
423 | * complex diff hard disk name is usually not desirable).
|
---|
424 | *
|
---|
425 | * For other media types, the location and the actual size are returned.
|
---|
426 | * Arguments @a fPredictDiff and @a aNoRoot are ignored in this case.
|
---|
427 | *
|
---|
428 | * @param fNoDiffs @c true to enable user-friendly "don't show diffs" mode.
|
---|
429 | * @param fPredictDiff @c true to mark the hard disk as differencing if
|
---|
430 | * attaching it would create a differencing hard disk (not
|
---|
431 | * used when @a aNoRoot is true).
|
---|
432 | * @param fUseHTML @c true to allow for emphasizing using bold and italics.
|
---|
433 | *
|
---|
434 | * @note Use #detailsHTML() instead of passing @c true for @a fUseHTML.
|
---|
435 | *
|
---|
436 | * @note The media object may become uninitialized by a third party while this
|
---|
437 | * method is reading its properties. In this case, the method will return
|
---|
438 | * an empty string.
|
---|
439 | */
|
---|
440 | QString UIMedium::details(bool fNoDiffs /* = false */,
|
---|
441 | bool fPredictDiff /* = false */,
|
---|
442 | bool fUseHTML /* = false */) const
|
---|
443 | {
|
---|
444 | // @todo the below check is rough; if m_medium becomes uninitialized, any
|
---|
445 | // of getters called afterwards will also fail. The same relates to the
|
---|
446 | // root hard disk object (that will be the hard disk itself in case of
|
---|
447 | // non-differencing disks). However, this check was added to fix a
|
---|
448 | // particular use case: when the hard disk is a differencing hard disk and
|
---|
449 | // it happens to be discarded (and uninitialized) after this method is
|
---|
450 | // called but before we read all its properties (yes, it's possible!), the
|
---|
451 | // root object will be null and calling methods on it will assert in the
|
---|
452 | // debug builds. This check seems to be enough as a quick solution (fresh
|
---|
453 | // hard disk attachments will be re-read by a machine state change signal
|
---|
454 | // after the discard operation is finished, so the user will eventually see
|
---|
455 | // correct data), but in order to solve the problem properly we need to use
|
---|
456 | // exceptions everywhere (or check the result after every method call). See
|
---|
457 | // @bugref{2149}.
|
---|
458 |
|
---|
459 | if (m_medium.isNull() || m_fHostDrive)
|
---|
460 | return m_strName;
|
---|
461 |
|
---|
462 | if (!m_medium.isOk())
|
---|
463 | return QString();
|
---|
464 |
|
---|
465 | QString strDetails, strText;
|
---|
466 |
|
---|
467 | UIMedium *pRoot = unconst(this);
|
---|
468 | KMediumState eState = m_state;
|
---|
469 |
|
---|
470 | if (m_type == UIMediumType_HardDisk)
|
---|
471 | {
|
---|
472 | if (fNoDiffs)
|
---|
473 | {
|
---|
474 | pRoot = &this->root();
|
---|
475 |
|
---|
476 | bool isDiff = (!fPredictDiff && m_pParent != NULL) || (fPredictDiff && m_fReadOnly);
|
---|
477 |
|
---|
478 | strDetails = isDiff && fUseHTML ?
|
---|
479 | QString("<i>%1</i>, ").arg(pRoot->m_strHardDiskType) :
|
---|
480 | QString("%1, ").arg(pRoot->m_strHardDiskType);
|
---|
481 |
|
---|
482 | eState = this->state(true /* fNoDiffs */);
|
---|
483 |
|
---|
484 | if (pRoot->m_state == KMediumState_NotCreated)
|
---|
485 | eState = KMediumState_NotCreated;
|
---|
486 | }
|
---|
487 | else
|
---|
488 | {
|
---|
489 | strDetails = QString("%1, ").arg(pRoot->m_strHardDiskType);
|
---|
490 | }
|
---|
491 | }
|
---|
492 |
|
---|
493 | // @todo prepend the details with the warning/error icon when not accessible
|
---|
494 |
|
---|
495 | switch (eState)
|
---|
496 | {
|
---|
497 | case KMediumState_NotCreated:
|
---|
498 | strText = VBoxGlobal::tr("Checking...", "medium");
|
---|
499 | strDetails += fUseHTML ? QString("<i>%1</i>").arg(strText) : strText;
|
---|
500 | break;
|
---|
501 | case KMediumState_Inaccessible:
|
---|
502 | strText = VBoxGlobal::tr("Inaccessible", "medium");
|
---|
503 | strDetails += fUseHTML ? QString("<b>%1</b>").arg(strText) : strText;
|
---|
504 | break;
|
---|
505 | default:
|
---|
506 | strDetails += m_type == UIMediumType_HardDisk ? pRoot->m_strLogicalSize : pRoot->m_strSize;
|
---|
507 | break;
|
---|
508 | }
|
---|
509 |
|
---|
510 | strDetails = fUseHTML ?
|
---|
511 | QString("%1 (<nobr>%2</nobr>)").arg(VBoxGlobal::locationForHTML(pRoot->m_strName), strDetails) :
|
---|
512 | QString("%1 (%2)").arg(VBoxGlobal::locationForHTML(pRoot->m_strName), strDetails);
|
---|
513 |
|
---|
514 | return strDetails;
|
---|
515 | }
|
---|
516 |
|
---|
517 | /**
|
---|
518 | * Checks if m_noDiffs is filled in and does it if not.
|
---|
519 | *
|
---|
520 | * @param fNoDiffs @if false, this method immediately returns.
|
---|
521 | */
|
---|
522 | void UIMedium::checkNoDiffs(bool fNoDiffs)
|
---|
523 | {
|
---|
524 | if (!fNoDiffs || m_noDiffs.isSet)
|
---|
525 | return;
|
---|
526 |
|
---|
527 | m_noDiffs.toolTip = QString();
|
---|
528 |
|
---|
529 | m_noDiffs.state = m_state;
|
---|
530 | for (UIMedium *cur = m_pParent; cur != NULL; cur = cur->m_pParent)
|
---|
531 | {
|
---|
532 | if (cur->m_state == KMediumState_Inaccessible)
|
---|
533 | {
|
---|
534 | m_noDiffs.state = cur->m_state;
|
---|
535 |
|
---|
536 | if (m_noDiffs.toolTip.isNull())
|
---|
537 | m_noDiffs.toolTip = m_sstrRow.arg(VBoxGlobal::tr("Some of the media in this hard disk chain "
|
---|
538 | "are inaccessible. Please use the Virtual Media "
|
---|
539 | "Manager in <b>Show Differencing Hard Disks</b> "
|
---|
540 | "mode to inspect these media.", "medium"));
|
---|
541 |
|
---|
542 | if (!cur->m_result.isOk())
|
---|
543 | {
|
---|
544 | m_noDiffs.result = cur->m_result;
|
---|
545 | break;
|
---|
546 | }
|
---|
547 | }
|
---|
548 | }
|
---|
549 |
|
---|
550 | if (m_pParent != NULL && !m_fReadOnly)
|
---|
551 | {
|
---|
552 | m_noDiffs.toolTip = root().tip() +
|
---|
553 | m_sstrRow.arg("<hr>") +
|
---|
554 | m_sstrRow.arg(VBoxGlobal::tr("This base hard disk is indirectly attached using "
|
---|
555 | "the following differencing hard disk:", "medium")) +
|
---|
556 | m_strToolTip + m_noDiffs.toolTip;
|
---|
557 | }
|
---|
558 |
|
---|
559 | if (m_noDiffs.toolTip.isNull())
|
---|
560 | m_noDiffs.toolTip = m_strToolTip;
|
---|
561 |
|
---|
562 | m_noDiffs.isSet = true;
|
---|
563 | }
|
---|
564 |
|
---|