VirtualBox

Changeset 8159 in vbox


Ignore:
Timestamp:
Apr 18, 2008 4:01:43 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
29869
Message:

FE/Qt4: Replaced VBoxListBox with QListView/Model/Delegate. Added some kind of Leopard style to
the Mac OS X version of the QListView.

Location:
trunk/src/VBox/Frontends/VirtualBox4
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox4/include/VBoxDefs.h

    r8155 r8159  
    66
    77/*
    8  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     8 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    172172};
    173173
     174#define MAC_LEOPARD_STYLE defined(Q_WS_MAC) && (QT_VERSION >= 0x040300)
     175
    174176#endif // __VBoxDefs_h__
    175177
  • trunk/src/VBox/Frontends/VirtualBox4/include/VBoxSelectorWnd.h

    r8155 r8159  
    66
    77/*
    8  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     8 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    3131#include <QMainWindow>
    3232
    33 class VBoxVMListBox;
    3433class VBoxSnapshotsWgt;
    3534class VBoxVMDetailsView;
    3635class VBoxVMDescriptionPage;
    3736class VBoxVMLogViewer;
     37class VBoxVMListView;
     38class VBoxVMModel;
     39class VBoxVMItem;
    3840
    3941class QTabWidget;
    40 class Q3ListBoxItem;
     42class QListView;
    4143class QEvent;
    4244class QUuid;
    4345
    44 class VBoxSelectorWnd : public QMainWindow
     46class VBoxSelectorWnd: public QMainWindow
    4547{
    4648    Q_OBJECT
     
    7678                                          bool aDescription);
    7779
    78     void showContextMenu (Q3ListBoxItem *, const QPoint &);
     80    void showContextMenu (VBoxVMItem *aItem, const QPoint &aPoint);
    7981
    8082protected:
     
    9193private slots:
    9294
    93     void vmListBoxCurrentChanged (bool aRefreshDetails = true,
    94                                   bool aRefreshSnapshots = true,
    95                                   bool aRefreshDescription = true);
     95    void vmListViewCurrentChanged (bool aRefreshDetails = true,
     96                                   bool aRefreshSnapshots = true,
     97                                   bool aRefreshDescription = true);
    9698
    9799    void mediaEnumStarted();
     
    133135    QAction *helpResetMessagesAction;
    134136
    135     /* widgets */
    136     VBoxVMListBox *vmListBox;
     137    /* The vm list view/model */
     138    VBoxVMListView *mVMListView;
     139    VBoxVMModel *mVMModel;
     140
     141    /* The right information widgets */
    137142    QTabWidget *vmTabWidget;
    138143    VBoxVMDetailsView *vmDetailsView;
  • trunk/src/VBox/Frontends/VirtualBox4/include/VBoxVMListBox.h

    r8155 r8159  
    22 *
    33 * VBox frontends: Qt GUI ("VirtualBox"):
    4  * VBoxVMListBox, VBoxVMListBoxItem class declarations
     4 * VBoxVMItem, VBoxVMModel, VBoxVMListView, VBoxVMItemPainter class declarations
    55 */
    66
    77/*
    8  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     8 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2424#define __VBoxVMListBox_h__
    2525
    26 #include "COMDefs.h"
    27 
    28 #include "VBoxSelectorWnd.h"
    2926#include "VBoxGlobal.h"
    30 
    31 #include <q3listbox.h>
    32 #include <qfont.h>
    33 #include <qdatetime.h>
    34 //Added by qt3to4:
    35 #include <QFocusEvent>
    36 
    37 struct QUuid;
    38 class QColorGroup;
    39 
    40 class VBoxVMListBoxTip;
    41 class VBoxVMListBoxItem;
    42 
    43 /**
    44  *
    45  *  The VBoxVMListBox class is a visual representation of the list of
    46  *  existing VMs in the VBox GUI.
    47  *
    48  *  Every item in the list box is an instance of the VBoxVMListBoxItem
    49  *  class.
    50  */
    51 class VBoxVMListBox : public Q3ListBox
    52 {
    53     Q_OBJECT
    54 
    55 public:
    56 
    57     VBoxVMListBox (QWidget *aParent = 0, const char *aName = NULL,
    58                    Qt::WFlags aFlags = 0);
    59 
    60     virtual ~VBoxVMListBox();
    61 
    62     QFont nameFont() const { return mNameFont; }
    63 
    64     QFont shotFont() const { return mShotFont; }
    65 
    66     QFont stateFont (KSessionState aS) const
    67     {
    68         return aS == KSessionState_Closed ? font() : mStateBusyFont;
    69     }
    70 
    71     int margin() const { return mMargin; }
    72 
    73     void refresh();
    74     void refresh (const QUuid &aID);
    75 
    76     VBoxVMListBoxItem *item (const QUuid &aID);
    77 
    78     const QColorGroup &activeColorGroup() const;
    79 
    80 protected:
    81 
    82     virtual void focusInEvent (QFocusEvent *aE);
    83     virtual void focusOutEvent (QFocusEvent *aE);
    84 
    85 private:
    86 
    87     CVirtualBox mVBox;
    88     QFont mNameFont;
    89     QFont mShotFont;
    90     QFont mStateBusyFont;
    91     int mMargin;
    92 
    93     VBoxVMListBoxTip *mToolTip;
    94     bool mGaveFocusToPopup;
    95 };
    96 
    97 /**
    98  *
    99  *  The VBoxVMListBoxItem class is a visual representation of the virtual
    100  *  machine in the VBoxVMListBox widget.
    101  *
    102  *  It holds a CMachine instance (passed to the constructor) to
    103  *  get an access to various VM data.
    104  */
    105 class VBoxVMListBoxItem : public Q3ListBoxItem
    106 {
    107 public:
    108 
    109     VBoxVMListBoxItem (VBoxVMListBox *aLB, const CMachine &aM);
    110     virtual ~VBoxVMListBoxItem();
    111 
    112     QString text() const { return mName; }
    113 
    114     VBoxVMListBox *vmListBox() const
    115     {
    116         return static_cast <VBoxVMListBox *> (listBox());
    117     }
     27#include "VBoxDefs.h"
     28
     29/* Qt includes */
     30#include <QAbstractListModel>
     31#include <QListView>
     32#include <QItemDelegate>
     33
     34class VBoxVMItem
     35{
     36public:
     37    VBoxVMItem (const CMachine &aM);
     38    virtual ~VBoxVMItem();
    11839
    11940    CMachine machine() const { return mMachine; }
    120     void setMachine (const CMachine &aM);
    121 
    122     void recache();
     41
     42    QString name() const { return mName; }
     43    QIcon osIcon() const { return mAccessible ? vboxGlobal().vmGuestOSTypeIcon (mOSTypeId) :QPixmap (":/os_unknown.png"); }
     44    QUuid id() const { return mId; }
     45   
     46    QString sessionStateName() const { return mAccessible ? vboxGlobal().toString (mState) : QObject::tr ("Inaccessible"); }
     47    QIcon sessionStateIcon() const { return mAccessible ? vboxGlobal().toIcon (mState) : QPixmap (":/state_aborted_16px.png"); }
     48
     49    QString snapshotName() const { return mSnapshotName; }
     50    ULONG snapshotCount() const { return mSnapshotCount; }
    12351
    12452    QString toolTipText() const;
    12553
    126     int height (const Q3ListBox *) const;
    127     int width (const Q3ListBox *) const;
    128 
    129     QUuid id() const { return mId; }
    13054    bool accessible() const { return mAccessible; }
    13155    const CVirtualBoxErrorInfo &accessError() const { return mAccessError; }
    132     QString name() const { return mName; }
    13356    KMachineState state() const { return mState; }
    13457    KSessionState sessionState() const { return mSessionState; }
    135     ULONG snapshotCount() const { return mSnapshotCount; }
    136 
    137     /// @todo see comments in #switchTo() in VBoxVMListBox.cpp
    138 #if 0
    139     bool canSwitchTo() const { return mWinId != (WId) ~0; }
    140 #endif
     58
     59    bool recache();
     60
    14161    bool canSwitchTo() const;
    14262    bool switchTo();
    14363
    144 protected:
    145 
    146     void paint (QPainter *aP);
    147 
    14864private:
    14965
     66    /* Private member vars */
    15067    CMachine mMachine;
    15168
    152     /* cached machine data (to minimize server requests) */
    153 
     69    /* Cached machine data (to minimize server requests) */
    15470    QUuid mId;
    15571    QString mSettingsFile;
     
    16783
    16884    ULONG mPid;
    169     /// @todo see comments in #switchTo() in VBoxVMListBox.cpp
    170 #if 0
    171     WId mWinId;
    172 #endif
    17385};
    17486
     87/* Make the pointer of this class public to the QVariant framework */
     88Q_DECLARE_METATYPE(VBoxVMItem *);
     89
     90class VBoxVMModel: public QAbstractListModel
     91{
     92    Q_OBJECT;
     93
     94public:
     95    enum { SnapShotDisplayRole = Qt::UserRole,
     96           SnapShotFontRole,
     97           SessionStateDisplayRole,
     98           SessionStateDecorationRole,
     99           SessionStateFontRole,
     100           VBoxVMItemPtrRole };
     101
     102    VBoxVMModel(QObject *aParent = 0)
     103        :QAbstractListModel (aParent) { refresh(); }
     104
     105    void addItem (VBoxVMItem *aItem);
     106    void removeItem (VBoxVMItem *aItem);
     107    void refreshItem (VBoxVMItem *aItem);
     108
     109    void itemChanged (VBoxVMItem *aItem);
     110
     111    void refresh();
     112
     113    VBoxVMItem *itemById (const QUuid &aId) const;
     114    QModelIndex indexById (const QUuid &aId) const;
     115
     116    int rowById (const QUuid &aId) const;;
     117
     118    void sort (Qt::SortOrder aOrder = Qt::AscendingOrder) { sort (0, aOrder); }
     119
     120    /* The following are necessary model implementations */
     121    void sort (int aColumn, Qt::SortOrder aOrder = Qt::AscendingOrder);
     122
     123    int rowCount (const QModelIndex &aParent = QModelIndex()) const;
     124
     125    QVariant data (const QModelIndex &aIndex, int aRole) const;
     126    QVariant headerData (int aSection, Qt::Orientation aOrientation,
     127                         int aRole = Qt::DisplayRole) const;
     128
     129    bool removeRows (int aRow, int aCount, const QModelIndex &aParent = QModelIndex());
     130
     131private:
     132    static bool VBoxVMItemNameCompareLessThan (VBoxVMItem* aItem1, VBoxVMItem* aItem2);
     133    static bool VBoxVMItemNameCompareGreaterThan (VBoxVMItem* aItem1, VBoxVMItem* aItem2);
     134
     135    /* Private member vars */
     136    QList<VBoxVMItem *> mVMItemList;
     137};
     138
     139class VBoxVMListView: public QListView
     140{
     141    Q_OBJECT;
     142
     143public:
     144    VBoxVMListView (QWidget *aParent = 0);
     145
     146    void selectItemByRow (int row);
     147    void selectItemById (const QUuid &aID);
     148    void ensureSomeRowSelected (int aRowHint);
     149    VBoxVMItem * selectedItem() const;
     150
     151    void ensureCurrentVisible();
     152
     153signals:
     154    void currentChanged();
     155    void activated();
     156    void contextMenuRequested (VBoxVMItem *aItem, const QPoint &aPoint);
     157
     158protected 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    void focusChanged (QWidget *aOld, QWidget *aNow);
     163
     164protected:
     165    void mousePressEvent (QMouseEvent *aEvent);
     166    bool selectCurrent();
     167};
     168
     169class VBoxVMItemPainter: public QItemDelegate
     170{
     171public:
     172    VBoxVMItemPainter (QObject *aParent = 0)
     173      : QItemDelegate (aParent), mMargin (8), mSpacing (mMargin * 3 / 2) {}
     174
     175    QSize sizeHint (const QStyleOptionViewItem &aOption,
     176                    const QModelIndex &aIndex) const;
     177
     178    void paint (QPainter *aPainter, const QStyleOptionViewItem &aOption,
     179                const QModelIndex &aIndex) const;
     180
     181protected:
     182    void drawBackground (QPainter *aPainter, const QStyleOptionViewItem &aOption,
     183                         const QModelIndex &aIndex) const;
     184
     185private:
     186    inline QFontMetrics fontMetric (const QModelIndex &aIndex, int aRole) const { return QFontMetrics (aIndex.data (aRole).value<QFont>()); }
     187    inline QIcon::Mode iconMode (QStyle::State aState) const
     188    {
     189        if (!(aState & QStyle::State_Enabled))
     190            return QIcon::Disabled;
     191        if (aState & QStyle::State_Selected)
     192            return QIcon::Selected;
     193        return QIcon::Normal;
     194    }
     195    inline QIcon::State iconState (QStyle::State aState) const { return aState & QStyle::State_Open ? QIcon::On : QIcon::Off; }
     196
     197    QRect rect (const QStyleOptionViewItem &aOption,
     198                const QModelIndex &aIndex, int aRole) const;
     199
     200    void calcLayout (const QModelIndex &aIndex,
     201                     QRect *aOSType, QRect *aVMName, QRect *aShot,
     202                     QRect *aStateIcon, QRect *aState) const;
     203
     204    /* Private member vars */
     205    int mMargin;
     206    int mSpacing;
     207};
     208
    175209#endif // __VBoxVMListItem_h__
  • trunk/src/VBox/Frontends/VirtualBox4/src/VBoxSelectorWnd.cpp

    r8155 r8159  
    66
    77/*
    8  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     8 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    219219    ~VBoxVMDescriptionPage() {}
    220220
    221     void setMachineItem (VBoxVMListBoxItem *aItem);
     221    void setMachineItem (VBoxVMItem *aItem);
    222222
    223223    void languageChange();
     
    230230private:
    231231
    232     VBoxVMListBoxItem *mItem;
     232    VBoxVMItem *mItem;
    233233
    234234    VBoxSelectorWnd *mParent;
     
    298298 * unnecessary RPC calls.
    299299 */
    300 void VBoxVMDescriptionPage::setMachineItem (VBoxVMListBoxItem *aItem)
     300void VBoxVMDescriptionPage::setMachineItem (VBoxVMItem *aItem)
    301301{
    302302    mItem = aItem;
     
    455455    QHBoxLayout *centralLayout =
    456456        new QHBoxLayout (centralWidget());
    457     centralLayout->setSpacing (9);
    458     VBoxGlobal::setLayoutMargin (centralLayout, 5);
    459457
    460458    /* left vertical box */
    461459    QVBoxLayout *leftVLayout = new QVBoxLayout ();
    462     leftVLayout->setSpacing (5);
    463460    /* right vertical box */
    464461    QVBoxLayout *rightVLayout = new QVBoxLayout ();
    465     rightVLayout->setSpacing (5);
    466     centralLayout->addLayout (leftVLayout, 3);
    467     centralLayout->addLayout (rightVLayout, 3);
     462    centralLayout->addLayout (leftVLayout, 1);
     463    centralLayout->addLayout (rightVLayout, 2);
    468464
    469465    /* VM list toolbar */
    470466    VBoxToolBar *vmTools = new VBoxToolBar (this);
    471 #if defined (Q_WS_MAC) && (QT_VERSION >= 0x040300)
     467#if MAC_LEOPARD_STYLE
    472468    /* Enable unified toolbars on Mac OS X. Available on Qt >= 4.3 */
    473469    setUnifiedTitleAndToolBarOnMac (true);
    474470    addToolBar (vmTools);
    475 #else
     471    /* No spacing/margin on the mac */
     472    VBoxGlobal::setLayoutMargin (centralLayout, 0);
     473    leftVLayout->setSpacing (0);
     474    rightVLayout->setSpacing (0);
     475#else /* MAC_LEOPARD_STYLE */
    476476    leftVLayout->addWidget(vmTools);
    477 #endif
    478 
    479     /* VM list box */
    480     vmListBox = new VBoxVMListBox ();
    481     leftVLayout->addWidget (vmListBox);
     477    centralLayout->setSpacing (9);
     478    VBoxGlobal::setLayoutMargin (centralLayout, 5);
     479    leftVLayout->setSpacing (5);
     480    rightVLayout->setSpacing (5);
     481#endif /* MAC_LEOPARD_STYLE */
     482
     483    /* VM list view */
     484    mVMListView = new VBoxVMListView();
     485    mVMModel = new VBoxVMModel();
     486    mVMListView->setModel (mVMModel);
     487
     488    leftVLayout->addWidget (mVMListView);
    482489
    483490    /* VM tab widget containing details and snapshots tabs */
     
    614621    }
    615622
     623    /* Reset to the first item */
     624    mVMListView->selectItemByRow (0);
    616625    /* restore the position of vm selector */
    617626    {
     
    619628        QString prevVMId = vbox.GetExtraData (VBoxDefs::GUI_LastVMSelected);
    620629
    621         VBoxVMListBoxItem *item = vmListBox->item (QUuid (prevVMId));
    622         if (item)
    623             vmListBox->setSelected (item, true);
     630        mVMListView->selectItemById (QUuid (prevVMId));
    624631    }
    625632
     
    653660             &vboxProblem(), SLOT (resetSuppressedMessages()));
    654661
    655     connect (vmListBox, SIGNAL (currentChanged(Q3ListBoxItem *)),
    656              this, SLOT (vmListBoxCurrentChanged()));
    657     connect (vmListBox, SIGNAL (selected (Q3ListBoxItem *)),
     662    connect (mVMListView, SIGNAL (currentChanged()),
     663             this, SLOT (vmListViewCurrentChanged()));
     664    connect (mVMListView, SIGNAL (activated ()),
    658665             this, SLOT (vmStart()));
    659     connect (vmListBox, SIGNAL (contextMenuRequested (Q3ListBoxItem *, const QPoint &)),
    660              this, SLOT (showContextMenu (Q3ListBoxItem *, const QPoint &)));
     666    connect (mVMListView, SIGNAL (contextMenuRequested (VBoxVMItem *, const QPoint &)),
     667             this, SLOT (showContextMenu (VBoxVMItem *, const QPoint &)));
    661668
    662669    connect (vmDetailsView, SIGNAL (linkClicked (const QString &)),
     
    682689
    683690    /* bring the VM list to the focus */
    684     vmListBox->setFocus();
     691    mVMListView->setFocus();
    685692}
    686693
     
    702709    /* save vm selector position */
    703710    {
    704         Q3ListBoxItem *item = vmListBox->selectedItem();
     711        VBoxVMItem *item = mVMListView->selectedItem();
    705712        QString curVMId = item ?
    706             QString (static_cast<VBoxVMListBoxItem*> (item)->id()) :
     713            QString (item->id()) :
    707714            QString::null;
    708715        vbox.SetExtraData (VBoxDefs::GUI_LastVMSelected, curVMId);
     
    755762
    756763        /* wait until the list is updated by OnMachineRegistered() */
    757         VBoxVMListBoxItem *item = 0;
    758         while (!item)
     764        QModelIndex index;
     765        while (!index.isValid())
    759766        {
    760767            qApp->processEvents();
    761             item = vmListBox->item (m.GetId());
    762         }
    763         /*
    764          *  we must use setSelected() instead of setCurrentItem() below because
    765          *  setCurrentItem() does nothing after the first item has been added
    766          *  to the list (since it is already the current one), but we still
    767          *  need currentChanged() to be emitted to sync things (QListBox doesn't
    768          *  emit currentChanged() when the current item index changes from -1
    769          *  to 0, i.e. when the first item is being added -- seems to be a Qt
    770          *  bug).
    771          */
    772         vmListBox->setSelected (item, true);
     768            index = mVMModel->indexById (m.GetId());
     769        }
     770        mVMListView->setCurrentIndex (index);
    773771    }
    774772}
     
    791789    }
    792790
    793     VBoxVMListBoxItem *item = (VBoxVMListBoxItem *) vmListBox->selectedItem();
     791    VBoxVMItem *item = mVMListView->selectedItem();
    794792
    795793    AssertMsgReturnVoid (item, ("Item must be always selected here"));
     
    818816            {
    819817                if (oldName.compare (m.GetName()))
    820                     vmListBox->sort();
     818                    mVMModel->sort();
    821819            }
    822820            else
     
    831829    }
    832830
    833     vmListBox->setFocus();
     831    mVMListView->setFocus();
    834832
    835833    session.Close();
     
    838836void VBoxSelectorWnd::vmDelete()
    839837{
    840     VBoxVMListBoxItem *item = (VBoxVMListBoxItem *) vmListBox->selectedItem();
     838    VBoxVMItem *item = mVMListView->selectedItem();
    841839
    842840    AssertMsgReturn (item, ("Item must be always selected here"), (void) 0);
     
    884882                machine.DeleteSettings();
    885883                /* remove the item shortly: cmachine it refers to is no longer valid! */
    886                 vmListBox->removeItem (vmListBox->index (item));
     884#warning "port me: check this"
     885                int row = mVMModel->rowById (item->id());
     886                mVMModel->removeItem (item);
     887                mVMListView->ensureSomeRowSelected (row);
    887888            }
    888889            if (!vbox.isOk() || !machine.isOk())
     
    894895void VBoxSelectorWnd::vmStart()
    895896{
    896     /* we always get here when vmListBox emits the selected() signal,
     897    /* we always get here when mVMListView emits the activated() signal,
    897898     * so we must explicitly check if the action is enabled or not. */
    898899    if (!vmStartAction->isEnabled())
    899900        return;
    900901
    901     VBoxVMListBoxItem *item = (VBoxVMListBoxItem *) vmListBox->selectedItem();
     902    VBoxVMItem *item = mVMListView->selectedItem();
    902903
    903904    AssertMsg (item, ("Item must be always selected here"));
     
    971972void VBoxSelectorWnd::vmDiscard()
    972973{
    973     VBoxVMListBoxItem *item = (VBoxVMListBoxItem *) vmListBox->selectedItem();
     974    VBoxVMItem *item = mVMListView->selectedItem();
    974975
    975976    AssertMsgReturn (item, ("Item must be always selected here"), (void) 0);
     
    10051006void VBoxSelectorWnd::vmPause (bool aPause)
    10061007{
    1007     VBoxVMListBoxItem *item = (VBoxVMListBoxItem *) vmListBox->selectedItem();
     1008    VBoxVMItem *item = mVMListView->selectedItem();
    10081009
    10091010    AssertMsgReturn (item, ("Item must be always selected here"), (void) 0);
     
    10361037void VBoxSelectorWnd::vmRefresh()
    10371038{
    1038     VBoxVMListBoxItem *item = (VBoxVMListBoxItem *) vmListBox->selectedItem();
     1039    VBoxVMItem *item = mVMListView->selectedItem();
    10391040
    10401041    AssertMsgReturn (item, ("Item must be always selected here"), (void) 0);
     
    10481049void VBoxSelectorWnd::vmShowLogs()
    10491050{
    1050     VBoxVMListBoxItem *item = (VBoxVMListBoxItem *) vmListBox->selectedItem();
     1051    VBoxVMItem *item = mVMListView->selectedItem();
    10511052    CMachine machine = item->machine();
    10521053    VBoxVMLogViewer::createLogViewer (machine);
     
    10551056void VBoxSelectorWnd::refreshVMList()
    10561057{
    1057     vmListBox->refresh();
    1058     vmListBoxCurrentChanged();
     1058    mVMModel->refresh();
     1059    vmListViewCurrentChanged();
    10591060}
    10601061
     
    10631064                                                       bool aDescription)
    10641065{
    1065     vmListBox->refresh (aID);
    1066     VBoxVMListBoxItem *item = (VBoxVMListBoxItem *) vmListBox->selectedItem();
    1067     if (item && item->id() == aID)
    1068         vmListBoxCurrentChanged (aDetails, aSnapshots, aDescription);
    1069 }
    1070 
    1071 void VBoxSelectorWnd::showContextMenu (Q3ListBoxItem *aItem, const QPoint &aPoint)
     1066    VBoxVMItem *item = mVMModel->itemById (aID);
     1067    if (item)
     1068    {
     1069        mVMModel->refreshItem (item);
     1070        if (item && item->id() == aID)
     1071            vmListViewCurrentChanged (aDetails, aSnapshots, aDescription);
     1072    }
     1073}
     1074
     1075void VBoxSelectorWnd::showContextMenu (VBoxVMItem *aItem, const QPoint &aPoint)
    10721076{
    10731077    if (aItem)
     
    11311135    vmTabWidget->setTabText (vmTabWidget->indexOf (vmDetailsView), tr ("&Details"));
    11321136    /* note: Snapshots and Details tabs are changed dynamically by
    1133      * vmListBoxCurrentChanged() */
     1137     * vmListViewCurrentChanged() */
    11341138
    11351139    /* ensure the details and screenshot view are updated */
    1136     vmListBoxCurrentChanged();
     1140    vmListViewCurrentChanged();
    11371141
    11381142    fileDiskMgrAction->setText (tr ("Virtual &Disk Manager..."));
     
    11781182    vmDeleteAction->setStatusTip (tr ("Delete the selected virtual machine"));
    11791183
    1180     /* Note: vmStartAction text is set up in vmListBoxCurrentChanged() */
     1184    /* Note: vmStartAction text is set up in vmListViewCurrentChanged() */
    11811185
    11821186    vmDiscardAction->setText (tr ("D&iscard"));
     
    12251229/////////////////////////////////////////////////////////////////////////////
    12261230
    1227 void VBoxSelectorWnd::vmListBoxCurrentChanged (bool aRefreshDetails,
     1231void VBoxSelectorWnd::vmListViewCurrentChanged (bool aRefreshDetails,
    12281232                                               bool aRefreshSnapshots,
    12291233                                               bool aRefreshDescription)
    12301234{
    1231     if (!vmListBox->selectedItem() && vmListBox->currentItem() >= 0)
    1232     {
    1233         /* selected always follows current */
    1234         vmListBox->setSelected (vmListBox->currentItem(), true);
    1235     }
    1236 
    1237     vmListBox->ensureCurrentVisible();
    1238     VBoxVMListBoxItem *item = (VBoxVMListBoxItem *) vmListBox->selectedItem();
     1235    VBoxVMItem *item = mVMListView->selectedItem();
    12391236
    12401237    if (item && item->accessible())
     
    13951392{
    13961393    /* refresh the current details to pick up hard disk sizes */
    1397     vmListBoxCurrentChanged (true /* aRefreshDetails */);
     1394    vmListViewCurrentChanged (true /* aRefreshDetails */);
    13981395}
    13991396
     
    14011398{
    14021399    /* refresh the current details to pick up hard disk sizes */
    1403     vmListBoxCurrentChanged (true /* aRefreshDetails */);
     1400    vmListViewCurrentChanged (true /* aRefreshDetails */);
    14041401
    14051402    /* we warn about inaccessible media only once (after media emumeration
     
    14651462        if (!m.isNull())
    14661463        {
    1467             new VBoxVMListBoxItem (vmListBox, m);
    1468             vmListBox->sort();
     1464            mVMModel->addItem (new VBoxVMItem (m));
     1465            mVMModel->sort();
     1466            /* Make sure the description, ... pages are properly updated.
     1467             * Actualy we haven't call the next method, but unfortunately Qt
     1468             * seems buggy if the new item is on the same position as the
     1469             * previous one. So go on the safe side and call this by our self. */
     1470            vmListViewCurrentChanged();
    14691471        }
    14701472        /* m.isNull() is ok (theoretically, the machine could have been
     
    14731475    else
    14741476    {
    1475         VBoxVMListBoxItem *item = vmListBox->item (e.id);
     1477        VBoxVMItem *item = mVMModel->itemById (e.id);
    14761478        if (item)
    1477             vmListBox->removeItem (vmListBox->index (item));
     1479        {
     1480            int row = mVMModel->rowById (item->id());
     1481            mVMModel->removeItem (item);
     1482            mVMListView->ensureSomeRowSelected (row);
     1483        }
     1484
    14781485        /* item = 0 is ok (if we originated this event then the item
    14791486         * has been already removed) */
  • trunk/src/VBox/Frontends/VirtualBox4/src/VBoxVMListBox.cpp

    r8155 r8159  
    22 *
    33 * VBox frontends: Qt GUI ("VirtualBox"):
    4  * VBoxVMListItem class implementation
     4 * VBoxVMItem, VBoxVMModel, VBoxVMListView, VBoxVMItemPainter class implementation
    55 */
    66
    77/*
    8  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     8 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
    99 *
    1010 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2222
    2323#include "VBoxVMListBox.h"
    24 
    2524#include "VBoxProblemReporter.h"
    2625
    27 #include <qpainter.h>
    28 #include <qfontmetrics.h>
    29 #include <qdrawutil.h>
    30 #include <qtooltip.h>
    31 #include <qmetaobject.h>
    32 #include <qstyle.h>
    33 
    34 #include <qfileinfo.h>
    35 //Added by qt3to4:
    36 #include <QPixmap>
    37 #include <q3mimefactory.h>
    38 #include <QFocusEvent>
     26/* Qt includes */
     27#include <QPainter>
     28#include <QFileInfo>
    3929
    4030#if defined (Q_WS_MAC)
    4131# include <Carbon/Carbon.h>
     32# if MAC_LEOPARD_STYLE
     33#  include <qmacstyle_mac.h>
     34# endif /* MAC_LEOPARD_STYLE */
    4235#endif
    4336
     
    144137#endif
    145138
    146 ////////////////////////////////////////////////////////////////////////////////
    147 // VBoxVMListBoxItem class
    148 ////////////////////////////////////////////////////////////////////////////////
    149 
    150 #warning port me
    151 //class VBoxVMListBoxTip : public QToolTip
    152 //{
    153 //public:
    154 //
    155 //    VBoxVMListBoxTip (VBoxVMListBox *aLB, QToolTipGroup *aTG = 0)
    156 //        : QToolTip (aLB, aTG)
    157 //    {}
    158 //
    159 //    virtual ~VBoxVMListBoxTip()
    160 //    {
    161 //        remove (parentWidget());
    162 //    }
    163 //
    164 //    void maybeTip (const QPoint &aPnt);
    165 //};
    166 //
    167 //void VBoxVMListBoxTip::maybeTip (const QPoint &aPnt)
    168 //{
    169 //    const VBoxVMListBox *lb = static_cast <VBoxVMListBox *> (parentWidget());
    170 //
    171 //    VBoxVMListBoxItem *vmi = static_cast <VBoxVMListBoxItem *> (lb->itemAt (aPnt));
    172 //    if (!vmi)
    173 //        return;
    174 //
    175 //    if (parentWidget()->topLevelWidget()->inherits ("QMainWindow"))
    176 //    {
    177 //        /*
    178 //         *  Ensure the main window doesn't show the text from the previous
    179 //         *  tooltip in the status bar.
    180 //         */
    181 //        QToolTipGroup *toolTipGroup =
    182 //            (::qt_cast <Q3MainWindow *> (parentWidget()->topLevelWidget()))->
    183 //                toolTipGroup();
    184 //        if (toolTipGroup)
    185 //        {
    186 //            int index = toolTipGroup->metaObject()->findSignal("removeTip()", false);
    187 //            toolTipGroup->qt_emit (index, 0);
    188 //        }
    189 //    }
    190 //
    191 //    tip (lb->itemRect (vmi), vmi->toolTipText());
    192 //}
    193 
    194 ////////////////////////////////////////////////////////////////////////////////
    195 // VBoxVMListBox class
    196 ////////////////////////////////////////////////////////////////////////////////
    197 
    198 /**
    199  *  Creates a box with the list of all virtual machines in the
    200  *  VirtualBox installation.
    201  */
    202 VBoxVMListBox::
    203 VBoxVMListBox (QWidget *aParent /* = 0 */, const char *aName /* = NULL */,
    204                Qt::WFlags aFlags /* = 0 */)
    205     : Q3ListBox (aParent, aName, aFlags)
    206 {
    207     mVBox = vboxGlobal().virtualBox();
    208 
    209     mNameFont = QFont (font().family(), font().pointSize() + 1, QFont::Bold);
    210     mShotFont = QFont (font().family(), font().pointSize() + 1);
    211     mStateBusyFont = font();
    212     mStateBusyFont.setItalic (true);
    213 
    214     mMargin = QMAX (fontMetrics().width (' ') * 2, 8);
    215 
    216 #warning port me
    217 //    mToolTip = new VBoxVMListBoxTip (this);
    218 
    219     mGaveFocusToPopup = false;
    220 
    221     refresh();
    222 }
    223 
    224 VBoxVMListBox::~VBoxVMListBox()
    225 {
    226 #warning port me
    227 //    delete mToolTip;
     139VBoxVMItem::VBoxVMItem (const CMachine &aM)
     140    : mMachine (aM)
     141{
     142    recache();
     143}
     144
     145VBoxVMItem::~VBoxVMItem()
     146{
    228147}
    229148
     
    231150////////////////////////////////////////////////////////////////////////////////
    232151
    233 /**
    234  *  Refreshes the box contents by rereading the list of VM's using
    235  *  the IVirtualBox instance.
    236  */
    237 void VBoxVMListBox::refresh()
    238 {
    239     clear();
    240 
    241     CMachineVector vec = mVBox.GetMachines2();
    242     for (CMachineVector::ConstIterator m = vec.begin();
    243          m != vec.end(); ++ m)
    244         new VBoxVMListBoxItem (this, *m);
    245 
    246     sort();
    247     setCurrentItem (0);
    248 }
    249 
    250 /**
    251  *  Refreshes the item corresponding to the given UUID.
    252  */
    253 void VBoxVMListBox::refresh (const QUuid &aID)
    254 {
    255     for (uint i = 0; i < count(); i++)
    256     {
    257         VBoxVMListBoxItem *vmi = (VBoxVMListBoxItem *) Q3ListBox::item (i);
    258         if (vmi->id() == aID)
    259         {
    260             vmi->recache();
    261             /* we call triggerUpdate() instead of updateItem() to cause the
    262              * layout to be redone for the case when the item width changes */
    263             triggerUpdate (true);
    264             break;
    265         }
    266     }
    267 }
    268 
    269 /**
    270  *  Returns the list item with the given UUID.
    271  */
    272 VBoxVMListBoxItem *VBoxVMListBox::item (const QUuid &aID)
    273 {
    274     for (uint i = 0; i < count(); i++)
    275     {
    276         VBoxVMListBoxItem *vmi = (VBoxVMListBoxItem *) Q3ListBox::item (i);
    277         if (vmi->id() == aID)
    278             return vmi;
    279     }
    280     return 0;
    281 }
    282 
    283 /**
    284  *  Returns the color group QListBox uses to prepare a place for painting
    285  *  a list box item (for example, to draw the highlighted rectangle of the
    286  *  currently selected item, etc.). Useful in item's QListBoxItem::paint()
    287  *  reimplementations to select correct colors that will contrast with the
    288  *  item rectangle.
    289  */
    290 const QColorGroup &VBoxVMListBox::activeColorGroup() const
    291 {
    292     /* Too bad QListBox doesn't allow to determine what color group it uses
    293      * to draw the item's rectangle before calling its paint() method. Not
    294      * knowing that, we cannot choose correct colors that will contrast with
    295      * that rectangle. So, we have to use the logic of QListBox itself.
    296      * Here is a modified extract from qlistbox.cpp: */
    297 
    298 #warning port me
    299 //    bool drawActiveSelection =
    300 //        !style().styleHint (QStyle::SH_ItemView_ChangeHighlightOnFocus, this) ||
    301 //        hasFocus() ||
    302 //        mGaveFocusToPopup;
    303 //
    304 //    return (drawActiveSelection ? colorGroup() : palette().inactive());
    305     return colorGroup();
    306 }
    307 
    308 // protected members
    309 ////////////////////////////////////////////////////////////////////////////////
    310 
    311 void VBoxVMListBox::focusInEvent (QFocusEvent *aE)
    312 {
    313     mGaveFocusToPopup = false;
    314     Q3ListBox::focusInEvent (aE);
    315 }
    316 
    317 void VBoxVMListBox::focusOutEvent (QFocusEvent *aE)
    318 {
    319     /* A modified extract from qlistbox.cpp (see #activeColorGroup()): */
    320     mGaveFocusToPopup =
    321 #warning port me: check this
    322         aE->reason() == QFocusEvent::Popup ||
    323 //        QFocusEvent::reason() == QFocusEvent::Popup ||
    324         (qApp->focusWidget() && qApp->focusWidget()->inherits ("QMenuBar"));
    325     Q3ListBox::focusOutEvent (aE);
    326 }
    327 
    328 // private members
    329 ////////////////////////////////////////////////////////////////////////////////
    330 
    331 ////////////////////////////////////////////////////////////////////////////////
    332 // VBoxVMListBoxItem class
    333 ////////////////////////////////////////////////////////////////////////////////
    334 
    335 VBoxVMListBoxItem::VBoxVMListBoxItem (VBoxVMListBox *aLB, const CMachine &aM)
    336     : Q3ListBoxItem (aLB), mMachine (aM)
    337 {
    338     recache();
    339 }
    340 
    341 VBoxVMListBoxItem::~VBoxVMListBoxItem()
    342 {
    343 }
    344 
    345 // public members
    346 ////////////////////////////////////////////////////////////////////////////////
    347 
    348 void VBoxVMListBoxItem::setMachine (const CMachine &aM)
    349 {
    350     Assert (!aM.isNull());
    351 
    352     mMachine = aM;
    353     recache();
    354     vmListBox()->triggerUpdate (true);
    355 }
    356 
    357 void VBoxVMListBoxItem::recache()
    358 {
    359     bool needsResort = true;
    360 
    361     mId = mMachine.GetId();
    362     mSettingsFile = mMachine.GetSettingsFilePath();
    363 
    364     mAccessible = mMachine.GetAccessible();
    365     if (mAccessible)
    366     {
    367         QString name = mMachine.GetName();
    368         CSnapshot snp = mMachine.GetCurrentSnapshot();
    369         mSnapshotName = snp.isNull() ? QString::null : snp.GetName();
    370         needsResort = name != mName;
    371         mName = name;
    372 
    373         mState = mMachine.GetState();
    374         mLastStateChange.setTime_t (mMachine.GetLastStateChange() / 1000);
    375         mSessionState = mMachine.GetSessionState();
    376         mOSTypeId = mMachine.GetOSTypeId();
    377         mSnapshotCount = mMachine.GetSnapshotCount();
    378 
    379         if (mState >= KMachineState_Running)
    380         {
    381             mPid = mMachine.GetSessionPid();
    382     /// @todo Remove. See @c todo in #switchTo() below.
    383 #if 0
    384             mWinId = FindWindowIdFromPid (mPid);
    385 #endif
    386         }
    387         else
    388         {
    389             mPid = (ULONG) ~0;
    390     /// @todo Remove. See @c todo in #switchTo() below.
    391 #if 0
    392             mWinId = (WId) ~0;
    393 #endif
    394         }
    395     }
    396     else
    397     {
    398         mAccessError = mMachine.GetAccessError();
    399 
    400         /* this should be in sync with
    401          * VBoxProblemReporter::confirmMachineDeletion() */
    402         QFileInfo fi (mSettingsFile);
    403         QString name = fi.extension().lower() == "xml" ?
    404                        fi.baseName (true) : fi.fileName();
    405         needsResort = name != mName;
    406         mName = name;
    407         mState = KMachineState_Null;
    408         mSessionState = KSessionState_Null;
    409         mLastStateChange = QDateTime::currentDateTime();
    410         mOSTypeId = QString::null;
    411         mSnapshotCount = 0;
    412 
    413         mPid = (ULONG) ~0;
    414     /// @todo Remove. See @c todo in #switchTo() below.
    415 #if 0
    416         mWinId = (WId) ~0;
    417 #endif
    418     }
    419 
    420     if (needsResort)
    421         vmListBox()->sort();
    422 }
    423 
    424 QString VBoxVMListBoxItem::toolTipText() const
     152QString VBoxVMItem::toolTipText() const
    425153{
    426154    QString dateTime = (mLastStateChange.date() == QDate::currentDate()) ?
     
    435163        if (!mSnapshotName.isNull())
    436164            toolTip += QString (" (%1)").arg (mSnapshotName);
    437         toolTip = QString (VBoxVMListBox::tr (
     165        toolTip = QString (QObject::tr (
    438166            "<nobr>%1<br></nobr>"
    439167            "<nobr>%2 since %3</nobr><br>"
     
    447175    else
    448176    {
    449         toolTip = QString (VBoxVMListBox::tr (
     177        toolTip = QString (QObject::tr (
    450178            "<nobr><b>%1</b><br></nobr>"
    451179            "<nobr>Inaccessible since %2</nobr>",
     
    458186}
    459187
    460 int VBoxVMListBoxItem::width (const Q3ListBox *) const
    461 {
    462     /* see the picture below for dimensions */
    463 
    464     const VBoxVMListBox *lb = vmListBox();
    465 
    466     QFontMetrics fmName = QFontMetrics (lb->nameFont());
    467     QFontMetrics fmShot = QFontMetrics (lb->shotFont());
    468     QFontMetrics fmState = QFontMetrics (lb->stateFont (mSessionState));
    469     const int marg = lb->margin();
    470 
    471     QPixmap pmOSType;
    472     QPixmap pmState;
    473     QString strState;
    474 
     188bool VBoxVMItem::recache()
     189{
     190    bool needsResort = true;
     191
     192    mId = mMachine.GetId();
     193    mSettingsFile = mMachine.GetSettingsFilePath();
     194
     195    mAccessible = mMachine.GetAccessible();
    475196    if (mAccessible)
    476197    {
    477         pmOSType = vboxGlobal().vmGuestOSTypeIcon (mOSTypeId);
    478         pmState = vboxGlobal().toIcon (mState);
    479         strState = vboxGlobal().toString (mState);
     198        QString name = mMachine.GetName();
     199        CSnapshot snp = mMachine.GetCurrentSnapshot();
     200        mSnapshotName = snp.isNull() ? QString::null : snp.GetName();
     201        needsResort = name != mName;
     202        mName = name;
     203
     204        mState = mMachine.GetState();
     205        mLastStateChange.setTime_t (mMachine.GetLastStateChange() / 1000);
     206        mSessionState = mMachine.GetSessionState();
     207        mOSTypeId = mMachine.GetOSTypeId();
     208        mSnapshotCount = mMachine.GetSnapshotCount();
     209
     210        if (mState >= KMachineState_Running)
     211        {
     212            mPid = mMachine.GetSessionPid();
     213    /// @todo Remove. See @c todo in #switchTo() below.
     214#if 0
     215            mWinId = FindWindowIdFromPid (mPid);
     216#endif
     217        }
     218        else
     219        {
     220            mPid = (ULONG) ~0;
     221    /// @todo Remove. See @c todo in #switchTo() below.
     222#if 0
     223            mWinId = (WId) ~0;
     224#endif
     225        }
    480226    }
    481227    else
    482228    {
    483         /// @todo (r=dmik) temporary
    484         pmOSType = QPixmap (":/os_unknown.png");
    485         pmState = QPixmap (":/state_aborted_16px.png");
    486         strState = VBoxVMListBox::tr ("Inaccessible");
    487     }
    488 
    489     int nameWidth = fmName.width (mName);
    490     if (!mSnapshotName.isNull())
    491         nameWidth += fmShot.width (QString (" (%1)").arg (mSnapshotName));
    492     int stateWidth = pmState.width() + fmState.width (' ') +
    493                      fmState.width (strState);
    494 
    495     return marg + pmOSType.width() + marg * 3 / 2 +
    496            QMAX (nameWidth, stateWidth) + marg;
    497 }
    498 
    499 int VBoxVMListBoxItem::height (const Q3ListBox *) const
    500 {
    501     /* see the picture below for dimensions */
    502 
    503     const VBoxVMListBox *lb = vmListBox();
    504 
    505     QFontMetrics fmName = QFontMetrics (lb->nameFont());
    506     QFontMetrics fmState = QFontMetrics (lb->stateFont (mSessionState));
    507     const int marg = lb->margin();
    508 
    509     QPixmap pmOSType;
    510     QPixmap pmState;
    511 
    512     if (mAccessible)
    513     {
    514         pmOSType = vboxGlobal().vmGuestOSTypeIcon (mOSTypeId);
    515         pmState = vboxGlobal().toIcon (mState);
    516     }
    517     else
    518     {
    519         /// @todo (r=dmik) temporary
    520         pmOSType = QPixmap (":/os_unknown.png");
    521         pmState = QPixmap (":/state_aborted_16px.png");
    522     }
    523 
    524     int strHeight = fmName.lineSpacing() +
    525                     QMAX (pmState.height(), fmState.height());
    526 
    527     return marg + QMAX (pmOSType.height(), strHeight) + marg;
     229        mAccessError = mMachine.GetAccessError();
     230
     231        /* this should be in sync with
     232         * VBoxProblemReporter::confirmMachineDeletion() */
     233        QFileInfo fi (mSettingsFile);
     234        QString name = fi.completeSuffix().toLower() == "xml" ?
     235                       fi.completeBaseName() : fi.fileName();
     236        needsResort = name != mName;
     237        mName = name;
     238        mState = KMachineState_Null;
     239        mSessionState = KSessionState_Null;
     240        mLastStateChange = QDateTime::currentDateTime();
     241        mOSTypeId = QString::null;
     242        mSnapshotCount = 0;
     243
     244        mPid = (ULONG) ~0;
     245    /// @todo Remove. See @c todo in #switchTo() below.
     246#if 0
     247        mWinId = (WId) ~0;
     248#endif
     249    }
     250
     251    return needsResort;
    528252}
    529253
     
    532256 * foreground, and @a false otherwise.
    533257 */
    534 bool VBoxVMListBoxItem::canSwitchTo() const
     258bool VBoxVMItem::canSwitchTo() const
    535259{
    536260    return const_cast <CMachine &> (mMachine).CanShowConsoleWindow();
     
    547271 * @return true if successfully switched and false otherwise.
    548272 */
    549 bool VBoxVMListBoxItem::switchTo()
     273bool VBoxVMItem::switchTo()
    550274{
    551275#ifdef Q_WS_MAC
     
    659383}
    660384
    661 // protected members
    662 ////////////////////////////////////////////////////////////////////////////////
    663 
     385/* VBoxVMModel class */
     386
     387void VBoxVMModel::addItem (VBoxVMItem *aItem)
     388{
     389    Assert (aItem);
     390    int row = mVMItemList.count();
     391    emit layoutAboutToBeChanged();
     392    beginInsertRows (QModelIndex(), row, row);
     393    mVMItemList << aItem;
     394    endInsertRows();
     395    refreshItem (aItem);
     396}
     397
     398void VBoxVMModel::removeItem (VBoxVMItem *aItem)
     399{
     400    Assert (aItem);
     401    int row = mVMItemList.indexOf (aItem);
     402    removeRows (row, 1);
     403}
     404
     405bool VBoxVMModel::removeRows (int aRow, int aCount, const QModelIndex &aParent /* = QModelIndex() */)
     406{
     407    emit layoutAboutToBeChanged();
     408    beginRemoveRows (aParent, aRow, aRow + aCount);
     409    mVMItemList.erase (mVMItemList.begin() + aRow, mVMItemList.begin() + aRow + aCount);
     410    endRemoveRows();
     411    emit layoutChanged();
     412    return true;
     413}
     414
     415/**
     416 *  Refreshes the item corresponding to the given UUID.
     417 */
     418void VBoxVMModel::refreshItem (VBoxVMItem *aItem)
     419{
     420    Assert (aItem);
     421    if (aItem->recache())
     422        sort();
     423    itemChanged (aItem);
     424}
     425
     426void VBoxVMModel::itemChanged (VBoxVMItem *aItem)
     427{
     428    Assert (aItem);
     429    int row = mVMItemList.indexOf (aItem);
     430    /* Emit an layout change signal for the case some dimensions of the item
     431     * has changed also. */
     432    emit layoutChanged();
     433    /* Emit an data changed signal. */
     434    emit dataChanged (index (row), index (row));
     435}
     436
     437/**
     438 *  Refreshes the model contents by rereading the list of VM's using the
     439 *  IVirtualBox instance.
     440 */
     441void VBoxVMModel::refresh()
     442{
     443    CVirtualBox vbox = vboxGlobal().virtualBox();
     444    CMachineVector vec = vbox.GetMachines2();
     445    for (CMachineVector::ConstIterator m = vec.begin();
     446         m != vec.end(); ++ m)
     447        addItem(new VBoxVMItem (*m));
     448
     449    sort();
     450}
     451
     452/**
     453 *  Returns the list item with the given UUID.
     454 */
     455VBoxVMItem *VBoxVMModel::itemById (const QUuid &aId) const
     456{
     457    foreach (VBoxVMItem *item, mVMItemList)
     458        if (item->id() == aId)
     459            return item;
     460    return NULL;
     461}
     462
     463QModelIndex VBoxVMModel::indexById (const QUuid &aId) const
     464{
     465    int row = rowById (aId);
     466    if (row >= 0)
     467        return index (row);
     468    else
     469        return QModelIndex();
     470}
     471
     472int VBoxVMModel::rowById (const QUuid &aId) const
     473{
     474    for (int i=0; i < mVMItemList.count(); ++i)
     475    {
     476        VBoxVMItem *item = mVMItemList.at (i);
     477        if (item->id() == aId)
     478            return i;
     479    }
     480    return -1;
     481}
     482
     483void VBoxVMModel::sort (int /* aColumn */, Qt::SortOrder aOrder /* = Qt::AscendingOrder */)
     484{
     485    emit layoutAboutToBeChanged();
     486    switch (aOrder)
     487    {
     488        case Qt::AscendingOrder: qSort (mVMItemList.begin(), mVMItemList.end(), VBoxVMItemNameCompareLessThan); break;
     489        case Qt::DescendingOrder: qSort (mVMItemList.begin(), mVMItemList.end(), VBoxVMItemNameCompareGreaterThan); break;
     490    }
     491    emit layoutChanged();
     492}
     493
     494int VBoxVMModel::rowCount(const QModelIndex & /* aParent = QModelIndex() */) const
     495{
     496    return mVMItemList.count();
     497}
     498
     499QVariant VBoxVMModel::data(const QModelIndex &aIndex, int aRole) const
     500{
     501    if (!aIndex.isValid())
     502        return QVariant();
     503
     504    if (aIndex.row() >= mVMItemList.size())
     505        return QVariant();
     506
     507    QVariant v;
     508    switch (aRole)
     509    {
     510        case Qt::DisplayRole:
     511            {
     512                v = mVMItemList.at (aIndex.row())->name();
     513                break;
     514            }
     515        case Qt::DecorationRole:
     516            {
     517                v = mVMItemList.at (aIndex.row())->osIcon();
     518                break;
     519            }
     520        case Qt::ToolTipRole:
     521            {
     522                v = mVMItemList.at (aIndex.row())->toolTipText();
     523                break;
     524            }
     525        case Qt::FontRole:
     526            {
     527                QFont f = qApp->font();
     528                f.setPointSize (f.pointSize() + 1);
     529                f.setWeight (QFont::Bold);
     530                v = f;
     531                break;
     532            }
     533        case SnapShotDisplayRole:
     534            {
     535                v = mVMItemList.at (aIndex.row())->snapshotName();
     536                break;
     537            }
     538        case SnapShotFontRole:
     539            {
     540                QFont f = qApp->font();
     541                v = f;
     542                break;
     543            }
     544        case SessionStateDisplayRole:
     545            {
     546                v = mVMItemList.at (aIndex.row())->sessionStateName();
     547                break;
     548            }
     549        case SessionStateDecorationRole:
     550            {
     551                v = mVMItemList.at (aIndex.row())->sessionStateIcon();
     552                break;
     553            }
     554        case SessionStateFontRole:
     555            {
     556                QFont f = qApp->font();
     557                f.setPointSize (f.pointSize());
     558                if (mVMItemList.at (aIndex.row())->sessionState() != KSessionState_Closed)
     559                    f.setItalic (true);
     560                v = f;
     561                break;
     562            }
     563        case VBoxVMItemPtrRole:
     564            {
     565                v = qVariantFromValue (mVMItemList.at (aIndex.row()));
     566            }
     567    }
     568    return v;
     569}
     570
     571QVariant VBoxVMModel::headerData(int aSection, Qt::Orientation aOrientation,
     572                                 int aRole /* = Qt::DisplayRole */) const
     573{
     574    if (aRole != Qt::DisplayRole)
     575        return QVariant();
     576
     577    if (aOrientation == Qt::Horizontal)
     578        return QString (tr ("VM"));
     579    else
     580        return QString ("%1").arg (aSection);
     581}
     582
     583bool VBoxVMModel::VBoxVMItemNameCompareLessThan (VBoxVMItem* aItem1, VBoxVMItem* aItem2)
     584{
     585    Assert (aItem1);
     586    Assert (aItem2);
     587    return aItem1->name().toLower() < aItem2->name().toLower();
     588}
     589
     590bool VBoxVMModel::VBoxVMItemNameCompareGreaterThan (VBoxVMItem* aItem1, VBoxVMItem* aItem2)
     591{
     592    Assert (aItem1);
     593    Assert (aItem2);
     594    return aItem2->name().toLower() < aItem1->name().toLower();
     595}
     596
     597/* VBoxVMListBox class */
     598
     599VBoxVMListView::VBoxVMListView (QWidget *aParent /* = 0 */)
     600    :QListView (aParent)
     601{
     602    /* Create & set our delegation class */
     603    VBoxVMItemPainter *delegate = new VBoxVMItemPainter(this);
     604    setItemDelegate(delegate);
     605    /* Default icon size */
     606    setIconSize (QSize (32, 32));
     607    /* Publish the activation of items */
     608    connect (this, SIGNAL (activated (const QModelIndex &)),
     609             this, SIGNAL (activated ()));
     610    /* Track if the application lost the focus */
     611#if MAC_LEOPARD_STYLE
     612    connect (QCoreApplication::instance(), SIGNAL (focusChanged (QWidget *, QWidget *)),
     613             this, SLOT (focusChanged (QWidget *, QWidget *)));
     614    /* 1 pixel line frame */
     615    setMidLineWidth (1);
     616    setLineWidth (0);
     617    setFrameShape (QFrame::Box);
     618    focusChanged (NULL, this);
     619    /* Nesty hack to disable the focus rect on the list view. This interface
     620     * may change at any time! */
     621    static_cast<QMacStyle *> (style())->setFocusRectPolicy (this, QMacStyle::FocusDisabled);
     622#endif /* MAC_LEOPARD_STYLE */
     623}
     624
     625void VBoxVMListView::selectItemByRow (int row)
     626{
     627    setCurrentIndex (model()->index (row, 0));
     628}
     629
     630void VBoxVMListView::selectItemById (const QUuid &aID)
     631{
     632    if (VBoxVMModel *m = qobject_cast<VBoxVMModel*> (model()))
     633    {
     634        QModelIndex i = m->indexById (aID);
     635        if (i.isValid())
     636            setCurrentIndex (i);
     637    }
     638}
     639
     640void VBoxVMListView::ensureSomeRowSelected (int aRowHint)
     641{
     642    VBoxVMItem *item = selectedItem();
     643    if(!item)
     644    {
     645        aRowHint = qBound (0, aRowHint, model()->rowCount() - 1);
     646        selectItemByRow (aRowHint);
     647        item = selectedItem ();
     648        if (!item)
     649            selectItemByRow (0);
     650    }
     651}
     652
     653VBoxVMItem * VBoxVMListView::selectedItem() const
     654{
     655    QModelIndexList indexes = selectedIndexes();
     656    if (indexes.isEmpty())
     657        return NULL;
     658    return model()->data (indexes.first(), VBoxVMModel::VBoxVMItemPtrRole).value<VBoxVMItem *>();
     659}
     660
     661void VBoxVMListView::ensureCurrentVisible()
     662{
     663    scrollTo (currentIndex(), QAbstractItemView::EnsureVisible);
     664}
     665
     666void VBoxVMListView::selectionChanged (const QItemSelection &aSelected, const QItemSelection &aDeselected)
     667{
     668    QListView::selectionChanged (aSelected, aDeselected);
     669    selectCurrent();
     670    ensureCurrentVisible();
     671    emit currentChanged();
     672}
     673
     674void VBoxVMListView::currentChanged (const QModelIndex &aCurrent, const QModelIndex &aPrevious)
     675{
     676    QListView::currentChanged (aCurrent, aPrevious);
     677    selectCurrent();
     678    ensureCurrentVisible();
     679    emit currentChanged();
     680}
     681
     682void VBoxVMListView::dataChanged (const QModelIndex &aTopLeft, const QModelIndex &aBottomRight)
     683{
     684    QListView::dataChanged (aTopLeft, aBottomRight);
     685    selectCurrent();
     686    ensureCurrentVisible();
     687    emit currentChanged();
     688}
     689
     690void VBoxVMListView::focusChanged (QWidget * /* aOld */, QWidget *aNow)
     691{
     692#if MAC_LEOPARD_STYLE
     693    QColor bgColor (212, 221, 229);
     694    if (aNow == NULL)
     695        bgColor.setRgb (232, 232, 232);
     696    QPalette pal = viewport()->palette();
     697    pal.setColor (QPalette::Base, bgColor);
     698    viewport()->setPalette (pal);
     699    viewport()->setAutoFillBackground (true);
     700#else /* MAC_LEOPARD_STYLE */
     701    NOREF (aNow);
     702#endif /* MAC_LEOPARD_STYLE */
     703}
     704
     705void VBoxVMListView::mousePressEvent (QMouseEvent *aEvent)
     706{
     707    /* First process event, in the case the user select a new item */
     708    QListView::mousePressEvent (aEvent);
     709    if (aEvent->button() == Qt::RightButton)
     710    {
     711        /* Send a context menu request if necessary */
     712        const QModelIndex &index = indexAt (aEvent->pos());
     713        if (index.isValid())
     714        {
     715            VBoxVMItem *item = model()->data (index, VBoxVMModel::VBoxVMItemPtrRole).value<VBoxVMItem *>();
     716            emit contextMenuRequested (item, aEvent->globalPos());
     717        }
     718    }
     719}
     720
     721bool VBoxVMListView::selectCurrent()
     722{
     723    QModelIndexList indexes = selectionModel()->selectedIndexes();
     724    if (indexes.isEmpty() ||
     725        indexes.first() != currentIndex())
     726    {
     727        /* Make sure that the current is always selected */
     728        selectionModel()->select (currentIndex(), QItemSelectionModel::Current | QItemSelectionModel::ClearAndSelect);
     729        return true;
     730    }
     731    return false;
     732}
     733
     734/* VBoxVMItemPainter class */
    664735/*
    665736 +----------------------------------------------+
     
    678749*/
    679750
    680 void VBoxVMListBoxItem::paint (QPainter *aP)
    681 {
    682     const VBoxVMListBox *lb = vmListBox();
    683 
    684     QFontMetrics fmName = QFontMetrics (lb->nameFont());
    685     QFontMetrics fmShot = QFontMetrics (lb->shotFont());
    686     QFontMetrics fmState = QFontMetrics (lb->stateFont (mSessionState));
    687     const int marg = lb->margin();
    688 
    689     QPixmap pmOSType;
    690     QPixmap pmState;
    691     QString strState;
    692 
    693     if (mAccessible)
    694     {
    695         pmOSType = vboxGlobal().vmGuestOSTypeIcon (mOSTypeId);
    696         pmState = vboxGlobal().toIcon (mState);
    697         strState = vboxGlobal().toString (mState);
    698     }
    699     else
    700     {
    701         /// @todo (r=dmik) temporary
    702         pmOSType = QPixmap (":/os_unknown.png");
    703         pmState = QPixmap (":/state_aborted_16px.png");
    704         strState = VBoxVMListBox::tr ("Inaccessible");
    705     }
    706 
    707     const QPalette &pal = lb->palette();
    708 
    709     int osTypeY = marg;
    710     int strHeight = fmName.lineSpacing() +
    711                     QMAX (pmState.height(), fmState.height());
    712     if (strHeight > pmOSType.height())
    713         osTypeY += (strHeight - pmOSType.height()) / 2;
    714 
    715     /* draw the OS type icon with border, vertically centered */
    716     aP->drawPixmap (marg, osTypeY, pmOSType);
    717 
    718     aP->setPen (isSelected() ?
    719                 pal.color (QPalette::Active, QPalette::HighlightedText) :
    720                 pal.color (QPalette::Active, QPalette::Text));
    721 
    722     int textX = marg + pmOSType.width() + marg * 3 / 2;
    723 
    724     /* draw the VM name */
    725     aP->setFont (lb->nameFont());
    726     aP->drawText (textX, marg + fmName.ascent(), mName);
    727 
    728     if (!mSnapshotName.isNull())
    729     {
    730         int nameWidth = fmName.width (mName);
    731         aP->setFont (lb->shotFont());
    732         QString shotName = QString (" (%1)").arg (mSnapshotName);
    733         aP->drawText (textX + nameWidth, marg + fmName.ascent(), shotName);
    734     }
    735 
    736     int stateY = marg + fmName.lineSpacing();
    737     int stateH = QMAX (pmState.height(), fmState.height());
    738 
    739     /* draw the VM state icon */
    740     aP->drawPixmap (textX, stateY + (stateH - pmState.height()) / 2,
    741                     pmState);
    742 
    743     /* draw the VM state text */
    744     aP->setFont (lb->stateFont (mSessionState));
    745     aP->drawText (textX + pmState.width() + fmState.width(' '),
    746                   stateY + (stateH - fmState.height()) / 2 + fmState.ascent(),
    747                   strState);
    748 }
     751/* Little helper class for layout calculation */
     752class QRectList: public QList<QRect *>
     753{
     754public:
     755    void alignVCenterTo (QRect* aWhich)
     756    {
     757        QRect b;
     758        foreach (QRect *rect, *this)
     759            if(rect != aWhich)
     760                b |= *rect;
     761        if (b.width() > aWhich->width())
     762            aWhich->moveCenter (QPoint (aWhich->center().x(), b.center().y()));
     763        else
     764        {
     765            foreach (QRect *rect, *this)
     766                if(rect != aWhich)
     767                    rect->moveCenter (QPoint (rect->center().x(), aWhich->center().y()));
     768        }
     769    }
     770};
     771
     772QSize VBoxVMItemPainter::sizeHint (const QStyleOptionViewItem &aOption,
     773                                   const QModelIndex &aIndex) const
     774{
     775    /* Get the size of every item */
     776    QRect osTypeRT = rect (aOption, aIndex, Qt::DecorationRole);
     777    QRect vmNameRT = rect (aOption, aIndex, Qt::DisplayRole);
     778    QRect shotRT = rect (aOption, aIndex, VBoxVMModel::SnapShotDisplayRole);
     779    QRect stateIconRT = rect (aOption, aIndex, VBoxVMModel::SessionStateDecorationRole);
     780    QRect stateRT = rect (aOption, aIndex, VBoxVMModel::SessionStateDisplayRole);
     781    /* Calculate the position for every item */
     782    calcLayout (aIndex, &osTypeRT, &vmNameRT, &shotRT, &stateIconRT, &stateRT);
     783    /* Calc the bounding rect */
     784    const QRect boundingRect = osTypeRT | vmNameRT | shotRT | stateIconRT | stateRT;
     785    /* Return + left/top/right/bottom margin */
     786    return (boundingRect.size() + QSize (2 * mMargin, 2 * mMargin));
     787}
     788
     789void VBoxVMItemPainter::paint (QPainter *aPainter, const QStyleOptionViewItem &aOption,
     790                               const QModelIndex &aIndex) const
     791{
     792    // Name and decoration
     793    const QString vmName = aIndex.data(Qt::DisplayRole).toString();
     794    const QFont nameFont = aIndex.data (Qt::FontRole).value<QFont>();
     795    const QPixmap osType = aIndex.data(Qt::DecorationRole).value<QIcon>().pixmap (aOption.decorationSize, iconMode (aOption.state), iconState (aOption.state));
     796
     797    const QString shot = aIndex.data(VBoxVMModel::SnapShotDisplayRole).toString();
     798    const QFont shotFont = aIndex.data (VBoxVMModel::SnapShotFontRole).value<QFont>();
     799
     800    const QString state = aIndex.data(VBoxVMModel::SessionStateDisplayRole).toString();
     801    const QFont stateFont = aIndex.data (VBoxVMModel::SessionStateFontRole).value<QFont>();
     802    const QPixmap stateIcon = aIndex.data(VBoxVMModel::SessionStateDecorationRole).value<QIcon>().pixmap (QSize (16, 16), iconMode (aOption.state), iconState (aOption.state));
     803
     804    /* Get the sizes for all items */
     805    QRect osTypeRT = rect (aOption, aIndex, Qt::DecorationRole);
     806    QRect vmNameRT = rect (aOption, aIndex, Qt::DisplayRole);
     807    QRect shotRT = rect (aOption, aIndex, VBoxVMModel::SnapShotDisplayRole);
     808    QRect stateIconRT = rect (aOption, aIndex, VBoxVMModel::SessionStateDecorationRole);
     809    QRect stateRT = rect (aOption, aIndex, VBoxVMModel::SessionStateDisplayRole);
     810
     811    /* Calculate the positions for all items */
     812    calcLayout (aIndex, &osTypeRT, &vmNameRT, &shotRT, &stateIconRT, &stateRT);
     813
     814    /* Get the appropiate pen for the current state */
     815    QPalette pal = aOption.palette;
     816    QPen pen = pal.color (QPalette::Active, QPalette::Text);
     817    if (aOption.state & QStyle::State_Selected)
     818        pen =  pal.color (QPalette::Active, QPalette::HighlightedText);
     819    /* Start drawing */
     820    drawBackground (aPainter, aOption, aIndex);
     821    aPainter->save();
     822    /* Set the current pen */
     823    aPainter->setPen (pen);
     824    /* Move the painter to the initial position */
     825    aPainter->translate (aOption.rect.x(), aOption.rect.y());
     826    /* os type icon */
     827    aPainter->drawPixmap (osTypeRT, osType);
     828    /* vm name */
     829    aPainter->setFont (nameFont);
     830    aPainter->drawText (vmNameRT, vmName);
     831    /* current snapshot in braces */
     832    if (!shot.isEmpty())
     833    {
     834        aPainter->setFont (shotFont);
     835        aPainter->drawText (shotRT, QString ("(%1)").arg (shot));
     836    }
     837    /* state icon */
     838    aPainter->drawPixmap (stateIconRT, stateIcon);
     839    /* textual state */
     840    aPainter->setFont (stateFont);
     841    aPainter->drawText (stateRT, state);
     842    /* For debugging */
     843//    QRect boundingRect = osTypeRT | vmNameRT | shotRT | stateIconRT | stateRT;
     844//    aPainter->drawRect (boundingRect);
     845    aPainter->restore();
     846    drawFocus(aPainter, aOption, aOption.rect);
     847}
     848
     849void VBoxVMItemPainter::drawBackground (QPainter *aPainter, const QStyleOptionViewItem &aOption,
     850                                        const QModelIndex &aIndex) const
     851{   
     852#if MAC_LEOPARD_STYLE
     853    NOREF (aIndex);
     854    /* Macify for Leopard */
     855    if (aOption.state & QStyle::State_Selected)
     856    {   
     857        /* Standard color for selected items and focus on the widget */
     858        QColor topLineColor (69, 128, 200);
     859        QColor topGradColor (92, 147, 214);
     860        QColor bottomGradColor (21, 83, 169);
     861        /* Color for selected items and no focus on the widget */
     862        if (QWidget *p = qobject_cast<QWidget *> (parent()))
     863            if (!p->hasFocus())
     864            {
     865                topLineColor.setRgb (145, 160, 192);
     866                topGradColor.setRgb (162, 177, 207);
     867                bottomGradColor.setRgb (110, 129, 169);
     868            }
     869        /* Color for selected items and no focus on the application at all */
     870        if (qApp->focusWidget() == NULL)
     871            {
     872                topLineColor.setRgb (151, 151, 151);
     873                topGradColor.setRgb (180, 180, 180);
     874                bottomGradColor.setRgb (137, 137, 137);
     875            }
     876        /* Paint the background */
     877        QRect r = aOption.rect;
     878        r.setTop (r.top() + 1);
     879        QLinearGradient linearGrad (QPointF(0, r.top()), QPointF(0, r.bottom()));
     880        linearGrad.setColorAt (0, topGradColor);
     881        linearGrad.setColorAt (1, bottomGradColor);
     882        aPainter->setPen (topLineColor);
     883        aPainter->drawLine (r.left(), r.top() - 1, r.right(), r.top() - 1);
     884        aPainter->fillRect (r, linearGrad);
     885    }
     886#else /* MAC_LEOPARD_STYLE */
     887    QItemDelegate::drawBackground (aPainter, aOption, aIndex);
     888#endif /* MAC_LEOPARD_STYLE */
     889}
     890
     891QRect VBoxVMItemPainter::rect (const QStyleOptionViewItem &aOption,
     892                               const QModelIndex &aIndex, int aRole) const
     893{
     894    switch (aRole)
     895    {
     896        case Qt::DisplayRole:
     897            {
     898                QString text = aIndex.data (Qt::DisplayRole).toString();
     899                QFontMetrics fm (fontMetric (aIndex, Qt::FontRole));
     900                return QRect (QPoint (0, 0), fm.size (0, text));
     901                break;
     902            }
     903        case Qt::DecorationRole:
     904            {
     905                QIcon icon = aIndex.data (Qt::DecorationRole).value<QIcon>();
     906                return QRect (QPoint (0, 0), icon.actualSize (aOption.decorationSize, iconMode (aOption.state), iconState (aOption.state)));
     907                break;
     908            }
     909        case VBoxVMModel::SnapShotDisplayRole:
     910            {
     911                QString text = aIndex.data (VBoxVMModel::SnapShotDisplayRole).toString();
     912                if (!text.isEmpty())
     913                {
     914                    QFontMetrics fm (fontMetric (aIndex, VBoxVMModel::SnapShotFontRole));
     915                    return QRect (QPoint (0, 0), fm.size (0, QString ("(%1)").arg (text)));
     916                }else
     917                    return QRect();
     918                break;
     919            }
     920        case VBoxVMModel::SessionStateDisplayRole:
     921            {
     922                QString text = aIndex.data (VBoxVMModel::SessionStateDisplayRole).toString();
     923                QFontMetrics fm (fontMetric (aIndex, VBoxVMModel::SessionStateFontRole));
     924                return QRect (QPoint (0, 0), fm.size (0, text));
     925                break;
     926            }
     927        case VBoxVMModel::SessionStateDecorationRole:
     928            {
     929                QIcon icon = aIndex.data (VBoxVMModel::SessionStateDecorationRole).value<QIcon>();
     930                return QRect (QPoint (0, 0), icon.actualSize (QSize (16, 16), iconMode (aOption.state), iconState (aOption.state)));
     931                break;
     932            }
     933    }
     934    return QRect();
     935}
     936
     937void VBoxVMItemPainter::calcLayout (const QModelIndex &aIndex,
     938                                    QRect *aOSType, QRect *aVMName, QRect *aShot,
     939                                    QRect *aStateIcon, QRect *aState) const
     940{
     941    const int nameSpaceWidth = fontMetric (aIndex, Qt::FontRole).width (' ');
     942    const int stateSpaceWidth = fontMetric (aIndex, VBoxVMModel::SessionStateFontRole).width (' ');
     943    /* Really basic layout managment.
     944     * First layout as usual */
     945    aOSType->moveTo (mMargin, mMargin);
     946    aVMName->moveTo (mMargin + aOSType->width() + mSpacing, mMargin);
     947    aShot->moveTo (aVMName->right() + nameSpaceWidth, aVMName->top());
     948    aStateIcon->moveTo (aVMName->left(), aVMName->bottom());
     949    aState->moveTo (aStateIcon->right() + stateSpaceWidth, aStateIcon->top());
     950    /* Do grouping for the automatic center routine.
     951     * First the states group: */
     952    QRectList statesLayout;
     953    statesLayout << aStateIcon << aState;
     954    /* All items in the layout: */
     955    QRectList allLayout;
     956    allLayout << aOSType << aVMName << aShot << statesLayout;
     957    /* Now verticaly center the items based on the reference item */
     958    statesLayout.alignVCenterTo (aStateIcon);
     959    allLayout.alignVCenterTo (aOSType);
     960}
     961
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette