UIVMListView.cpp revision 46fecc499044c1c2248f10d3b219b8d478df9d2e
/* $Id$ */
/** @file
*
* VBox frontends: Qt GUI ("VirtualBox"):
* UIVMItemModel, UIVMListView, UIVMItemPainter class implementation
*/
/*
* Copyright (C) 2006-2010 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.
*/
# include "precomp.h"
#else /* !VBOX_WITH_PRECOMPILED_HEADERS */
/* Local includes */
#include "UIVMListView.h"
#include "UIMessageCenter.h"
/* Global includes */
#include <QScrollBar>
#include <QPainter>
#include <QLinearGradient>
#include <QPixmapCache>
#include <QDropEvent>
#include <QUrl>
#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
/* UIVMItemModel class */
{
}
{
}
{
}
{
}
bool UIVMItemModel::removeRows(int aRow, int aCount, const QModelIndex &aParent /* = QModelIndex() */)
{
delete m_VMItemList.takeAt(i);
return true;
}
/**
* Refreshes the item corresponding to the given UUID.
*/
{
}
{
/* Emit an layout change signal for the case some dimensions of the item
* has changed also. */
/* Emit an data changed signal. */
}
/**
* Clear the item model list. Please note that the items itself are also
* deleted.
*/
void UIVMItemModel::clear()
{
}
/**
* Returns the list item with the given UUID.
*/
{
return item;
return NULL;
}
{
}
{
if (row >= 0)
else
return QModelIndex();
}
{
for (int i=0; i < m_VMItemList.count(); ++i)
{
return i;
}
return -1;
}
{
return list;
}
void UIVMItemModel::sortByIdList(const QStringList &list, Qt::SortOrder order /* = Qt::AscendingOrder */)
{
/* Iterate over all ids and move the corresponding items ordered in the new
list. */
{
{
{
m_VMItemList << pItem;
break;
}
}
}
/* If there are items which didn't have been in the id list, we sort them
by name and appending them to the new list afterward. This make sure the
old behavior of VBox is respected. */
if (tmpVMItemList.count() > 0)
{
qSort(tmpVMItemList.begin(), tmpVMItemList.end(), order == Qt::AscendingOrder ? UIVMItemNameCompareLessThan : UIVMItemNameCompareMoreThan);
}
}
{
return m_VMItemList.count();
}
{
return QVariant();
return QVariant();
QVariant v;
switch (aRole)
{
case Qt::DisplayRole:
{
break;
}
case Qt::DecorationRole:
{
break;
}
case Qt::ToolTipRole:
{
break;
}
{
v = f;
break;
}
case Qt::AccessibleTextRole:
{
v = QString("%1 (%2)\n%3")
break;
}
case SnapShotDisplayRole:
{
break;
}
case SnapShotFontRole:
{
v = f;
break;
}
case MachineStateDisplayRole:
{
break;
}
{
break;
}
case MachineStateFontRole:
{
f.setPointSize(f.pointSize());
f.setItalic(true);
v = f;
break;
}
case SessionStateDisplayRole:
{
break;
}
case OSTypeIdRole:
{
break;
}
case UIVMItemPtrRole:
{
break;
}
}
return v;
}
int /* aRole = Qt::DisplayRole */) const
{
return QVariant();
}
{
}
{
}
{
else
}
{
return Qt::MoveAction;
}
{
}
{
return types;
}
{
return pMimeData;
}
bool UIVMItemModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
{
return true;
if (column > 0)
return false;
int beginRow;
if (row != -1)
else
{
/* Only move allowed. */
return false;
/* Get our own mime data type. */
if (pMimeData)
{
return true;
}
}
return false;
}
/* UIVMListView class */
, m_fItemInMove(false)
{
/* For queued events Q_DECLARE_METATYPE isn't sufficient. */
setDragEnabled(true);
setAcceptDrops(true);
setDropIndicatorShown(true);
/* Create & set our delegation class */
/* Default icon size */
/* Publish the activation of items */
/* Use the correct policy for the context menu */
}
{
}
{
{
if (i.isValid())
setCurrentIndex(i);
}
}
{
if (!item)
{
item = selectedItem();
if (!item)
selectItemByRow(0);
}
}
{
return NULL;
}
void UIVMListView::ensureCurrentVisible()
{
}
void UIVMListView::selectionChanged(const QItemSelection &aSelected, const QItemSelection &aDeselected)
{
}
{
}
{
// ensureCurrentVisible();
}
void UIVMListView::sltRowsAboutToBeInserted(const QModelIndex & /* parent */, int /* start */, int /* end */)
{
/* On D&D the items in the view jumps like hell, cause after inserting the
new item, but before deleting the old item an update is triggered. We
disable the updates now. */
if (m_fItemInMove)
setUpdatesEnabled(false);
}
{
/* Select the new item, after a D&D operation. Note: don't call the base
class, cause this will trigger an update. */
if (m_fItemInMove)
}
bool UIVMListView::selectCurrent()
{
{
/* Make sure that the current is always selected */
selectionModel()->select(currentIndex(), QItemSelectionModel::Current | QItemSelectionModel::ClearAndSelect);
return true;
}
return false;
}
{
if (qApp->activeModalWidget() != 0)
else
{
}
}
{
}
{
{
{
{
}
{
{
}
}
}
{
{
}
}
{
/* Select all indexes which are currently selected and dragable. */
{
}
{
m_fItemInMove = true;
if (!data)
return;
/* We only support one at the time. Also we need a persistent index,
cause the position of the old index may change. */
/* Now start the drag. */
/* Remove the old item */
m_fItemInMove = false;
setUpdatesEnabled(true);
}
}
{
p.drawText(QRect(margin, margin + osTypeSize.height() + space, s.width() - 2 * margin, nameSize.height()), Qt::AlignCenter, name);
/* Transparent icons are not supported on all platforms. */
#endif /* defined(Q_WS_MAC) || defined(Q_WS_WIN) */
p.end();
/* Some Qt versions seems buggy in creating QPixmap from QImage. Seems they
* don't clear the background. */
return i1;
}
QModelIndex UIVMListView::moveCursor(QAbstractItemView::CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
{
{
switch (cursorAction)
{
case QAbstractItemView::MoveUp:
{
}
case QAbstractItemView::MoveDown:
{
}
case QAbstractItemView::MovePageUp:
{
}
case QAbstractItemView::MovePageDown:
{
return moveItemTo(index, qMin(model()->rowCount(), index.row() + verticalScrollBar()->pageStep() + 1));
}
case QAbstractItemView::MoveHome:
return moveItemTo(currentIndex(), 0);
case QAbstractItemView::MoveEnd:
default:
break;
}
}
}
{
return QModelIndex();
return QModelIndex();
m_fItemInMove = true;
m_fItemInMove = false;
setUpdatesEnabled(true);
return QModelIndex(newIndex);
}
/* UIVMItemPainter class */
/*
+----------------------------------------------+
| marg |
| +----------+ m |
| m | | m a name_string___________ m |
| a | OSType | a r a |
| r | icon | r g +--+ r |
| g | | g / |si| state_string g |
| +----------+ 2 +--+ |
| marg |
+----------------------------------------------+
si = state icon
*/
/* Little helper class for layout calculation */
{
public:
{
QRect b;
b |= *rect;
else
{
}
}
};
const QModelIndex &aIndex) const
{
/* Get the size of every item */
/* Calculate the position for every item */
/* Calc the bounding rect */
}
const QModelIndex &index) const
{
/* Generate the key used in the pixmap cache. Needs to be composed with all
* values which might be changed. */
/* Check if the pixmap already exists in the cache. */
{
/* If not, generate a new one */
/* Highlight background if an item is selected in any case.
* (Fix for selector in the windows style.) */
tmpOption.showDecorationSelected = true;
/* Create a temporary pixmap and painter to work on.*/
/* Normally we operate on a painter which is in the size of the list
* view widget. Here we process one item only, so shift all the stuff
* out of the view. It will be translated back in the following
* methods. */
/* Start drawing with the background */
/* Blend the content */
/* Draw a focus rectangle when necessary */
/* Finish drawing */
tmpPainter.end();
/* Fill the cache */
}
}
const QModelIndex &index) const
{
/* Name and decoration */
const QPixmap osType = index.data(Qt::DecorationRole).value<QIcon>().pixmap(option.decorationSize, iconMode(option.state), iconState(option.state));
const QPixmap stateIcon = index.data(UIVMItemModel::MachineStateDecorationRole).value<QIcon>().pixmap(QSize(16, 16), iconMode(option.state), iconState(option.state));
/* Get the sizes for all items */
/* Calculate the positions for all items */
/* Get the appropriate pen for the current state */
/* Set the current pen */
/* os type icon */
/* vm name */
/* current snapshot in braces */
{
}
/* state icon */
/* textual state */
/* For debugging */
// pPainter->drawRect(boundingRect);
return boundingRect;
}
const QModelIndex &index) const
{
/* This is as always a big fat mess on Mac OS X. We can't use QImage for
* rendering text, cause this looks like shit. We can't do all the drawing
* on the widget, cause the composition modes are not working correctly.
* The same count for doing composition on a QPixmap. The work around is to
* the antialiasing is messed up), blitting this into a QImage to make the
* composition stuff and finally blitting this QImage into the QWidget.
* Yipi a yeah. Btw, no problem on Linux at all. */
/* Initialize with the base image color. */
/* Create the painter to operate on. */
/* Initialize the painter with the corresponding widget */
/* The translation is necessary, cause drawBackground expect the whole drawing area. */
basePainter.save();
/* Now paint the content. */
/* Finished with the OS dependent part. */
basePainter.end();
/* Time for the OS independent part (That is, use the QRasterEngine) */
/* Initialize the painter with the corresponding widget */
/* Fully copy the source to the destination */
{
/* Now use the alpha value of the source to blend the destination in. */
}
/* Finished with the OS independent part. */
rasterPainter.end();
/* Finally blit our hard work on the widget. */
}
{
switch (aRole)
{
case Qt::DisplayRole:
{
break;
}
case Qt::DecorationRole:
{
return QRect(QPoint(0, 0), icon.actualSize(aOption.decorationSize, iconMode(aOption.state), iconState(aOption.state)));
break;
}
case UIVMItemModel::SnapShotDisplayRole:
{
{
}else
return QRect();
break;
}
{
break;
}
{
return QRect(QPoint(0, 0), icon.actualSize(QSize(16, 16), iconMode(aOption.state), iconState(aOption.state)));
break;
}
}
return QRect();
}
{
/* Really basic layout management.
* First layout as usual */
/* Do grouping for the automatic center routine.
* First the states group: */
/* All items in the layout: */
/* Now vertically center the items based on the reference item */
}