Changeset 30691 in vbox
- Timestamp:
- Jul 7, 2010 9:10:21 AM (15 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox
- Files:
-
- 3 edited
- 2 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk
r30677 r30691 394 394 src/VBoxUpdateDlg.cpp \ 395 395 src/VBoxVMInformationDlg.cpp \ 396 src/UIVMItem.cpp \ 396 397 src/UIVMListView.cpp \ 397 398 src/UIVirtualBoxEventHandler.cpp \ -
trunk/src/VBox/Frontends/VirtualBox/src/UIVMItem.cpp
r30352 r30691 3 3 * 4 4 * VBox frontends: Qt GUI ("VirtualBox"): 5 * UIVMItem , UIVMItemModel, UIVMListView, UIVMItemPainterclass implementation5 * UIVMItem class implementation 6 6 */ 7 7 … … 21 21 # include "precomp.h" 22 22 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 23 #include "UIVMListView.h" 24 #include "VBoxProblemReporter.h" 25 #include " VBoxSelectorWnd.h"23 24 /* Local includes */ 25 #include "UIVMItem.h" 26 26 27 27 /* Qt includes */ 28 #include <QPainter>29 28 #include <QFileInfo> 30 #include <QLinearGradient> 31 #include <QPixmapCache> 32 33 #if defined (Q_WS_MAC) 34 # include "VBoxUtils.h" 29 30 #ifdef Q_WS_MAC 31 //# include "VBoxUtils.h" 35 32 # include <ApplicationServices/ApplicationServices.h> 36 #endif 33 #endif /* Q_WS_MAC */ 34 37 35 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 38 39 36 40 37 // Helpers … … 155 152 { 156 153 return m_fAccessible ? vboxGlobal().toString(m_state) : 157 UIVMListView::tr("Inaccessible");154 QApplication::translate("UIVMListView", "Inaccessible"); 158 155 } 159 156 … … 171 168 if (!m_strSnapshotName.isNull()) 172 169 toolTip += QString(" (%1)").arg(m_strSnapshotName); 173 toolTip = Q String(UIVMListView::tr(170 toolTip = QApplication::translate("UIVMListView", 174 171 "<nobr>%1<br></nobr>" 175 172 "<nobr>%2 since %3</nobr><br>" 176 173 "<nobr>Session %4</nobr>", 177 "VM tooltip (name, last state change, session state)") )174 "VM tooltip (name, last state change, session state)") 178 175 .arg(toolTip) 179 176 .arg(vboxGlobal().toString(m_state)) … … 183 180 else 184 181 { 185 toolTip = Q String(UIVMListView::tr(182 toolTip = QApplication::translate("UIVMListView", 186 183 "<nobr><b>%1</b><br></nobr>" 187 184 "<nobr>Inaccessible since %2</nobr>", 188 "Inaccessible VM tooltip (name, last state change)") )185 "Inaccessible VM tooltip (name, last state change)") 189 186 .arg(m_strSettingsFile) 190 187 .arg(dateTime); … … 396 393 } 397 394 398 /* UIVMItemModel class */399 400 void UIVMItemModel::addItem(UIVMItem *aItem)401 {402 Assert(aItem);403 int row = m_VMItemList.count();404 emit layoutAboutToBeChanged();405 beginInsertRows(QModelIndex(), row, row);406 m_VMItemList << aItem;407 endInsertRows();408 refreshItem(aItem);409 }410 411 void UIVMItemModel::removeItem(UIVMItem *aItem)412 {413 Assert(aItem);414 int row = m_VMItemList.indexOf(aItem);415 removeRows(row, 1);416 }417 418 bool UIVMItemModel::removeRows(int aRow, int aCount, const QModelIndex &aParent /* = QModelIndex() */)419 {420 emit layoutAboutToBeChanged();421 beginRemoveRows(aParent, aRow, aRow + aCount);422 m_VMItemList.erase(m_VMItemList.begin() + aRow, m_VMItemList.begin() + aRow + aCount);423 endRemoveRows();424 emit layoutChanged();425 return true;426 }427 428 /**429 * Refreshes the item corresponding to the given UUID.430 */431 void UIVMItemModel::refreshItem(UIVMItem *aItem)432 {433 Assert(aItem);434 if (aItem->recache())435 sort();436 itemChanged(aItem);437 }438 439 void UIVMItemModel::itemChanged(UIVMItem *aItem)440 {441 Assert(aItem);442 int row = m_VMItemList.indexOf(aItem);443 /* Emit an layout change signal for the case some dimensions of the item444 * has changed also. */445 emit layoutChanged();446 /* Emit an data changed signal. */447 emit dataChanged(index(row), index(row));448 }449 450 /**451 * Clear the item model list. Please note that the items itself are also452 * deleted.453 */454 void UIVMItemModel::clear()455 {456 qDeleteAll(m_VMItemList);457 }458 459 /**460 * Returns the list item with the given UUID.461 */462 UIVMItem *UIVMItemModel::itemById(const QString &aId) const463 {464 foreach(UIVMItem *item, m_VMItemList)465 if (item->id() == aId)466 return item;467 return NULL;468 }469 470 UIVMItem *UIVMItemModel::itemByRow(int aRow) const471 {472 return m_VMItemList.at(aRow);473 }474 475 QModelIndex UIVMItemModel::indexById(const QString &aId) const476 {477 int row = rowById(aId);478 if (row >= 0)479 return index(row);480 else481 return QModelIndex();482 }483 484 int UIVMItemModel::rowById(const QString &aId) const485 {486 for (int i=0; i < m_VMItemList.count(); ++i)487 {488 UIVMItem *item = m_VMItemList.at(i);489 if (item->id() == aId)490 return i;491 }492 return -1;493 }494 495 void UIVMItemModel::sort(int /* aColumn */, Qt::SortOrder aOrder /* = Qt::AscendingOrder */)496 {497 emit layoutAboutToBeChanged();498 switch (aOrder)499 {500 case Qt::AscendingOrder: qSort(m_VMItemList.begin(), m_VMItemList.end(), UIVMItemNameCompareLessThan); break;501 case Qt::DescendingOrder: qSort(m_VMItemList.begin(), m_VMItemList.end(), UIVMItemNameCompareGreaterThan); break;502 }503 emit layoutChanged();504 }505 506 int UIVMItemModel::rowCount(const QModelIndex & /* aParent = QModelIndex() */) const507 {508 return m_VMItemList.count();509 }510 511 QVariant UIVMItemModel::data(const QModelIndex &aIndex, int aRole) const512 {513 if (!aIndex.isValid())514 return QVariant();515 516 if (aIndex.row() >= m_VMItemList.size())517 return QVariant();518 519 QVariant v;520 switch (aRole)521 {522 case Qt::DisplayRole:523 {524 v = m_VMItemList.at(aIndex.row())->name();525 break;526 }527 case Qt::DecorationRole:528 {529 v = m_VMItemList.at(aIndex.row())->osIcon();530 break;531 }532 case Qt::ToolTipRole:533 {534 v = m_VMItemList.at(aIndex.row())->toolTipText();535 break;536 }537 case Qt::FontRole:538 {539 QFont f = qApp->font();540 f.setPointSize(f.pointSize() + 1);541 f.setWeight(QFont::Bold);542 v = f;543 break;544 }545 case Qt::AccessibleTextRole:546 {547 UIVMItem *item = m_VMItemList.at(aIndex.row());548 v = QString("%1 (%2)\n%3")549 .arg(item->name())550 .arg(item->snapshotName())551 .arg(item->sessionStateName());552 break;553 }554 case SnapShotDisplayRole:555 {556 v = m_VMItemList.at(aIndex.row())->snapshotName();557 break;558 }559 case SnapShotFontRole:560 {561 QFont f = qApp->font();562 v = f;563 break;564 }565 case SessionStateDisplayRole:566 {567 v = m_VMItemList.at(aIndex.row())->sessionStateName();568 break;569 }570 case SessionStateDecorationRole:571 {572 v = m_VMItemList.at(aIndex.row())->sessionStateIcon();573 break;574 }575 case SessionStateFontRole:576 {577 QFont f = qApp->font();578 f.setPointSize(f.pointSize());579 if (m_VMItemList.at(aIndex.row())->sessionState() != KSessionState_Closed)580 f.setItalic(true);581 v = f;582 break;583 }584 case OSTypeIdRole:585 {586 v = m_VMItemList.at(aIndex.row())->osTypeId();587 break;588 }589 case UIVMItemPtrRole:590 {591 v = qVariantFromValue(m_VMItemList.at(aIndex.row()));592 break;593 }594 }595 return v;596 }597 598 QVariant UIVMItemModel::headerData(int /*aSection*/, Qt::Orientation /*aOrientation*/,599 int /*aRole = Qt::DisplayRole */) const600 {601 return QVariant();602 }603 604 bool UIVMItemModel::UIVMItemNameCompareLessThan(UIVMItem* aItem1, UIVMItem* aItem2)605 {606 Assert(aItem1);607 Assert(aItem2);608 return aItem1->name().toLower() < aItem2->name().toLower();609 }610 611 bool UIVMItemModel::UIVMItemNameCompareGreaterThan(UIVMItem* aItem1, UIVMItem* aItem2)612 {613 Assert(aItem1);614 Assert(aItem2);615 return aItem2->name().toLower() < aItem1->name().toLower();616 }617 618 /* UIVMListView class */619 620 UIVMListView::UIVMListView(QWidget *aParent /* = 0 */)621 :QIListView(aParent)622 {623 /* Create & set our delegation class */624 UIVMItemPainter *delegate = new UIVMItemPainter(this);625 setItemDelegate(delegate);626 /* Default icon size */627 setIconSize(QSize(32, 32));628 /* Publish the activation of items */629 connect(this, SIGNAL(activated(const QModelIndex &)),630 this, SIGNAL(activated()));631 /* Use the correct policy for the context menu */632 setContextMenuPolicy(Qt::CustomContextMenu);633 }634 635 void UIVMListView::selectItemByRow(int row)636 {637 setCurrentIndex(model()->index(row, 0));638 }639 640 void UIVMListView::selectItemById(const QString &aID)641 {642 if (UIVMItemModel *m = qobject_cast <UIVMItemModel*>(model()))643 {644 QModelIndex i = m->indexById(aID);645 if (i.isValid())646 setCurrentIndex(i);647 }648 }649 650 void UIVMListView::ensureSomeRowSelected(int aRowHint)651 {652 UIVMItem *item = selectedItem();653 if (!item)654 {655 aRowHint = qBound(0, aRowHint, model()->rowCount() - 1);656 selectItemByRow(aRowHint);657 item = selectedItem();658 if (!item)659 selectItemByRow(0);660 }661 }662 663 UIVMItem * UIVMListView::selectedItem() const664 {665 QModelIndexList indexes = selectedIndexes();666 if (indexes.isEmpty())667 return NULL;668 return model()->data(indexes.first(), UIVMItemModel::UIVMItemPtrRole).value <UIVMItem *>();669 }670 671 void UIVMListView::ensureCurrentVisible()672 {673 scrollTo(currentIndex(), QAbstractItemView::EnsureVisible);674 }675 676 void UIVMListView::selectionChanged(const QItemSelection &aSelected, const QItemSelection &aDeselected)677 {678 QListView::selectionChanged(aSelected, aDeselected);679 selectCurrent();680 ensureCurrentVisible();681 emit currentChanged();682 }683 684 void UIVMListView::currentChanged(const QModelIndex &aCurrent, const QModelIndex &aPrevious)685 {686 QListView::currentChanged(aCurrent, aPrevious);687 selectCurrent();688 ensureCurrentVisible();689 emit currentChanged();690 }691 692 void UIVMListView::dataChanged(const QModelIndex &aTopLeft, const QModelIndex &aBottomRight)693 {694 QListView::dataChanged(aTopLeft, aBottomRight);695 selectCurrent();696 // ensureCurrentVisible();697 emit currentChanged();698 }699 700 bool UIVMListView::selectCurrent()701 {702 QModelIndexList indexes = selectionModel()->selectedIndexes();703 if (indexes.isEmpty() ||704 indexes.first() != currentIndex())705 {706 /* Make sure that the current is always selected */707 selectionModel()->select(currentIndex(), QItemSelectionModel::Current | QItemSelectionModel::ClearAndSelect);708 return true;709 }710 return false;711 }712 713 /* UIVMItemPainter class */714 /*715 +----------------------------------------------+716 | marg |717 | +----------+ m |718 | m | | m a name_string___________ m |719 | a | OSType | a r a |720 | r | icon | r g +--+ r |721 | g | | g / |si| state_string g |722 | +----------+ 2 +--+ |723 | marg |724 +----------------------------------------------+725 726 si = state icon727 728 */729 730 /* Little helper class for layout calculation */731 class QRectList: public QList<QRect *>732 {733 public:734 void alignVCenterTo(QRect* aWhich)735 {736 QRect b;737 foreach(QRect *rect, *this)738 if(rect != aWhich)739 b |= *rect;740 if (b.width() > aWhich->width())741 aWhich->moveCenter(QPoint(aWhich->center().x(), b.center().y()));742 else743 {744 foreach(QRect *rect, *this)745 if(rect != aWhich)746 rect->moveCenter(QPoint(rect->center().x(), aWhich->center().y()));747 }748 }749 };750 751 QSize UIVMItemPainter::sizeHint(const QStyleOptionViewItem &aOption,752 const QModelIndex &aIndex) const753 {754 /* Get the size of every item */755 QRect osTypeRT = rect(aOption, aIndex, Qt::DecorationRole);756 QRect vmNameRT = rect(aOption, aIndex, Qt::DisplayRole);757 QRect shotRT = rect(aOption, aIndex, UIVMItemModel::SnapShotDisplayRole);758 QRect stateIconRT = rect(aOption, aIndex, UIVMItemModel::SessionStateDecorationRole);759 QRect stateRT = rect(aOption, aIndex, UIVMItemModel::SessionStateDisplayRole);760 /* Calculate the position for every item */761 calcLayout(aIndex, &osTypeRT, &vmNameRT, &shotRT, &stateIconRT, &stateRT);762 /* Calc the bounding rect */763 const QRect boundingRect = osTypeRT | vmNameRT | shotRT | stateIconRT | stateRT;764 /* Return + left/top/right/bottom margin */765 return (boundingRect.size() + QSize(2 * m_Margin, 2 * m_Margin));766 }767 768 void UIVMItemPainter::paint(QPainter *pPainter, const QStyleOptionViewItem &option,769 const QModelIndex &index) const770 {771 /* Generate the key used in the pixmap cache. Needs to be composed with all772 * values which might be changed. */773 QString key = QString("vbox:%1:%2:%3:%4:%5:%6")774 .arg(index.data(Qt::DisplayRole).toString())775 .arg(index.data(UIVMItemModel::OSTypeIdRole).toString())776 .arg(index.data(UIVMItemModel::SnapShotDisplayRole).toString())777 .arg(index.data(UIVMItemModel::SessionStateDisplayRole).toString())778 .arg(option.state)779 .arg(option.rect.width());780 781 /* Check if the pixmap already exists in the cache. */782 QPixmap pixmap;783 if (!QPixmapCache::find(key, pixmap))784 {785 /* If not, generate a new one */786 QStyleOptionViewItem tmpOption(option);787 /* Highlight background if an item is selected in any case.788 * (Fix for selector in the windows style.) */789 tmpOption.showDecorationSelected = true;790 791 /* Create a temporary pixmap and painter to work on.*/792 QPixmap tmpPixmap(option.rect.size());793 tmpPixmap.fill(Qt::transparent);794 QPainter tmpPainter(&tmpPixmap);795 796 /* Normally we operate on a painter which is in the size of the list797 * view widget. Here we process one item only, so shift all the stuff798 * out of the view. It will be translated back in the following799 * methods. */800 tmpPainter.translate(-option.rect.x(), -option.rect.y());801 802 /* Start drawing with the background */803 drawBackground(&tmpPainter, tmpOption, index);804 805 /* Blend the content */806 blendContent(&tmpPainter, tmpOption, index);807 808 /* Draw a focus rectangle when necessary */809 drawFocus(&tmpPainter, tmpOption, tmpOption.rect);810 811 /* Finish drawing */812 tmpPainter.end();813 814 pixmap = tmpPixmap;815 /* Fill the cache */816 QPixmapCache::insert(key, tmpPixmap);817 }818 pPainter->drawPixmap(option.rect, pixmap);819 }820 821 void UIVMItemPainter::paintContent(QPainter *pPainter, const QStyleOptionViewItem &option,822 const QModelIndex &index) const823 {824 /* Name and decoration */825 const QString vmName = index.data(Qt::DisplayRole).toString();826 const QFont nameFont = index.data(Qt::FontRole).value<QFont>();827 const QPixmap osType = index.data(Qt::DecorationRole).value<QIcon>().pixmap(option.decorationSize, iconMode(option.state), iconState(option.state));828 829 const QString shot = index.data(UIVMItemModel::SnapShotDisplayRole).toString();830 const QFont shotFont = index.data(UIVMItemModel::SnapShotFontRole).value<QFont>();831 832 const QString state = index.data(UIVMItemModel::SessionStateDisplayRole).toString();833 const QFont stateFont = index.data(UIVMItemModel::SessionStateFontRole).value<QFont>();834 const QPixmap stateIcon = index.data(UIVMItemModel::SessionStateDecorationRole).value<QIcon>().pixmap(QSize(16, 16), iconMode(option.state), iconState(option.state));835 836 /* Get the sizes for all items */837 QRect osTypeRT = rect(option, index, Qt::DecorationRole);838 QRect vmNameRT = rect(option, index, Qt::DisplayRole);839 QRect shotRT = rect(option, index, UIVMItemModel::SnapShotDisplayRole);840 QRect stateIconRT = rect(option, index, UIVMItemModel::SessionStateDecorationRole);841 QRect stateRT = rect(option, index, UIVMItemModel::SessionStateDisplayRole);842 843 /* Calculate the positions for all items */844 calcLayout(index, &osTypeRT, &vmNameRT, &shotRT, &stateIconRT, &stateRT);845 /* Get the appropriate pen for the current state */846 QPalette pal = option.palette;847 QPen pen = pal.color(QPalette::Active, QPalette::Text);848 if (option.state & QStyle::State_Selected &&849 (option.state & QStyle::State_HasFocus ||850 QApplication::style()->styleHint(QStyle::SH_ItemView_ChangeHighlightOnFocus, &option) == 0))851 pen = pal.color(QPalette::Active, QPalette::HighlightedText);852 /* Set the current pen */853 pPainter->setPen(pen);854 /* os type icon */855 pPainter->drawPixmap(osTypeRT, osType);856 /* vm name */857 pPainter->setFont(nameFont);858 pPainter->drawText(vmNameRT, vmName);859 /* current snapshot in braces */860 if (!shot.isEmpty())861 {862 pPainter->setFont(shotFont);863 pPainter->drawText(shotRT, QString("(%1)").arg(shot));864 }865 /* state icon */866 pPainter->drawPixmap(stateIconRT, stateIcon);867 /* textual state */868 pPainter->setFont(stateFont);869 pPainter->drawText(stateRT, state);870 /* For debugging */871 // QRect boundingRect = osTypeRT | vmNameRT | shotRT | stateIconRT | stateRT;872 // pPainter->drawRect(boundingRect);873 }874 875 void UIVMItemPainter::blendContent(QPainter *pPainter, const QStyleOptionViewItem &option,876 const QModelIndex &index) const877 {878 QRect r = option.rect;879 QWidget *pParent = qobject_cast<QListView *>(parent())->viewport();880 /* This is as always a big fat mess on Mac OS X. We can't use QImage for881 * rendering text, cause this looks like shit. We can't do all the drawing882 * on the widget, cause the composition modes are not working correctly.883 * The same count for doing composition on a QPixmap. The work around is to884 * draw all into a QPixmap (also the background color/gradient, otherwise885 * the antialiasing is messed up), bliting this into a QImage to make the886 * composition stuff and finally bliting this QImage into the QWidget.887 * Yipi a yeah. Btw, no problem on Linux at all. */888 QPixmap basePixmap(r.width(), r.height());//889 /* Initialize with the base image color. */890 basePixmap.fill(pParent->palette().base().color());891 /* Create the painter to operate on. */892 QPainter basePainter(&basePixmap);893 /* Initialize the painter with the corresponding widget */894 basePainter.initFrom(pParent);895 basePainter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing, true);896 /* The translation is necessary, cause drawBackground expect the whole drawing area. */897 basePainter.save();898 basePainter.translate(-option.rect.x(), -option.rect.y());899 drawBackground(&basePainter, option, index);900 basePainter.restore();901 /* Now paint the content. */902 paintContent(&basePainter, option, index);903 /* Finished with the OS dependent part. */904 basePainter.end();905 /* Time for the OS independent part (That is, use the QRasterEngine) */906 QImage baseImage(r.width(), r.height(), QImage::Format_ARGB32_Premultiplied);907 QPainter rasterPainter(&baseImage);908 /* Initialize the painter with the corresponding widget */909 rasterPainter.initFrom(pParent);910 rasterPainter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing, true);911 /* Fully copy the source to the destination */912 rasterPainter.setCompositionMode(QPainter::CompositionMode_Source);913 rasterPainter.drawPixmap(0, 0, basePixmap);914 /* Now use the alpha value of the source to blend the destination in. */915 rasterPainter.setCompositionMode(QPainter::CompositionMode_DestinationIn);916 917 const int blendWidth = qMin(70, r.width());918 QLinearGradient lg(r.width()-blendWidth, 0, r.width(), 0);919 lg.setColorAt(0, QColor(Qt::white));920 lg.setColorAt(0.95, QColor(Qt::transparent));921 lg.setColorAt(1, QColor(Qt::transparent));922 rasterPainter.fillRect(r.width()-blendWidth, 0, blendWidth, r.height(), lg);923 /* Finished with the OS independent part. */924 rasterPainter.end();925 926 /* Finally blit our hard work on the widget. */927 pPainter->drawImage(option.rect.x(), option.rect.y(), baseImage);928 }929 930 QRect UIVMItemPainter::rect(const QStyleOptionViewItem &aOption,931 const QModelIndex &aIndex, int aRole) const932 {933 switch (aRole)934 {935 case Qt::DisplayRole:936 {937 QString text = aIndex.data(Qt::DisplayRole).toString();938 QFontMetrics fm(fontMetric(aIndex, Qt::FontRole));939 return QRect(QPoint(0, 0), fm.size(0, text));940 break;941 }942 case Qt::DecorationRole:943 {944 QIcon icon = aIndex.data(Qt::DecorationRole).value<QIcon>();945 return QRect(QPoint(0, 0), icon.actualSize(aOption.decorationSize, iconMode(aOption.state), iconState(aOption.state)));946 break;947 }948 case UIVMItemModel::SnapShotDisplayRole:949 {950 QString text = aIndex.data(UIVMItemModel::SnapShotDisplayRole).toString();951 if (!text.isEmpty())952 {953 QFontMetrics fm(fontMetric(aIndex, UIVMItemModel::SnapShotFontRole));954 return QRect(QPoint(0, 0), fm.size(0, QString("(%1)").arg(text)));955 }else956 return QRect();957 break;958 }959 case UIVMItemModel::SessionStateDisplayRole:960 {961 QString text = aIndex.data(UIVMItemModel::SessionStateDisplayRole).toString();962 QFontMetrics fm(fontMetric(aIndex, UIVMItemModel::SessionStateFontRole));963 return QRect(QPoint(0, 0), fm.size(0, text));964 break;965 }966 case UIVMItemModel::SessionStateDecorationRole:967 {968 QIcon icon = aIndex.data(UIVMItemModel::SessionStateDecorationRole).value<QIcon>();969 return QRect(QPoint(0, 0), icon.actualSize(QSize(16, 16), iconMode(aOption.state), iconState(aOption.state)));970 break;971 }972 }973 return QRect();974 }975 976 void UIVMItemPainter::calcLayout(const QModelIndex &aIndex,977 QRect *aOSType, QRect *aVMName, QRect *aShot,978 QRect *aStateIcon, QRect *aState) const979 {980 const int nameSpaceWidth = fontMetric(aIndex, Qt::FontRole).width(' ');981 const int stateSpaceWidth = fontMetric(aIndex, UIVMItemModel::SessionStateFontRole).width(' ');982 /* Really basic layout managment.983 * First layout as usual */984 aOSType->moveTo(m_Margin, m_Margin);985 aVMName->moveTo(m_Margin + aOSType->width() + m_Spacing, m_Margin);986 aShot->moveTo(aVMName->right() + nameSpaceWidth, aVMName->top());987 aStateIcon->moveTo(aVMName->left(), aVMName->bottom());988 aState->moveTo(aStateIcon->right() + stateSpaceWidth, aStateIcon->top());989 /* Do grouping for the automatic center routine.990 * First the states group: */991 QRectList statesLayout;992 statesLayout << aStateIcon << aState;993 /* All items in the layout: */994 QRectList allLayout;995 allLayout << aOSType << aVMName << aShot << statesLayout;996 /* Now verticaly center the items based on the reference item */997 statesLayout.alignVCenterTo(aStateIcon);998 allLayout.alignVCenterTo(aOSType);999 }1000 -
trunk/src/VBox/Frontends/VirtualBox/src/UIVMItem.h
r30352 r30691 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * UIVMItem , UIVMItemModel, UIVMListView, UIVMItemPainterclass declarations4 * UIVMItem class declarations 5 5 */ 6 6 … … 17 17 */ 18 18 19 #ifndef __UIVM ListView_h__20 #define __UIVM ListView_h__19 #ifndef __UIVMItem_h__ 20 #define __UIVMItem_h__ 21 21 22 /* Local includes */ 22 23 #include "VBoxGlobal.h" 23 #include "QIListView.h"24 24 25 /* Qt includes */ 26 #include <QAbstractListModel> 25 /* Global includes */ 27 26 #include <QDateTime> 28 29 class VBoxSelectorWnd;30 27 31 28 class UIVMItem … … 87 84 Q_DECLARE_METATYPE(UIVMItem *); 88 85 89 class UIVMItemModel: public QAbstractListModel 90 { 91 Q_OBJECT; 86 #endif /* __UIVMItem_h__ */ 92 87 93 public:94 enum { SnapShotDisplayRole = Qt::UserRole,95 SnapShotFontRole,96 SessionStateDisplayRole,97 SessionStateDecorationRole,98 SessionStateFontRole,99 OSTypeIdRole,100 UIVMItemPtrRole };101 102 UIVMItemModel(QObject *aParent = 0)103 :QAbstractListModel(aParent) {}104 105 void addItem(UIVMItem *aItem);106 void removeItem(UIVMItem *aItem);107 void refreshItem(UIVMItem *aItem);108 109 void itemChanged(UIVMItem *aItem);110 111 void clear();112 113 UIVMItem *itemById(const QString &aId) const;114 UIVMItem *itemByRow(int aRow) const;115 QModelIndex indexById(const QString &aId) const;116 117 int rowById(const QString &aId) const;;118 119 void sort(Qt::SortOrder aOrder = Qt::AscendingOrder) { sort(0, aOrder); }120 121 /* The following are necessary model implementations */122 void sort(int aColumn, Qt::SortOrder aOrder = Qt::AscendingOrder);123 124 int rowCount(const QModelIndex &aParent = QModelIndex()) const;125 126 QVariant data(const QModelIndex &aIndex, int aRole) const;127 QVariant headerData(int aSection, Qt::Orientation aOrientation,128 int aRole = Qt::DisplayRole) const;129 130 bool removeRows(int aRow, int aCount, const QModelIndex &aParent = QModelIndex());131 132 private:133 static bool UIVMItemNameCompareLessThan(UIVMItem* aItem1, UIVMItem* aItem2);134 static bool UIVMItemNameCompareGreaterThan(UIVMItem* aItem1, UIVMItem* aItem2);135 136 /* Private member vars */137 QList<UIVMItem *> m_VMItemList;138 };139 140 class UIVMListView: public QIListView141 {142 Q_OBJECT;143 144 public:145 UIVMListView(QWidget *aParent = 0);146 147 void selectItemByRow(int row);148 void selectItemById(const QString &aID);149 void ensureSomeRowSelected(int aRowHint);150 UIVMItem * selectedItem() const;151 152 void ensureCurrentVisible();153 154 signals:155 void currentChanged();156 void activated();157 158 protected slots:159 void selectionChanged(const QItemSelection &aSelected, const QItemSelection &aDeselected);160 void currentChanged(const QModelIndex &aCurrent, const QModelIndex &aPrevious);161 void dataChanged(const QModelIndex &aTopLeft, const QModelIndex &aBottomRight);162 163 protected:164 bool selectCurrent();165 };166 167 class UIVMItemPainter: public QIItemDelegate168 {169 public:170 UIVMItemPainter(QObject *aParent = 0)171 : QIItemDelegate(aParent), m_Margin(8), m_Spacing(m_Margin * 3 / 2) {}172 173 QSize sizeHint(const QStyleOptionViewItem &aOption,174 const QModelIndex &aIndex) const;175 176 void paint(QPainter *aPainter, const QStyleOptionViewItem &aOption,177 const QModelIndex &aIndex) const;178 179 private:180 void paintContent(QPainter *pPainter, const QStyleOptionViewItem &option, const QModelIndex &index) const;181 void blendContent(QPainter *pPainter, const QStyleOptionViewItem &option, const QModelIndex &index) const;182 inline QFontMetrics fontMetric(const QModelIndex &aIndex, int aRole) const { return QFontMetrics(aIndex.data(aRole).value<QFont>()); }183 inline QIcon::Mode iconMode(QStyle::State aState) const184 {185 if (!(aState & QStyle::State_Enabled))186 return QIcon::Disabled;187 if (aState & QStyle::State_Selected)188 return QIcon::Selected;189 return QIcon::Normal;190 }191 inline QIcon::State iconState(QStyle::State aState) const { return aState & QStyle::State_Open ? QIcon::On : QIcon::Off; }192 193 QRect rect(const QStyleOptionViewItem &aOption,194 const QModelIndex &aIndex, int aRole) const;195 196 void calcLayout(const QModelIndex &aIndex,197 QRect *aOSType, QRect *aVMName, QRect *aShot,198 QRect *aStateIcon, QRect *aState) const;199 200 /* Private member vars */201 int m_Margin;202 int m_Spacing;203 };204 205 #endif /* __UIVMListView_h__ */206 -
trunk/src/VBox/Frontends/VirtualBox/src/UIVMListView.cpp
r30062 r30691 3 3 * 4 4 * VBox frontends: Qt GUI ("VirtualBox"): 5 * UIVMItem , UIVMItemModel, UIVMListView, UIVMItemPainter class implementation5 * UIVMItemModel, UIVMListView, UIVMItemPainter class implementation 6 6 */ 7 7 … … 21 21 # include "precomp.h" 22 22 #else /* !VBOX_WITH_PRECOMPILED_HEADERS */ 23 24 /* Local includes */ 23 25 #include "UIVMListView.h" 24 26 #include "VBoxProblemReporter.h" 25 27 #include "VBoxSelectorWnd.h" 26 28 27 /* Qtincludes */29 /* Global includes */ 28 30 #include <QPainter> 29 #include <QFileInfo>30 31 #include <QLinearGradient> 31 32 #include <QPixmapCache> 32 33 33 #if defined (Q_WS_MAC)34 # include "VBoxUtils.h"35 # include <ApplicationServices/ApplicationServices.h>36 #endif37 34 #endif /* !VBOX_WITH_PRECOMPILED_HEADERS */ 38 39 40 // Helpers41 ////////////////////////////////////////////////////////////////////////////////42 43 /// @todo Remove. See @c todo in #switchTo() below.44 #if 045 46 #if defined (Q_WS_WIN32)47 48 struct EnumWindowsProcData49 {50 ULONG pid;51 WId wid;52 };53 54 BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)55 {56 EnumWindowsProcData *d = (EnumWindowsProcData *) lParam;57 58 DWORD pid = 0;59 GetWindowThreadProcessId(hwnd, &pid);60 61 if (d->pid == pid)62 {63 WINDOWINFO info;64 if (!GetWindowInfo(hwnd, &info))65 return TRUE;66 67 #if 068 LogFlowFunc(("pid=%d, wid=%08X\n", pid, hwnd));69 LogFlowFunc((" parent=%08X\n", GetParent(hwnd)));70 LogFlowFunc((" owner=%08X\n", GetWindow(hwnd, GW_OWNER)));71 TCHAR buf [256];72 LogFlowFunc((" rcWindow=%d,%d;%d,%d\n",73 info.rcWindow.left, info.rcWindow.top,74 info.rcWindow.right, info.rcWindow.bottom));75 LogFlowFunc((" dwStyle=%08X\n", info.dwStyle));76 LogFlowFunc((" dwExStyle=%08X\n", info.dwExStyle));77 GetClassName(hwnd, buf, 256);78 LogFlowFunc((" class=%ls\n", buf));79 GetWindowText(hwnd, buf, 256);80 LogFlowFunc((" text=%ls\n", buf));81 #endif82 83 /* we are interested in unowned top-level windows only */84 if (!(info.dwStyle & (WS_CHILD | WS_POPUP)) &&85 info.rcWindow.left < info.rcWindow.right &&86 info.rcWindow.top < info.rcWindow.bottom &&87 GetParent(hwnd) == NULL &&88 GetWindow(hwnd, GW_OWNER) == NULL)89 {90 d->wid = hwnd;91 /* if visible, stop the search immediately */92 if (info.dwStyle & WS_VISIBLE)93 return FALSE;94 /* otherwise, give other top-level windows a chance95 * (the last one wins) */96 }97 }98 99 return TRUE;100 }101 102 #endif103 104 /**105 * Searches for a main window of the given process.106 *107 * @param aPid process ID to search for108 *109 * @return window ID on success or <tt>(WId) ~0</tt> otherwise.110 */111 static WId FindWindowIdFromPid(ULONG aPid)112 {113 #if defined (Q_WS_WIN32)114 115 EnumWindowsProcData d = { aPid, (WId) ~0 };116 EnumWindows(EnumWindowsProc, (LPARAM) &d);117 LogFlowFunc(("SELECTED wid=%08X\n", d.wid));118 return d.wid;119 120 #elif defined (Q_WS_X11)121 122 NOREF(aPid);123 return (WId) ~0;124 125 #elif defined (Q_WS_MAC)126 127 /** @todo Figure out how to get access to another windows of another process...128 * Or at least check that it's not a VBoxVRDP process. */129 NOREF (aPid);130 return (WId) 0;131 132 #else133 134 return (WId) ~0;135 136 #endif137 }138 139 #endif140 141 UIVMItem::UIVMItem(const CMachine &aMachine)142 : m_machine(aMachine)143 {144 recache();145 }146 147 UIVMItem::~UIVMItem()148 {149 }150 151 // public members152 ////////////////////////////////////////////////////////////////////////////////153 154 QString UIVMItem::sessionStateName() const155 {156 return m_fAccessible ? vboxGlobal().toString(m_state) :157 UIVMListView::tr("Inaccessible");158 }159 160 QString UIVMItem::toolTipText() const161 {162 QString dateTime = (m_lastStateChange.date() == QDate::currentDate()) ?163 m_lastStateChange.time().toString(Qt::LocalDate) :164 m_lastStateChange.toString(Qt::LocalDate);165 166 QString toolTip;167 168 if (m_fAccessible)169 {170 toolTip = QString("<b>%1</b>").arg(m_strName);171 if (!m_strSnapshotName.isNull())172 toolTip += QString(" (%1)").arg(m_strSnapshotName);173 toolTip = QString(UIVMListView::tr(174 "<nobr>%1<br></nobr>"175 "<nobr>%2 since %3</nobr><br>"176 "<nobr>Session %4</nobr>",177 "VM tooltip (name, last state change, session state)"))178 .arg(toolTip)179 .arg(vboxGlobal().toString(m_state))180 .arg(dateTime)181 .arg(vboxGlobal().toString(m_sessionState));182 }183 else184 {185 toolTip = QString(UIVMListView::tr(186 "<nobr><b>%1</b><br></nobr>"187 "<nobr>Inaccessible since %2</nobr>",188 "Inaccessible VM tooltip (name, last state change)"))189 .arg(m_strSettingsFile)190 .arg(dateTime);191 }192 193 return toolTip;194 }195 196 bool UIVMItem::recache()197 {198 bool needsResort = true;199 200 m_strId = m_machine.GetId();201 m_strSettingsFile = m_machine.GetSettingsFilePath();202 203 m_fAccessible = m_machine.GetAccessible();204 if (m_fAccessible)205 {206 QString name = m_machine.GetName();207 208 CSnapshot snp = m_machine.GetCurrentSnapshot();209 m_strSnapshotName = snp.isNull() ? QString::null : snp.GetName();210 needsResort = name != m_strName;211 m_strName = name;212 213 m_state = m_machine.GetState();214 m_lastStateChange.setTime_t(m_machine.GetLastStateChange() / 1000);215 m_sessionState = m_machine.GetSessionState();216 m_strOSTypeId = m_machine.GetOSTypeId();217 m_cSnaphot = m_machine.GetSnapshotCount();218 219 if ( m_state == KMachineState_PoweredOff220 || m_state == KMachineState_Saved221 || m_state == KMachineState_Teleported222 || m_state == KMachineState_Aborted223 )224 {225 m_pid = (ULONG) ~0;226 /// @todo Remove. See @c todo in #switchTo() below.227 #if 0228 mWinId = (WId) ~0;229 #endif230 }231 else232 {233 m_pid = m_machine.GetSessionPid();234 /// @todo Remove. See @c todo in #switchTo() below.235 #if 0236 mWinId = FindWindowIdFromPid(m_pid);237 #endif238 }239 }240 else241 {242 m_accessError = m_machine.GetAccessError();243 244 /* this should be in sync with245 * VBoxProblemReporter::confirm_machineDeletion() */246 QFileInfo fi(m_strSettingsFile);247 QString name = fi.completeSuffix().toLower() == "xml" ?248 fi.completeBaseName() : fi.fileName();249 needsResort = name != m_strName;250 m_strName = name;251 m_state = KMachineState_Null;252 m_sessionState = KSessionState_Null;253 m_lastStateChange = QDateTime::currentDateTime();254 m_strOSTypeId = QString::null;255 m_cSnaphot = 0;256 257 m_pid = (ULONG) ~0;258 /// @todo Remove. See @c todo in #switchTo() below.259 #if 0260 mWinId = (WId) ~0;261 #endif262 }263 264 return needsResort;265 }266 267 /**268 * Returns @a true if we can activate and bring the VM console window to269 * foreground, and @a false otherwise.270 */271 bool UIVMItem::canSwitchTo() const272 {273 return const_cast <CMachine &>(m_machine).CanShowConsoleWindow();274 275 /// @todo Remove. See @c todo in #switchTo() below.276 #if 0277 return mWinId != (WId) ~0;278 #endif279 }280 281 /**282 * Tries to switch to the main window of the VM process.283 *284 * @return true if successfully switched and false otherwise.285 */286 bool UIVMItem::switchTo()287 {288 #ifdef Q_WS_MAC289 ULONG64 id = m_machine.ShowConsoleWindow();290 #else291 WId id = (WId) m_machine.ShowConsoleWindow();292 #endif293 AssertWrapperOk(m_machine);294 if (!m_machine.isOk())295 return false;296 297 /* winId = 0 it means the console window has already done everything298 * necessary to implement the "show window" semantics. */299 if (id == 0)300 return true;301 302 #if defined (Q_WS_WIN32) || defined (Q_WS_X11)303 304 return vboxGlobal().activateWindow(id, true);305 306 #elif defined (Q_WS_MAC)307 /*308 * This is just for the case were the other process cannot steal309 * the focus from us. It will send us a PSN so we can try.310 */311 ProcessSerialNumber psn;312 psn.highLongOfPSN = id >> 32;313 psn.lowLongOfPSN = (UInt32)id;314 OSErr rc = ::SetFrontProcess(&psn);315 if (!rc)316 Log(("GUI: %#RX64 couldn't do SetFrontProcess on itself, the selector (we) had to do it...\n", id));317 else318 Log(("GUI: Failed to bring %#RX64 to front. rc=%#x\n", id, rc));319 return !rc;320 321 #endif322 323 return false;324 325 /// @todo Below is the old method of switching to the console window326 // based on the process ID of the console process. It should go away327 // after the new (callback-based) method is fully tested.328 #if 0329 330 if (!canSwitchTo())331 return false;332 333 #if defined (Q_WS_WIN32)334 335 HWND hwnd = mWinId;336 337 /* if there are ownees (modal and modeless dialogs, etc), find the338 * topmost one */339 HWND hwndAbove = NULL;340 do341 {342 hwndAbove = GetNextWindow(hwnd, GW_HWNDPREV);343 HWND hwndOwner;344 if (hwndAbove != NULL &&345 ((hwndOwner = GetWindow(hwndAbove, GW_OWNER)) == hwnd ||346 hwndOwner == hwndAbove))347 hwnd = hwndAbove;348 else349 break;350 }351 while (1);352 353 /* first, check that the primary window is visible */354 if (IsIconic(mWinId))355 ShowWindow(mWinId, SW_RESTORE);356 else if (!IsWindowVisible(mWinId))357 ShowWindow(mWinId, SW_SHOW);358 359 #if 0360 LogFlowFunc(("mWinId=%08X hwnd=%08X\n", mWinId, hwnd));361 #endif362 363 /* then, activate the topmost in the group */364 AllowSetForegroundWindow(m_pid);365 SetForegroundWindow(hwnd);366 367 return true;368 369 #elif defined (Q_WS_X11)370 371 return false;372 373 #elif defined (Q_WS_MAC)374 375 ProcessSerialNumber psn;376 OSStatus rc = ::GetProcessForPID(m_pid, &psn);377 if (!rc)378 {379 rc = ::SetFrontProcess(&psn);380 381 if (!rc)382 {383 ShowHideProcess(&psn, true);384 return true;385 }386 }387 return false;388 389 #else390 391 return false;392 393 #endif394 395 #endif396 }397 35 398 36 /* UIVMItemModel class */ -
trunk/src/VBox/Frontends/VirtualBox/src/UIVMListView.h
r30062 r30691 2 2 * 3 3 * VBox frontends: Qt GUI ("VirtualBox"): 4 * UIVMItem , UIVMItemModel, UIVMListView, UIVMItemPainter class declarations4 * UIVMItemModel, UIVMListView, UIVMItemPainter class declarations 5 5 */ 6 6 … … 20 20 #define __UIVMListView_h__ 21 21 22 /* Self includes */ 22 23 #include "VBoxGlobal.h" 23 24 #include "QIListView.h" 25 #include "UIVMItem.h" 24 26 25 27 /* Qt includes */ 26 28 #include <QAbstractListModel> 27 #include <QDateTime>28 29 class VBoxSelectorWnd;30 31 class UIVMItem32 {33 public:34 35 UIVMItem(const CMachine &aMachine);36 virtual ~UIVMItem();37 38 CMachine machine() const { return m_machine; }39 40 QString name() const { return m_strName; }41 QIcon osIcon() const { return m_fAccessible ? vboxGlobal().vmGuestOSTypeIcon(m_strOSTypeId) : QPixmap(":/os_other.png"); }42 QString osTypeId() const { return m_strOSTypeId; }43 QString id() const { return m_strId; }44 45 QString sessionStateName() const;46 QIcon sessionStateIcon() const { return m_fAccessible ? vboxGlobal().toIcon(m_state) : QPixmap(":/state_aborted_16px.png"); }47 48 QString snapshotName() const { return m_strSnapshotName; }49 ULONG snapshotCount() const { return m_cSnaphot; }50 51 QString toolTipText() const;52 53 bool accessible() const { return m_fAccessible; }54 const CVirtualBoxErrorInfo &accessError() const { return m_accessError; }55 KMachineState state() const { return m_state; }56 KSessionState sessionState() const { return m_sessionState; }57 58 bool recache();59 60 bool canSwitchTo() const;61 bool switchTo();62 63 private:64 65 /* Private member vars */66 CMachine m_machine;67 68 /* Cached machine data (to minimize server requests) */69 QString m_strId;70 QString m_strSettingsFile;71 72 bool m_fAccessible;73 CVirtualBoxErrorInfo m_accessError;74 75 QString m_strName;76 QString m_strSnapshotName;77 KMachineState m_state;78 QDateTime m_lastStateChange;79 KSessionState m_sessionState;80 QString m_strOSTypeId;81 ULONG m_cSnaphot;82 83 ULONG m_pid;84 };85 86 /* Make the pointer of this class public to the QVariant framework */87 Q_DECLARE_METATYPE(UIVMItem *);88 29 89 30 class UIVMItemModel: public QAbstractListModel
Note:
See TracChangeset
for help on using the changeset viewer.