dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync/* $Id$ */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync/** @file
d34409ad02ea0d28e08a6c4b089a412fdb3b4c9cvboxsync * VBox Qt GUI - UIPopupStackViewport class implementation.
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync/*
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync * Copyright (C) 2013 Oracle Corporation
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync *
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync * available from http://www.virtualbox.org. This file is free software;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync * you can redistribute it and/or modify it under the terms of the GNU
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync * General Public License (GPL) as published by the Free Software
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync#ifdef VBOX_WITH_PRECOMPILED_HEADERS
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync# include <precomp.h>
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync#else /* !VBOX_WITH_PRECOMPILED_HEADERS */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync/* GUI includes: */
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync# include "UIPopupStackViewport.h"
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync# include "UIPopupPane.h"
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync/* Other VBox includes: */
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync# include <VBox/sup.h>
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
a9b62afc62b28da7a1a77f34259f8013892d9664vboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsyncUIPopupStackViewport::UIPopupStackViewport()
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync : m_iLayoutMargin(1)
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync , m_iLayoutSpacing(1)
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync{
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync}
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsyncbool UIPopupStackViewport::exists(const QString &strPopupPaneID) const
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync{
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Is there already popup-pane with the same ID? */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync return m_panes.contains(strPopupPaneID);
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync}
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsyncvoid UIPopupStackViewport::createPopupPane(const QString &strPopupPaneID,
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync const QString &strMessage, const QString &strDetails,
85c47558a85759cf449e710088b4194f43515d15vboxsync const QMap<int, QString> &buttonDescriptions)
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync{
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Make sure there is no such popup-pane already: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync if (m_panes.contains(strPopupPaneID))
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync {
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync AssertMsgFailed(("Popup-pane already exists!"));
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync return;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync }
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Create new popup-pane: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync UIPopupPane *pPopupPane = m_panes[strPopupPaneID] = new UIPopupPane(this,
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync strMessage, strDetails,
85c47558a85759cf449e710088b4194f43515d15vboxsync buttonDescriptions);
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Attach popup-pane connection: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync connect(this, SIGNAL(sigProposePopupPaneWidth(int)), pPopupPane, SLOT(sltHandleProposalForWidth(int)));
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync connect(pPopupPane, SIGNAL(sigSizeHintChanged()), this, SLOT(sltAdjustGeometry()));
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync connect(pPopupPane, SIGNAL(sigDone(int)), this, SLOT(sltPopupPaneDone(int)));
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Show popup-pane: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync pPopupPane->show();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync}
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsyncvoid UIPopupStackViewport::updatePopupPane(const QString &strPopupPaneID,
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync const QString &strMessage, const QString &strDetails)
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync{
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Make sure there is such popup-pane already: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync if (!m_panes.contains(strPopupPaneID))
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync {
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync AssertMsgFailed(("Popup-pane doesn't exists!"));
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync return;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync }
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Get existing popup-pane: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync UIPopupPane *pPopupPane = m_panes[strPopupPaneID];
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Update message and details: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync pPopupPane->setMessage(strMessage);
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync pPopupPane->setDetails(strDetails);
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync}
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsyncvoid UIPopupStackViewport::recallPopupPane(const QString &strPopupPaneID)
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync{
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Make sure there is such popup-pane already: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync if (!m_panes.contains(strPopupPaneID))
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync {
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync AssertMsgFailed(("Popup-pane doesn't exists!"));
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync return;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync }
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Get existing popup-pane: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync UIPopupPane *pPopupPane = m_panes[strPopupPaneID];
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Recall popup-pane: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync pPopupPane->recall();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync}
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsyncvoid UIPopupStackViewport::sltHandleProposalForWidth(int iWidth)
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync{
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Subtract layout margins: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync iWidth -= 2 * m_iLayoutMargin;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Propagate resulting width to popups: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync emit sigProposePopupPaneWidth(iWidth);
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync}
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsyncvoid UIPopupStackViewport::sltAdjustGeometry()
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync{
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Update size-hint: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync updateSizeHint();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Layout content: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync layoutContent();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Notify parent popup-stack: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync emit sigSizeHintChanged();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync}
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsyncvoid UIPopupStackViewport::sltPopupPaneDone(int iResultCode)
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync{
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Make sure the sender is the popup-pane: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync UIPopupPane *pPopupPane = qobject_cast<UIPopupPane*>(sender());
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync if (!pPopupPane)
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync {
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync AssertMsgFailed(("Should be called by popup-pane only!"));
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync return;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync }
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Make sure the popup-pane still exists: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync const QString strPopupPaneID(m_panes.key(pPopupPane, QString()));
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync if (strPopupPaneID.isNull())
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync {
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync AssertMsgFailed(("Popup-pane already destroyed!"));
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync return;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync }
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Notify listeners about popup-pane removal: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync emit sigPopupPaneDone(strPopupPaneID, iResultCode);
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
9220181e2319f5f20bf6481f215af1ea2528026evboxsync /* Delete popup-pane asyncronously.
9220181e2319f5f20bf6481f215af1ea2528026evboxsync * To avoid issues with events which already posted: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync m_panes.remove(strPopupPaneID);
9220181e2319f5f20bf6481f215af1ea2528026evboxsync pPopupPane->deleteLater();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Notify listeners about popup-pane removed: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync emit sigPopupPaneRemoved(strPopupPaneID);
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Adjust geometry: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync sltAdjustGeometry();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Make sure this stack still contains popup-panes: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync if (!m_panes.isEmpty())
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync return;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Notify listeners about popup-stack: */
613a7010f7f9418848e9aa20f28285c3971c8e6bvboxsync emit sigPopupPanesRemoved();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync}
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsyncvoid UIPopupStackViewport::updateSizeHint()
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync{
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Calculate minimum width-hint: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync int iMinimumWidthHint = 0;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync {
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Take into account all the panes: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync foreach (UIPopupPane *pPane, m_panes)
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync iMinimumWidthHint = qMax(iMinimumWidthHint, pPane->minimumSizeHint().width());
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* And two margins finally: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync iMinimumWidthHint += 2 * m_iLayoutMargin;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync }
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Calculate minimum height-hint: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync int iMinimumHeightHint = 0;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync {
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Take into account all the panes: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync foreach (UIPopupPane *pPane, m_panes)
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync iMinimumHeightHint += pPane->minimumSizeHint().height();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Take into account all the spacings, if any: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync if (!m_panes.isEmpty())
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync iMinimumHeightHint += (m_panes.size() - 1) * m_iLayoutSpacing;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* And two margins finally: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync iMinimumHeightHint += 2 * m_iLayoutMargin;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync }
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Compose minimum size-hint: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync m_minimumSizeHint = QSize(iMinimumWidthHint, iMinimumHeightHint);
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync}
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsyncvoid UIPopupStackViewport::layoutContent()
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync{
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Get attributes: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync int iX = m_iLayoutMargin;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync int iY = m_iLayoutMargin;
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Layout every pane we have: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync foreach (UIPopupPane *pPane, m_panes)
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync {
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Get pane attributes: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync QSize paneSize = pPane->minimumSizeHint();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync const int iPaneWidth = paneSize.width();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync const int iPaneHeight = paneSize.height();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Adjust geometry for the pane: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync pPane->setGeometry(iX, iY, iPaneWidth, iPaneHeight);
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync pPane->layoutContent();
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync /* Increment placeholder: */
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync iY += (iPaneHeight + m_iLayoutSpacing);
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync }
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync}
dea4c76f53ae051bc7e5920b5371c1d44694b55bvboxsync