UIVMPreviewWindow.cpp revision 194a8ad893b721dfc22ac5f955671f09db015a3f
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync/* $Id$ */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync/** @file
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync *
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * VBox frontends: Qt GUI ("VirtualBox"):
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * UIPreviewWindow class implementation
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync/*
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * Copyright (C) 2010 Oracle Corporation
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync *
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * available from http://www.virtualbox.org. This file is free software;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * you can redistribute it and/or modify it under the terms of the GNU
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * General Public License (GPL) as published by the Free Software
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync/* Local includes */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync#include "UIVMPreviewWindow.h"
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync#include "UIVirtualBoxEventHandler.h"
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync#include "UIImageTools.h"
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync#include "VBoxGlobal.h"
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync/* Global includes */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync#include <QContextMenuEvent>
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync#include <QMenu>
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync#include <QPainter>
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync#include <QTimer>
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsyncUIVMPreviewWindow::UIVMPreviewWindow(QWidget *pParent)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync : QIWithRetranslateUI<QWidget>(pParent)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync , m_machineState(KMachineState_Null)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync , m_pUpdateTimer(new QTimer(this))
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync , m_vMargin(10)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync , m_pbgImage(0)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync , m_pPreviewImg(0)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync , m_pGlossyImg(0)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync{
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync setContentsMargins(0, 5, 0, 5);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Connect the update timer */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync connect(m_pUpdateTimer, SIGNAL(timeout()),
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync this, SLOT(sltRecreatePreview()));
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Connect the machine state event */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync connect(gVBoxEvents, SIGNAL(sigMachineStateChange(QString, KMachineState)),
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync this, SLOT(sltMachineStateChange(QString, KMachineState)));
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Create the context menu */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync setContextMenuPolicy(Qt::DefaultContextMenu);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_pUpdateTimerMenu = new QMenu(this);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QActionGroup *pUpdateTimeG = new QActionGroup(this);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync pUpdateTimeG->setExclusive(true);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync for(int i = 0; i < UpdateEnd; ++i)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync {
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QAction *pUpdateTime = new QAction(pUpdateTimeG);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync pUpdateTime->setData(i);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync pUpdateTime->setCheckable(true);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync pUpdateTimeG->addAction(pUpdateTime);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_pUpdateTimerMenu->addAction(pUpdateTime);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_actions[static_cast<UpdateInterval>(i)] = pUpdateTime;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync }
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_pUpdateTimerMenu->insertSeparator(m_actions[static_cast<UpdateInterval>(Update1Sec)]);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Default value */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync UpdateInterval interval = Update1Sec;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QString strInterval = vboxGlobal().virtualBox().GetExtraData(VBoxDefs::GUI_PreviewUpdate);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync if (strInterval == "disabled")
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync interval = UpdateDisabled;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync else if (strInterval == "1")
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync interval = Update1Sec;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync else if (strInterval == "2")
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync interval = Update2Sec;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync else if (strInterval == "5")
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync interval = Update5Sec;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync else if (strInterval == "10")
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync interval = Update10Sec;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Initialize with the new update interval */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync setUpdateInterval(interval, false);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Retranslate the UI */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync retranslateUi();
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync}
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsyncvoid UIVMPreviewWindow::setMachine(const CMachine& machine)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync{
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_pUpdateTimer->stop();
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_machine = machine;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync restart();
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync}
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsyncCMachine UIVMPreviewWindow::machine() const
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync{
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync return m_machine;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync}
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsyncQSize UIVMPreviewWindow::sizeHint() const
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync{
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync return QSize(220, 220 * 3.0/4.0);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync}
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsyncvoid UIVMPreviewWindow::retranslateUi()
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync{
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_actions.value(UpdateDisabled)->setText(tr("Update Disabled"));
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_actions.value(Update1Sec)->setText(tr("Every 1 s"));
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_actions.value(Update2Sec)->setText(tr("Every 2 s"));
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_actions.value(Update5Sec)->setText(tr("Every 5 s"));
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_actions.value(Update10Sec)->setText(tr("Every 10 s"));
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync}
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsyncvoid UIVMPreviewWindow::resizeEvent(QResizeEvent *pEvent)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync{
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync repaintBGImages();
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QWidget::resizeEvent(pEvent);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync}
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsyncvoid UIVMPreviewWindow::showEvent(QShowEvent *pEvent)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync{
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Make sure there is some valid preview image when shown. */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync restart();
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QWidget::showEvent(pEvent);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync}
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsyncvoid UIVMPreviewWindow::hideEvent(QHideEvent *pEvent)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync{
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Stop the update time when we aren't visible */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync m_pUpdateTimer->stop();
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QWidget::hideEvent(pEvent);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync}
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsyncvoid UIVMPreviewWindow::paintEvent(QPaintEvent *pEvent)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync{
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QPainter painter(this);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Enable clipping */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync painter.setClipRect(pEvent->rect());
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Where should the content go */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QRect cr = contentsRect();
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Draw the background with the monitor and the shadow */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync painter.drawImage(cr.x(), cr.y(), *m_pbgImage);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync// painter.setPen(Qt::red);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync// painter.drawRect(cr.adjusted(0, 0, -1, -1));
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync// return;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* If there is a preview image available, use it. */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync if (m_pPreviewImg)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync painter.drawImage(0, 0, *m_pPreviewImg);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync else
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync {
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QString strName = tr("No Preview");
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync if (!m_machine.isNull())
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync strName = m_machine.GetName();
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Paint the name in the center of the monitor */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync painter.fillRect(m_vRect, Qt::black);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QFont font = painter.font();
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync font.setBold(true);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync int fFlags = Qt::AlignCenter | Qt::TextWordWrap;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync float h = m_vRect.size().height() * .2;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QRect r;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Make a little magic to find out if the given text fits into
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * our rectangle. Decrease the font pixel size as long as it
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync * doesn't fit. */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync int cMax = 30;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync do
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync {
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync h = h * .8;
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync font.setPixelSize(h);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync painter.setFont(font);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync r = painter.boundingRect(m_vRect, fFlags, strName);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync }while (( r.height() > m_vRect.height()
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync || r.width() > m_vRect.width())
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync && cMax-- != 0);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync painter.setPen(Qt::white);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync painter.drawText(m_vRect, fFlags, strName);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync }
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync /* Draw the glossy overlay last */
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync painter.drawImage(m_vRect.x(), m_vRect.y(), *m_pGlossyImg);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync}
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsyncvoid UIVMPreviewWindow::contextMenuEvent(QContextMenuEvent *pEvent)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync{
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync QAction *pReturn = m_pUpdateTimerMenu->exec(pEvent->globalPos(), 0);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync if (pReturn)
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync {
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync UpdateInterval interval = static_cast<UpdateInterval>(pReturn->data().toInt());
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync setUpdateInterval(interval, true);
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync restart();
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync }
8c3d541c7ee7442f570b22eca3d82808b35b0385vboxsync}
void UIVMPreviewWindow::sltMachineStateChange(QString strId, KMachineState state)
{
if ( !m_machine.isNull()
&& m_machine.GetId() == strId)
{
/* Cache the machine state */
m_machineState = state;
restart();
}
}
void UIVMPreviewWindow::sltRecreatePreview()
{
/* Only do this if we are visible */
if (!isVisible())
return;
if (m_pPreviewImg)
{
delete m_pPreviewImg;
m_pPreviewImg = 0;
}
if (!m_machine.isNull())
{
Assert(m_machineState != KMachineState_Null);
QImage image(size(), QImage::Format_ARGB32);
image.fill(Qt::transparent);
QPainter painter(&image);
bool fDone = false;
/* Preview enabled? */
if (m_pUpdateTimer->interval() > 0)
{
/* Use the image which may be included in the save state. */
if ( m_machineState == KMachineState_Saved
|| m_machineState == KMachineState_Restoring)
{
ULONG width = 0, height = 0;
QVector<BYTE> screenData = m_machine.ReadSavedScreenshotPNGToArray(0, width, height);
if (screenData.size() != 0)
{
QImage shot = QImage::fromData(screenData.data(), screenData.size(), "PNG").scaled(m_vRect.size());
dimImage(shot);
painter.drawImage(m_vRect.x(), m_vRect.y(), shot);
fDone = true;
}
}
/* Use the current VM output. */
else if ( m_machineState == KMachineState_Running
// || m_machineState == KMachineState_Saving /* Not sure if this is valid */
|| m_machineState == KMachineState_Paused)
{
CSession session;
session.createInstance(CLSID_Session);
if (!session.isNull())
{
CVirtualBox vbox = vboxGlobal().virtualBox();
m_machine.LockForSession(session, true /* fPermitShared */);
if (vbox.isOk())
{
CDisplay display = session.GetConsole().GetDisplay();
/* Todo: correct aspect radio */
// ULONG w, h, bpp;
// display.GetScreenResolution(0, w, h, bpp);
// QImage shot = QImage(w, h, QImage::Format_RGB32);
// shot.fill(Qt::black);
// display.TakeScreenShot(0, shot.bits(), shot.width(), shot.height());
QVector<BYTE> screenData = display.TakeScreenShotToArray(0, m_vRect.width(), m_vRect.height());
if ( display.isOk()
&& screenData.size() != 0)
{
/* Unfortunately we have to reorder the pixel
* data, cause the VBox API returns RGBA data,
* which is not a format QImage understand.
* Todo: check for 32bit alignment, for both
* the data and the scanlines. Maybe we need to
* copy the data in any case. */
uint32_t *d = (uint32_t*)screenData.data();
for (int i = 0; i < screenData.size() / 4; ++i)
{
uint32_t e = d[i];
d[i] = RT_MAKE_U32_FROM_U8(RT_BYTE3(e), RT_BYTE2(e), RT_BYTE1(e), RT_BYTE4(e));
}
QImage shot = QImage((uchar*)d, m_vRect.width(), m_vRect.height(), QImage::Format_RGB32);
if (m_machineState == KMachineState_Paused)
dimImage(shot);
painter.drawImage(m_vRect.x(), m_vRect.y(), shot);
fDone = true;
}
}
}
}
}
if (fDone)
m_pPreviewImg = new QImage(image);
}
update();
}
void UIVMPreviewWindow::setUpdateInterval(UpdateInterval interval, bool fSave)
{
switch (interval)
{
case UpdateDisabled:
{
if (fSave)
vboxGlobal().virtualBox().SetExtraData(VBoxDefs::GUI_PreviewUpdate, "disabled");
m_pUpdateTimer->setInterval(0);
m_pUpdateTimer->stop();
m_actions[interval]->setChecked(true);
break;
}
case Update1Sec:
{
if (fSave)
vboxGlobal().virtualBox().SetExtraData(VBoxDefs::GUI_PreviewUpdate, "1");
m_pUpdateTimer->setInterval(1000);
m_actions[interval]->setChecked(true);
break;
}
case Update2Sec:
{
if (fSave)
vboxGlobal().virtualBox().SetExtraData(VBoxDefs::GUI_PreviewUpdate, "2");
m_pUpdateTimer->setInterval(2000);
m_actions[interval]->setChecked(true);
break;
}
case Update5Sec:
{
if (fSave)
vboxGlobal().virtualBox().SetExtraData(VBoxDefs::GUI_PreviewUpdate, "5");
m_pUpdateTimer->setInterval(5000);
m_actions[interval]->setChecked(true);
break;
}
case Update10Sec:
{
if (fSave)
vboxGlobal().virtualBox().SetExtraData(VBoxDefs::GUI_PreviewUpdate, "10");
m_pUpdateTimer->setInterval(10000);
m_actions[interval]->setChecked(true);
break;
}
case UpdateEnd: break;
}
}
void UIVMPreviewWindow::restart()
{
/* Fetch the latest machine state */
if (!m_machine.isNull())
m_machineState = m_machine.GetState();
/* Recreate the preview image */
sltRecreatePreview();
/* Start the timer */
if (!m_machine.isNull())
{
if ( m_pUpdateTimer->interval() > 0
&& m_machineState == KMachineState_Running)
m_pUpdateTimer->start();
}
}
void UIVMPreviewWindow::repaintBGImages()
{
QPalette pal = palette();
QRect cr = contentsRect();
m_wRect = cr.adjusted(10, 10, -10, -10);
m_vRect = m_wRect.adjusted(m_vMargin, m_vMargin, -m_vMargin, -m_vMargin).adjusted(-3, -3, 3, 3);
/* First draw the shadow. Its a rounded rectangle which get blured. */
QImage imageW(cr.size(), QImage::Format_ARGB32);
QColor bg = pal.color(QPalette::Base);
bg.setAlpha(0); /* We want blur to transparent _and_ whatever the base color is. */
imageW.fill(bg.rgba());
QPainter pW(&imageW);
pW.setBrush(QColor(30, 30, 30)); /* Dark gray */
pW.setPen(Qt::NoPen);
pW.drawRoundedRect(QRect(QPoint(0, 0), cr.size()).adjusted(10, 10, -10, -10), m_vMargin, m_vMargin);
pW.end();
/* Blur the rectangle */
QImage imageO(cr.size(), QImage::Format_ARGB32);
blurImage(imageW, imageO, 10);
QPainter pO(&imageO);
#if 1
/* Now paint the border with a gradient to get a look of a monitor. */
QRect rr = QRect(QPoint(0, 0), cr.size()).adjusted(10, 10, -10, -10);
QLinearGradient lg(0, rr.y(), 0, rr.height());
QColor base(200, 200, 200); /* light variant */
// QColor base(80, 80, 80); /* Dark variant */
lg.setColorAt(0, base);
lg.setColorAt(0.4, base.darker(300));
lg.setColorAt(0.5, base.darker(400));
lg.setColorAt(0.7, base.darker(300));
lg.setColorAt(1, base);
pO.setBrush(lg);
pO.setPen(QPen(base.darker(150), 1));
pO.drawRoundedRect(rr, m_vMargin, m_vMargin);
pO.end();
#endif
/* Make a copy of the new bg image */
if (m_pbgImage)
delete m_pbgImage;
m_pbgImage = new QImage(imageO);
/* Now the glossy overlay has to be created. Start with defining a nice
* looking painter path. */
QRect gRect = QRect(QPoint(0, 0), m_vRect.size());
QPainterPath glossyPath(QPointF(gRect.x(), gRect.y()));
glossyPath.lineTo(gRect.x() + gRect.width(), gRect.y());
glossyPath.lineTo(gRect.x() + gRect.width(), gRect.y() + gRect.height() * 1.0/3.0);
glossyPath.cubicTo(gRect.x() + gRect.width() / 2.0, gRect.y() + gRect.height() * 1.0/3.0,
gRect.x() + gRect.width() / 2.0, gRect.y() + gRect.height() * 2.0/3.0,
gRect.x(), gRect.y() + gRect.height() * 2.0/3.0);
glossyPath.closeSubpath();
/* Paint the glossy path on a QImage */
if (m_pGlossyImg)
delete m_pGlossyImg;
QImage image(m_vRect.size(), QImage::Format_ARGB32);
QColor bg1(Qt::white); /* We want blur to transparent _and_ white. */
bg1.setAlpha(0);
image.fill(bg1.rgba());
QPainter painter(&image);
painter.fillPath(glossyPath, QColor(255, 255, 255, 80));
painter.end();
/* Blur the image to get a much more smooth feeling */
QImage image1(m_vRect.size(), QImage::Format_ARGB32);
blurImage(image, image1, 7);
m_pGlossyImg = new QImage(image1);
/* Repaint */
update();
}