UIGMachinePreview.cpp revision d01bb88591e2ae070aa233b99c81e58598d557e1
/* $Id$ */
/** @file
*
* VBox frontends: Qt GUI ("VirtualBox"):
* UIGMachinePreview class implementation
*/
/*
* Copyright (C) 2010-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/* Qt includes: */
#include <QGraphicsSceneContextMenuEvent>
#include <QMenu>
#include <QPainter>
#include <QTimer>
/* GUI includes: */
#include "UIGMachinePreview.h"
#include "UIVirtualBoxEventHandler.h"
#include "UIExtraDataManager.h"
#include "UIImageTools.h"
#include "UIConverter.h"
#include "UIIconPool.h"
#include "VBoxGlobal.h"
/* COM includes: */
#include "CConsole.h"
#include "CDisplay.h"
, m_pUpdateTimer(new QTimer(this))
, m_pUpdateTimerMenu(0)
, m_iMargin(0)
, m_pPreviewImg(0)
{
/* Create session instance: */
/* Cache aspect-ratio preset settings: */
m_emptyPixmaps.insert(AspectRatioPreset_16x10, new QPixmap(empty16x10.pixmap(m_sizes.value(AspectRatioPreset_16x10))));
m_emptyPixmaps.insert(AspectRatioPreset_16x9, new QPixmap(empty16x9.pixmap(m_sizes.value(AspectRatioPreset_16x9))));
m_emptyPixmaps.insert(AspectRatioPreset_4x3, new QPixmap(empty4x3.pixmap(m_sizes.value(AspectRatioPreset_4x3))));
m_fullPixmaps.insert(AspectRatioPreset_16x10, new QPixmap(full16x10.pixmap(m_sizes.value(AspectRatioPreset_16x10))));
m_fullPixmaps.insert(AspectRatioPreset_16x9, new QPixmap(full16x9.pixmap(m_sizes.value(AspectRatioPreset_16x9))));
m_fullPixmaps.insert(AspectRatioPreset_4x3, new QPixmap(full4x3.pixmap(m_sizes.value(AspectRatioPreset_4x3))));
/* Setup contents (depends on presets above!): */
/* Create the context menu: */
m_pUpdateTimerMenu = new QMenu;
pUpdateTimeG->setExclusive(true);
for(int i = 0; i < PreviewUpdateIntervalType_Max; ++i)
{
pUpdateTime->setData(i);
pUpdateTime->setCheckable(true);
}
m_pUpdateTimerMenu->insertSeparator(m_actions[static_cast<PreviewUpdateIntervalType>(PreviewUpdateIntervalType_500ms)]);
/* Initialize with the new update interval: */
/* Setup connections: */
/* Retranslate the UI */
}
{
/* Close any open session: */
/* Destroy background images: */
{
}
{
}
/* Destroy preview image: */
if (m_pPreviewImg)
delete m_pPreviewImg;
/* Destroy update timer: */
if (m_pUpdateTimerMenu)
delete m_pUpdateTimerMenu;
}
{
/* Pause: */
stop();
/* Assign new machine: */
/* Fetch machine data: */
/* Resume: */
restart();
}
{
return m_machine;
}
{
/* Make sure its the event for our machine: */
return;
/* Restart the preview: */
restart();
}
void UIGMachinePreview::sltRecreatePreview()
{
/* Skip invisible preview: */
if (!isVisible())
return;
/* Cleanup previous image: */
if (m_pPreviewImg)
{
delete m_pPreviewImg;
m_pPreviewImg = 0;
}
/* Fetch actual machine-state: */
/* We are creating preview only for assigned and accessible VMs: */
{
/* Prepare image: */
/* Use 10x9 as the aspect-ratio preset by default: */
/* Preview update enabled? */
if (m_pUpdateTimer->interval() > 0)
{
/* Depending on machine state: */
switch (machineState)
{
case KMachineState_Saved:
case KMachineState_Restoring:
{
/* Use the screenshot from saved-state if possible: */
/* Make sure screen-data is OK: */
break;
/* Calculate aspect-ratio: */
/* Look for the best aspect-ratio preset: */
/* Create image based on shallow copy or screenshot data,
* scale image down if necessary to the size possible to reflect: */
/* Dim image to give it required look: */
break;
}
case KMachineState_Running:
case KMachineState_Paused:
{
/* Make sure session state is Locked: */
break;
/* Make sure console is OK: */
break;
/* Make sure display is OK: */
break;
/* Calculate aspect-ratio: */
/* Look for the best aspect-ratio preset preset: */
/* Calculate size corresponding to aspect-ratio: */
/* Use direct VM content: */
QVector<BYTE> screenData = display.TakeScreenShotToArray(0, size.width(), size.height(), KBitmapFormat_BGR0);
/* Make sure screen-data is OK: */
break;
/* Create image based on shallow copy or reordered data: */
/* Dim image to give it required look for PAUSED state: */
if (machineState == KMachineState_Paused)
break;
}
default:
break;
}
}
/* If image initialized: */
{
/* Shallow copy that image: */
/* And detach that copy: */
m_pPreviewImg->bits();
}
/* If preset changed: */
{
/* Save new preset: */
/* And update geometry: */
}
}
/* Redraw preview in any case: */
update();
}
{
}
{
restart();
}
{
stop();
}
{
if (pReturn)
{
PreviewUpdateIntervalType interval = static_cast<PreviewUpdateIntervalType>(pReturn->data().toInt());
setUpdateInterval(interval, true);
restart();
}
}
void UIGMachinePreview::retranslateUi()
{
}
QSizeF UIGMachinePreview::sizeHint(Qt::SizeHint which, const QSizeF &constraint /* = QSizeF() */) const
{
{
if (m_iMargin != 0)
{
}
return size;
}
}
{
/* Where should the content go: */
return;
/* If there is a preview image available: */
if (m_pPreviewImg)
{
/* Draw empty monitor frame: */
/* Move image to viewport center: */
/* Draw preview image: */
}
else
{
/* Draw full monitor frame: */
/* Paint preview name: */
QRect r;
/* Make a little magic to find out if the given text fits into our rectangle.
* Decrease the font pixel size as long as it doesn't fit. */
int cMax = 30;
do
{
h = h * .8;
font.setPixelSize((int)h);
}
}
}
{
switch (interval)
{
{
/* Stop the timer: */
m_pUpdateTimer->stop();
/* And continue with other cases: */
}
{
/* Set the timer interval: */
/* Check corresponding action: */
break;
}
break;
}
if (fSave)
}
{
/* Contents rectangle: */
}
void UIGMachinePreview::restart()
{
/* Fetch the latest machine-state: */
/* Reopen session if necessary: */
{
/* Lock the session for the current machine: */
}
/* Recreate the preview image: */
/* Start the timer if necessary: */
{
m_pUpdateTimer->start();
}
}
void UIGMachinePreview::stop()
{
/* Stop the timer: */
m_pUpdateTimer->stop();
}
/* static */
UIGMachinePreview::AspectRatioPreset UIGMachinePreview::bestAspectRatioPreset(const double dAspectRatio,
{
/* Use 16x9 preset as the 'best' by 'default': */
/* Calculate minimum diff based on 'default' preset: */
/* Now look for the 'best' aspect-ratio preset among existing: */
{
/* Calculate current diff based on 'current' preset: */
/* If new 'best' preset found: */
if (dDiff < dMinimumDiff)
{
/* Remember new diff: */
/* And new preset: */
}
}
/* Return 'best' preset: */
return bestPreset;
}
/* static */
{
/* Guest-screen more thin by vertical than host-screen: */
if (dGuestAspectRatio >= dHostAspectRatio)
{
/* Get host width: */
/* And calculate height based on guest aspect ratio: */
/* But no more than host height: */
}
/* Host-screen more thin by vertical than guest-screen: */
else
{
/* Get host height: */
/* And calculate width based on guest aspect ratio: */
/* But no more than host width: */
}
/* Return actual size: */
}